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 % 401 309
Test Date: 2026-08-16 08:12:25 Functions: 100.0 % 5 5

            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_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, 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           95 :     uint8_t peer_aead_limit_exponent = SECURED_MESSAGE_AEAD_LIMIT_EXPONENT_DEFAULT;
     339              : 
     340              :     /* -=[Check Parameters Phase]=- */
     341           95 :     LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xff));
     342           95 :     LIBSPDM_ASSERT((slot_id != 0xff) ||
     343              :                    (spdm_context->local_context.peer_public_key_provision_size != 0));
     344           95 :     LIBSPDM_ASSERT(measurement_hash_type == SPDM_KEY_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH ||
     345              :                    measurement_hash_type == SPDM_KEY_EXCHANGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH ||
     346              :                    measurement_hash_type == SPDM_KEY_EXCHANGE_REQUEST_ALL_MEASUREMENTS_HASH);
     347           95 :     LIBSPDM_ASSERT((libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) ||
     348              :                    ((session_policy & SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY)
     349              :                     == 0) ||
     350              :                    libspdm_is_capabilities_flag_supported(
     351              :                        spdm_context, true, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EVENT_CAP));
     352              : 
     353              :     /* -=[Verify State Phase]=- */
     354           95 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     355            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     356              :     }
     357              : 
     358           95 :     if (!libspdm_is_capabilities_flag_supported(
     359              :             spdm_context, true,
     360              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
     361              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
     362            1 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     363              :     }
     364              : 
     365              :     /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
     366              :      * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
     367              :      */
     368           94 :     if (!libspdm_is_capabilities_flag_supported(
     369              :             spdm_context, true,
     370              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
     371              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
     372            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     373              :     }
     374              : 
     375           94 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     376            2 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     377              :     }
     378              : 
     379           92 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     380            3 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     381              :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
     382            0 :             return LIBSPDM_STATUS_INVALID_STATE_PEER;
     383              :         }
     384              :     }
     385              : 
     386           92 :     req_session_id = libspdm_allocate_req_session_id(spdm_context, false);
     387           92 :     if (req_session_id == (INVALID_SESSION_ID & 0xFFFF)) {
     388            0 :         return LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     389              :     }
     390              : 
     391           92 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL, SPDM_KEY_EXCHANGE);
     392              : 
     393              :     /* -=[Construct Request Phase]=- */
     394           92 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
     395           92 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     396           92 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     397            1 :         return status;
     398              :     }
     399           91 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
     400              :                     spdm_context->local_context.capability.transport_tail_size);
     401           91 :     spdm_request = (void *)(message + transport_header_size);
     402           91 :     spdm_request_size = message_size - transport_header_size -
     403           91 :                         spdm_context->local_context.capability.transport_tail_size;
     404              : 
     405           91 :     LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t));
     406           91 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     407           91 :     spdm_request->header.request_response_code = SPDM_KEY_EXCHANGE;
     408           91 :     spdm_request->header.param1 = measurement_hash_type;
     409           91 :     spdm_request->header.param2 = slot_id;
     410           91 :     if (requester_random_in == NULL) {
     411           90 :         if (!libspdm_get_random_number(SPDM_RANDOM_DATA_SIZE, spdm_request->random_data)) {
     412            0 :             libspdm_release_sender_buffer (spdm_context);
     413            0 :             return LIBSPDM_STATUS_LOW_ENTROPY;
     414              :         }
     415              :     } else {
     416            1 :         libspdm_copy_mem(spdm_request->random_data, sizeof(spdm_request->random_data),
     417              :                          requester_random_in, SPDM_RANDOM_DATA_SIZE);
     418              :     }
     419           91 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterRandomData (0x%x) - ",
     420              :                    SPDM_RANDOM_DATA_SIZE));
     421           91 :     LIBSPDM_INTERNAL_DUMP_DATA(spdm_request->random_data, SPDM_RANDOM_DATA_SIZE);
     422           91 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     423           91 :     if (requester_random != NULL) {
     424            1 :         libspdm_copy_mem(requester_random, SPDM_RANDOM_DATA_SIZE,
     425            1 :                          spdm_request->random_data, SPDM_RANDOM_DATA_SIZE);
     426              :     }
     427              : 
     428           91 :     spdm_request->req_session_id = req_session_id;
     429           91 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     430            3 :         spdm_request->session_policy = session_policy;
     431              :     } else {
     432           88 :         spdm_request->session_policy = 0;
     433              :     }
     434           91 :     spdm_request->reserved = 0;
     435              : 
     436           91 :     ptr = spdm_request->exchange_data;
     437           91 :     dhe_context = NULL;
     438           91 :     kem_context = NULL;
     439           91 :     if (spdm_context->connection_info.algorithm.kem_alg != 0) {
     440            0 :         kem_encap_key_size = libspdm_get_kem_encap_key_size(
     441              :             spdm_context->connection_info.algorithm.kem_alg);
     442            0 :         kem_cipher_text_size = libspdm_get_kem_cipher_text_size(
     443              :             spdm_context->connection_info.algorithm.kem_alg);
     444            0 :         kem_context = libspdm_secured_message_kem_new(
     445            0 :             spdm_context->connection_info.version,
     446              :             spdm_context->connection_info.algorithm.kem_alg, true);
     447            0 :         if (kem_context == NULL) {
     448            0 :             libspdm_release_sender_buffer (spdm_context);
     449            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     450              :         }
     451              : 
     452            0 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) + kem_encap_key_size);
     453            0 :         result = libspdm_secured_message_kem_generate_key(
     454              :             spdm_context->connection_info.algorithm.kem_alg,
     455              :             kem_context, ptr, &kem_encap_key_size);
     456            0 :         if (!result) {
     457            0 :             libspdm_secured_message_kem_free(
     458              :                 spdm_context->connection_info.algorithm.kem_alg, kem_context);
     459            0 :             libspdm_release_sender_buffer (spdm_context);
     460            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     461              :         }
     462            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterKey (0x%zx):\n", kem_encap_key_size));
     463            0 :         LIBSPDM_INTERNAL_DUMP_HEX(ptr, kem_encap_key_size);
     464            0 :         ptr += kem_encap_key_size;
     465            0 :         req_key_exchange_size = kem_encap_key_size;
     466            0 :         rsp_key_exchange_size = kem_cipher_text_size;
     467              :     } else {
     468          182 :         dhe_key_size = libspdm_get_dhe_pub_key_size(
     469           91 :             spdm_context->connection_info.algorithm.dhe_named_group);
     470           91 :         dhe_context = libspdm_secured_message_dhe_new(
     471           91 :             spdm_context->connection_info.version,
     472           91 :             spdm_context->connection_info.algorithm.dhe_named_group, true);
     473           91 :         if (dhe_context == NULL) {
     474            0 :             libspdm_release_sender_buffer (spdm_context);
     475            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     476              :         }
     477              : 
     478           91 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) + dhe_key_size);
     479           91 :         result = libspdm_secured_message_dhe_generate_key(
     480           91 :             spdm_context->connection_info.algorithm.dhe_named_group,
     481              :             dhe_context, ptr, &dhe_key_size);
     482           91 :         if (!result) {
     483            0 :             libspdm_secured_message_dhe_free(
     484            0 :                 spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
     485            0 :             libspdm_release_sender_buffer (spdm_context);
     486            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     487              :         }
     488           91 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterKey (0x%zx):\n", dhe_key_size));
     489           91 :         LIBSPDM_INTERNAL_DUMP_HEX(ptr, dhe_key_size);
     490           91 :         ptr += dhe_key_size;
     491           91 :         req_key_exchange_size = dhe_key_size;
     492           91 :         rsp_key_exchange_size = dhe_key_size;
     493              :     }
     494              : 
     495           91 :     if (requester_opaque_data != NULL) {
     496            1 :         LIBSPDM_ASSERT(requester_opaque_data_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
     497              : 
     498            1 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) +
     499              :                         req_key_exchange_size +
     500              :                         sizeof(uint16_t) + requester_opaque_data_size);
     501              : 
     502            1 :         libspdm_write_uint16(ptr, (uint16_t)requester_opaque_data_size);
     503            1 :         ptr += sizeof(uint16_t);
     504              : 
     505            1 :         libspdm_copy_mem(ptr,
     506            1 :                          (spdm_request_size - (sizeof(spdm_key_exchange_request_t) +
     507              :                                                req_key_exchange_size)),
     508              :                          requester_opaque_data, requester_opaque_data_size);
     509            1 :         opaque_key_exchange_req_size = requester_opaque_data_size;
     510              :     } else {
     511              :         size_t supported_version_size;
     512              : 
     513              :         spdm_version_number_t local_max_secured_version =
     514           90 :             libspdm_local_max_secured_message_version(spdm_context);
     515              : 
     516           90 :         supported_version_size =
     517           90 :             libspdm_get_opaque_data_supported_version_data_size(spdm_context);
     518              :         /* DSP0277 1.3: also advertise this endpoint's AEAD limit in the request opaque data when it
     519              :          * offers secured message version 1.3 (no version is negotiated yet at request time). */
     520           90 :         opaque_key_exchange_req_size = supported_version_size +
     521           90 :                                        libspdm_get_opaque_data_aead_limit_element_size(
     522              :             spdm_context, local_max_secured_version);
     523           90 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) +
     524              :                         req_key_exchange_size +
     525              :                         sizeof(uint16_t) + opaque_key_exchange_req_size);
     526              : 
     527           90 :         libspdm_write_uint16(ptr, (uint16_t)opaque_key_exchange_req_size);
     528           90 :         ptr += sizeof(uint16_t);
     529              : 
     530              :         /* opaque_key_exchange_req_size holds the reserved opaque data capacity (supported version +
     531              :          * AEAD limit); it is the capacity passed to the append below. */
     532           90 :         libspdm_build_opaque_data_supported_version_data(
     533              :             spdm_context, &supported_version_size, ptr);
     534           90 :         libspdm_build_opaque_data_aead_limit_element(
     535              :             spdm_context, local_max_secured_version, &opaque_key_exchange_req_size, ptr);
     536              :     }
     537           91 :     ptr += opaque_key_exchange_req_size;
     538              : 
     539           91 :     spdm_request_size = (size_t)ptr - (size_t)spdm_request;
     540              : 
     541              :     /* -=[Send Request Phase]=- */
     542           91 :     status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size, spdm_request);
     543           91 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     544            2 :         libspdm_release_sender_buffer (spdm_context);
     545            2 :         goto free_exchange;
     546              :     }
     547           89 :     libspdm_release_sender_buffer (spdm_context);
     548           89 :     spdm_request = (void *)spdm_context->last_spdm_request;
     549              : 
     550              :     /* -=[Receive Response Phase]=- */
     551           89 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     552           89 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     553            1 :         goto free_exchange;
     554              :     }
     555           88 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
     556           88 :     spdm_response = (void *)(message);
     557           88 :     spdm_response_size = message_size;
     558              : 
     559           88 :     status = libspdm_receive_spdm_response(
     560              :         spdm_context, NULL, &spdm_response_size, (void **)&spdm_response);
     561           88 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     562            0 :         goto receive_done;
     563              :     }
     564              : 
     565              :     /* -=[Validate Response Phase]=- */
     566           88 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     567            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     568            0 :         goto receive_done;
     569              :     }
     570           88 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     571           46 :         status = libspdm_handle_error_response_main(
     572              :             spdm_context, NULL, &spdm_response_size,
     573              :             (void **)&spdm_response, SPDM_KEY_EXCHANGE,
     574              :             SPDM_KEY_EXCHANGE_RSP);
     575           46 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     576           45 :             goto receive_done;
     577              :         }
     578           42 :     } else if (spdm_response->header.request_response_code != SPDM_KEY_EXCHANGE_RSP) {
     579            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     580            1 :         goto receive_done;
     581              :     }
     582           42 :     if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     583            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     584            1 :         goto receive_done;
     585              :     }
     586           41 :     if (spdm_response_size < sizeof(spdm_key_exchange_response_t)) {
     587            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     588            0 :         goto receive_done;
     589              :     }
     590              : 
     591           41 :     if (!libspdm_is_capabilities_flag_supported(
     592              :             spdm_context, true,
     593              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     594              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     595           39 :         if (spdm_response->header.param1 != 0) {
     596            2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     597            2 :             goto receive_done;
     598              :         }
     599              :     }
     600           39 :     if (heartbeat_period != NULL) {
     601           35 :         *heartbeat_period = spdm_response->header.param1;
     602              :     }
     603              : 
     604           39 :     *req_slot_id_param = spdm_response->req_slot_id_param & 0xf;
     605           39 :     mut_auth_requested = spdm_response->mut_auth_requested & 0x7;
     606              : 
     607           39 :     if (mut_auth_requested != 0) {
     608           13 :         const bool mut_auth_cap_both = libspdm_is_capabilities_flag_supported(
     609              :             spdm_context, true,
     610              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP,
     611              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP);
     612           13 :         const bool cert_cap = libspdm_is_capabilities_flag_supported(
     613              :             spdm_context, true,
     614              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP,
     615              :             0);
     616           13 :         const bool pub_key_id_cap = libspdm_is_capabilities_flag_supported(
     617              :             spdm_context, true,
     618              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP,
     619              :             0);
     620              : 
     621           13 :         if (!mut_auth_cap_both) {
     622            1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     623            1 :             goto receive_done;
     624              :         }
     625           12 :         if ((mut_auth_requested != SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED) &&
     626              :             (mut_auth_requested !=
     627            7 :              SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST) &&
     628              :             (mut_auth_requested !=
     629              :              SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS)) {
     630            6 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     631            6 :             goto receive_done;
     632              :         }
     633              : 
     634            6 :         if (mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED) {
     635              :             /* Non-encapsulated flow.
     636              :              * Requester has either CERT_CAP or PUB_KEY_ID_CAP set. */
     637              : 
     638            2 :             if ((cert_cap && (*req_slot_id_param >= SPDM_MAX_SLOT_COUNT)) ||
     639            0 :                 (pub_key_id_cap && (*req_slot_id_param != 0xf))) {
     640            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     641            1 :                 goto receive_done;
     642              :             }
     643            1 :             if ((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
     644            0 :                 spdm_context->connection_info.multi_key_conn_req &&
     645            0 :                 (*req_slot_id_param != 0xf)) {
     646            0 :                 if ((spdm_context->local_context.local_key_usage_bit_mask[*req_slot_id_param] &
     647              :                      SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE) == 0) {
     648            0 :                     status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     649            0 :                     goto receive_done;
     650              :                 }
     651              :             }
     652              :         } else {
     653              :             /* Encapsulated flow. */
     654              : 
     655              :             /* If Responder has Requester's public key then it cannot use the encapsulated flow. */
     656            4 :             if (pub_key_id_cap) {
     657            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     658            1 :                 goto receive_done;
     659              :             }
     660              :             /* Encapsulated flow requires support for encapsulated messages by both endpoints. */
     661            3 :             if (!libspdm_is_encap_supported(spdm_context)) {
     662            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     663            1 :                 goto receive_done;
     664              :             }
     665              :         }
     666              :     }
     667              : 
     668           29 :     if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     669            0 :         signature_size = libspdm_get_pqc_asym_signature_size(
     670              :             spdm_context->connection_info.algorithm.pqc_asym_algo);
     671              :     } else {
     672           29 :         signature_size = libspdm_get_asym_signature_size(
     673              :             spdm_context->connection_info.algorithm.base_asym_algo);
     674              :     }
     675           29 :     measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
     676              :         spdm_context, true, measurement_hash_type);
     677           29 :     hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     678              : 
     679           29 :     if (libspdm_is_capabilities_flag_supported(
     680              :             spdm_context, true,
     681              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     682              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     683            1 :         hmac_size = 0;
     684              :     }
     685              : 
     686           29 :     if (spdm_response_size <
     687           29 :         sizeof(spdm_key_exchange_response_t) + rsp_key_exchange_size +
     688           29 :         measurement_summary_hash_size + sizeof(uint16_t) + signature_size + hmac_size) {
     689            4 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     690            4 :         goto receive_done;
     691              :     }
     692              : 
     693           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderRandomData (0x%x) - ", SPDM_RANDOM_DATA_SIZE));
     694           25 :     LIBSPDM_INTERNAL_DUMP_DATA(spdm_response->random_data, SPDM_RANDOM_DATA_SIZE);
     695           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     696           25 :     if (responder_random != NULL) {
     697            1 :         libspdm_copy_mem(responder_random, SPDM_RANDOM_DATA_SIZE,
     698            1 :                          spdm_response->random_data, SPDM_RANDOM_DATA_SIZE);
     699              :     }
     700              : 
     701           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderKey (0x%zx):\n", rsp_key_exchange_size));
     702           25 :     LIBSPDM_INTERNAL_DUMP_HEX(spdm_response->exchange_data, rsp_key_exchange_size);
     703              : 
     704           25 :     ptr = spdm_response->exchange_data;
     705           25 :     ptr += rsp_key_exchange_size;
     706              : 
     707           25 :     measurement_summary_hash = ptr;
     708           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "measurement_summary_hash (0x%x) - ",
     709              :                    measurement_summary_hash_size));
     710           25 :     LIBSPDM_INTERNAL_DUMP_DATA(measurement_summary_hash, measurement_summary_hash_size);
     711           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     712              : 
     713           25 :     ptr += measurement_summary_hash_size;
     714              : 
     715           25 :     opaque_length = libspdm_read_uint16((const uint8_t *)ptr);
     716           25 :     if (opaque_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
     717            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     718            1 :         goto receive_done;
     719              :     }
     720           24 :     ptr += sizeof(uint16_t);
     721           24 :     if (spdm_response_size <
     722           24 :         sizeof(spdm_key_exchange_response_t) + rsp_key_exchange_size +
     723           24 :         measurement_summary_hash_size + sizeof(uint16_t) +
     724           24 :         opaque_length + signature_size + hmac_size) {
     725            2 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     726            2 :         goto receive_done;
     727              :     }
     728           22 :     if (opaque_length != 0) {
     729           22 :         result = libspdm_process_general_opaque_data_check(spdm_context, opaque_length, ptr);
     730           22 :         if (!result) {
     731            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     732            0 :             goto receive_done;
     733              :         }
     734           22 :         status = libspdm_process_opaque_data_version_selection_data(
     735              :             spdm_context, opaque_length, ptr, &secured_message_version);
     736           22 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     737            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     738            0 :             goto receive_done;
     739              :         }
     740              :         /* DSP0277 1.3: read the Responder's AEAD limit (absent -> default 64). */
     741           22 :         status = libspdm_process_opaque_data_aead_limit(
     742              :             spdm_context, secured_message_version, opaque_length, ptr,
     743              :             &peer_aead_limit_exponent);
     744           22 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     745            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     746            0 :             goto receive_done;
     747              :         }
     748              :     }
     749              : 
     750           22 :     if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
     751            1 :         if (opaque_length >= *responder_opaque_data_size) {
     752            0 :             status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     753            0 :             goto receive_done;
     754              :         }
     755            1 :         libspdm_copy_mem(responder_opaque_data, *responder_opaque_data_size, ptr, opaque_length);
     756            1 :         *responder_opaque_data_size = opaque_length;
     757              :     }
     758              : 
     759           22 :     ptr += opaque_length;
     760              : 
     761           22 :     spdm_response_size = sizeof(spdm_key_exchange_response_t) +
     762           22 :                          rsp_key_exchange_size + measurement_summary_hash_size +
     763           22 :                          sizeof(uint16_t) + opaque_length + signature_size + hmac_size;
     764              : 
     765           22 :     rsp_session_id = spdm_response->rsp_session_id;
     766           22 :     *session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
     767           22 :     session_info = libspdm_assign_session_id(spdm_context, *session_id, secured_message_version,
     768              :                                              false);
     769           22 :     if (session_info == NULL) {
     770            0 :         status = LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     771            0 :         goto receive_done;
     772              :     }
     773           22 :     session_info->peer_used_cert_chain_slot_id = slot_id;
     774           22 :     session_info->local_used_cert_chain_slot_id = *req_slot_id_param;
     775              : 
     776              :     /* DSP0277 1.3: program the session's AEAD limit (min of local and peer) when secured message
     777              :      * version 1.3 was negotiated. */
     778           22 :     if (libspdm_get_version_from_version_number(secured_message_version) >=
     779              :         SECURED_SPDM_VERSION_13) {
     780            0 :         libspdm_apply_aead_limit_to_session(spdm_context, session_info,
     781              :                                             peer_aead_limit_exponent);
     782              :     }
     783              : 
     784              :     /* -=[Process Response Phase]=- */
     785           22 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_request,
     786              :                                       spdm_request_size);
     787           22 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     788            0 :         libspdm_free_session_id(spdm_context, *session_id);
     789            0 :         goto receive_done;
     790              :     }
     791              : 
     792           22 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_response,
     793           22 :                                       spdm_response_size - signature_size - hmac_size);
     794           22 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     795            0 :         libspdm_free_session_id(spdm_context, *session_id);
     796            0 :         goto receive_done;
     797              :     }
     798              : 
     799           22 :     signature = ptr;
     800           22 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature (0x%x):\n", signature_size));
     801           22 :     LIBSPDM_INTERNAL_DUMP_HEX(signature, signature_size);
     802           22 :     ptr += signature_size;
     803           22 :     result = libspdm_verify_key_exchange_rsp_signature(
     804              :         spdm_context, session_info, signature, signature_size);
     805           22 :     if (!result) {
     806            2 :         libspdm_free_session_id(spdm_context, *session_id);
     807            2 :         status = LIBSPDM_STATUS_VERIF_FAIL;
     808            2 :         goto receive_done;
     809              :     }
     810              : 
     811           20 :     status = libspdm_append_message_k(spdm_context, session_info, true, signature, signature_size);
     812           20 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     813            0 :         libspdm_free_session_id(spdm_context, *session_id);
     814            0 :         goto receive_done;
     815              :     }
     816              : 
     817           20 :     if (spdm_context->connection_info.algorithm.kem_alg != 0) {
     818            0 :         result = libspdm_secured_message_kem_decapsulate(
     819              :             spdm_context->connection_info.algorithm.kem_alg,
     820            0 :             kem_context, spdm_response->exchange_data, kem_cipher_text_size,
     821              :             session_info->secured_message_context);
     822            0 :         libspdm_secured_message_kem_free(
     823              :             spdm_context->connection_info.algorithm.kem_alg, kem_context);
     824            0 :         kem_context = NULL;
     825              :     } else {
     826           20 :         result = libspdm_secured_message_dhe_compute_key(
     827           20 :             spdm_context->connection_info.algorithm.dhe_named_group,
     828           20 :             dhe_context, spdm_response->exchange_data, dhe_key_size,
     829              :             session_info->secured_message_context);
     830           20 :         libspdm_secured_message_dhe_free(
     831           20 :             spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
     832           20 :         dhe_context = NULL;
     833              :     }
     834           20 :     if (!result) {
     835            0 :         libspdm_free_session_id(spdm_context, *session_id);
     836            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     837            0 :         goto receive_done;
     838              :     }
     839              : 
     840           20 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
     841              :                    *session_id));
     842           20 :     result = libspdm_calculate_th1_hash(spdm_context, session_info, true, th1_hash_data);
     843           20 :     if (!result) {
     844            0 :         libspdm_free_session_id(spdm_context, *session_id);
     845            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     846            0 :         goto receive_done;
     847              :     }
     848           20 :     result = libspdm_generate_session_handshake_key(
     849              :         session_info->secured_message_context, th1_hash_data);
     850           20 :     if (!result) {
     851            0 :         libspdm_free_session_id(spdm_context, *session_id);
     852            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     853            0 :         goto receive_done;
     854              :     }
     855              : 
     856           20 :     if (!libspdm_is_capabilities_flag_supported(
     857              :             spdm_context, true,
     858              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     859              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     860           19 :         verify_data = ptr;
     861           19 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%x):\n", hmac_size));
     862           19 :         LIBSPDM_INTERNAL_DUMP_HEX(verify_data, hmac_size);
     863           19 :         result = libspdm_verify_key_exchange_rsp_hmac(
     864              :             spdm_context, session_info, verify_data, hmac_size);
     865           19 :         if (!result) {
     866            0 :             libspdm_free_session_id(spdm_context, *session_id);
     867            0 :             status = LIBSPDM_STATUS_VERIF_FAIL;
     868            0 :             goto receive_done;
     869              :         }
     870           19 :         ptr += hmac_size;
     871              : 
     872           19 :         status = libspdm_append_message_k(spdm_context, session_info, true, verify_data, hmac_size);
     873           19 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     874            0 :             libspdm_free_session_id(spdm_context, *session_id);
     875            0 :             goto receive_done;
     876              :         }
     877              :     }
     878              : 
     879           20 :     if (measurement_hash != NULL) {
     880           20 :         libspdm_copy_mem(measurement_hash, measurement_summary_hash_size,
     881              :                          measurement_summary_hash, measurement_summary_hash_size);
     882              :     }
     883           20 :     session_info->heartbeat_period = spdm_response->header.param1;
     884           20 :     session_info->mut_auth_requested = mut_auth_requested;
     885           20 :     session_info->session_policy = session_policy;
     886              : 
     887              :     /* -=[Update State Phase]=- */
     888           20 :     libspdm_secured_message_set_session_state(
     889              :         session_info->secured_message_context, LIBSPDM_SESSION_STATE_HANDSHAKING);
     890              : 
     891              :     /* -=[Log Message Phase]=- */
     892              :     #if LIBSPDM_ENABLE_MSG_LOG
     893           20 :     libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     894              :     #endif /* LIBSPDM_ENABLE_MSG_LOG */
     895              : 
     896           20 :     status = LIBSPDM_STATUS_SUCCESS;
     897              : 
     898           88 : receive_done:
     899           88 :     libspdm_release_receiver_buffer (spdm_context);
     900           91 : free_exchange:
     901           91 :     if (dhe_context != NULL) {
     902           71 :         libspdm_secured_message_dhe_free(
     903           71 :             spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
     904              :     }
     905           91 :     if (kem_context != NULL) {
     906            0 :         libspdm_secured_message_kem_free(
     907              :             spdm_context->connection_info.algorithm.kem_alg, kem_context);
     908              :     }
     909           91 :     return status;
     910              : }
     911              : 
     912           93 : libspdm_return_t libspdm_send_receive_key_exchange(
     913              :     libspdm_context_t *spdm_context, uint8_t measurement_hash_type,
     914              :     uint8_t slot_id, uint8_t session_policy, uint32_t *session_id,
     915              :     uint8_t *heartbeat_period,
     916              :     uint8_t *req_slot_id_param, void *measurement_hash)
     917              : {
     918              :     size_t retry;
     919              :     uint64_t retry_delay_time;
     920              :     libspdm_return_t status;
     921              : 
     922           93 :     spdm_context->crypto_request = true;
     923           93 :     retry = spdm_context->retry_times;
     924           93 :     retry_delay_time = spdm_context->retry_delay_time;
     925              :     do {
     926           94 :         status = libspdm_try_send_receive_key_exchange(
     927              :             spdm_context, measurement_hash_type, slot_id, session_policy,
     928              :             session_id, heartbeat_period, req_slot_id_param,
     929              :             measurement_hash,
     930              :             NULL, NULL, NULL, NULL, 0, NULL, NULL);
     931           94 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     932           91 :             return status;
     933              :         }
     934              : 
     935            3 :         libspdm_sleep(retry_delay_time);
     936            3 :     } while (retry-- != 0);
     937              : 
     938            2 :     return status;
     939              : }
     940              : 
     941            1 : libspdm_return_t libspdm_send_receive_key_exchange_ex(
     942              :     libspdm_context_t *spdm_context, uint8_t measurement_hash_type,
     943              :     uint8_t slot_id, uint8_t session_policy, uint32_t *session_id,
     944              :     uint8_t *heartbeat_period,
     945              :     uint8_t *req_slot_id_param, void *measurement_hash,
     946              :     const void *requester_random_in,
     947              :     void *requester_random, void *responder_random,
     948              :     const void *requester_opaque_data,
     949              :     size_t requester_opaque_data_size,
     950              :     void *responder_opaque_data,
     951              :     size_t *responder_opaque_data_size)
     952              : {
     953              :     size_t retry;
     954              :     uint64_t retry_delay_time;
     955              :     libspdm_return_t status;
     956              : 
     957            1 :     spdm_context->crypto_request = true;
     958            1 :     retry = spdm_context->retry_times;
     959            1 :     retry_delay_time = spdm_context->retry_delay_time;
     960              :     do {
     961            1 :         status = libspdm_try_send_receive_key_exchange(
     962              :             spdm_context, measurement_hash_type, slot_id, session_policy,
     963              :             session_id, heartbeat_period, req_slot_id_param,
     964              :             measurement_hash, requester_random_in,
     965              :             requester_random, responder_random,
     966              :             requester_opaque_data, requester_opaque_data_size,
     967              :             responder_opaque_data, responder_opaque_data_size);
     968            1 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     969            1 :             return status;
     970              :         }
     971              : 
     972            0 :         libspdm_sleep(retry_delay_time);
     973            0 :     } while (retry-- != 0);
     974              : 
     975            0 :     return status;
     976              : }
     977              : 
     978              : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
        

Generated by: LCOV version 2.0-1