Code coverage report for DMTF/libspdm
Current view: top level - library/spdm_requester_lib - libspdm_req_key_exchange.c (source / functions) Coverage Total Hit
Test: 36148b912f76d231c18d216d6dee5c0858575bb1 Lines: 77.6 % 406 315
Test Date: 2026-10-25 08:40:22 Functions: 100.0 % 5 5
Branches: 70.3 % 182 128

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

Generated by: LCOV version 2.0-1