LCOV - code coverage report
Current view: top level - spdm_requester_lib - libspdm_req_psk_exchange.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 89.5 % 285 255
Test Date: 2026-10-01 20:56:25 Functions: 100.0 % 4 4
Branches: 81.8 % 154 126

             Branch data     Line data    Source code
       1                 :             : /**
       2                 :             :  *  Copyright Notice:
       3                 :             :  *  Copyright 2021-2026 DMTF. All rights reserved.
       4                 :             :  *  License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
       5                 :             :  **/
       6                 :             : 
       7                 :             : #include "internal/libspdm_requester_lib.h"
       8                 :             : #include "internal/libspdm_secured_message_lib.h"
       9                 :             : 
      10                 :             : #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
      11                 :             : 
      12                 :             : #pragma pack(1)
      13                 :             : typedef struct {
      14                 :             :     spdm_message_header_t header;
      15                 :             :     uint16_t req_session_id;
      16                 :             :     uint16_t psk_hint_length;
      17                 :             :     uint16_t context_length;
      18                 :             :     uint16_t opaque_length;
      19                 :             :     uint8_t psk_hint[LIBSPDM_PSK_MAX_HINT_LENGTH];
      20                 :             :     uint8_t context[LIBSPDM_PSK_CONTEXT_LENGTH];
      21                 :             :     uint8_t opaque_data[SPDM_MAX_OPAQUE_DATA_SIZE];
      22                 :             : } libspdm_psk_exchange_request_mine_t;
      23                 :             : 
      24                 :             : typedef struct {
      25                 :             :     spdm_message_header_t header;
      26                 :             :     uint16_t rsp_session_id;
      27                 :             :     uint16_t reserved;
      28                 :             :     uint16_t context_length;
      29                 :             :     uint16_t opaque_length;
      30                 :             :     uint8_t measurement_summary_hash[LIBSPDM_MAX_HASH_SIZE];
      31                 :             :     uint8_t context[LIBSPDM_PSK_CONTEXT_LENGTH];
      32                 :             :     uint8_t opaque_data[SPDM_MAX_OPAQUE_DATA_SIZE];
      33                 :             :     uint8_t verify_data[LIBSPDM_MAX_HASH_SIZE];
      34                 :             : } libspdm_psk_exchange_response_max_t;
      35                 :             : #pragma pack()
      36                 :             : 
      37                 :          21 : bool libspdm_verify_psk_exchange_rsp_hmac(libspdm_context_t *spdm_context,
      38                 :             :                                           libspdm_session_info_t *session_info,
      39                 :             :                                           const void *hmac_data,
      40                 :             :                                           size_t hmac_data_size)
      41                 :             : {
      42                 :             :     size_t hash_size;
      43                 :             :     uint8_t calc_hmac_data[LIBSPDM_MAX_HASH_SIZE];
      44                 :             :     bool result;
      45                 :             : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      46                 :             :     uint8_t *th_curr_data;
      47                 :             :     size_t th_curr_data_size;
      48                 :             :     libspdm_th_managed_buffer_t th_curr;
      49                 :             :     uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
      50                 :             : #endif
      51                 :             : 
      52                 :          21 :     hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
      53         [ -  + ]:          21 :     LIBSPDM_ASSERT(hash_size == hmac_data_size);
      54                 :             : 
      55                 :             : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      56                 :             :     result = libspdm_calculate_th_for_exchange(spdm_context, session_info,
      57                 :             :                                                NULL, 0, &th_curr);
      58                 :             :     if (!result) {
      59                 :             :         return false;
      60                 :             :     }
      61                 :             :     th_curr_data = libspdm_get_managed_buffer(&th_curr);
      62                 :             :     th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
      63                 :             : 
      64                 :             :     result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
      65                 :             :                                th_curr_data, th_curr_data_size, hash_data);
      66                 :             :     if (!result) {
      67                 :             :         return false;
      68                 :             :     }
      69                 :             : 
      70                 :             :     result = libspdm_hmac_all_with_response_finished_key(
      71                 :             :         session_info->secured_message_context, hash_data,
      72                 :             :         hash_size, calc_hmac_data);
      73                 :             :     if (!result) {
      74                 :             :         return false;
      75                 :             :     }
      76                 :             : #else
      77                 :          21 :     result = libspdm_calculate_th_hmac_for_exchange_rsp(
      78                 :             :         spdm_context, session_info, &hash_size, calc_hmac_data);
      79         [ -  + ]:          21 :     if (!result) {
      80                 :           0 :         return false;
      81                 :             :     }
      82                 :             : #endif
      83                 :          21 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
      84                 :          21 :     LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
      85                 :          21 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
      86                 :             : 
      87         [ +  + ]:          21 :     if (!libspdm_consttime_is_mem_equal(calc_hmac_data, hmac_data, hash_size)) {
      88                 :           1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_psk_exchange_rsp_hmac - FAIL !!!\n"));
      89                 :           1 :         return false;
      90                 :             :     }
      91                 :          20 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_psk_exchange_rsp_hmac - PASS !!!\n"));
      92                 :             : 
      93                 :          20 :     return true;
      94                 :             : }
      95                 :             : 
      96                 :             : /**
      97                 :             :  * This function sends PSK_EXCHANGE and receives PSK_EXCHANGE_RSP for SPDM PSK exchange.
      98                 :             :  *
      99                 :             :  * @param  spdm_context              A pointer to the SPDM context.
     100                 :             :  * @param  measurement_hash_type     measurement_hash_type to the PSK_EXCHANGE request.
     101                 :             :  * @param  session_policy            The policy for the session.
     102                 :             :  * @param  session_id                session_id from the PSK_EXCHANGE_RSP response.
     103                 :             :  * @param  heartbeat_period          heartbeat_period from the PSK_EXCHANGE_RSP response.
     104                 :             :  * @param  measurement_hash          measurement_hash from the PSK_EXCHANGE_RSP response.
     105                 :             :  * @param  requester_context_in      A buffer to hold the requester context as input, if not NULL.
     106                 :             :  * @param  requester_context_in_size The size of requester_context_in.
     107                 :             :  *                                   It must be 32 bytes at least, but not exceed LIBSPDM_PSK_CONTEXT_LENGTH.
     108                 :             :  * @param  requester_context         A buffer to hold the requester context, if not NULL.
     109                 :             :  * @param  requester_context_size    On input, the size of requester_context buffer.
     110                 :             :  *                                   On output, the size of data returned in requester_context buffer.
     111                 :             :  *                                   It must be 32 bytes at least.
     112                 :             :  * @param  responder_context         A buffer to hold the responder context, if not NULL.
     113                 :             :  * @param  responder_context_size    On input, the size of responder_context buffer.
     114                 :             :  *                                   On output, the size of data returned in responder_context buffer.
     115                 :             :  *                                   It could be 0 if device does not support context.
     116                 :             :  * @param  responder_opaque_data     A buffer to hold the responder opaque data, if not NULL.
     117                 :             :  * @param  responder_opaque_data_size          On input, the size of the opaque data buffer.
     118                 :             :  *                                   Responder opaque data should be less than 1024 bytes.
     119                 :             :  *                                   On output, the size of the opaque data.
     120                 :             :  **/
     121                 :          77 : static libspdm_return_t libspdm_try_send_receive_psk_exchange(
     122                 :             :     libspdm_context_t *spdm_context,
     123                 :             :     const void *psk_hint, uint16_t psk_hint_size,
     124                 :             :     uint8_t measurement_hash_type,
     125                 :             :     uint8_t session_policy,
     126                 :             :     uint32_t *session_id, uint8_t *heartbeat_period,
     127                 :             :     void *measurement_hash,
     128                 :             :     const void *requester_context_in,
     129                 :             :     size_t requester_context_in_size,
     130                 :             :     void *requester_context,
     131                 :             :     size_t *requester_context_size,
     132                 :             :     void *responder_context,
     133                 :             :     size_t *responder_context_size,
     134                 :             :     const void *requester_opaque_data,
     135                 :             :     size_t requester_opaque_data_size,
     136                 :             :     void *responder_opaque_data,
     137                 :             :     size_t *responder_opaque_data_size)
     138                 :             : {
     139                 :             :     bool result;
     140                 :             :     libspdm_return_t status;
     141                 :             :     libspdm_psk_exchange_request_mine_t *spdm_request;
     142                 :             :     size_t spdm_request_size;
     143                 :             :     libspdm_psk_exchange_response_max_t *spdm_response;
     144                 :             :     size_t spdm_response_size;
     145                 :             :     uint32_t measurement_summary_hash_size;
     146                 :             :     uint32_t hmac_size;
     147                 :             :     uint8_t *ptr;
     148                 :             :     void *measurement_summary_hash;
     149                 :             :     uint8_t *verify_data;
     150                 :             :     uint16_t req_session_id;
     151                 :             :     uint16_t rsp_session_id;
     152                 :             :     libspdm_session_info_t *session_info;
     153                 :             :     size_t opaque_psk_exchange_req_size;
     154                 :             :     uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
     155                 :             :     uint8_t th2_hash_data[LIBSPDM_MAX_HASH_SIZE];
     156                 :             :     uint32_t algo_size;
     157                 :             :     uint8_t *message;
     158                 :             :     size_t message_size;
     159                 :             :     size_t transport_header_size;
     160                 :             :     spdm_version_number_t secured_message_version;
     161                 :             :     spdm_version_number_t local_max_secured_version;
     162                 :          77 :     uint8_t peer_aead_limit_exponent = SECURED_MESSAGE_AEAD_LIMIT_EXPONENT_DEFAULT;
     163                 :             : 
     164   [ +  +  +  +  :          77 :     LIBSPDM_ASSERT(measurement_hash_type == SPDM_PSK_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH ||
                   -  + ]
     165                 :             :                    measurement_hash_type == SPDM_PSK_EXCHANGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH ||
     166                 :             :                    measurement_hash_type == SPDM_PSK_EXCHANGE_REQUEST_ALL_MEASUREMENTS_HASH);
     167                 :             : 
     168         [ +  + ]:          77 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     169                 :           1 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     170                 :             :     }
     171                 :             : 
     172                 :             :     /* Check capabilities even if GET_CAPABILITIES is not sent.
     173                 :             :      * Assuming capabilities are provisioned.*/
     174         [ +  + ]:          76 :     if (!libspdm_is_capabilities_flag_supported(
     175                 :             :             spdm_context, true,
     176                 :             :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
     177                 :             :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
     178                 :           3 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     179                 :             :     }
     180                 :             : 
     181                 :             :     /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
     182                 :             :      * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
     183                 :             :      */
     184         [ +  + ]:          73 :     if (!libspdm_is_capabilities_flag_supported(
     185                 :             :             spdm_context, true,
     186                 :             :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
     187                 :             :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
     188                 :           5 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     189                 :             :     }
     190                 :             : 
     191         [ +  + ]:          68 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     192                 :           1 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     193                 :             :     }
     194         [ +  + ]:          67 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     195         [ +  + ]:           8 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     196                 :             :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
     197                 :           1 :             return LIBSPDM_STATUS_INVALID_STATE_PEER;
     198                 :             :         }
     199                 :             :     }
     200                 :             : 
     201                 :          66 :     req_session_id = libspdm_allocate_req_session_id(spdm_context, true);
     202         [ +  + ]:          66 :     if (req_session_id == (INVALID_SESSION_ID & 0xFFFF)) {
     203                 :           1 :         return LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     204                 :             :     }
     205                 :             : 
     206                 :          65 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL, SPDM_PSK_EXCHANGE);
     207                 :             :     {
     208                 :             :         /* Double check if algorithm has been provisioned, because NEGOTIATE_ALGORITHMS might be skipped.*/
     209         [ +  + ]:          65 :         if (libspdm_is_capabilities_flag_supported(
     210                 :             :                 spdm_context, true, 0,
     211                 :             :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP)) {
     212                 :          17 :             if (spdm_context->connection_info.algorithm
     213         [ +  + ]:          17 :                 .measurement_spec !=
     214                 :             :                 SPDM_MEASUREMENT_SPECIFICATION_DMTF) {
     215                 :           1 :                 return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     216                 :             :             }
     217                 :          16 :             algo_size = libspdm_get_measurement_hash_size(
     218                 :             :                 spdm_context->connection_info.algorithm.measurement_hash_algo);
     219         [ +  + ]:          16 :             if (algo_size == 0) {
     220                 :           1 :                 return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     221                 :             :             }
     222                 :             :         }
     223                 :          63 :         algo_size = libspdm_get_hash_size(
     224                 :             :             spdm_context->connection_info.algorithm.base_hash_algo);
     225         [ +  + ]:          63 :         if (algo_size == 0) {
     226                 :           1 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     227                 :             :         }
     228         [ +  + ]:          62 :         if (spdm_context->connection_info.algorithm.key_schedule !=
     229                 :             :             SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM) {
     230                 :           1 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     231                 :             :         }
     232                 :             :     }
     233                 :             : 
     234                 :          61 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
     235                 :          61 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     236         [ +  + ]:          61 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     237                 :           1 :         return status;
     238                 :             :     }
     239         [ -  + ]:          60 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
     240                 :             :                     spdm_context->local_context.capability.transport_tail_size);
     241                 :          60 :     spdm_request = (void *)(message + transport_header_size);
     242                 :          60 :     spdm_request_size = message_size - transport_header_size -
     243                 :          60 :                         spdm_context->local_context.capability.transport_tail_size;
     244                 :             : 
     245         [ -  + ]:          60 :     LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_psk_exchange_request_t) + psk_hint_size);
     246                 :          60 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     247                 :          60 :     spdm_request->header.request_response_code = SPDM_PSK_EXCHANGE;
     248                 :          60 :     spdm_request->header.param1 = measurement_hash_type;
     249         [ +  + ]:          60 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     250                 :           7 :         spdm_request->header.param2 = session_policy;
     251                 :             :     } else {
     252                 :          53 :         spdm_request->header.param2 = 0;
     253                 :             :     }
     254                 :          60 :     spdm_request->psk_hint_length = psk_hint_size;
     255         [ +  + ]:          60 :     if (requester_context_in == NULL) {
     256                 :          59 :         spdm_request->context_length = LIBSPDM_PSK_CONTEXT_LENGTH;
     257                 :             :     } else {
     258         [ -  + ]:           1 :         LIBSPDM_ASSERT (requester_context_in_size <= LIBSPDM_PSK_CONTEXT_LENGTH);
     259                 :           1 :         spdm_request->context_length = (uint16_t)requester_context_in_size;
     260                 :             :     }
     261                 :             : 
     262                 :             :     /* No secured message version is negotiated yet at request time, so the AEADlimitOE element is
     263                 :             :      * gated on the highest secured message version this endpoint offers. */
     264                 :          60 :     local_max_secured_version = libspdm_local_max_secured_message_version(spdm_context);
     265                 :             : 
     266         [ +  + ]:          60 :     if (requester_opaque_data != NULL) {
     267         [ -  + ]:           1 :         LIBSPDM_ASSERT(requester_opaque_data_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
     268                 :             : 
     269                 :           1 :         opaque_psk_exchange_req_size = (uint16_t)requester_opaque_data_size;
     270                 :             :     } else {
     271                 :             :         /* DSP0277 1.3: also advertise this endpoint's AEAD limit in the request opaque data. */
     272                 :          59 :         opaque_psk_exchange_req_size =
     273                 :         118 :             libspdm_get_opaque_data_supported_version_data_size(spdm_context) +
     274                 :          59 :             libspdm_get_opaque_data_aead_limit_element_size(spdm_context,
     275                 :             :                                                             local_max_secured_version);
     276                 :             :     }
     277                 :             : 
     278         [ -  + ]:          60 :     LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_psk_exchange_request_t) + psk_hint_size +
     279                 :             :                    spdm_request->context_length + opaque_psk_exchange_req_size);
     280                 :          60 :     spdm_request->opaque_length = (uint16_t)opaque_psk_exchange_req_size;
     281                 :             : 
     282                 :          60 :     spdm_request->req_session_id = req_session_id;
     283                 :             : 
     284                 :          60 :     ptr = spdm_request->psk_hint;
     285   [ +  +  +  - ]:          60 :     if ((psk_hint != NULL) && (psk_hint_size > 0)) {
     286                 :          59 :         libspdm_copy_mem(ptr, sizeof(spdm_request->psk_hint),
     287                 :             :                          psk_hint,
     288                 :             :                          psk_hint_size);
     289                 :             :     }
     290                 :          60 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "psk_hint (0x%x) - ", spdm_request->psk_hint_length));
     291                 :          60 :     LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_request->psk_hint_length);
     292                 :          60 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     293                 :          60 :     ptr += spdm_request->psk_hint_length;
     294                 :             : 
     295         [ +  + ]:          60 :     if (requester_context_in == NULL) {
     296         [ -  + ]:          59 :         if (!libspdm_get_random_number(LIBSPDM_PSK_CONTEXT_LENGTH, ptr)) {
     297                 :           0 :             libspdm_release_sender_buffer (spdm_context);
     298                 :           0 :             return LIBSPDM_STATUS_LOW_ENTROPY;
     299                 :             :         }
     300                 :             :     } else {
     301                 :           1 :         libspdm_copy_mem(ptr, sizeof(spdm_request->context),
     302                 :           1 :                          requester_context_in, spdm_request->context_length);
     303                 :             :     }
     304                 :          60 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterContextData (0x%x) - ",
     305                 :             :                    spdm_request->context_length));
     306                 :          60 :     LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_request->context_length);
     307                 :          60 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     308         [ +  + ]:          60 :     if (requester_context != NULL) {
     309         [ +  - ]:           1 :         if (*requester_context_size > spdm_request->context_length) {
     310                 :           1 :             *requester_context_size = spdm_request->context_length;
     311                 :             :         }
     312                 :           1 :         libspdm_copy_mem(requester_context, *requester_context_size,
     313                 :             :                          ptr, *requester_context_size);
     314                 :             :     }
     315                 :          60 :     ptr += spdm_request->context_length;
     316                 :             : 
     317         [ +  + ]:          60 :     if (requester_opaque_data != NULL) {
     318                 :           1 :         libspdm_copy_mem(ptr, opaque_psk_exchange_req_size,
     319                 :             :                          requester_opaque_data, opaque_psk_exchange_req_size);
     320                 :             :     } else {
     321                 :          59 :         size_t supported_version_size =
     322                 :          59 :             libspdm_get_opaque_data_supported_version_data_size(spdm_context);
     323                 :          59 :         libspdm_build_opaque_data_supported_version_data(
     324                 :             :             spdm_context, &supported_version_size, ptr);
     325                 :             :         /* opaque_psk_exchange_req_size holds the reserved opaque data capacity (supported version +
     326                 :             :          * AEAD limit); it is the capacity passed to the append below. */
     327                 :          59 :         libspdm_build_opaque_data_aead_limit_element(
     328                 :             :             spdm_context, local_max_secured_version, &opaque_psk_exchange_req_size, ptr);
     329                 :             :     }
     330                 :          60 :     ptr += opaque_psk_exchange_req_size;
     331                 :             : 
     332                 :          60 :     spdm_request_size = (size_t)ptr - (size_t)spdm_request;
     333                 :          60 :     status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size,
     334                 :             :                                        spdm_request);
     335         [ +  + ]:          60 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     336                 :           1 :         libspdm_release_sender_buffer (spdm_context);
     337                 :           1 :         return status;
     338                 :             :     }
     339                 :          59 :     libspdm_release_sender_buffer (spdm_context);
     340                 :          59 :     spdm_request = (void *)spdm_context->last_spdm_request;
     341                 :             : 
     342                 :             :     /* receive */
     343                 :             : 
     344                 :          59 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     345         [ +  + ]:          59 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     346                 :           1 :         return status;
     347                 :             :     }
     348         [ -  + ]:          58 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
     349                 :          58 :     spdm_response = (void *)(message);
     350                 :          58 :     spdm_response_size = message_size;
     351                 :             : 
     352                 :          58 :     status = libspdm_receive_spdm_response(
     353                 :             :         spdm_context, NULL, &spdm_response_size, (void **)&spdm_response);
     354         [ +  + ]:          58 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     355                 :           1 :         goto receive_done;
     356                 :             :     }
     357         [ -  + ]:          57 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     358                 :           0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     359                 :           0 :         goto receive_done;
     360                 :             :     }
     361         [ +  + ]:          57 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     362                 :          26 :         status = libspdm_handle_error_response_main(
     363                 :             :             spdm_context, NULL, &spdm_response_size,
     364                 :             :             (void **)&spdm_response, SPDM_PSK_EXCHANGE,
     365                 :             :             SPDM_PSK_EXCHANGE_RSP);
     366         [ +  + ]:          26 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     367                 :          25 :             goto receive_done;
     368                 :             :         }
     369         [ +  + ]:          31 :     } else if (spdm_response->header.request_response_code != SPDM_PSK_EXCHANGE_RSP) {
     370                 :           1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     371                 :           1 :         goto receive_done;
     372                 :             :     }
     373         [ +  + ]:          31 :     if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     374                 :           1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     375                 :           1 :         goto receive_done;
     376                 :             :     }
     377         [ +  + ]:          30 :     if (spdm_response_size < sizeof(spdm_psk_exchange_response_t)) {
     378                 :           1 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     379                 :           1 :         goto receive_done;
     380                 :             :     }
     381                 :             : 
     382         [ +  + ]:          29 :     if (!libspdm_is_capabilities_flag_supported(
     383                 :             :             spdm_context, true,
     384                 :             :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     385                 :             :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     386         [ +  + ]:          27 :         if (spdm_response->header.param1 != 0) {
     387                 :           1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     388                 :           1 :             goto receive_done;
     389                 :             :         }
     390                 :             :     }
     391         [ +  - ]:          28 :     if (heartbeat_period != NULL) {
     392                 :          28 :         *heartbeat_period = spdm_response->header.param1;
     393                 :             :     }
     394                 :             : 
     395                 :          28 :     measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
     396                 :             :         spdm_context, true, measurement_hash_type);
     397                 :          28 :     hmac_size = libspdm_get_hash_size(
     398                 :             :         spdm_context->connection_info.algorithm.base_hash_algo);
     399                 :             : 
     400                 :          28 :     if (spdm_response_size <
     401                 :             :         sizeof(spdm_psk_exchange_response_t) +
     402                 :          28 :         spdm_response->context_length + spdm_response->opaque_length +
     403         [ +  + ]:          28 :         measurement_summary_hash_size + hmac_size) {
     404                 :           2 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     405                 :           2 :         goto receive_done;
     406                 :             :     }
     407                 :             : 
     408                 :          26 :     ptr = (uint8_t *)spdm_response + sizeof(spdm_psk_exchange_response_t) +
     409                 :          26 :           measurement_summary_hash_size + spdm_response->context_length;
     410                 :          26 :     secured_message_version = 0;
     411         [ +  + ]:          26 :     if (spdm_response->opaque_length != 0) {
     412                 :          23 :         result = libspdm_process_general_opaque_data_check(spdm_context,
     413                 :          23 :                                                            spdm_response->opaque_length, ptr);
     414         [ +  + ]:          23 :         if (!result) {
     415                 :           1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     416                 :           1 :             goto receive_done;
     417                 :             :         }
     418                 :          22 :         status = libspdm_process_opaque_data_version_selection_data(
     419                 :          22 :             spdm_context, spdm_response->opaque_length, ptr, &secured_message_version);
     420         [ +  + ]:          22 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     421                 :           1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     422                 :           1 :             goto receive_done;
     423                 :             :         }
     424                 :             :         /* DSP0277 1.3: read the Responder's AEAD limit (absent -> default 64). */
     425                 :          21 :         status = libspdm_process_opaque_data_aead_limit(
     426                 :          21 :             spdm_context, secured_message_version, spdm_response->opaque_length, ptr,
     427                 :             :             &peer_aead_limit_exponent);
     428         [ -  + ]:          21 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     429                 :           0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     430                 :           0 :             goto receive_done;
     431                 :             :         }
     432                 :             :     }
     433                 :             : 
     434                 :          24 :     spdm_response_size = sizeof(spdm_psk_exchange_response_t) +
     435                 :          24 :                          spdm_response->context_length +
     436                 :          24 :                          spdm_response->opaque_length +
     437                 :          24 :                          measurement_summary_hash_size + hmac_size;
     438                 :             : 
     439                 :          24 :     ptr = (uint8_t *)(spdm_response->measurement_summary_hash);
     440                 :          24 :     measurement_summary_hash = ptr;
     441                 :          24 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "measurement_summary_hash (0x%x) - ",
     442                 :             :                    measurement_summary_hash_size));
     443                 :          24 :     LIBSPDM_INTERNAL_DUMP_DATA(measurement_summary_hash,
     444                 :             :                                measurement_summary_hash_size);
     445                 :          24 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     446                 :             : 
     447                 :          24 :     ptr += measurement_summary_hash_size;
     448                 :             : 
     449         [ -  + ]:          24 :     if (spdm_response->opaque_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
     450                 :           0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     451                 :           0 :         goto receive_done;
     452                 :             :     }
     453                 :             : 
     454         [ +  + ]:          24 :     if (libspdm_is_capabilities_flag_supported(
     455                 :             :             spdm_context, true, 0,
     456                 :             :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER)) {
     457         [ +  + ]:           4 :         if (spdm_response->context_length != 0) {
     458                 :           1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     459                 :           1 :             goto receive_done;
     460                 :             :         }
     461                 :             :     } else {
     462         [ +  + ]:          20 :         if (spdm_response->context_length == 0) {
     463                 :           1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     464                 :           1 :             goto receive_done;
     465                 :             :         }
     466                 :             :     }
     467                 :             : 
     468                 :          22 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderContextData (0x%x) - ",
     469                 :             :                    spdm_response->context_length));
     470                 :          22 :     LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_response->context_length);
     471                 :          22 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     472         [ +  + ]:          22 :     if (responder_context != NULL) {
     473         [ +  - ]:           1 :         if (*responder_context_size > spdm_response->context_length) {
     474                 :           1 :             *responder_context_size = spdm_response->context_length;
     475                 :             :         }
     476                 :           1 :         libspdm_copy_mem(responder_context, *responder_context_size,
     477                 :             :                          ptr, *responder_context_size);
     478                 :             :     }
     479                 :             : 
     480                 :          22 :     ptr += spdm_response->context_length;
     481                 :             : 
     482   [ +  +  +  - ]:          22 :     if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
     483         [ +  + ]:           2 :         if (spdm_response->opaque_length >= *responder_opaque_data_size) {
     484                 :           1 :             status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     485                 :           1 :             goto receive_done;
     486                 :             :         }
     487                 :           1 :         libspdm_copy_mem(responder_opaque_data, *responder_opaque_data_size,
     488                 :           1 :                          ptr, spdm_response->opaque_length);
     489                 :           1 :         *responder_opaque_data_size = spdm_response->opaque_length;
     490                 :             :     }
     491                 :             : 
     492                 :          21 :     ptr += spdm_response->opaque_length;
     493                 :             : 
     494                 :          21 :     rsp_session_id = spdm_response->rsp_session_id;
     495                 :          21 :     *session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
     496                 :          21 :     session_info = libspdm_assign_session_id(spdm_context, *session_id, secured_message_version,
     497                 :             :                                              true);
     498         [ -  + ]:          21 :     if (session_info == NULL) {
     499                 :           0 :         status = LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     500                 :           0 :         goto receive_done;
     501                 :             :     }
     502                 :          21 :     libspdm_session_info_set_psk_hint(session_info,
     503                 :             :                                       psk_hint,
     504                 :             :                                       psk_hint_size);
     505                 :             : 
     506                 :             :     /* DSP0277 1.3: program the session's AEAD limit (min of local and peer) when secured message
     507                 :             :      * version 1.3 was negotiated. */
     508         [ -  + ]:          21 :     if (libspdm_get_version_from_version_number(secured_message_version) >=
     509                 :             :         SECURED_SPDM_VERSION_13) {
     510                 :           0 :         libspdm_apply_aead_limit_to_session(spdm_context, session_info,
     511                 :             :                                             peer_aead_limit_exponent);
     512                 :             :     }
     513                 :             : 
     514                 :             :     /* Cache session data*/
     515                 :             : 
     516                 :          21 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_request,
     517                 :             :                                       spdm_request_size);
     518         [ -  + ]:          21 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     519                 :           0 :         libspdm_free_session_id(spdm_context, *session_id);
     520                 :           0 :         goto receive_done;
     521                 :             :     }
     522                 :             : 
     523                 :          21 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_response,
     524                 :             :                                       spdm_response_size - hmac_size);
     525         [ -  + ]:          21 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     526                 :           0 :         libspdm_free_session_id(spdm_context, *session_id);
     527                 :           0 :         goto receive_done;
     528                 :             :     }
     529                 :             : 
     530                 :          21 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
     531                 :             :                    *session_id));
     532                 :          21 :     result = libspdm_calculate_th1_hash(spdm_context, session_info, true,
     533                 :             :                                         th1_hash_data);
     534         [ -  + ]:          21 :     if (!result) {
     535                 :           0 :         libspdm_free_session_id(spdm_context, *session_id);
     536                 :           0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     537                 :           0 :         goto receive_done;
     538                 :             :     }
     539                 :          21 :     result = libspdm_generate_session_handshake_key(
     540                 :             :         session_info->secured_message_context, th1_hash_data);
     541         [ -  + ]:          21 :     if (!result) {
     542                 :           0 :         libspdm_free_session_id(spdm_context, *session_id);
     543                 :           0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     544                 :           0 :         goto receive_done;
     545                 :             :     }
     546                 :             : 
     547                 :          21 :     verify_data = ptr;
     548                 :          21 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%x):\n", hmac_size));
     549                 :          21 :     LIBSPDM_INTERNAL_DUMP_HEX(verify_data, hmac_size);
     550                 :          21 :     result = libspdm_verify_psk_exchange_rsp_hmac(spdm_context, session_info,
     551                 :             :                                                   verify_data, hmac_size);
     552         [ +  + ]:          21 :     if (!result) {
     553                 :           1 :         libspdm_free_session_id(spdm_context, *session_id);
     554                 :           1 :         status = LIBSPDM_STATUS_VERIF_FAIL;
     555                 :           1 :         goto receive_done;
     556                 :             :     }
     557                 :             : 
     558                 :          20 :     status = libspdm_append_message_k(spdm_context, session_info, true, verify_data, hmac_size);
     559         [ -  + ]:          20 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     560                 :           0 :         libspdm_free_session_id(spdm_context, *session_id);
     561                 :           0 :         goto receive_done;
     562                 :             :     }
     563                 :             : 
     564         [ +  - ]:          20 :     if (measurement_hash != NULL) {
     565                 :          20 :         libspdm_copy_mem(measurement_hash, measurement_summary_hash_size,
     566                 :             :                          measurement_summary_hash, measurement_summary_hash_size);
     567                 :             :     }
     568                 :             : 
     569                 :          20 :     session_info->session_policy = session_policy;
     570                 :             : 
     571                 :          20 :     libspdm_secured_message_set_session_state(
     572                 :             :         session_info->secured_message_context,
     573                 :             :         LIBSPDM_SESSION_STATE_HANDSHAKING);
     574                 :             : 
     575         [ +  + ]:          20 :     if (!libspdm_is_capabilities_flag_supported(
     576                 :             :             spdm_context, true, 0,
     577                 :             :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
     578                 :             :         /* No need to send PSK_FINISH, enter application phase directly.*/
     579                 :             : 
     580                 :           3 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n",
     581                 :             :                        *session_id));
     582                 :           3 :         result = libspdm_calculate_th2_hash(spdm_context, session_info,
     583                 :             :                                             true, th2_hash_data);
     584         [ -  + ]:           3 :         if (!result) {
     585                 :           0 :             libspdm_free_session_id(spdm_context, *session_id);
     586                 :           0 :             status = LIBSPDM_STATUS_CRYPTO_ERROR;
     587                 :           0 :             goto receive_done;
     588                 :             :         }
     589                 :           3 :         result = libspdm_generate_session_data_key(
     590                 :             :             session_info->secured_message_context, th2_hash_data);
     591         [ -  + ]:           3 :         if (!result) {
     592                 :           0 :             libspdm_free_session_id(spdm_context, *session_id);
     593                 :           0 :             status = LIBSPDM_STATUS_CRYPTO_ERROR;
     594                 :           0 :             goto receive_done;
     595                 :             :         }
     596                 :             : 
     597                 :           3 :         libspdm_secured_message_set_session_state(
     598                 :             :             session_info->secured_message_context,
     599                 :             :             LIBSPDM_SESSION_STATE_ESTABLISHED);
     600                 :             :     }
     601                 :             : 
     602                 :          20 :     session_info->heartbeat_period = spdm_response->header.param1;
     603                 :             : 
     604                 :             :     /* -=[Log Message Phase]=- */
     605                 :             :     #if LIBSPDM_ENABLE_MSG_LOG
     606                 :          20 :     libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     607                 :             :     #endif /* LIBSPDM_ENABLE_MSG_LOG */
     608                 :             : 
     609                 :          20 :     status = LIBSPDM_STATUS_SUCCESS;
     610                 :             : 
     611                 :          58 : receive_done:
     612                 :          58 :     libspdm_release_receiver_buffer (spdm_context);
     613                 :          58 :     return status;
     614                 :             : }
     615                 :             : 
     616                 :          68 : libspdm_return_t libspdm_send_receive_psk_exchange(libspdm_context_t *spdm_context,
     617                 :             :                                                    const void *psk_hint,
     618                 :             :                                                    uint16_t psk_hint_size,
     619                 :             :                                                    uint8_t measurement_hash_type,
     620                 :             :                                                    uint8_t session_policy,
     621                 :             :                                                    uint32_t *session_id,
     622                 :             :                                                    uint8_t *heartbeat_period,
     623                 :             :                                                    void *measurement_hash)
     624                 :             : {
     625                 :             :     size_t retry;
     626                 :             :     uint64_t retry_delay_time;
     627                 :             :     libspdm_return_t status;
     628                 :             : 
     629                 :          68 :     spdm_context->crypto_request = true;
     630                 :          68 :     retry = spdm_context->retry_times;
     631                 :          68 :     retry_delay_time = spdm_context->retry_delay_time;
     632                 :             :     do {
     633                 :          69 :         status = libspdm_try_send_receive_psk_exchange(
     634                 :             :             spdm_context, psk_hint, psk_hint_size,
     635                 :             :             measurement_hash_type, session_policy, session_id,
     636                 :             :             heartbeat_period, measurement_hash,
     637                 :             :             NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL);
     638         [ +  + ]:          69 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     639                 :          67 :             return status;
     640                 :             :         }
     641                 :             : 
     642                 :           2 :         libspdm_sleep(retry_delay_time);
     643         [ +  + ]:           2 :     } while (retry-- != 0);
     644                 :             : 
     645                 :           1 :     return status;
     646                 :             : }
     647                 :             : 
     648                 :           7 : libspdm_return_t libspdm_send_receive_psk_exchange_ex(libspdm_context_t *spdm_context,
     649                 :             :                                                       const void *psk_hint,
     650                 :             :                                                       uint16_t psk_hint_size,
     651                 :             :                                                       uint8_t measurement_hash_type,
     652                 :             :                                                       uint8_t session_policy,
     653                 :             :                                                       uint32_t *session_id,
     654                 :             :                                                       uint8_t *heartbeat_period,
     655                 :             :                                                       void *measurement_hash,
     656                 :             :                                                       const void *requester_context_in,
     657                 :             :                                                       size_t requester_context_in_size,
     658                 :             :                                                       void *requester_context,
     659                 :             :                                                       size_t *requester_context_size,
     660                 :             :                                                       void *responder_context,
     661                 :             :                                                       size_t *responder_context_size,
     662                 :             :                                                       const void *requester_opaque_data,
     663                 :             :                                                       size_t requester_opaque_data_size,
     664                 :             :                                                       void *responder_opaque_data,
     665                 :             :                                                       size_t *responder_opaque_data_size)
     666                 :             : {
     667                 :             :     size_t retry;
     668                 :             :     uint64_t retry_delay_time;
     669                 :             :     libspdm_return_t status;
     670                 :             : 
     671                 :           7 :     spdm_context->crypto_request = true;
     672                 :           7 :     retry = spdm_context->retry_times;
     673                 :           7 :     retry_delay_time = spdm_context->retry_delay_time;
     674                 :             :     do {
     675                 :           8 :         status = libspdm_try_send_receive_psk_exchange(
     676                 :             :             spdm_context, psk_hint, psk_hint_size,
     677                 :             :             measurement_hash_type, session_policy, session_id,
     678                 :             :             heartbeat_period, measurement_hash,
     679                 :             :             requester_context_in, requester_context_in_size,
     680                 :             :             requester_context, requester_context_size,
     681                 :             :             responder_context, responder_context_size,
     682                 :             :             requester_opaque_data, requester_opaque_data_size,
     683                 :             :             responder_opaque_data, responder_opaque_data_size);
     684         [ +  + ]:           8 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     685                 :           6 :             return status;
     686                 :             :         }
     687                 :             : 
     688                 :           2 :         libspdm_sleep(retry_delay_time);
     689         [ +  + ]:           2 :     } while (retry-- != 0);
     690                 :             : 
     691                 :           1 :     return status;
     692                 :             : }
     693                 :             : 
     694                 :             : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
        

Generated by: LCOV version 2.0-1