Code coverage report for DMTF/libspdm
Current view: top level - library/spdm_requester_lib - libspdm_req_psk_exchange.c (source / functions) Coverage Total Hit
Test: 36148b912f76d231c18d216d6dee5c0858575bb1 Lines: 90.2 % 285 257
Test Date: 2026-10-25 08:40:22 Functions: 100.0 % 4 4
Branches: 85.8 % 134 115

             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                 :          44 : 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                 :          44 :     hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
      53                 :          44 :     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                 :          44 :     result = libspdm_calculate_th_hmac_for_exchange_rsp(
      78                 :             :         spdm_context, session_info, &hash_size, calc_hmac_data);
      79         [ -  + ]:          44 :     if (!result) {
      80                 :           0 :         return false;
      81                 :             :     }
      82                 :             : #endif
      83                 :          44 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
      84                 :          44 :     LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
      85                 :          44 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
      86                 :             : 
      87         [ +  + ]:          44 :     if (!libspdm_consttime_is_mem_equal(calc_hmac_data, hmac_data, hash_size)) {
      88                 :           2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_psk_exchange_rsp_hmac - FAIL !!!\n"));
      89                 :           2 :         return false;
      90                 :             :     }
      91                 :          42 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_psk_exchange_rsp_hmac - PASS !!!\n"));
      92                 :             : 
      93                 :          42 :     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                 :         166 : 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                 :         166 :     uint8_t peer_aead_limit_exponent = SECURED_MESSAGE_AEAD_LIMIT_EXPONENT_DEFAULT;
     163                 :             : 
     164                 :         166 :     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         [ +  + ]:         166 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     169                 :           2 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     170                 :             :     }
     171                 :             : 
     172                 :             :     /* Check capabilities even if GET_CAPABILITIES is not sent.
     173                 :             :      * Assuming capabilities are provisioned.*/
     174         [ +  + ]:         164 :     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                 :           6 :         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         [ +  + ]:         158 :     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                 :          18 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     189                 :             :     }
     190                 :             : 
     191         [ +  + ]:         140 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     192                 :           2 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     193                 :             :     }
     194         [ +  + ]:         138 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     195         [ +  + ]:          18 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     196                 :             :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
     197                 :           2 :             return LIBSPDM_STATUS_INVALID_STATE_PEER;
     198                 :             :         }
     199                 :             :     }
     200                 :             : 
     201                 :         136 :     req_session_id = libspdm_allocate_req_session_id(spdm_context, true);
     202         [ +  + ]:         136 :     if (req_session_id == (INVALID_SESSION_ID & 0xFFFF)) {
     203                 :           2 :         return LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     204                 :             :     }
     205                 :             : 
     206                 :         134 :     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         [ +  + ]:         134 :         if (libspdm_is_capabilities_flag_supported(
     210                 :             :                 spdm_context, true, 0,
     211                 :             :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP)) {
     212                 :          34 :             if (spdm_context->connection_info.algorithm
     213         [ +  + ]:          34 :                 .measurement_spec !=
     214                 :             :                 SPDM_MEASUREMENT_SPECIFICATION_DMTF) {
     215                 :           2 :                 return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     216                 :             :             }
     217                 :          32 :             algo_size = libspdm_get_measurement_hash_size(
     218                 :             :                 spdm_context->connection_info.algorithm.measurement_hash_algo);
     219         [ +  + ]:          32 :             if (algo_size == 0) {
     220                 :           2 :                 return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     221                 :             :             }
     222                 :             :         }
     223                 :         130 :         algo_size = libspdm_get_hash_size(
     224                 :             :             spdm_context->connection_info.algorithm.base_hash_algo);
     225         [ +  + ]:         130 :         if (algo_size == 0) {
     226                 :           2 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     227                 :             :         }
     228         [ +  + ]:         128 :         if (spdm_context->connection_info.algorithm.key_schedule !=
     229                 :             :             SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM) {
     230                 :           2 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     231                 :             :         }
     232                 :             :     }
     233                 :             : 
     234                 :         126 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
     235                 :         126 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     236         [ +  + ]:         126 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     237                 :           2 :         return status;
     238                 :             :     }
     239                 :         124 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
     240                 :             :                     spdm_context->local_context.capability.transport_tail_size);
     241                 :         124 :     spdm_request = (void *)(message + transport_header_size);
     242                 :         124 :     spdm_request_size = message_size - transport_header_size -
     243                 :         124 :                         spdm_context->local_context.capability.transport_tail_size;
     244                 :             : 
     245                 :         124 :     LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_psk_exchange_request_t) + psk_hint_size);
     246                 :         124 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     247                 :         124 :     spdm_request->header.request_response_code = SPDM_PSK_EXCHANGE;
     248                 :         124 :     spdm_request->header.param1 = measurement_hash_type;
     249         [ +  + ]:         124 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     250                 :          16 :         spdm_request->header.param2 = session_policy;
     251                 :             :     } else {
     252                 :         108 :         spdm_request->header.param2 = 0;
     253                 :             :     }
     254                 :         124 :     spdm_request->psk_hint_length = psk_hint_size;
     255         [ +  + ]:         124 :     if (requester_context_in == NULL) {
     256                 :         122 :         spdm_request->context_length = LIBSPDM_PSK_CONTEXT_LENGTH;
     257                 :             :     } else {
     258                 :           2 :         LIBSPDM_ASSERT (requester_context_in_size <= LIBSPDM_PSK_CONTEXT_LENGTH);
     259                 :           2 :         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                 :         124 :     local_max_secured_version = libspdm_local_max_secured_message_version(spdm_context);
     265                 :             : 
     266         [ +  + ]:         124 :     if (requester_opaque_data != NULL) {
     267                 :           2 :         LIBSPDM_ASSERT(requester_opaque_data_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
     268                 :             : 
     269                 :           2 :         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                 :         122 :         opaque_psk_exchange_req_size =
     273                 :         244 :             libspdm_get_opaque_data_supported_version_data_size(spdm_context) +
     274                 :         122 :             libspdm_get_opaque_data_aead_limit_element_size(spdm_context,
     275                 :             :                                                             local_max_secured_version);
     276                 :             :     }
     277                 :             : 
     278                 :         124 :     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                 :         124 :     spdm_request->opaque_length = (uint16_t)opaque_psk_exchange_req_size;
     281                 :             : 
     282                 :         124 :     spdm_request->req_session_id = req_session_id;
     283                 :             : 
     284                 :         124 :     ptr = spdm_request->psk_hint;
     285   [ +  +  +  - ]:         124 :     if ((psk_hint != NULL) && (psk_hint_size > 0)) {
     286                 :         122 :         libspdm_copy_mem(ptr, sizeof(spdm_request->psk_hint),
     287                 :             :                          psk_hint,
     288                 :             :                          psk_hint_size);
     289                 :             :     }
     290                 :         124 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "psk_hint (0x%x) - ", spdm_request->psk_hint_length));
     291                 :         124 :     LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_request->psk_hint_length);
     292                 :         124 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     293                 :         124 :     ptr += spdm_request->psk_hint_length;
     294                 :             : 
     295         [ +  + ]:         124 :     if (requester_context_in == NULL) {
     296         [ -  + ]:         122 :         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                 :           2 :         libspdm_copy_mem(ptr, sizeof(spdm_request->context),
     302                 :           2 :                          requester_context_in, spdm_request->context_length);
     303                 :             :     }
     304                 :         124 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterContextData (0x%x) - ",
     305                 :             :                    spdm_request->context_length));
     306                 :         124 :     LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_request->context_length);
     307                 :         124 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     308         [ +  + ]:         124 :     if (requester_context != NULL) {
     309         [ +  - ]:           2 :         if (*requester_context_size > spdm_request->context_length) {
     310                 :           2 :             *requester_context_size = spdm_request->context_length;
     311                 :             :         }
     312                 :           2 :         libspdm_copy_mem(requester_context, *requester_context_size,
     313                 :             :                          ptr, *requester_context_size);
     314                 :             :     }
     315                 :         124 :     ptr += spdm_request->context_length;
     316                 :             : 
     317         [ +  + ]:         124 :     if (requester_opaque_data != NULL) {
     318                 :           2 :         libspdm_copy_mem(ptr, opaque_psk_exchange_req_size,
     319                 :             :                          requester_opaque_data, opaque_psk_exchange_req_size);
     320                 :             :     } else {
     321                 :         122 :         size_t supported_version_size =
     322                 :         122 :             libspdm_get_opaque_data_supported_version_data_size(spdm_context);
     323                 :         122 :         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                 :         122 :         libspdm_build_opaque_data_aead_limit_element(
     328                 :             :             spdm_context, local_max_secured_version, &opaque_psk_exchange_req_size, ptr);
     329                 :             :     }
     330                 :         124 :     ptr += opaque_psk_exchange_req_size;
     331                 :             : 
     332                 :         124 :     spdm_request_size = (size_t)ptr - (size_t)spdm_request;
     333                 :         124 :     status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size,
     334                 :             :                                        spdm_request);
     335         [ +  + ]:         124 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     336                 :           2 :         libspdm_release_sender_buffer (spdm_context);
     337                 :           2 :         return status;
     338                 :             :     }
     339                 :         122 :     libspdm_release_sender_buffer (spdm_context);
     340                 :         122 :     spdm_request = (void *)spdm_context->last_spdm_request;
     341                 :             : 
     342                 :             :     /* receive */
     343                 :             : 
     344                 :         122 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     345         [ +  + ]:         122 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     346                 :           2 :         return status;
     347                 :             :     }
     348                 :         120 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
     349                 :         120 :     spdm_response = (void *)(message);
     350                 :         120 :     spdm_response_size = message_size;
     351                 :             : 
     352                 :         120 :     status = libspdm_receive_spdm_response(
     353                 :             :         spdm_context, NULL, &spdm_response_size, (void **)&spdm_response);
     354         [ +  + ]:         120 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     355                 :           2 :         goto receive_done;
     356                 :             :     }
     357         [ -  + ]:         118 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     358                 :           0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     359                 :           0 :         goto receive_done;
     360                 :             :     }
     361         [ +  + ]:         118 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     362                 :          52 :         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         [ +  + ]:          52 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     367                 :          50 :             goto receive_done;
     368                 :             :         }
     369         [ +  + ]:          66 :     } else if (spdm_response->header.request_response_code != SPDM_PSK_EXCHANGE_RSP) {
     370                 :           2 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     371                 :           2 :         goto receive_done;
     372                 :             :     }
     373         [ +  + ]:          66 :     if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     374                 :           2 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     375                 :           2 :         goto receive_done;
     376                 :             :     }
     377         [ +  + ]:          64 :     if (spdm_response_size < sizeof(spdm_psk_exchange_response_t)) {
     378                 :           2 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     379                 :           2 :         goto receive_done;
     380                 :             :     }
     381                 :             : 
     382         [ +  + ]:          62 :     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         [ +  + ]:          58 :         if (spdm_response->header.param1 != 0) {
     387                 :           2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     388                 :           2 :             goto receive_done;
     389                 :             :         }
     390                 :             :     }
     391         [ +  - ]:          60 :     if (heartbeat_period != NULL) {
     392                 :          60 :         *heartbeat_period = spdm_response->header.param1;
     393                 :             :     }
     394                 :             : 
     395                 :          60 :     measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
     396                 :             :         spdm_context, true, measurement_hash_type);
     397                 :          60 :     hmac_size = libspdm_get_hash_size(
     398                 :             :         spdm_context->connection_info.algorithm.base_hash_algo);
     399                 :             : 
     400         [ +  + ]:          60 :     if (spdm_response->opaque_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
     401                 :           2 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     402                 :           2 :         goto receive_done;
     403                 :             :     }
     404                 :          58 :     if (spdm_response_size <
     405                 :             :         sizeof(spdm_psk_exchange_response_t) +
     406                 :          58 :         spdm_response->context_length + spdm_response->opaque_length +
     407         [ +  + ]:          58 :         measurement_summary_hash_size + hmac_size) {
     408                 :           4 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     409                 :           4 :         goto receive_done;
     410                 :             :     }
     411                 :             : 
     412                 :          54 :     ptr = (uint8_t *)spdm_response + sizeof(spdm_psk_exchange_response_t) +
     413                 :          54 :           measurement_summary_hash_size + spdm_response->context_length;
     414                 :          54 :     secured_message_version = 0;
     415         [ +  + ]:          54 :     if (spdm_response->opaque_length != 0) {
     416                 :          48 :         result = libspdm_process_general_opaque_data_check(spdm_context,
     417                 :          48 :                                                            spdm_response->opaque_length, ptr);
     418         [ +  + ]:          48 :         if (!result) {
     419                 :           2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     420                 :           2 :             goto receive_done;
     421                 :             :         }
     422                 :          46 :         status = libspdm_process_opaque_data_version_selection_data(
     423                 :          46 :             spdm_context, spdm_response->opaque_length, ptr, &secured_message_version);
     424         [ +  + ]:          46 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     425                 :           2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     426                 :           2 :             goto receive_done;
     427                 :             :         }
     428                 :             :         /* DSP0277 1.3: read the Responder's AEAD limit (absent -> default 64). */
     429                 :          44 :         status = libspdm_process_opaque_data_aead_limit(
     430                 :          44 :             spdm_context, secured_message_version, spdm_response->opaque_length, ptr,
     431                 :             :             &peer_aead_limit_exponent);
     432         [ -  + ]:          44 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     433                 :           0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     434                 :           0 :             goto receive_done;
     435                 :             :         }
     436                 :             :     }
     437                 :             : 
     438                 :          50 :     spdm_response_size = sizeof(spdm_psk_exchange_response_t) +
     439                 :          50 :                          spdm_response->context_length +
     440                 :          50 :                          spdm_response->opaque_length +
     441                 :          50 :                          measurement_summary_hash_size + hmac_size;
     442                 :             : 
     443                 :          50 :     ptr = (uint8_t *)(spdm_response->measurement_summary_hash);
     444                 :          50 :     measurement_summary_hash = ptr;
     445                 :          50 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "measurement_summary_hash (0x%x) - ",
     446                 :             :                    measurement_summary_hash_size));
     447                 :          50 :     LIBSPDM_INTERNAL_DUMP_DATA(measurement_summary_hash,
     448                 :             :                                measurement_summary_hash_size);
     449                 :          50 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     450                 :             : 
     451                 :          50 :     ptr += measurement_summary_hash_size;
     452                 :             : 
     453         [ +  + ]:          50 :     if (libspdm_is_capabilities_flag_supported(
     454                 :             :             spdm_context, true, 0,
     455                 :             :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER)) {
     456         [ +  + ]:          10 :         if (spdm_response->context_length != 0) {
     457                 :           2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     458                 :           2 :             goto receive_done;
     459                 :             :         }
     460                 :             :     } else {
     461         [ +  + ]:          40 :         if (spdm_response->context_length == 0) {
     462                 :           2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     463                 :           2 :             goto receive_done;
     464                 :             :         }
     465                 :             :     }
     466                 :             : 
     467                 :          46 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderContextData (0x%x) - ",
     468                 :             :                    spdm_response->context_length));
     469                 :          46 :     LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_response->context_length);
     470                 :          46 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     471         [ +  + ]:          46 :     if (responder_context != NULL) {
     472         [ +  - ]:           2 :         if (*responder_context_size > spdm_response->context_length) {
     473                 :           2 :             *responder_context_size = spdm_response->context_length;
     474                 :             :         }
     475                 :           2 :         libspdm_copy_mem(responder_context, *responder_context_size,
     476                 :             :                          ptr, *responder_context_size);
     477                 :             :     }
     478                 :             : 
     479                 :          46 :     ptr += spdm_response->context_length;
     480                 :             : 
     481   [ +  +  +  - ]:          46 :     if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
     482         [ +  + ]:           4 :         if (spdm_response->opaque_length > *responder_opaque_data_size) {
     483                 :           2 :             status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     484                 :           2 :             goto receive_done;
     485                 :             :         }
     486                 :           2 :         libspdm_copy_mem(responder_opaque_data, *responder_opaque_data_size,
     487                 :           2 :                          ptr, spdm_response->opaque_length);
     488                 :           2 :         *responder_opaque_data_size = spdm_response->opaque_length;
     489                 :             :     }
     490                 :             : 
     491                 :          44 :     ptr += spdm_response->opaque_length;
     492                 :             : 
     493                 :          44 :     rsp_session_id = spdm_response->rsp_session_id;
     494                 :          44 :     *session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
     495                 :          44 :     session_info = libspdm_assign_session_id(spdm_context, *session_id, secured_message_version,
     496                 :             :                                              true);
     497         [ -  + ]:          44 :     if (session_info == NULL) {
     498                 :           0 :         status = LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     499                 :           0 :         goto receive_done;
     500                 :             :     }
     501                 :          44 :     libspdm_session_info_set_psk_hint(session_info,
     502                 :             :                                       psk_hint,
     503                 :             :                                       psk_hint_size);
     504                 :             : 
     505                 :             :     /* DSP0277 1.3: program the session's AEAD limit (min of local and peer) when secured message
     506                 :             :      * version 1.3 was negotiated. */
     507         [ -  + ]:          44 :     if (libspdm_get_version_from_version_number(secured_message_version) >=
     508                 :             :         SECURED_SPDM_VERSION_13) {
     509                 :           0 :         libspdm_apply_aead_limit_to_session(spdm_context, session_info,
     510                 :             :                                             peer_aead_limit_exponent);
     511                 :             :     }
     512                 :             : 
     513                 :             :     /* Cache session data*/
     514                 :             : 
     515                 :          44 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_request,
     516                 :             :                                       spdm_request_size);
     517         [ -  + ]:          44 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     518                 :           0 :         libspdm_free_session_id(spdm_context, *session_id);
     519                 :           0 :         goto receive_done;
     520                 :             :     }
     521                 :             : 
     522                 :          44 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_response,
     523                 :             :                                       spdm_response_size - hmac_size);
     524         [ -  + ]:          44 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     525                 :           0 :         libspdm_free_session_id(spdm_context, *session_id);
     526                 :           0 :         goto receive_done;
     527                 :             :     }
     528                 :             : 
     529                 :          44 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
     530                 :             :                    *session_id));
     531                 :          44 :     result = libspdm_calculate_th1_hash(spdm_context, session_info, true,
     532                 :             :                                         th1_hash_data);
     533         [ -  + ]:          44 :     if (!result) {
     534                 :           0 :         libspdm_free_session_id(spdm_context, *session_id);
     535                 :           0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     536                 :           0 :         goto receive_done;
     537                 :             :     }
     538                 :          44 :     result = libspdm_generate_session_handshake_key(
     539                 :             :         session_info->secured_message_context, th1_hash_data);
     540         [ -  + ]:          44 :     if (!result) {
     541                 :           0 :         libspdm_free_session_id(spdm_context, *session_id);
     542                 :           0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     543                 :           0 :         goto receive_done;
     544                 :             :     }
     545                 :             : 
     546                 :          44 :     verify_data = ptr;
     547                 :          44 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%x):\n", hmac_size));
     548                 :          44 :     LIBSPDM_INTERNAL_DUMP_HEX(verify_data, hmac_size);
     549                 :          44 :     result = libspdm_verify_psk_exchange_rsp_hmac(spdm_context, session_info,
     550                 :             :                                                   verify_data, hmac_size);
     551         [ +  + ]:          44 :     if (!result) {
     552                 :           2 :         libspdm_free_session_id(spdm_context, *session_id);
     553                 :           2 :         status = LIBSPDM_STATUS_VERIF_FAIL;
     554                 :           2 :         goto receive_done;
     555                 :             :     }
     556                 :             : 
     557                 :          42 :     status = libspdm_append_message_k(spdm_context, session_info, true, verify_data, hmac_size);
     558         [ -  + ]:          42 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     559                 :           0 :         libspdm_free_session_id(spdm_context, *session_id);
     560                 :           0 :         goto receive_done;
     561                 :             :     }
     562                 :             : 
     563         [ +  - ]:          42 :     if (measurement_hash != NULL) {
     564                 :          42 :         libspdm_copy_mem(measurement_hash, measurement_summary_hash_size,
     565                 :             :                          measurement_summary_hash, measurement_summary_hash_size);
     566                 :             :     }
     567                 :             : 
     568                 :          42 :     session_info->session_policy = session_policy;
     569                 :             : 
     570                 :          42 :     libspdm_secured_message_set_session_state(
     571                 :             :         session_info->secured_message_context,
     572                 :             :         LIBSPDM_SESSION_STATE_HANDSHAKING);
     573                 :             : 
     574         [ +  + ]:          42 :     if (!libspdm_is_capabilities_flag_supported(
     575                 :             :             spdm_context, true, 0,
     576                 :             :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
     577                 :             :         /* No need to send PSK_FINISH, enter application phase directly.*/
     578                 :             : 
     579                 :           8 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n",
     580                 :             :                        *session_id));
     581                 :           8 :         result = libspdm_calculate_th2_hash(spdm_context, session_info,
     582                 :             :                                             true, th2_hash_data);
     583         [ -  + ]:           8 :         if (!result) {
     584                 :           0 :             libspdm_free_session_id(spdm_context, *session_id);
     585                 :           0 :             status = LIBSPDM_STATUS_CRYPTO_ERROR;
     586                 :           0 :             goto receive_done;
     587                 :             :         }
     588                 :           8 :         result = libspdm_generate_session_data_key(
     589                 :             :             session_info->secured_message_context, th2_hash_data);
     590         [ -  + ]:           8 :         if (!result) {
     591                 :           0 :             libspdm_free_session_id(spdm_context, *session_id);
     592                 :           0 :             status = LIBSPDM_STATUS_CRYPTO_ERROR;
     593                 :           0 :             goto receive_done;
     594                 :             :         }
     595                 :             : 
     596                 :           8 :         libspdm_secured_message_set_session_state(
     597                 :             :             session_info->secured_message_context,
     598                 :             :             LIBSPDM_SESSION_STATE_ESTABLISHED);
     599                 :             :     }
     600                 :             : 
     601                 :          42 :     session_info->heartbeat_period = spdm_response->header.param1;
     602                 :             : 
     603                 :             :     /* -=[Log Message Phase]=- */
     604                 :             :     #if LIBSPDM_ENABLE_MSG_LOG
     605                 :          42 :     libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     606                 :             :     #endif /* LIBSPDM_ENABLE_MSG_LOG */
     607                 :             : 
     608                 :          42 :     status = LIBSPDM_STATUS_SUCCESS;
     609                 :             : 
     610                 :         120 : receive_done:
     611                 :         120 :     libspdm_release_receiver_buffer (spdm_context);
     612                 :         120 :     return status;
     613                 :             : }
     614                 :             : 
     615                 :         142 : libspdm_return_t libspdm_send_receive_psk_exchange(libspdm_context_t *spdm_context,
     616                 :             :                                                    const void *psk_hint,
     617                 :             :                                                    uint16_t psk_hint_size,
     618                 :             :                                                    uint8_t measurement_hash_type,
     619                 :             :                                                    uint8_t session_policy,
     620                 :             :                                                    uint32_t *session_id,
     621                 :             :                                                    uint8_t *heartbeat_period,
     622                 :             :                                                    void *measurement_hash)
     623                 :             : {
     624                 :             :     size_t retry;
     625                 :             :     uint64_t retry_delay_time;
     626                 :             :     libspdm_return_t status;
     627                 :             : 
     628                 :         142 :     spdm_context->crypto_request = true;
     629                 :         142 :     retry = spdm_context->retry_times;
     630                 :         142 :     retry_delay_time = spdm_context->retry_delay_time;
     631                 :             :     do {
     632                 :         144 :         status = libspdm_try_send_receive_psk_exchange(
     633                 :             :             spdm_context, psk_hint, psk_hint_size,
     634                 :             :             measurement_hash_type, session_policy, session_id,
     635                 :             :             heartbeat_period, measurement_hash,
     636                 :             :             NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL);
     637         [ +  + ]:         144 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     638                 :         140 :             return status;
     639                 :             :         }
     640                 :             : 
     641                 :           4 :         libspdm_sleep(retry_delay_time);
     642         [ +  + ]:           4 :     } while (retry-- != 0);
     643                 :             : 
     644                 :           2 :     return status;
     645                 :             : }
     646                 :             : 
     647                 :          20 : libspdm_return_t libspdm_send_receive_psk_exchange_ex(libspdm_context_t *spdm_context,
     648                 :             :                                                       const void *psk_hint,
     649                 :             :                                                       uint16_t psk_hint_size,
     650                 :             :                                                       uint8_t measurement_hash_type,
     651                 :             :                                                       uint8_t session_policy,
     652                 :             :                                                       uint32_t *session_id,
     653                 :             :                                                       uint8_t *heartbeat_period,
     654                 :             :                                                       void *measurement_hash,
     655                 :             :                                                       const void *requester_context_in,
     656                 :             :                                                       size_t requester_context_in_size,
     657                 :             :                                                       void *requester_context,
     658                 :             :                                                       size_t *requester_context_size,
     659                 :             :                                                       void *responder_context,
     660                 :             :                                                       size_t *responder_context_size,
     661                 :             :                                                       const void *requester_opaque_data,
     662                 :             :                                                       size_t requester_opaque_data_size,
     663                 :             :                                                       void *responder_opaque_data,
     664                 :             :                                                       size_t *responder_opaque_data_size)
     665                 :             : {
     666                 :             :     size_t retry;
     667                 :             :     uint64_t retry_delay_time;
     668                 :             :     libspdm_return_t status;
     669                 :             : 
     670                 :          20 :     spdm_context->crypto_request = true;
     671                 :          20 :     retry = spdm_context->retry_times;
     672                 :          20 :     retry_delay_time = spdm_context->retry_delay_time;
     673                 :             :     do {
     674                 :          22 :         status = libspdm_try_send_receive_psk_exchange(
     675                 :             :             spdm_context, psk_hint, psk_hint_size,
     676                 :             :             measurement_hash_type, session_policy, session_id,
     677                 :             :             heartbeat_period, measurement_hash,
     678                 :             :             requester_context_in, requester_context_in_size,
     679                 :             :             requester_context, requester_context_size,
     680                 :             :             responder_context, responder_context_size,
     681                 :             :             requester_opaque_data, requester_opaque_data_size,
     682                 :             :             responder_opaque_data, responder_opaque_data_size);
     683         [ +  + ]:          22 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     684                 :          18 :             return status;
     685                 :             :         }
     686                 :             : 
     687                 :           4 :         libspdm_sleep(retry_delay_time);
     688         [ +  + ]:           4 :     } while (retry-- != 0);
     689                 :             : 
     690                 :           2 :     return status;
     691                 :             : }
     692                 :             : 
     693                 :             : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
        

Generated by: LCOV version 2.0-1