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-08-24 08:11:14 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 = spdm_context->connection_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              :     } else {
      67              :         result = libspdm_get_peer_cert_chain_buffer(
      68              :             spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
      69              :     }
      70              :     if (!result) {
      71              :         return false;
      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, true, &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 = spdm_context->connection_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              :     } else {
     148              :         result = libspdm_get_peer_cert_chain_buffer(
     149              :             spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
     150              :     }
     151              :     if (!result) {
     152              :         return false;
     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              :         result = libspdm_get_peer_cert_chain_data(
     208              :             spdm_context, (const void **)&cert_chain_data, &cert_chain_data_size);
     209              :         if (!result) {
     210              :             return false;
     211              :         }
     212              :         result = libspdm_x509_get_cert_from_cert_chain(
     213              :             cert_chain_data, cert_chain_data_size, -1, &cert_buffer, &cert_buffer_size);
     214              :         if (!result) {
     215              :             return false;
     216              :         }
     217              : 
     218              :         if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     219              :             result = libspdm_pqc_asym_get_public_key_from_x509(
     220              :                 spdm_context->connection_info.algorithm.pqc_asym_algo,
     221              :                 cert_buffer, cert_buffer_size, &context);
     222              :         } else {
     223              :             result = libspdm_asym_get_public_key_from_x509(
     224              :                 spdm_context->connection_info.algorithm.base_asym_algo,
     225              :                 cert_buffer, cert_buffer_size, &context);
     226              :         }
     227              :         if (!result) {
     228              :             return false;
     229              :         }
     230              : #else
     231           21 :         context = spdm_context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key;
     232           21 :         LIBSPDM_ASSERT(context != NULL);
     233              : #endif
     234              :     }
     235              : 
     236              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     237              :     if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     238              :         result = libspdm_pqc_asym_verify(
     239              :             spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
     240              :             spdm_context->connection_info.algorithm.pqc_asym_algo,
     241              :             spdm_context->connection_info.algorithm.base_hash_algo,
     242              :             context, th_curr_data, th_curr_data_size, sign_data, sign_data_size);
     243              :         libspdm_pqc_asym_free(spdm_context->connection_info.algorithm.pqc_asym_algo, context);
     244              :     } else {
     245              :         result = libspdm_asym_verify_ex(
     246              :             spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
     247              :             spdm_context->connection_info.algorithm.base_asym_algo,
     248              :             spdm_context->connection_info.algorithm.base_hash_algo,
     249              :             context, th_curr_data, th_curr_data_size, sign_data, sign_data_size,
     250              :             &spdm_context->spdm_10_11_verify_signature_endian);
     251              :         libspdm_asym_free(spdm_context->connection_info.algorithm.base_asym_algo, context);
     252              :     }
     253              : #else
     254           22 :     if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     255            0 :         result = libspdm_pqc_asym_verify_hash(
     256            0 :             spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
     257              :             spdm_context->connection_info.algorithm.pqc_asym_algo,
     258              :             spdm_context->connection_info.algorithm.base_hash_algo,
     259              :             context, hash_data, hash_size, sign_data, sign_data_size);
     260            0 :         if (slot_id == 0xFF) {
     261            0 :             libspdm_pqc_asym_free(spdm_context->connection_info.algorithm.pqc_asym_algo, context);
     262              :         }
     263              :     } else {
     264           22 :         result = libspdm_asym_verify_hash_ex(
     265           22 :             spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
     266              :             spdm_context->connection_info.algorithm.base_asym_algo,
     267              :             spdm_context->connection_info.algorithm.base_hash_algo,
     268              :             context, hash_data, hash_size, sign_data, sign_data_size,
     269              :             &spdm_context->spdm_10_11_verify_signature_endian);
     270           22 :         if (slot_id == 0xFF) {
     271            1 :             libspdm_asym_free(spdm_context->connection_info.algorithm.base_asym_algo, context);
     272              :         }
     273              :     }
     274              : #endif
     275           22 :     if (!result) {
     276            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_key_exchange_signature - FAIL !!!\n"));
     277            2 :         return false;
     278              :     }
     279           20 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_key_exchange_signature - PASS !!!\n"));
     280              : 
     281           20 :     return true;
     282              : }
     283              : 
     284              : /**
     285              :  * This function sends KEY_EXCHANGE and receives KEY_EXCHANGE_RSP for SPDM key exchange.
     286              :  *
     287              :  * @param  spdm_context           A pointer to the SPDM context.
     288              :  * @param  measurement_hash_type  Measurement_hash_type to the KEY_EXCHANGE request.
     289              :  * @param  slot_id                slot_id to the KEY_EXCHANGE request.
     290              :  * @param  session_policy         The policy for the session.
     291              :  * @param  session_id             session_id from the KEY_EXCHANGE_RSP response.
     292              :  * @param  heartbeat_period       Heartbeat_period from the KEY_EXCHANGE_RSP response.
     293              :  * @param  req_slot_id_param      req_slot_id_param from the KEY_EXCHANGE_RSP response.
     294              :  * @param  measurement_hash       Measurement_hash from the KEY_EXCHANGE_RSP response.
     295              :  * @param  requester_nonce_in     If not NULL, a buffer that holds the requester nonce (32 bytes)
     296              :  * @param  requester_nonce        If not NULL, a buffer to hold the requester nonce (32 bytes).
     297              :  * @param  responder_nonce        If not NULL, a buffer to hold the responder nonce (32 bytes).
     298              :  **/
     299           95 : static libspdm_return_t libspdm_try_send_receive_key_exchange(
     300              :     libspdm_context_t *spdm_context, uint8_t measurement_hash_type,
     301              :     uint8_t slot_id, uint8_t session_policy, uint32_t *session_id,
     302              :     uint8_t *heartbeat_period,
     303              :     uint8_t *req_slot_id_param, void *measurement_hash,
     304              :     const void *requester_random_in,
     305              :     void *requester_random, void *responder_random,
     306              :     const void *requester_opaque_data, size_t requester_opaque_data_size,
     307              :     void *responder_opaque_data, size_t *responder_opaque_data_size)
     308              : {
     309              :     bool result;
     310              :     libspdm_return_t status;
     311              :     libspdm_key_exchange_request_mine_t *spdm_request;
     312              :     size_t spdm_request_size;
     313              :     libspdm_key_exchange_response_max_t *spdm_response;
     314              :     size_t spdm_response_size;
     315              :     size_t dhe_key_size;
     316              :     size_t kem_encap_key_size;
     317              :     size_t kem_cipher_text_size;
     318              :     size_t req_key_exchage_size;
     319              :     size_t rsp_key_exchage_size;
     320              :     uint32_t measurement_summary_hash_size;
     321              :     uint32_t signature_size;
     322              :     uint32_t hmac_size;
     323              :     uint8_t *ptr;
     324              :     void *measurement_summary_hash;
     325              :     uint16_t opaque_length;
     326              :     uint8_t *signature;
     327              :     uint8_t *verify_data;
     328              :     void *dhe_context;
     329              :     void *kem_context;
     330              :     uint16_t req_session_id;
     331              :     uint16_t rsp_session_id;
     332              :     libspdm_session_info_t *session_info;
     333              :     size_t opaque_key_exchange_req_size;
     334              :     uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
     335              :     uint8_t *message;
     336              :     size_t message_size;
     337              :     size_t transport_header_size;
     338              :     uint8_t mut_auth_requested;
     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 :     spdm_context->connection_info.peer_used_cert_chain_slot_id = slot_id;
     395           92 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
     396           92 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     397           92 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     398            1 :         return status;
     399              :     }
     400           91 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
     401              :                     spdm_context->local_context.capability.transport_tail_size);
     402           91 :     spdm_request = (void *)(message + transport_header_size);
     403           91 :     spdm_request_size = message_size - transport_header_size -
     404           91 :                         spdm_context->local_context.capability.transport_tail_size;
     405              : 
     406           91 :     LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t));
     407           91 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     408           91 :     spdm_request->header.request_response_code = SPDM_KEY_EXCHANGE;
     409           91 :     spdm_request->header.param1 = measurement_hash_type;
     410           91 :     spdm_request->header.param2 = slot_id;
     411           91 :     if (requester_random_in == NULL) {
     412           90 :         if (!libspdm_get_random_number(SPDM_RANDOM_DATA_SIZE, spdm_request->random_data)) {
     413            0 :             libspdm_release_sender_buffer (spdm_context);
     414            0 :             return LIBSPDM_STATUS_LOW_ENTROPY;
     415              :         }
     416              :     } else {
     417            1 :         libspdm_copy_mem(spdm_request->random_data, sizeof(spdm_request->random_data),
     418              :                          requester_random_in, SPDM_RANDOM_DATA_SIZE);
     419              :     }
     420           91 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterRandomData (0x%x) - ",
     421              :                    SPDM_RANDOM_DATA_SIZE));
     422           91 :     LIBSPDM_INTERNAL_DUMP_DATA(spdm_request->random_data, SPDM_RANDOM_DATA_SIZE);
     423           91 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     424           91 :     if (requester_random != NULL) {
     425            1 :         libspdm_copy_mem(requester_random, SPDM_RANDOM_DATA_SIZE,
     426            1 :                          spdm_request->random_data, SPDM_RANDOM_DATA_SIZE);
     427              :     }
     428              : 
     429           91 :     spdm_request->req_session_id = req_session_id;
     430           91 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     431            3 :         spdm_request->session_policy = session_policy;
     432              :     } else {
     433           88 :         spdm_request->session_policy = 0;
     434              :     }
     435           91 :     spdm_request->reserved = 0;
     436              : 
     437           91 :     ptr = spdm_request->exchange_data;
     438           91 :     dhe_context = NULL;
     439           91 :     kem_context = NULL;
     440           91 :     if (spdm_context->connection_info.algorithm.kem_alg != 0) {
     441            0 :         kem_encap_key_size = libspdm_get_kem_encap_key_size(
     442              :             spdm_context->connection_info.algorithm.kem_alg);
     443            0 :         kem_cipher_text_size = libspdm_get_kem_cipher_text_size(
     444              :             spdm_context->connection_info.algorithm.kem_alg);
     445            0 :         kem_context = libspdm_secured_message_kem_new(
     446            0 :             spdm_context->connection_info.version,
     447              :             spdm_context->connection_info.algorithm.kem_alg, true);
     448            0 :         if (kem_context == NULL) {
     449            0 :             libspdm_release_sender_buffer (spdm_context);
     450            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     451              :         }
     452              : 
     453            0 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) + kem_encap_key_size);
     454            0 :         result = libspdm_secured_message_kem_generate_key(
     455              :             spdm_context->connection_info.algorithm.kem_alg,
     456              :             kem_context, ptr, &kem_encap_key_size);
     457            0 :         if (!result) {
     458            0 :             libspdm_secured_message_kem_free(
     459              :                 spdm_context->connection_info.algorithm.kem_alg, kem_context);
     460            0 :             libspdm_release_sender_buffer (spdm_context);
     461            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     462              :         }
     463            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterKey (0x%zx):\n", kem_encap_key_size));
     464            0 :         LIBSPDM_INTERNAL_DUMP_HEX(ptr, kem_encap_key_size);
     465            0 :         ptr += kem_encap_key_size;
     466            0 :         req_key_exchage_size = kem_encap_key_size;
     467            0 :         rsp_key_exchage_size = kem_cipher_text_size;
     468              :     } else {
     469          182 :         dhe_key_size = libspdm_get_dhe_pub_key_size(
     470           91 :             spdm_context->connection_info.algorithm.dhe_named_group);
     471           91 :         dhe_context = libspdm_secured_message_dhe_new(
     472           91 :             spdm_context->connection_info.version,
     473           91 :             spdm_context->connection_info.algorithm.dhe_named_group, true);
     474           91 :         if (dhe_context == NULL) {
     475            0 :             libspdm_release_sender_buffer (spdm_context);
     476            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     477              :         }
     478              : 
     479           91 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) + dhe_key_size);
     480           91 :         result = libspdm_secured_message_dhe_generate_key(
     481           91 :             spdm_context->connection_info.algorithm.dhe_named_group,
     482              :             dhe_context, ptr, &dhe_key_size);
     483           91 :         if (!result) {
     484            0 :             libspdm_secured_message_dhe_free(
     485            0 :                 spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
     486            0 :             libspdm_release_sender_buffer (spdm_context);
     487            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     488              :         }
     489           91 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterKey (0x%zx):\n", dhe_key_size));
     490           91 :         LIBSPDM_INTERNAL_DUMP_HEX(ptr, dhe_key_size);
     491           91 :         ptr += dhe_key_size;
     492           91 :         req_key_exchage_size = dhe_key_size;
     493           91 :         rsp_key_exchage_size = dhe_key_size;
     494              :     }
     495              : 
     496           91 :     if (requester_opaque_data != NULL) {
     497            1 :         LIBSPDM_ASSERT(requester_opaque_data_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
     498              : 
     499            1 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) +
     500              :                         req_key_exchage_size +
     501              :                         sizeof(uint16_t) + requester_opaque_data_size);
     502              : 
     503            1 :         libspdm_write_uint16(ptr, (uint16_t)requester_opaque_data_size);
     504            1 :         ptr += sizeof(uint16_t);
     505              : 
     506            1 :         libspdm_copy_mem(ptr,
     507            1 :                          (spdm_request_size - (sizeof(spdm_key_exchange_request_t) +
     508              :                                                req_key_exchage_size)),
     509              :                          requester_opaque_data, requester_opaque_data_size);
     510            1 :         opaque_key_exchange_req_size = requester_opaque_data_size;
     511              :     } else {
     512           90 :         opaque_key_exchange_req_size =
     513           90 :             libspdm_get_opaque_data_supported_version_data_size(spdm_context);
     514           90 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) +
     515              :                         req_key_exchage_size +
     516              :                         sizeof(uint16_t) + opaque_key_exchange_req_size);
     517              : 
     518           90 :         libspdm_write_uint16(ptr, (uint16_t)opaque_key_exchange_req_size);
     519           90 :         ptr += sizeof(uint16_t);
     520              : 
     521           90 :         libspdm_build_opaque_data_supported_version_data(
     522              :             spdm_context, &opaque_key_exchange_req_size, ptr);
     523              :     }
     524           91 :     ptr += opaque_key_exchange_req_size;
     525              : 
     526           91 :     spdm_request_size = (size_t)ptr - (size_t)spdm_request;
     527              : 
     528              :     /* -=[Send Request Phase]=- */
     529           91 :     status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size, spdm_request);
     530           91 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     531            2 :         libspdm_release_sender_buffer (spdm_context);
     532            2 :         goto free_exchange;
     533              :     }
     534           89 :     libspdm_release_sender_buffer (spdm_context);
     535           89 :     spdm_request = (void *)spdm_context->last_spdm_request;
     536              : 
     537              :     /* -=[Receive Response Phase]=- */
     538           89 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     539           89 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     540            1 :         goto free_exchange;
     541              :     }
     542           88 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
     543           88 :     spdm_response = (void *)(message);
     544           88 :     spdm_response_size = message_size;
     545              : 
     546           88 :     status = libspdm_receive_spdm_response(
     547              :         spdm_context, NULL, &spdm_response_size, (void **)&spdm_response);
     548           88 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     549            0 :         goto receive_done;
     550              :     }
     551              : 
     552              :     /* -=[Validate Response Phase]=- */
     553           88 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     554            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     555            0 :         goto receive_done;
     556              :     }
     557           88 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     558           46 :         status = libspdm_handle_error_response_main(
     559              :             spdm_context, NULL, &spdm_response_size,
     560              :             (void **)&spdm_response, SPDM_KEY_EXCHANGE,
     561              :             SPDM_KEY_EXCHANGE_RSP);
     562           46 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     563           45 :             goto receive_done;
     564              :         }
     565           42 :     } else if (spdm_response->header.request_response_code != SPDM_KEY_EXCHANGE_RSP) {
     566            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     567            1 :         goto receive_done;
     568              :     }
     569           42 :     if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     570            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     571            1 :         goto receive_done;
     572              :     }
     573           41 :     if (spdm_response_size < sizeof(spdm_key_exchange_response_t)) {
     574            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     575            0 :         goto receive_done;
     576              :     }
     577              : 
     578           41 :     if (!libspdm_is_capabilities_flag_supported(
     579              :             spdm_context, true,
     580              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     581              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     582           39 :         if (spdm_response->header.param1 != 0) {
     583            2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     584            2 :             goto receive_done;
     585              :         }
     586              :     }
     587           39 :     if (heartbeat_period != NULL) {
     588           35 :         *heartbeat_period = spdm_response->header.param1;
     589              :     }
     590              : 
     591           39 :     *req_slot_id_param = spdm_response->req_slot_id_param & 0xf;
     592           39 :     mut_auth_requested = spdm_response->mut_auth_requested & 0x7;
     593              : 
     594           39 :     if (mut_auth_requested != 0) {
     595           13 :         const bool mut_auth_cap_both = libspdm_is_capabilities_flag_supported(
     596              :             spdm_context, true,
     597              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP,
     598              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP);
     599           13 :         const bool cert_cap = libspdm_is_capabilities_flag_supported(
     600              :             spdm_context, true,
     601              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP,
     602              :             0);
     603           13 :         const bool pub_key_id_cap = libspdm_is_capabilities_flag_supported(
     604              :             spdm_context, true,
     605              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP,
     606              :             0);
     607              : 
     608           13 :         if (!mut_auth_cap_both) {
     609            1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     610            1 :             goto receive_done;
     611              :         }
     612           12 :         if ((mut_auth_requested != SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED) &&
     613              :             (mut_auth_requested !=
     614            7 :              SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST) &&
     615              :             (mut_auth_requested !=
     616              :              SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS)) {
     617            6 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     618            6 :             goto receive_done;
     619              :         }
     620              : 
     621            6 :         if (mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED) {
     622              :             /* Non-encapsulated flow.
     623              :              * Requester has either CERT_CAP or PUB_KEY_ID_CAP set. */
     624              : 
     625            2 :             if ((cert_cap && (*req_slot_id_param >= SPDM_MAX_SLOT_COUNT)) ||
     626            0 :                 (pub_key_id_cap && (*req_slot_id_param != 0xf))) {
     627            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     628            1 :                 goto receive_done;
     629              :             }
     630            1 :             if ((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
     631            0 :                 spdm_context->connection_info.multi_key_conn_req &&
     632            0 :                 (*req_slot_id_param != 0xf)) {
     633            0 :                 if ((spdm_context->local_context.local_key_usage_bit_mask[*req_slot_id_param] &
     634              :                      SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE) == 0) {
     635            0 :                     status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     636            0 :                     goto receive_done;
     637              :                 }
     638              :             }
     639              :         } else {
     640              :             /* Encapsulated flow. */
     641              : 
     642              :             /* If Responder has Requester's public key then it cannot use the encapsulated flow. */
     643            4 :             if (pub_key_id_cap) {
     644            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     645            1 :                 goto receive_done;
     646              :             }
     647              :             /* Encapsulated flow requires support for encapsulated messages by both endpoints. */
     648            3 :             if (!libspdm_is_encap_supported(spdm_context)) {
     649            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     650            1 :                 goto receive_done;
     651              :             }
     652              :         }
     653              :     }
     654              : 
     655           29 :     if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     656            0 :         signature_size = libspdm_get_pqc_asym_signature_size(
     657              :             spdm_context->connection_info.algorithm.pqc_asym_algo);
     658              :     } else {
     659           29 :         signature_size = libspdm_get_asym_signature_size(
     660              :             spdm_context->connection_info.algorithm.base_asym_algo);
     661              :     }
     662           29 :     measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
     663              :         spdm_context, true, measurement_hash_type);
     664           29 :     hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     665              : 
     666           29 :     if (libspdm_is_capabilities_flag_supported(
     667              :             spdm_context, true,
     668              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     669              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     670            1 :         hmac_size = 0;
     671              :     }
     672              : 
     673           29 :     if (spdm_response_size <
     674           29 :         sizeof(spdm_key_exchange_response_t) + rsp_key_exchage_size +
     675           29 :         measurement_summary_hash_size + sizeof(uint16_t) + signature_size + hmac_size) {
     676            4 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     677            4 :         goto receive_done;
     678              :     }
     679              : 
     680           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderRandomData (0x%x) - ", SPDM_RANDOM_DATA_SIZE));
     681           25 :     LIBSPDM_INTERNAL_DUMP_DATA(spdm_response->random_data, SPDM_RANDOM_DATA_SIZE);
     682           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     683           25 :     if (responder_random != NULL) {
     684            1 :         libspdm_copy_mem(responder_random, SPDM_RANDOM_DATA_SIZE,
     685            1 :                          spdm_response->random_data, SPDM_RANDOM_DATA_SIZE);
     686              :     }
     687              : 
     688           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderKey (0x%zx):\n", rsp_key_exchage_size));
     689           25 :     LIBSPDM_INTERNAL_DUMP_HEX(spdm_response->exchange_data, rsp_key_exchage_size);
     690              : 
     691           25 :     ptr = spdm_response->exchange_data;
     692           25 :     ptr += rsp_key_exchage_size;
     693              : 
     694           25 :     measurement_summary_hash = ptr;
     695           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "measurement_summary_hash (0x%x) - ",
     696              :                    measurement_summary_hash_size));
     697           25 :     LIBSPDM_INTERNAL_DUMP_DATA(measurement_summary_hash, measurement_summary_hash_size);
     698           25 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     699              : 
     700           25 :     ptr += measurement_summary_hash_size;
     701              : 
     702           25 :     opaque_length = libspdm_read_uint16((const uint8_t *)ptr);
     703           25 :     if (opaque_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
     704            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     705            1 :         goto receive_done;
     706              :     }
     707           24 :     ptr += sizeof(uint16_t);
     708           24 :     if (spdm_response_size <
     709           24 :         sizeof(spdm_key_exchange_response_t) + rsp_key_exchage_size +
     710           24 :         measurement_summary_hash_size + sizeof(uint16_t) +
     711           24 :         opaque_length + signature_size + hmac_size) {
     712            2 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     713            2 :         goto receive_done;
     714              :     }
     715           22 :     if (opaque_length != 0) {
     716           22 :         result = libspdm_process_general_opaque_data_check(spdm_context, opaque_length, ptr);
     717           22 :         if (!result) {
     718            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     719            0 :             goto receive_done;
     720              :         }
     721           22 :         status = libspdm_process_opaque_data_version_selection_data(
     722              :             spdm_context, opaque_length, ptr);
     723           22 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     724            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     725            0 :             goto receive_done;
     726              :         }
     727              :     }
     728              : 
     729           22 :     if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
     730            1 :         if (opaque_length >= *responder_opaque_data_size) {
     731            0 :             status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     732            0 :             goto receive_done;
     733              :         }
     734            1 :         libspdm_copy_mem(responder_opaque_data, *responder_opaque_data_size, ptr, opaque_length);
     735            1 :         *responder_opaque_data_size = opaque_length;
     736              :     }
     737              : 
     738           22 :     ptr += opaque_length;
     739              : 
     740           22 :     spdm_response_size = sizeof(spdm_key_exchange_response_t) +
     741           22 :                          rsp_key_exchage_size + measurement_summary_hash_size +
     742           22 :                          sizeof(uint16_t) + opaque_length + signature_size + hmac_size;
     743              : 
     744           22 :     rsp_session_id = spdm_response->rsp_session_id;
     745           22 :     *session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
     746           22 :     session_info = libspdm_assign_session_id(spdm_context, *session_id, false);
     747              : 
     748           22 :     if (session_info == NULL) {
     749            0 :         status = LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     750            0 :         goto receive_done;
     751              :     }
     752              : 
     753              :     /* -=[Process Response Phase]=- */
     754           22 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_request,
     755              :                                       spdm_request_size);
     756           22 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     757            0 :         libspdm_free_session_id(spdm_context, *session_id);
     758            0 :         goto receive_done;
     759              :     }
     760              : 
     761           22 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_response,
     762           22 :                                       spdm_response_size - signature_size - hmac_size);
     763           22 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     764            0 :         libspdm_free_session_id(spdm_context, *session_id);
     765            0 :         goto receive_done;
     766              :     }
     767              : 
     768           22 :     signature = ptr;
     769           22 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature (0x%x):\n", signature_size));
     770           22 :     LIBSPDM_INTERNAL_DUMP_HEX(signature, signature_size);
     771           22 :     ptr += signature_size;
     772           22 :     result = libspdm_verify_key_exchange_rsp_signature(
     773              :         spdm_context, session_info, signature, signature_size);
     774           22 :     if (!result) {
     775            2 :         libspdm_free_session_id(spdm_context, *session_id);
     776            2 :         status = LIBSPDM_STATUS_VERIF_FAIL;
     777            2 :         goto receive_done;
     778              :     }
     779              : 
     780           20 :     status = libspdm_append_message_k(spdm_context, session_info, true, signature, signature_size);
     781           20 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     782            0 :         libspdm_free_session_id(spdm_context, *session_id);
     783            0 :         goto receive_done;
     784              :     }
     785              : 
     786           20 :     if (spdm_context->connection_info.algorithm.kem_alg != 0) {
     787            0 :         result = libspdm_secured_message_kem_decapsulate(
     788              :             spdm_context->connection_info.algorithm.kem_alg,
     789            0 :             kem_context, spdm_response->exchange_data, kem_cipher_text_size,
     790              :             session_info->secured_message_context);
     791            0 :         libspdm_secured_message_kem_free(
     792              :             spdm_context->connection_info.algorithm.kem_alg, kem_context);
     793            0 :         kem_context = NULL;
     794              :     } else {
     795           20 :         result = libspdm_secured_message_dhe_compute_key(
     796           20 :             spdm_context->connection_info.algorithm.dhe_named_group,
     797           20 :             dhe_context, spdm_response->exchange_data, dhe_key_size,
     798              :             session_info->secured_message_context);
     799           20 :         libspdm_secured_message_dhe_free(
     800           20 :             spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
     801           20 :         dhe_context = NULL;
     802              :     }
     803           20 :     if (!result) {
     804            0 :         libspdm_free_session_id(spdm_context, *session_id);
     805            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     806            0 :         goto receive_done;
     807              :     }
     808              : 
     809           20 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
     810              :                    *session_id));
     811           20 :     result = libspdm_calculate_th1_hash(spdm_context, session_info, true, th1_hash_data);
     812           20 :     if (!result) {
     813            0 :         libspdm_free_session_id(spdm_context, *session_id);
     814            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     815            0 :         goto receive_done;
     816              :     }
     817           20 :     result = libspdm_generate_session_handshake_key(
     818              :         session_info->secured_message_context, th1_hash_data);
     819           20 :     if (!result) {
     820            0 :         libspdm_free_session_id(spdm_context, *session_id);
     821            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     822            0 :         goto receive_done;
     823              :     }
     824              : 
     825           20 :     if (!libspdm_is_capabilities_flag_supported(
     826              :             spdm_context, true,
     827              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     828              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     829           19 :         verify_data = ptr;
     830           19 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%x):\n", hmac_size));
     831           19 :         LIBSPDM_INTERNAL_DUMP_HEX(verify_data, hmac_size);
     832           19 :         result = libspdm_verify_key_exchange_rsp_hmac(
     833              :             spdm_context, session_info, verify_data, hmac_size);
     834           19 :         if (!result) {
     835            0 :             libspdm_free_session_id(spdm_context, *session_id);
     836            0 :             status = LIBSPDM_STATUS_VERIF_FAIL;
     837            0 :             goto receive_done;
     838              :         }
     839           19 :         ptr += hmac_size;
     840              : 
     841           19 :         status = libspdm_append_message_k(spdm_context, session_info, true, verify_data, hmac_size);
     842           19 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     843            0 :             libspdm_free_session_id(spdm_context, *session_id);
     844            0 :             goto receive_done;
     845              :         }
     846              :     }
     847              : 
     848           20 :     if (measurement_hash != NULL) {
     849           20 :         libspdm_copy_mem(measurement_hash, measurement_summary_hash_size,
     850              :                          measurement_summary_hash, measurement_summary_hash_size);
     851              :     }
     852           20 :     session_info->heartbeat_period = spdm_response->header.param1;
     853           20 :     session_info->mut_auth_requested = mut_auth_requested;
     854           20 :     session_info->session_policy = session_policy;
     855              : 
     856              :     /* -=[Update State Phase]=- */
     857           20 :     libspdm_secured_message_set_session_state(
     858              :         session_info->secured_message_context, LIBSPDM_SESSION_STATE_HANDSHAKING);
     859              : 
     860              :     /* -=[Log Message Phase]=- */
     861              :     #if LIBSPDM_ENABLE_MSG_LOG
     862           20 :     libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     863              :     #endif /* LIBSPDM_ENABLE_MSG_LOG */
     864              : 
     865           20 :     status = LIBSPDM_STATUS_SUCCESS;
     866              : 
     867           88 : receive_done:
     868           88 :     libspdm_release_receiver_buffer (spdm_context);
     869           91 : free_exchange:
     870           91 :     if (dhe_context != NULL) {
     871           71 :         libspdm_secured_message_dhe_free(
     872           71 :             spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
     873              :     }
     874           91 :     if (kem_context != NULL) {
     875            0 :         libspdm_secured_message_kem_free(
     876              :             spdm_context->connection_info.algorithm.kem_alg, kem_context);
     877              :     }
     878           91 :     return status;
     879              : }
     880              : 
     881           93 : libspdm_return_t libspdm_send_receive_key_exchange(
     882              :     libspdm_context_t *spdm_context, uint8_t measurement_hash_type,
     883              :     uint8_t slot_id, uint8_t session_policy, uint32_t *session_id,
     884              :     uint8_t *heartbeat_period,
     885              :     uint8_t *req_slot_id_param, void *measurement_hash)
     886              : {
     887              :     size_t retry;
     888              :     uint64_t retry_delay_time;
     889              :     libspdm_return_t status;
     890              : 
     891           93 :     spdm_context->crypto_request = true;
     892           93 :     retry = spdm_context->retry_times;
     893           93 :     retry_delay_time = spdm_context->retry_delay_time;
     894              :     do {
     895           94 :         status = libspdm_try_send_receive_key_exchange(
     896              :             spdm_context, measurement_hash_type, slot_id, session_policy,
     897              :             session_id, heartbeat_period, req_slot_id_param,
     898              :             measurement_hash,
     899              :             NULL, NULL, NULL, NULL, 0, NULL, NULL);
     900           94 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     901           91 :             return status;
     902              :         }
     903              : 
     904            3 :         libspdm_sleep(retry_delay_time);
     905            3 :     } while (retry-- != 0);
     906              : 
     907            2 :     return status;
     908              : }
     909              : 
     910            1 : libspdm_return_t libspdm_send_receive_key_exchange_ex(
     911              :     libspdm_context_t *spdm_context, uint8_t measurement_hash_type,
     912              :     uint8_t slot_id, uint8_t session_policy, uint32_t *session_id,
     913              :     uint8_t *heartbeat_period,
     914              :     uint8_t *req_slot_id_param, void *measurement_hash,
     915              :     const void *requester_random_in,
     916              :     void *requester_random, void *responder_random,
     917              :     const void *requester_opaque_data,
     918              :     size_t requester_opaque_data_size,
     919              :     void *responder_opaque_data,
     920              :     size_t *responder_opaque_data_size)
     921              : {
     922              :     size_t retry;
     923              :     uint64_t retry_delay_time;
     924              :     libspdm_return_t status;
     925              : 
     926            1 :     spdm_context->crypto_request = true;
     927            1 :     retry = spdm_context->retry_times;
     928            1 :     retry_delay_time = spdm_context->retry_delay_time;
     929              :     do {
     930            1 :         status = libspdm_try_send_receive_key_exchange(
     931              :             spdm_context, measurement_hash_type, slot_id, session_policy,
     932              :             session_id, heartbeat_period, req_slot_id_param,
     933              :             measurement_hash, requester_random_in,
     934              :             requester_random, responder_random,
     935              :             requester_opaque_data, requester_opaque_data_size,
     936              :             responder_opaque_data, responder_opaque_data_size);
     937            1 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     938            1 :             return status;
     939              :         }
     940              : 
     941            0 :         libspdm_sleep(retry_delay_time);
     942            0 :     } while (retry-- != 0);
     943              : 
     944            0 :     return status;
     945              : }
     946              : 
     947              : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
        

Generated by: LCOV version 2.0-1