LCOV - code coverage report
Current view: top level - library/spdm_requester_lib - libspdm_req_key_exchange.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 77.1 % 389 300
Test Date: 2025-12-21 08:10:27 Functions: 100.0 % 5 5

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2025 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_KEY_EX_CAP
      11              : 
      12              : #pragma pack(1)
      13              : typedef struct {
      14              :     spdm_message_header_t header;
      15              :     uint16_t req_session_id;
      16              :     uint8_t session_policy;
      17              :     uint8_t reserved;
      18              :     uint8_t random_data[SPDM_RANDOM_DATA_SIZE];
      19              :     uint8_t exchange_data[LIBSPDM_REQ_EXCHANGE_DATA_MAX_SIZE];
      20              :     uint16_t opaque_length;
      21              :     uint8_t opaque_data[SPDM_MAX_OPAQUE_DATA_SIZE];
      22              : } libspdm_key_exchange_request_mine_t;
      23              : 
      24              : typedef struct {
      25              :     spdm_message_header_t header;
      26              :     uint16_t rsp_session_id;
      27              :     uint8_t mut_auth_requested;
      28              :     uint8_t req_slot_id_param;
      29              :     uint8_t random_data[SPDM_RANDOM_DATA_SIZE];
      30              :     uint8_t exchange_data[LIBSPDM_RSP_EXCHANGE_DATA_MAX_SIZE];
      31              :     uint8_t measurement_summary_hash[LIBSPDM_MAX_HASH_SIZE];
      32              :     uint16_t opaque_length;
      33              :     uint8_t opaque_data[SPDM_MAX_OPAQUE_DATA_SIZE];
      34              :     uint8_t signature[LIBSPDM_RSP_SIGNATURE_DATA_MAX_SIZE];
      35              :     uint8_t verify_data[LIBSPDM_MAX_HASH_SIZE];
      36              : } libspdm_key_exchange_response_max_t;
      37              : #pragma pack()
      38              : 
      39           19 : bool libspdm_verify_key_exchange_rsp_hmac(libspdm_context_t *spdm_context,
      40              :                                           libspdm_session_info_t *session_info,
      41              :                                           const void *hmac_data,
      42              :                                           size_t hmac_data_size)
      43              : {
      44              :     size_t hash_size;
      45              :     uint8_t calc_hmac_data[LIBSPDM_MAX_HASH_SIZE];
      46              :     bool result;
      47              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      48              :     uint8_t slot_id;
      49              :     uint8_t *cert_chain_buffer;
      50              :     size_t cert_chain_buffer_size;
      51              :     uint8_t *th_curr_data;
      52              :     size_t th_curr_data_size;
      53              :     libspdm_th_managed_buffer_t th_curr;
      54              :     uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
      55              : #endif
      56              : 
      57           19 :     hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
      58           19 :     LIBSPDM_ASSERT(hash_size == hmac_data_size);
      59              : 
      60              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      61              :     slot_id = session_info->peer_used_cert_chain_slot_id;
      62              :     LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
      63              :     if (slot_id == 0xFF) {
      64              :         result = libspdm_get_peer_public_key_buffer(
      65              :             spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
      66              :         if (!result) {
      67              :            return false;
      68              :         }
      69              :     } else {
      70              :         libspdm_get_peer_cert_chain_buffer(
      71              :             spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
      72              :     }
      73              : 
      74              :     result = libspdm_calculate_th_for_exchange(
      75              :         spdm_context, session_info, cert_chain_buffer,
      76              :         cert_chain_buffer_size, &th_curr);
      77              :     if (!result) {
      78              :         return false;
      79              :     }
      80              :     th_curr_data = libspdm_get_managed_buffer(&th_curr);
      81              :     th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
      82              : 
      83              :     result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
      84              :                                th_curr_data, th_curr_data_size, hash_data);
      85              :     if (!result) {
      86              :         return false;
      87              :     }
      88              : 
      89              :     result = libspdm_hmac_all_with_response_finished_key(
      90              :         session_info->secured_message_context, hash_data,
      91              :         hash_size, calc_hmac_data);
      92              :     if (!result) {
      93              :         return false;
      94              :     }
      95              : #else
      96           19 :     result = libspdm_calculate_th_hmac_for_exchange_rsp(
      97              :         spdm_context, session_info, &hash_size, calc_hmac_data);
      98           19 :     if (!result) {
      99            0 :         return false;
     100              :     }
     101              : #endif
     102           19 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
     103           19 :     LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
     104           19 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     105              : 
     106           19 :     if (!libspdm_consttime_is_mem_equal(calc_hmac_data, hmac_data, hash_size)) {
     107            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_key_exchange_hmac - FAIL !!!\n"));
     108            0 :         return false;
     109              :     }
     110           19 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_key_exchange_hmac - PASS !!!\n"));
     111              : 
     112           19 :     return true;
     113              : }
     114              : 
     115           22 : bool libspdm_verify_key_exchange_rsp_signature(
     116              :     libspdm_context_t *spdm_context, libspdm_session_info_t *session_info,
     117              :     const void *sign_data, const size_t sign_data_size)
     118              : {
     119              :     bool result;
     120              :     void *context;
     121              :     uint8_t slot_id;
     122              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     123              :     uint8_t *cert_chain_buffer;
     124              :     size_t cert_chain_buffer_size;
     125              :     uint8_t *th_curr_data;
     126              :     size_t th_curr_data_size;
     127              :     libspdm_th_managed_buffer_t th_curr;
     128              :     const uint8_t *cert_chain_data;
     129              :     size_t cert_chain_data_size;
     130              :     const uint8_t *cert_buffer;
     131              :     size_t cert_buffer_size;
     132              : #endif
     133              : #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
     134              :     size_t hash_size;
     135              :     uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
     136              : 
     137           22 :     hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     138              : #endif
     139              : 
     140           22 :     slot_id = session_info->peer_used_cert_chain_slot_id;
     141           22 :     LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
     142              : 
     143              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     144              :     if (slot_id == 0xFF) {
     145              :         result = libspdm_get_peer_public_key_buffer(
     146              :             spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
     147              :         if (!result) {
     148              :            return false;
     149              :         }
     150              :     } else {
     151              :         libspdm_get_peer_cert_chain_buffer(
     152              :             spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
     153              :     }
     154              : 
     155              :     result = libspdm_calculate_th_for_exchange(
     156              :         spdm_context, session_info, cert_chain_buffer,
     157              :         cert_chain_buffer_size, &th_curr);
     158              :     if (!result) {
     159              :         return false;
     160              :     }
     161              :     th_curr_data = libspdm_get_managed_buffer(&th_curr);
     162              :     th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
     163              : 
     164              :     /* Debug code only - required for debug print of th_curr hash below*/
     165              :     LIBSPDM_DEBUG_CODE(
     166              :         if (!libspdm_hash_all(
     167              :                 spdm_context->connection_info.algorithm.base_hash_algo,
     168              :                 th_curr_data, th_curr_data_size, hash_data)) {
     169              :         return false;
     170              :     }
     171              :         );
     172              : #else
     173           22 :     result = libspdm_calculate_th_hash_for_exchange(
     174              :         spdm_context, session_info, &hash_size, hash_data);
     175           22 :     if (!result) {
     176            0 :         return false;
     177              :     }
     178              : #endif
     179           22 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hash - "));
     180           22 :     LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size);
     181           22 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     182              : 
     183           22 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature - "));
     184           22 :     LIBSPDM_INTERNAL_DUMP_DATA(sign_data, sign_data_size);
     185           22 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     186              : 
     187           22 :     if (slot_id == 0xFF) {
     188            1 :         if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     189            0 :             result = libspdm_pqc_asym_get_public_key_from_der(
     190              :                 spdm_context->connection_info.algorithm.pqc_asym_algo,
     191            0 :                 spdm_context->local_context.peer_public_key_provision,
     192              :                 spdm_context->local_context.peer_public_key_provision_size,
     193              :                 &context);
     194              :         } else {
     195            1 :             result = libspdm_asym_get_public_key_from_der(
     196              :                 spdm_context->connection_info.algorithm.base_asym_algo,
     197            1 :                 spdm_context->local_context.peer_public_key_provision,
     198              :                 spdm_context->local_context.peer_public_key_provision_size,
     199              :                 &context);
     200              :         }
     201            1 :         if (!result) {
     202            0 :             return false;
     203              :         }
     204              :     } else {
     205              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     206              :         /* Get leaf cert from cert chain*/
     207              :         libspdm_get_peer_cert_chain_data(
     208              :             spdm_context, slot_id, (const void **)&cert_chain_data, &cert_chain_data_size);
     209              : 
     210              :         result = libspdm_x509_get_cert_from_cert_chain(
     211              :             cert_chain_data, cert_chain_data_size, -1, &cert_buffer, &cert_buffer_size);
     212              :         if (!result) {
     213              :             return false;
     214              :         }
     215              : 
     216              :         if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     217              :             result = libspdm_pqc_asym_get_public_key_from_x509(
     218              :                 spdm_context->connection_info.algorithm.pqc_asym_algo,
     219              :                 cert_buffer, cert_buffer_size, &context);
     220              :         } else {
     221              :             result = libspdm_asym_get_public_key_from_x509(
     222              :                 spdm_context->connection_info.algorithm.base_asym_algo,
     223              :                 cert_buffer, cert_buffer_size, &context);
     224              :         }
     225              :         if (!result) {
     226              :             return false;
     227              :         }
     228              : #else
     229           21 :         context = spdm_context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key;
     230           21 :         LIBSPDM_ASSERT(context != NULL);
     231              : #endif
     232              :     }
     233              : 
     234              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     235              :     if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     236              :         result = libspdm_pqc_asym_verify(
     237              :             spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
     238              :             spdm_context->connection_info.algorithm.pqc_asym_algo,
     239              :             spdm_context->connection_info.algorithm.base_hash_algo,
     240              :             context, th_curr_data, th_curr_data_size, sign_data, sign_data_size);
     241              :         libspdm_pqc_asym_free(spdm_context->connection_info.algorithm.pqc_asym_algo, context);
     242              :     } else {
     243              :         result = libspdm_asym_verify_ex(
     244              :             spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
     245              :             spdm_context->connection_info.algorithm.base_asym_algo,
     246              :             spdm_context->connection_info.algorithm.base_hash_algo,
     247              :             context, th_curr_data, th_curr_data_size, sign_data, sign_data_size,
     248              :             &spdm_context->spdm_10_11_verify_signature_endian);
     249              :         libspdm_asym_free(spdm_context->connection_info.algorithm.base_asym_algo, context);
     250              :     }
     251              : #else
     252           22 :     if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     253            0 :         result = libspdm_pqc_asym_verify_hash(
     254            0 :             spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
     255              :             spdm_context->connection_info.algorithm.pqc_asym_algo,
     256              :             spdm_context->connection_info.algorithm.base_hash_algo,
     257              :             context, hash_data, hash_size, sign_data, sign_data_size);
     258            0 :         if (slot_id == 0xFF) {
     259            0 :             libspdm_pqc_asym_free(spdm_context->connection_info.algorithm.pqc_asym_algo, context);
     260              :         }
     261              :     } else {
     262           22 :         result = libspdm_asym_verify_hash_ex(
     263           22 :             spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
     264              :             spdm_context->connection_info.algorithm.base_asym_algo,
     265              :             spdm_context->connection_info.algorithm.base_hash_algo,
     266              :             context, hash_data, hash_size, sign_data, sign_data_size,
     267              :             &spdm_context->spdm_10_11_verify_signature_endian);
     268           22 :         if (slot_id == 0xFF) {
     269            1 :             libspdm_asym_free(spdm_context->connection_info.algorithm.base_asym_algo, context);
     270              :         }
     271              :     }
     272              : #endif
     273           22 :     if (!result) {
     274            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_key_exchange_signature - FAIL !!!\n"));
     275            2 :         return false;
     276              :     }
     277           20 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_key_exchange_signature - PASS !!!\n"));
     278              : 
     279           20 :     return true;
     280              : }
     281              : 
     282              : /**
     283              :  * This function sends KEY_EXCHANGE and receives KEY_EXCHANGE_RSP for SPDM key exchange.
     284              :  *
     285              :  * @param  spdm_context           A pointer to the SPDM context.
     286              :  * @param  measurement_hash_type  Measurement_hash_type to the KEY_EXCHANGE request.
     287              :  * @param  slot_id                slot_id to the KEY_EXCHANGE request.
     288              :  * @param  session_policy         The policy for the session.
     289              :  * @param  session_id             session_id from the KEY_EXCHANGE_RSP response.
     290              :  * @param  heartbeat_period       Heartbeat_period from the KEY_EXCHANGE_RSP response.
     291              :  * @param  req_slot_id_param      req_slot_id_param from the KEY_EXCHANGE_RSP response.
     292              :  * @param  measurement_hash       Measurement_hash from the KEY_EXCHANGE_RSP response.
     293              :  * @param  requester_nonce_in     If not NULL, a buffer that holds the requester nonce (32 bytes)
     294              :  * @param  requester_nonce        If not NULL, a buffer to hold the requester nonce (32 bytes).
     295              :  * @param  responder_nonce        If not NULL, a buffer to hold the responder nonce (32 bytes).
     296              :  **/
     297           95 : static libspdm_return_t libspdm_try_send_receive_key_exchange(
     298              :     libspdm_context_t *spdm_context, uint8_t measurement_hash_type,
     299              :     uint8_t slot_id, uint8_t session_policy, uint32_t *session_id,
     300              :     uint8_t *heartbeat_period,
     301              :     uint8_t *req_slot_id_param, void *measurement_hash,
     302              :     const void *requester_random_in,
     303              :     void *requester_random, void *responder_random,
     304              :     const void *requester_opaque_data, size_t requester_opaque_data_size,
     305              :     void *responder_opaque_data, size_t *responder_opaque_data_size)
     306              : {
     307              :     bool result;
     308              :     libspdm_return_t status;
     309              :     libspdm_key_exchange_request_mine_t *spdm_request;
     310              :     size_t spdm_request_size;
     311              :     libspdm_key_exchange_response_max_t *spdm_response;
     312              :     size_t spdm_response_size;
     313              :     size_t dhe_key_size;
     314              :     size_t kem_encap_key_size;
     315              :     size_t kem_cipher_text_size;
     316              :     size_t req_key_exchange_size;
     317              :     size_t rsp_key_exchange_size;
     318              :     uint32_t measurement_summary_hash_size;
     319              :     uint32_t signature_size;
     320              :     uint32_t hmac_size;
     321              :     uint8_t *ptr;
     322              :     void *measurement_summary_hash;
     323              :     uint16_t opaque_length;
     324              :     uint8_t *signature;
     325              :     uint8_t *verify_data;
     326              :     void *dhe_context;
     327              :     void *kem_context;
     328              :     uint16_t req_session_id;
     329              :     uint16_t rsp_session_id;
     330              :     libspdm_session_info_t *session_info;
     331              :     size_t opaque_key_exchange_req_size;
     332              :     uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
     333              :     uint8_t *message;
     334              :     size_t message_size;
     335              :     size_t transport_header_size;
     336              :     uint8_t mut_auth_requested;
     337              :     spdm_version_number_t secured_message_version;
     338              : 
     339              :     /* -=[Check Parameters Phase]=- */
     340           95 :     LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xff));
     341           95 :     LIBSPDM_ASSERT((slot_id != 0xff) ||
     342              :                    (spdm_context->local_context.peer_public_key_provision_size != 0));
     343           95 :     LIBSPDM_ASSERT(measurement_hash_type == SPDM_KEY_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH ||
     344              :                    measurement_hash_type == SPDM_KEY_EXCHANGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH ||
     345              :                    measurement_hash_type == SPDM_KEY_EXCHANGE_REQUEST_ALL_MEASUREMENTS_HASH);
     346           95 :     LIBSPDM_ASSERT((libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) ||
     347              :                    ((session_policy & SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY)
     348              :                     == 0) ||
     349              :                    libspdm_is_capabilities_flag_supported(
     350              :                        spdm_context, true, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EVENT_CAP));
     351              : 
     352              :     /* -=[Verify State Phase]=- */
     353           95 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     354            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     355              :     }
     356              : 
     357           95 :     if (!libspdm_is_capabilities_flag_supported(
     358              :             spdm_context, true,
     359              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
     360              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
     361            1 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     362              :     }
     363              : 
     364              :     /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
     365              :      * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
     366              :      */
     367           94 :     if (!libspdm_is_capabilities_flag_supported(
     368              :             spdm_context, true,
     369              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
     370              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
     371            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     372              :     }
     373              : 
     374           94 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     375            2 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     376              :     }
     377              : 
     378           92 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     379            3 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     380              :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
     381            0 :             return LIBSPDM_STATUS_INVALID_STATE_PEER;
     382              :         }
     383              :     }
     384              : 
     385           92 :     req_session_id = libspdm_allocate_req_session_id(spdm_context, false);
     386           92 :     if (req_session_id == (INVALID_SESSION_ID & 0xFFFF)) {
     387            0 :         return LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     388              :     }
     389              : 
     390           92 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL, SPDM_KEY_EXCHANGE);
     391              : 
     392              :     /* -=[Construct Request Phase]=- */
     393           92 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
     394           92 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     395           92 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     396            1 :         return status;
     397              :     }
     398           91 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
     399              :                     spdm_context->local_context.capability.transport_tail_size);
     400           91 :     spdm_request = (void *)(message + transport_header_size);
     401           91 :     spdm_request_size = message_size - transport_header_size -
     402           91 :                         spdm_context->local_context.capability.transport_tail_size;
     403              : 
     404           91 :     LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t));
     405           91 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     406           91 :     spdm_request->header.request_response_code = SPDM_KEY_EXCHANGE;
     407           91 :     spdm_request->header.param1 = measurement_hash_type;
     408           91 :     spdm_request->header.param2 = slot_id;
     409           91 :     if (requester_random_in == NULL) {
     410           90 :         if (!libspdm_get_random_number(SPDM_RANDOM_DATA_SIZE, spdm_request->random_data)) {
     411            0 :             libspdm_release_sender_buffer (spdm_context);
     412            0 :             return LIBSPDM_STATUS_LOW_ENTROPY;
     413              :         }
     414              :     } else {
     415            1 :         libspdm_copy_mem(spdm_request->random_data, sizeof(spdm_request->random_data),
     416              :                          requester_random_in, SPDM_RANDOM_DATA_SIZE);
     417              :     }
     418           91 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterRandomData (0x%x) - ",
     419              :                    SPDM_RANDOM_DATA_SIZE));
     420           91 :     LIBSPDM_INTERNAL_DUMP_DATA(spdm_request->random_data, SPDM_RANDOM_DATA_SIZE);
     421           91 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     422           91 :     if (requester_random != NULL) {
     423            1 :         libspdm_copy_mem(requester_random, SPDM_RANDOM_DATA_SIZE,
     424            1 :                          spdm_request->random_data, SPDM_RANDOM_DATA_SIZE);
     425              :     }
     426              : 
     427           91 :     spdm_request->req_session_id = req_session_id;
     428           91 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     429            3 :         spdm_request->session_policy = session_policy;
     430              :     } else {
     431           88 :         spdm_request->session_policy = 0;
     432              :     }
     433           91 :     spdm_request->reserved = 0;
     434              : 
     435           91 :     ptr = spdm_request->exchange_data;
     436           91 :     dhe_context = NULL;
     437           91 :     kem_context = NULL;
     438           91 :     if (spdm_context->connection_info.algorithm.kem_alg != 0) {
     439            0 :         kem_encap_key_size = libspdm_get_kem_encap_key_size(
     440              :             spdm_context->connection_info.algorithm.kem_alg);
     441            0 :         kem_cipher_text_size = libspdm_get_kem_cipher_text_size(
     442              :             spdm_context->connection_info.algorithm.kem_alg);
     443            0 :         kem_context = libspdm_secured_message_kem_new(
     444            0 :             spdm_context->connection_info.version,
     445              :             spdm_context->connection_info.algorithm.kem_alg, true);
     446            0 :         if (kem_context == NULL) {
     447            0 :             libspdm_release_sender_buffer (spdm_context);
     448            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     449              :         }
     450              : 
     451            0 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) + kem_encap_key_size);
     452            0 :         result = libspdm_secured_message_kem_generate_key(
     453              :             spdm_context->connection_info.algorithm.kem_alg,
     454              :             kem_context, ptr, &kem_encap_key_size);
     455            0 :         if (!result) {
     456            0 :             libspdm_secured_message_kem_free(
     457              :                 spdm_context->connection_info.algorithm.kem_alg, kem_context);
     458            0 :             libspdm_release_sender_buffer (spdm_context);
     459            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     460              :         }
     461            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterKey (0x%zx):\n", kem_encap_key_size));
     462            0 :         LIBSPDM_INTERNAL_DUMP_HEX(ptr, kem_encap_key_size);
     463            0 :         ptr += kem_encap_key_size;
     464            0 :         req_key_exchange_size = kem_encap_key_size;
     465            0 :         rsp_key_exchange_size = kem_cipher_text_size;
     466              :     } else {
     467          182 :         dhe_key_size = libspdm_get_dhe_pub_key_size(
     468           91 :             spdm_context->connection_info.algorithm.dhe_named_group);
     469           91 :         dhe_context = libspdm_secured_message_dhe_new(
     470           91 :             spdm_context->connection_info.version,
     471           91 :             spdm_context->connection_info.algorithm.dhe_named_group, true);
     472           91 :         if (dhe_context == NULL) {
     473            0 :             libspdm_release_sender_buffer (spdm_context);
     474            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     475              :         }
     476              : 
     477           91 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) + dhe_key_size);
     478           91 :         result = libspdm_secured_message_dhe_generate_key(
     479           91 :             spdm_context->connection_info.algorithm.dhe_named_group,
     480              :             dhe_context, ptr, &dhe_key_size);
     481           91 :         if (!result) {
     482            0 :             libspdm_secured_message_dhe_free(
     483            0 :                 spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
     484            0 :             libspdm_release_sender_buffer (spdm_context);
     485            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     486              :         }
     487           91 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterKey (0x%zx):\n", dhe_key_size));
     488           91 :         LIBSPDM_INTERNAL_DUMP_HEX(ptr, dhe_key_size);
     489           91 :         ptr += dhe_key_size;
     490           91 :         req_key_exchange_size = dhe_key_size;
     491           91 :         rsp_key_exchange_size = dhe_key_size;
     492              :     }
     493              : 
     494           91 :     if (requester_opaque_data != NULL) {
     495            1 :         LIBSPDM_ASSERT(requester_opaque_data_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
     496              : 
     497            1 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) +
     498              :                         req_key_exchange_size +
     499              :                         sizeof(uint16_t) + requester_opaque_data_size);
     500              : 
     501            1 :         libspdm_write_uint16(ptr, (uint16_t)requester_opaque_data_size);
     502            1 :         ptr += sizeof(uint16_t);
     503              : 
     504            1 :         libspdm_copy_mem(ptr,
     505            1 :                          (spdm_request_size - (sizeof(spdm_key_exchange_request_t) +
     506              :                                                req_key_exchange_size)),
     507              :                          requester_opaque_data, requester_opaque_data_size);
     508            1 :         opaque_key_exchange_req_size = requester_opaque_data_size;
     509              :     } else {
     510           90 :         opaque_key_exchange_req_size =
     511           90 :             libspdm_get_opaque_data_supported_version_data_size(spdm_context);
     512           90 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) +
     513              :                         req_key_exchange_size +
     514              :                         sizeof(uint16_t) + opaque_key_exchange_req_size);
     515              : 
     516           90 :         libspdm_write_uint16(ptr, (uint16_t)opaque_key_exchange_req_size);
     517           90 :         ptr += sizeof(uint16_t);
     518              : 
     519           90 :         libspdm_build_opaque_data_supported_version_data(
     520              :             spdm_context, &opaque_key_exchange_req_size, ptr);
     521              :     }
     522           91 :     ptr += opaque_key_exchange_req_size;
     523              : 
     524           91 :     spdm_request_size = (size_t)ptr - (size_t)spdm_request;
     525              : 
     526              :     /* -=[Send Request Phase]=- */
     527           91 :     status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size, spdm_request);
     528           91 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     529            2 :         libspdm_release_sender_buffer (spdm_context);
     530            2 :         goto free_exchange;
     531              :     }
     532           89 :     libspdm_release_sender_buffer (spdm_context);
     533           89 :     spdm_request = (void *)spdm_context->last_spdm_request;
     534              : 
     535              :     /* -=[Receive Response Phase]=- */
     536           89 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     537           89 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     538            1 :         goto free_exchange;
     539              :     }
     540           88 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
     541           88 :     spdm_response = (void *)(message);
     542           88 :     spdm_response_size = message_size;
     543              : 
     544           88 :     status = libspdm_receive_spdm_response(
     545              :         spdm_context, NULL, &spdm_response_size, (void **)&spdm_response);
     546           88 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     547            0 :         goto receive_done;
     548              :     }
     549              : 
     550              :     /* -=[Validate Response Phase]=- */
     551           88 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     552            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     553            0 :         goto receive_done;
     554              :     }
     555           88 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     556           46 :         status = libspdm_handle_error_response_main(
     557              :             spdm_context, NULL, &spdm_response_size,
     558              :             (void **)&spdm_response, SPDM_KEY_EXCHANGE,
     559              :             SPDM_KEY_EXCHANGE_RSP);
     560           46 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     561           45 :             goto receive_done;
     562              :         }
     563           42 :     } else if (spdm_response->header.request_response_code != SPDM_KEY_EXCHANGE_RSP) {
     564            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     565            1 :         goto receive_done;
     566              :     }
     567           42 :     if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     568            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     569            1 :         goto receive_done;
     570              :     }
     571           41 :     if (spdm_response_size < sizeof(spdm_key_exchange_response_t)) {
     572            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     573            0 :         goto receive_done;
     574              :     }
     575              : 
     576           41 :     if (!libspdm_is_capabilities_flag_supported(
     577              :             spdm_context, true,
     578              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     579              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     580           39 :         if (spdm_response->header.param1 != 0) {
     581            2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     582            2 :             goto receive_done;
     583              :         }
     584              :     }
     585           39 :     if (heartbeat_period != NULL) {
     586           35 :         *heartbeat_period = spdm_response->header.param1;
     587              :     }
     588              : 
     589           39 :     *req_slot_id_param = spdm_response->req_slot_id_param & 0xf;
     590           39 :     mut_auth_requested = spdm_response->mut_auth_requested & 0x7;
     591              : 
     592           39 :     if (mut_auth_requested != 0) {
     593           13 :         const bool mut_auth_cap_both = libspdm_is_capabilities_flag_supported(
     594              :             spdm_context, true,
     595              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP,
     596              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP);
     597           13 :         const bool cert_cap = libspdm_is_capabilities_flag_supported(
     598              :             spdm_context, true,
     599              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP,
     600              :             0);
     601           13 :         const bool pub_key_id_cap = libspdm_is_capabilities_flag_supported(
     602              :             spdm_context, true,
     603              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP,
     604              :             0);
     605              : 
     606           13 :         if (!mut_auth_cap_both) {
     607            1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     608            1 :             goto receive_done;
     609              :         }
     610           12 :         if ((mut_auth_requested != SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED) &&
     611              :             (mut_auth_requested !=
     612            7 :              SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST) &&
     613              :             (mut_auth_requested !=
     614              :              SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS)) {
     615            6 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     616            6 :             goto receive_done;
     617              :         }
     618              : 
     619            6 :         if (mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED) {
     620              :             /* Non-encapsulated flow.
     621              :              * Requester has either CERT_CAP or PUB_KEY_ID_CAP set. */
     622              : 
     623            2 :             if ((cert_cap && (*req_slot_id_param >= SPDM_MAX_SLOT_COUNT)) ||
     624            0 :                 (pub_key_id_cap && (*req_slot_id_param != 0xf))) {
     625            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     626            1 :                 goto receive_done;
     627              :             }
     628            1 :             if ((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
     629            0 :                 spdm_context->connection_info.multi_key_conn_req &&
     630            0 :                 (*req_slot_id_param != 0xf)) {
     631            0 :                 if ((spdm_context->local_context.local_key_usage_bit_mask[*req_slot_id_param] &
     632              :                      SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE) == 0) {
     633            0 :                     status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     634            0 :                     goto receive_done;
     635              :                 }
     636              :             }
     637              :         } else {
     638              :             /* Encapsulated flow. */
     639              : 
     640              :             /* If Responder has Requester's public key then it cannot use the encapsulated flow. */
     641            4 :             if (pub_key_id_cap) {
     642            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     643            1 :                 goto receive_done;
     644              :             }
     645              :             /* Encapsulated flow requires support for encapsulated messages by both endpoints. */
     646            3 :             if (!libspdm_is_encap_supported(spdm_context)) {
     647            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     648            1 :                 goto receive_done;
     649              :             }
     650              :         }
     651              :     }
     652              : 
     653           29 :     if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     654            0 :         signature_size = libspdm_get_pqc_asym_signature_size(
     655              :             spdm_context->connection_info.algorithm.pqc_asym_algo);
     656              :     } else {
     657           29 :         signature_size = libspdm_get_asym_signature_size(
     658              :             spdm_context->connection_info.algorithm.base_asym_algo);
     659              :     }
     660           29 :     measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
     661              :         spdm_context, true, measurement_hash_type);
     662           29 :     hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     663              : 
     664           29 :     if (libspdm_is_capabilities_flag_supported(
     665              :             spdm_context, true,
     666              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     667              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     668            1 :         hmac_size = 0;
     669              :     }
     670              : 
     671           29 :     if (spdm_response_size <
     672           29 :         sizeof(spdm_key_exchange_response_t) + rsp_key_exchange_size +
     673           29 :         measurement_summary_hash_size + sizeof(uint16_t) + signature_size + hmac_size) {
     674            4 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     675            4 :         goto receive_done;
     676              :     }
     677              : 
     678           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderRandomData (0x%x) - ", SPDM_RANDOM_DATA_SIZE));
     679           25 :     LIBSPDM_INTERNAL_DUMP_DATA(spdm_response->random_data, SPDM_RANDOM_DATA_SIZE);
     680           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     681           25 :     if (responder_random != NULL) {
     682            1 :         libspdm_copy_mem(responder_random, SPDM_RANDOM_DATA_SIZE,
     683            1 :                          spdm_response->random_data, SPDM_RANDOM_DATA_SIZE);
     684              :     }
     685              : 
     686           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderKey (0x%zx):\n", rsp_key_exchange_size));
     687           25 :     LIBSPDM_INTERNAL_DUMP_HEX(spdm_response->exchange_data, rsp_key_exchange_size);
     688              : 
     689           25 :     ptr = spdm_response->exchange_data;
     690           25 :     ptr += rsp_key_exchange_size;
     691              : 
     692           25 :     measurement_summary_hash = ptr;
     693           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "measurement_summary_hash (0x%x) - ",
     694              :                    measurement_summary_hash_size));
     695           25 :     LIBSPDM_INTERNAL_DUMP_DATA(measurement_summary_hash, measurement_summary_hash_size);
     696           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     697              : 
     698           25 :     ptr += measurement_summary_hash_size;
     699              : 
     700           25 :     opaque_length = libspdm_read_uint16((const uint8_t *)ptr);
     701           25 :     if (opaque_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
     702            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     703            1 :         goto receive_done;
     704              :     }
     705           24 :     ptr += sizeof(uint16_t);
     706           24 :     if (spdm_response_size <
     707           24 :         sizeof(spdm_key_exchange_response_t) + rsp_key_exchange_size +
     708           24 :         measurement_summary_hash_size + sizeof(uint16_t) +
     709           24 :         opaque_length + signature_size + hmac_size) {
     710            2 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     711            2 :         goto receive_done;
     712              :     }
     713           22 :     if (opaque_length != 0) {
     714           22 :         result = libspdm_process_general_opaque_data_check(spdm_context, opaque_length, ptr);
     715           22 :         if (!result) {
     716            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     717            0 :             goto receive_done;
     718              :         }
     719           22 :         status = libspdm_process_opaque_data_version_selection_data(
     720              :             spdm_context, opaque_length, ptr, &secured_message_version);
     721           22 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     722            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     723            0 :             goto receive_done;
     724              :         }
     725              :     }
     726              : 
     727           22 :     if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
     728            1 :         if (opaque_length >= *responder_opaque_data_size) {
     729            0 :             status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     730            0 :             goto receive_done;
     731              :         }
     732            1 :         libspdm_copy_mem(responder_opaque_data, *responder_opaque_data_size, ptr, opaque_length);
     733            1 :         *responder_opaque_data_size = opaque_length;
     734              :     }
     735              : 
     736           22 :     ptr += opaque_length;
     737              : 
     738           22 :     spdm_response_size = sizeof(spdm_key_exchange_response_t) +
     739           22 :                          rsp_key_exchange_size + measurement_summary_hash_size +
     740           22 :                          sizeof(uint16_t) + opaque_length + signature_size + hmac_size;
     741              : 
     742           22 :     rsp_session_id = spdm_response->rsp_session_id;
     743           22 :     *session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
     744           22 :     session_info = libspdm_assign_session_id(spdm_context, *session_id, secured_message_version,
     745              :                                              false);
     746           22 :     if (session_info == NULL) {
     747            0 :         status = LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     748            0 :         goto receive_done;
     749              :     }
     750           22 :     session_info->peer_used_cert_chain_slot_id = slot_id;
     751              : 
     752              :     /* -=[Process Response Phase]=- */
     753           22 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_request,
     754              :                                       spdm_request_size);
     755           22 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     756            0 :         libspdm_free_session_id(spdm_context, *session_id);
     757            0 :         goto receive_done;
     758              :     }
     759              : 
     760           22 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_response,
     761           22 :                                       spdm_response_size - signature_size - hmac_size);
     762           22 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     763            0 :         libspdm_free_session_id(spdm_context, *session_id);
     764            0 :         goto receive_done;
     765              :     }
     766              : 
     767           22 :     signature = ptr;
     768           22 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature (0x%x):\n", signature_size));
     769           22 :     LIBSPDM_INTERNAL_DUMP_HEX(signature, signature_size);
     770           22 :     ptr += signature_size;
     771           22 :     result = libspdm_verify_key_exchange_rsp_signature(
     772              :         spdm_context, session_info, signature, signature_size);
     773           22 :     if (!result) {
     774            2 :         libspdm_free_session_id(spdm_context, *session_id);
     775            2 :         status = LIBSPDM_STATUS_VERIF_FAIL;
     776            2 :         goto receive_done;
     777              :     }
     778              : 
     779           20 :     status = libspdm_append_message_k(spdm_context, session_info, true, signature, signature_size);
     780           20 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     781            0 :         libspdm_free_session_id(spdm_context, *session_id);
     782            0 :         goto receive_done;
     783              :     }
     784              : 
     785           20 :     if (spdm_context->connection_info.algorithm.kem_alg != 0) {
     786            0 :         result = libspdm_secured_message_kem_decapsulate(
     787              :             spdm_context->connection_info.algorithm.kem_alg,
     788            0 :             kem_context, spdm_response->exchange_data, kem_cipher_text_size,
     789              :             session_info->secured_message_context);
     790            0 :         libspdm_secured_message_kem_free(
     791              :             spdm_context->connection_info.algorithm.kem_alg, kem_context);
     792            0 :         kem_context = NULL;
     793              :     } else {
     794           20 :         result = libspdm_secured_message_dhe_compute_key(
     795           20 :             spdm_context->connection_info.algorithm.dhe_named_group,
     796           20 :             dhe_context, spdm_response->exchange_data, dhe_key_size,
     797              :             session_info->secured_message_context);
     798           20 :         libspdm_secured_message_dhe_free(
     799           20 :             spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
     800           20 :         dhe_context = NULL;
     801              :     }
     802           20 :     if (!result) {
     803            0 :         libspdm_free_session_id(spdm_context, *session_id);
     804            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     805            0 :         goto receive_done;
     806              :     }
     807              : 
     808           20 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
     809              :                    *session_id));
     810           20 :     result = libspdm_calculate_th1_hash(spdm_context, session_info, true, th1_hash_data);
     811           20 :     if (!result) {
     812            0 :         libspdm_free_session_id(spdm_context, *session_id);
     813            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     814            0 :         goto receive_done;
     815              :     }
     816           20 :     result = libspdm_generate_session_handshake_key(
     817              :         session_info->secured_message_context, th1_hash_data);
     818           20 :     if (!result) {
     819            0 :         libspdm_free_session_id(spdm_context, *session_id);
     820            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     821            0 :         goto receive_done;
     822              :     }
     823              : 
     824           20 :     if (!libspdm_is_capabilities_flag_supported(
     825              :             spdm_context, true,
     826              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     827              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     828           19 :         verify_data = ptr;
     829           19 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%x):\n", hmac_size));
     830           19 :         LIBSPDM_INTERNAL_DUMP_HEX(verify_data, hmac_size);
     831           19 :         result = libspdm_verify_key_exchange_rsp_hmac(
     832              :             spdm_context, session_info, verify_data, hmac_size);
     833           19 :         if (!result) {
     834            0 :             libspdm_free_session_id(spdm_context, *session_id);
     835            0 :             status = LIBSPDM_STATUS_VERIF_FAIL;
     836            0 :             goto receive_done;
     837              :         }
     838           19 :         ptr += hmac_size;
     839              : 
     840           19 :         status = libspdm_append_message_k(spdm_context, session_info, true, verify_data, hmac_size);
     841           19 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     842            0 :             libspdm_free_session_id(spdm_context, *session_id);
     843            0 :             goto receive_done;
     844              :         }
     845              :     }
     846              : 
     847           20 :     if (measurement_hash != NULL) {
     848           20 :         libspdm_copy_mem(measurement_hash, measurement_summary_hash_size,
     849              :                          measurement_summary_hash, measurement_summary_hash_size);
     850              :     }
     851           20 :     session_info->heartbeat_period = spdm_response->header.param1;
     852           20 :     session_info->mut_auth_requested = mut_auth_requested;
     853           20 :     session_info->session_policy = session_policy;
     854              : 
     855              :     /* -=[Update State Phase]=- */
     856           20 :     libspdm_secured_message_set_session_state(
     857              :         session_info->secured_message_context, LIBSPDM_SESSION_STATE_HANDSHAKING);
     858              : 
     859              :     /* -=[Log Message Phase]=- */
     860              :     #if LIBSPDM_ENABLE_MSG_LOG
     861           20 :     libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     862              :     #endif /* LIBSPDM_ENABLE_MSG_LOG */
     863              : 
     864           20 :     status = LIBSPDM_STATUS_SUCCESS;
     865              : 
     866           88 : receive_done:
     867           88 :     libspdm_release_receiver_buffer (spdm_context);
     868           91 : free_exchange:
     869           91 :     if (dhe_context != NULL) {
     870           71 :         libspdm_secured_message_dhe_free(
     871           71 :             spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
     872              :     }
     873           91 :     if (kem_context != NULL) {
     874            0 :         libspdm_secured_message_kem_free(
     875              :             spdm_context->connection_info.algorithm.kem_alg, kem_context);
     876              :     }
     877           91 :     return status;
     878              : }
     879              : 
     880           93 : libspdm_return_t libspdm_send_receive_key_exchange(
     881              :     libspdm_context_t *spdm_context, uint8_t measurement_hash_type,
     882              :     uint8_t slot_id, uint8_t session_policy, uint32_t *session_id,
     883              :     uint8_t *heartbeat_period,
     884              :     uint8_t *req_slot_id_param, void *measurement_hash)
     885              : {
     886              :     size_t retry;
     887              :     uint64_t retry_delay_time;
     888              :     libspdm_return_t status;
     889              : 
     890           93 :     spdm_context->crypto_request = true;
     891           93 :     retry = spdm_context->retry_times;
     892           93 :     retry_delay_time = spdm_context->retry_delay_time;
     893              :     do {
     894           94 :         status = libspdm_try_send_receive_key_exchange(
     895              :             spdm_context, measurement_hash_type, slot_id, session_policy,
     896              :             session_id, heartbeat_period, req_slot_id_param,
     897              :             measurement_hash,
     898              :             NULL, NULL, NULL, NULL, 0, NULL, NULL);
     899           94 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     900           91 :             return status;
     901              :         }
     902              : 
     903            3 :         libspdm_sleep(retry_delay_time);
     904            3 :     } while (retry-- != 0);
     905              : 
     906            2 :     return status;
     907              : }
     908              : 
     909            1 : libspdm_return_t libspdm_send_receive_key_exchange_ex(
     910              :     libspdm_context_t *spdm_context, uint8_t measurement_hash_type,
     911              :     uint8_t slot_id, uint8_t session_policy, uint32_t *session_id,
     912              :     uint8_t *heartbeat_period,
     913              :     uint8_t *req_slot_id_param, void *measurement_hash,
     914              :     const void *requester_random_in,
     915              :     void *requester_random, void *responder_random,
     916              :     const void *requester_opaque_data,
     917              :     size_t requester_opaque_data_size,
     918              :     void *responder_opaque_data,
     919              :     size_t *responder_opaque_data_size)
     920              : {
     921              :     size_t retry;
     922              :     uint64_t retry_delay_time;
     923              :     libspdm_return_t status;
     924              : 
     925            1 :     spdm_context->crypto_request = true;
     926            1 :     retry = spdm_context->retry_times;
     927            1 :     retry_delay_time = spdm_context->retry_delay_time;
     928              :     do {
     929            1 :         status = libspdm_try_send_receive_key_exchange(
     930              :             spdm_context, measurement_hash_type, slot_id, session_policy,
     931              :             session_id, heartbeat_period, req_slot_id_param,
     932              :             measurement_hash, requester_random_in,
     933              :             requester_random, responder_random,
     934              :             requester_opaque_data, requester_opaque_data_size,
     935              :             responder_opaque_data, responder_opaque_data_size);
     936            1 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     937            1 :             return status;
     938              :         }
     939              : 
     940            0 :         libspdm_sleep(retry_delay_time);
     941            0 :     } while (retry-- != 0);
     942              : 
     943            0 :     return status;
     944              : }
     945              : 
     946              : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
        

Generated by: LCOV version 2.0-1