LCOV - code coverage report
Current view: top level - library/spdm_responder_lib - libspdm_rsp_key_exchange_rsp.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 76.2 % 366 279
Test Date: 2026-09-13 08:13:44 Functions: 100.0 % 4 4

            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_responder_lib.h"
       8              : #include "internal/libspdm_secured_message_lib.h"
       9              : 
      10              : #if LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
      11              : 
      12              : #if (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP)
      13            1 : static void init_encap_state(libspdm_context_t *spdm_context, uint8_t mut_auth_requested)
      14              : {
      15            1 :     spdm_context->encap_context.session_id = INVALID_SESSION_ID;
      16            1 :     spdm_context->encap_context.current_request_op_code = 0x00;
      17            1 :     if (mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS) {
      18            0 :         spdm_context->encap_context.current_request_op_code = SPDM_GET_DIGESTS;
      19              :     }
      20            1 :     spdm_context->encap_context.request_id = 0;
      21            1 :     spdm_context->encap_context.last_encap_request_size = 0;
      22            1 :     libspdm_zero_mem(&spdm_context->encap_context.last_encap_request_header,
      23              :                      sizeof(spdm_context->encap_context.last_encap_request_header));
      24            1 :     spdm_context->mut_auth_cert_chain_buffer_size = 0;
      25              : 
      26              :     /* Clear cache. */
      27            1 :     libspdm_reset_message_mut_b(spdm_context);
      28            1 :     libspdm_reset_message_mut_c(spdm_context);
      29              : 
      30              :     /* Possible Sequence:
      31              :      * 2. Session Mutual Auth: (spdm_context->last_spdm_request_session_id_valid)
      32              :      *    2.1 GET_DIGEST/GET_CERTIFICATE
      33              :      *        (MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST or MUT_AUTH_REQUESTED_WITH_GET_DIGESTS,
      34              :      *         encap_context.req_slot_id must not be 0xFF)
      35              :      *    2.2 N/A (REQUEST_FLAGS_PUB_KEY_ID_CAP, MUT_AUTH_REQUESTED, encap_context.req_slot_id may
      36              :      *             or may not be 0xFF)*/
      37              : 
      38            1 :     libspdm_zero_mem(spdm_context->encap_context.request_op_code_sequence,
      39              :                      sizeof(spdm_context->encap_context.request_op_code_sequence));
      40              : 
      41              :     /* Session mutual authentication. */
      42            1 :     if (libspdm_is_capabilities_flag_supported(
      43              :             spdm_context, false,
      44              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP, 0)) {
      45            0 :         LIBSPDM_ASSERT(spdm_context->encap_context.req_slot_id == 0xFF);
      46            0 :         LIBSPDM_ASSERT(mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED);
      47              :     } else {
      48            1 :         LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer != NULL);
      49            1 :         LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer_max_size != 0);
      50              :     }
      51              : 
      52            1 :     switch (mut_auth_requested) {
      53            0 :     case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED:
      54              :         /* No encapsulation is required. */
      55            0 :         spdm_context->encap_context.request_op_code_count = 0;
      56            0 :         break;
      57            1 :     case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST:
      58              :     case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS:
      59            1 :         LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id != 0xFF);
      60            1 :         spdm_context->encap_context.request_op_code_count = 2;
      61            1 :         spdm_context->encap_context.request_op_code_sequence[0] = SPDM_GET_DIGESTS;
      62            1 :         spdm_context->encap_context.request_op_code_sequence[1] = SPDM_GET_CERTIFICATE;
      63            1 :         break;
      64            0 :     default:
      65            0 :         LIBSPDM_ASSERT (false);
      66            0 :         spdm_context->encap_context.request_op_code_count = 0;
      67            0 :         break;
      68              :     }
      69              : 
      70            1 :     if (spdm_context->encap_context.request_op_code_count != 0) {
      71              :         /* Change state only if encapsulation is required. */
      72            1 :         spdm_context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
      73              :     }
      74            1 : }
      75              : #endif /* (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) */
      76              : 
      77           14 : bool libspdm_generate_key_exchange_rsp_hmac(libspdm_context_t *spdm_context,
      78              :                                             libspdm_session_info_t *session_info,
      79              :                                             uint8_t *hmac)
      80              : {
      81              :     uint8_t hmac_data[LIBSPDM_MAX_HASH_SIZE];
      82              :     size_t hash_size;
      83              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      84              :     uint8_t slot_id;
      85              :     uint8_t *cert_chain_buffer;
      86              :     size_t cert_chain_buffer_size;
      87              :     uint8_t *th_curr_data;
      88              :     size_t th_curr_data_size;
      89              :     libspdm_th_managed_buffer_t th_curr;
      90              :     uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
      91              : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
      92              :     bool result;
      93              : 
      94           14 :     hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
      95              : 
      96              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      97              :     slot_id = session_info->local_used_cert_chain_slot_id;
      98              :     LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
      99              :     if (slot_id == 0xFF) {
     100              :         result = libspdm_get_local_public_key_buffer(
     101              :             spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
     102              :         if (!result) {
     103              :             return false;
     104              :         }
     105              :     } else {
     106              :         libspdm_get_local_cert_chain_buffer(
     107              :             spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
     108              :     }
     109              : 
     110              :     result = libspdm_calculate_th_for_exchange(
     111              :         spdm_context, session_info, cert_chain_buffer, cert_chain_buffer_size, &th_curr);
     112              :     if (!result) {
     113              :         return false;
     114              :     }
     115              :     th_curr_data = libspdm_get_managed_buffer(&th_curr);
     116              :     th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
     117              : 
     118              :     result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
     119              :                                th_curr_data, th_curr_data_size, hash_data);
     120              :     if (!result) {
     121              :         return false;
     122              :     }
     123              : 
     124              :     result = libspdm_hmac_all_with_response_finished_key(
     125              :         session_info->secured_message_context, hash_data, hash_size, hmac_data);
     126              :     if (!result) {
     127              :         return false;
     128              :     }
     129              : #else
     130           14 :     result = libspdm_calculate_th_hmac_for_exchange_rsp(
     131              :         spdm_context, session_info, &hash_size, hmac_data);
     132           14 :     if (!result) {
     133            0 :         return false;
     134              :     }
     135              : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
     136           14 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
     137           14 :     LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
     138           14 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     139           14 :     libspdm_copy_mem(hmac, hash_size, hmac_data, hash_size);
     140              : 
     141           14 :     return true;
     142              : }
     143              : 
     144           17 : bool libspdm_generate_key_exchange_rsp_signature(libspdm_context_t *spdm_context,
     145              :                                                  libspdm_session_info_t *session_info,
     146              :                                                  uint8_t slot_id,
     147              :                                                  uint8_t *signature)
     148              : {
     149              :     bool result;
     150              :     size_t signature_size;
     151              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     152              :     uint8_t *th_curr_data;
     153              :     size_t th_curr_data_size;
     154              :     libspdm_th_managed_buffer_t th_curr;
     155              :     const uint8_t *cert_chain_buffer;
     156              :     size_t cert_chain_buffer_size;
     157              : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
     158              : #if ((LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) && (LIBSPDM_DEBUG_BLOCK_ENABLE)) || \
     159              :     !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT)
     160              :     uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
     161              : #endif
     162              : #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
     163              :     size_t hash_size;
     164              : 
     165           17 :     hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     166              : #endif
     167              : 
     168           17 :     if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     169            0 :         signature_size = libspdm_get_pqc_asym_signature_size(
     170              :             spdm_context->connection_info.algorithm.pqc_asym_algo);
     171              :     } else {
     172           17 :         signature_size = libspdm_get_asym_signature_size(
     173              :             spdm_context->connection_info.algorithm.base_asym_algo);
     174              :     }
     175              : 
     176              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     177              :     LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
     178              :     if (slot_id == 0xFF) {
     179              :         result = libspdm_get_local_public_key_buffer(
     180              :             spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
     181              :         if (!result) {
     182              :             return false;
     183              :         }
     184              :     } else {
     185              :         libspdm_get_local_cert_chain_buffer(
     186              :             spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
     187              :     }
     188              : 
     189              :     result = libspdm_calculate_th_for_exchange(
     190              :         spdm_context, session_info, cert_chain_buffer, cert_chain_buffer_size, &th_curr);
     191              :     if (!result) {
     192              :         return false;
     193              :     }
     194              :     th_curr_data = libspdm_get_managed_buffer(&th_curr);
     195              :     th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
     196              : 
     197              :     /* Debug code only - required for debug print of th_curr hash below*/
     198              :     LIBSPDM_DEBUG_CODE(
     199              :         if (!libspdm_hash_all(
     200              :                 spdm_context->connection_info.algorithm.base_hash_algo,
     201              :                 th_curr_data, th_curr_data_size, hash_data)) {
     202              :         return false;
     203              :     }
     204              :         );
     205              : #else
     206           17 :     result = libspdm_calculate_th_hash_for_exchange(
     207              :         spdm_context, session_info, &hash_size, hash_data);
     208           17 :     if (!result) {
     209            0 :         return false;
     210              :     }
     211              : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
     212           17 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hash - "));
     213           17 :     LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size);
     214           17 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     215              : 
     216              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     217              :     result = libspdm_responder_data_sign(
     218              :         spdm_context,
     219              :         spdm_context->connection_info.version,
     220              :         libspdm_slot_id_to_key_pair_id(spdm_context, slot_id, false),
     221              :         SPDM_KEY_EXCHANGE_RSP,
     222              :         spdm_context->connection_info.algorithm.base_asym_algo,
     223              :         spdm_context->connection_info.algorithm.pqc_asym_algo,
     224              :         spdm_context->connection_info.algorithm.base_hash_algo,
     225              :         false, th_curr_data, th_curr_data_size, signature, &signature_size);
     226              : #else
     227           34 :     result = libspdm_responder_data_sign(
     228              :         spdm_context,
     229           17 :         spdm_context->connection_info.version,
     230           17 :         libspdm_slot_id_to_key_pair_id(spdm_context, slot_id, false),
     231              :         SPDM_KEY_EXCHANGE_RSP,
     232              :         spdm_context->connection_info.algorithm.base_asym_algo,
     233              :         spdm_context->connection_info.algorithm.pqc_asym_algo,
     234              :         spdm_context->connection_info.algorithm.base_hash_algo,
     235              :         true, hash_data, hash_size, signature, &signature_size);
     236              : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
     237           17 :     if (result) {
     238           17 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature - "));
     239           17 :         LIBSPDM_INTERNAL_DUMP_DATA(signature, signature_size);
     240           17 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     241              :     }
     242           17 :     return result;
     243              : }
     244              : 
     245           43 : libspdm_return_t libspdm_get_response_key_exchange(libspdm_context_t *spdm_context,
     246              :                                                    size_t request_size,
     247              :                                                    const void *request,
     248              :                                                    size_t *response_size,
     249              :                                                    void *response)
     250              : {
     251              :     const spdm_key_exchange_request_t *spdm_request;
     252              :     spdm_key_exchange_response_t *spdm_response;
     253              :     size_t dhe_key_size;
     254              :     size_t kem_encap_key_size;
     255              :     size_t kem_cipher_text_size;
     256              :     size_t req_key_exchange_size;
     257              :     size_t rsp_key_exchange_size;
     258              :     uint32_t measurement_summary_hash_size;
     259              :     uint32_t signature_size;
     260              :     uint32_t hmac_size;
     261              :     uint8_t *ptr;
     262              :     const uint8_t *req_opaque_data;
     263              :     uint8_t *rsp_opaque_data;
     264              :     uint16_t opaque_data_length;
     265              :     bool result;
     266              :     uint8_t slot_id;
     267              :     uint32_t session_id;
     268              :     void *dhe_context;
     269              :     void *kem_context;
     270              :     libspdm_session_info_t *session_info;
     271              :     size_t total_size;
     272              :     uint16_t req_session_id;
     273              :     uint16_t rsp_session_id;
     274              :     libspdm_return_t status;
     275              :     size_t opaque_key_exchange_rsp_size;
     276              :     bool use_default_opaque_data;
     277              :     uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
     278              :     spdm_version_number_t secured_message_version;
     279           43 :     uint8_t peer_aead_limit_exponent = SECURED_MESSAGE_AEAD_LIMIT_EXPONENT_DEFAULT;
     280              : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
     281              :     uint8_t req_slot_id;
     282              :     uint8_t mut_auth_requested;
     283              :     bool mandatory_mut_auth;
     284              : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
     285              : 
     286           43 :     spdm_request = request;
     287              : 
     288              :     /* -=[Check Parameters Phase]=- */
     289           43 :     LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_KEY_EXCHANGE);
     290              : 
     291           43 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     292            0 :         return libspdm_generate_error_response(spdm_context,
     293              :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     294              :                                                SPDM_KEY_EXCHANGE,
     295              :                                                response_size, response);
     296              :     }
     297              : 
     298           43 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
     299            0 :         return libspdm_generate_error_response(spdm_context,
     300              :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
     301              :                                                response_size, response);
     302              :     }
     303           43 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
     304            3 :         return libspdm_responder_handle_response_state(
     305              :             spdm_context,
     306            3 :             spdm_request->header.request_response_code,
     307              :             response_size, response);
     308              :     }
     309           40 :     if (!libspdm_is_capabilities_flag_supported(
     310              :             spdm_context, false,
     311              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
     312              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
     313            0 :         return libspdm_generate_error_response(
     314              :             spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     315              :             SPDM_KEY_EXCHANGE, response_size, response);
     316              :     }
     317              : 
     318              :     /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
     319              :      * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
     320              :      */
     321           40 :     if (!libspdm_is_capabilities_flag_supported(
     322              :             spdm_context, false,
     323              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
     324              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
     325            0 :         return libspdm_generate_error_response(
     326              :             spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
     327              :             SPDM_KEY_EXCHANGE, response_size, response);
     328              :     }
     329              : 
     330           40 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     331            1 :         return libspdm_generate_error_response(spdm_context,
     332              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
     333              :                                                0, response_size, response);
     334              :     }
     335           39 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     336            7 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     337              :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
     338            0 :             return libspdm_generate_error_response(
     339              :                 spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
     340              :                 0, response_size, response);
     341              :         }
     342              :     }
     343           39 :     if (spdm_context->last_spdm_request_session_id_valid) {
     344            0 :         return libspdm_generate_error_response(spdm_context,
     345              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
     346              :                                                0, response_size, response);
     347              :     }
     348              : 
     349           39 :     if (spdm_request->header.param1 > 0) {
     350            4 :         if (!libspdm_is_capabilities_flag_supported(
     351              :                 spdm_context, false,
     352            3 :                 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) ||
     353            3 :             (spdm_context->connection_info.algorithm.measurement_spec == 0) ||
     354            3 :             (spdm_context->connection_info.algorithm.measurement_hash_algo == 0) ) {
     355            1 :             return libspdm_generate_error_response(
     356              :                 spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
     357              :                 0, response_size, response);
     358              :         }
     359              :     }
     360              : 
     361           38 :     slot_id = spdm_request->header.param2;
     362              : 
     363           38 :     if (libspdm_is_capabilities_flag_supported(
     364              :             spdm_context, false,
     365              :             0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP)) {
     366           36 :         if (slot_id >= SPDM_MAX_SLOT_COUNT) {
     367            1 :             return libspdm_generate_error_response(spdm_context,
     368              :                                                    SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     369              :                                                    response_size, response);
     370              :         }
     371           35 :         if (spdm_context->local_context.local_cert_chain_provision[slot_id] == NULL) {
     372            0 :             return libspdm_generate_error_response(spdm_context,
     373              :                                                    SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     374              :                                                    response_size, response);
     375              :         }
     376              :     } else {
     377            2 :         if (slot_id != 0xff) {
     378            1 :             return libspdm_generate_error_response(spdm_context,
     379              :                                                    SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     380              :                                                    response_size, response);
     381              :         }
     382            1 :         if (spdm_context->local_context.local_public_key_provision == NULL) {
     383            0 :             return libspdm_generate_error_response(spdm_context,
     384              :                                                    SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     385              :                                                    response_size, response);
     386              :         }
     387              :     }
     388              : 
     389           36 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     390            3 :         if (spdm_context->connection_info.multi_key_conn_rsp && (slot_id != 0xff)) {
     391            1 :             if ((spdm_context->local_context.local_key_usage_bit_mask[slot_id] &
     392              :                  SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE) == 0) {
     393            1 :                 return libspdm_generate_error_response(
     394              :                     spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     395              :             }
     396              :         }
     397              : 
     398            2 :         if ((spdm_request->session_policy &
     399              :              SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY) != 0) {
     400            1 :             if (!libspdm_is_capabilities_flag_supported(
     401              :                     spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EVENT_CAP)) {
     402            0 :                 return libspdm_generate_error_response(spdm_context,
     403              :                                                        SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     404              :                                                        response_size, response);
     405              :             }
     406              :         }
     407              :     }
     408              : 
     409           35 :     if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     410            0 :         signature_size = libspdm_get_pqc_asym_signature_size(
     411              :             spdm_context->connection_info.algorithm.pqc_asym_algo);
     412              :     } else {
     413           35 :         signature_size = libspdm_get_asym_signature_size(
     414              :             spdm_context->connection_info.algorithm.base_asym_algo);
     415              :     }
     416           35 :     hmac_size = libspdm_get_hash_size(
     417              :         spdm_context->connection_info.algorithm.base_hash_algo);
     418           35 :     if (spdm_context->connection_info.algorithm.kem_alg != 0) {
     419            0 :         kem_encap_key_size = libspdm_get_kem_encap_key_size(
     420              :             spdm_context->connection_info.algorithm.kem_alg);
     421            0 :         kem_cipher_text_size = libspdm_get_kem_cipher_text_size(
     422              :             spdm_context->connection_info.algorithm.kem_alg);
     423            0 :         req_key_exchange_size = kem_encap_key_size;
     424            0 :         rsp_key_exchange_size = kem_cipher_text_size;
     425              :     } else {
     426           70 :         dhe_key_size = libspdm_get_dhe_pub_key_size(
     427           35 :             spdm_context->connection_info.algorithm.dhe_named_group);
     428           35 :         req_key_exchange_size = dhe_key_size;
     429           35 :         rsp_key_exchange_size = dhe_key_size;
     430              :     }
     431           35 :     measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
     432           35 :         spdm_context, false, spdm_request->header.param1);
     433              : 
     434           35 :     if ((measurement_summary_hash_size == 0) &&
     435           33 :         (spdm_request->header.param1 != SPDM_KEY_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH)) {
     436            1 :         return libspdm_generate_error_response(spdm_context,
     437              :                                                SPDM_ERROR_CODE_INVALID_REQUEST,
     438              :                                                0, response_size, response);
     439              :     }
     440           34 :     if (request_size < sizeof(spdm_key_exchange_request_t) + req_key_exchange_size +
     441              :         sizeof(uint16_t)) {
     442            1 :         return libspdm_generate_error_response(spdm_context,
     443              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     444              :                                                response_size, response);
     445              :     }
     446           33 :     opaque_data_length = libspdm_read_uint16((const uint8_t *)request +
     447           33 :                                              sizeof(spdm_key_exchange_request_t) +
     448              :                                              req_key_exchange_size);
     449           33 :     if (request_size < sizeof(spdm_key_exchange_request_t) + req_key_exchange_size +
     450           33 :         sizeof(uint16_t) + opaque_data_length) {
     451            0 :         return libspdm_generate_error_response(spdm_context,
     452              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     453              :                                                response_size, response);
     454              :     }
     455           33 :     request_size = sizeof(spdm_key_exchange_request_t) + req_key_exchange_size +
     456           33 :                    sizeof(uint16_t) + opaque_data_length;
     457              : 
     458           33 :     if (opaque_data_length != 0) {
     459           33 :         req_opaque_data = (const uint8_t *)request + sizeof(spdm_key_exchange_request_t) +
     460           33 :                           req_key_exchange_size + sizeof(uint16_t);
     461              : 
     462              :         /*
     463              :          * Here allows integrator generate own opaque data for Key Exchange Response.
     464              :          * If libspdm_key_exchange_rsp_opaque_data() returns false,
     465              :          * libspdm will generate version selection opaque data.
     466              :          */
     467           33 :         opaque_key_exchange_rsp_size = *response_size - sizeof(spdm_key_exchange_response_t) -
     468           33 :                                        rsp_key_exchange_size - measurement_summary_hash_size -
     469           33 :                                        sizeof(uint16_t) - signature_size - hmac_size;
     470              : 
     471           33 :         use_default_opaque_data = false;
     472           33 :         result = libspdm_key_exchange_rsp_opaque_data(
     473           33 :             spdm_context, spdm_request->header.spdm_version,
     474           33 :             spdm_request->header.param1, slot_id, spdm_request->session_policy,
     475              :             req_opaque_data, opaque_data_length, NULL,
     476              :             &opaque_key_exchange_rsp_size);
     477           33 :         if (!result) {
     478           32 :             use_default_opaque_data = true;
     479           32 :             opaque_key_exchange_rsp_size =
     480           32 :                 libspdm_get_opaque_data_version_selection_data_size(spdm_context);
     481              :         }
     482              : 
     483           33 :         if (use_default_opaque_data) {
     484           32 :             result = libspdm_process_general_opaque_data_check(spdm_context, opaque_data_length,
     485              :                                                                req_opaque_data);
     486           32 :             if (!result) {
     487            0 :                 return libspdm_generate_error_response(spdm_context,
     488              :                                                        SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     489              :                                                        response_size, response);
     490              :             }
     491           32 :             status = libspdm_process_opaque_data_supported_version_data(
     492              :                 spdm_context, opaque_data_length, req_opaque_data, &secured_message_version);
     493           32 :             if (LIBSPDM_STATUS_IS_ERROR(status)) {
     494            0 :                 return libspdm_generate_error_response(spdm_context,
     495              :                                                        SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     496              :                                                        response_size, response);
     497              :             }
     498              :             /* DSP0277 1.3: reserve room for this Responder's AEADlimitOE. The size helper returns 0
     499              :              * unless the negotiated secured message version is 1.3 or later. */
     500           32 :             opaque_key_exchange_rsp_size +=
     501           32 :                 libspdm_get_opaque_data_aead_limit_element_size(spdm_context,
     502              :                                                                 secured_message_version);
     503              :         } else {
     504              :             /* use response buffer to temporarily store opaque data */
     505            1 :             rsp_opaque_data = (uint8_t *)response;
     506            1 :             result = libspdm_key_exchange_rsp_opaque_data(
     507            1 :                 spdm_context, spdm_request->header.spdm_version,
     508            1 :                 spdm_request->header.param1, slot_id, spdm_request->session_policy,
     509              :                 req_opaque_data, opaque_data_length, rsp_opaque_data,
     510              :                 &opaque_key_exchange_rsp_size);
     511            1 :             if (!result) {
     512            0 :                 return libspdm_generate_error_response(spdm_context,
     513              :                                                        SPDM_ERROR_CODE_UNSPECIFIED, 0,
     514              :                                                        response_size, response);
     515              :             }
     516              :             /*
     517              :              * parse responder opaque data from integrator
     518              :              * to get secured_message_version.
     519              :              */
     520            1 :             status = libspdm_process_opaque_data_version_selection_data(
     521              :                 spdm_context, opaque_key_exchange_rsp_size,
     522              :                 rsp_opaque_data, &secured_message_version);
     523            1 :             if (LIBSPDM_STATUS_IS_ERROR(status)) {
     524            0 :                 return libspdm_generate_error_response(spdm_context,
     525              :                                                        SPDM_ERROR_CODE_UNSPECIFIED, 0,
     526              :                                                        response_size, response);
     527              :             }
     528              :         }
     529              :         /* DSP0277 1.3: read the Requester's AEAD limit from the request (absent -> default 64).
     530              :          * This is independent of whether the Responder builds default or custom response opaque
     531              :          * data, so it runs for both paths. */
     532           33 :         status = libspdm_process_opaque_data_aead_limit(
     533              :             spdm_context, secured_message_version, opaque_data_length, req_opaque_data,
     534              :             &peer_aead_limit_exponent);
     535           33 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     536            0 :             return libspdm_generate_error_response(spdm_context,
     537              :                                                    SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     538              :                                                    response_size, response);
     539              :         }
     540              :     } else {
     541            0 :         secured_message_version = 0;
     542            0 :         opaque_key_exchange_rsp_size = 0;
     543            0 :         req_opaque_data = NULL;
     544              :     }
     545              : 
     546           33 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
     547           33 :                                                   spdm_request->header.request_response_code);
     548              : 
     549           33 :     if (libspdm_is_capabilities_flag_supported(
     550              :             spdm_context, false,
     551              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     552              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     553            3 :         hmac_size = 0;
     554              :     }
     555              : 
     556           33 :     req_session_id = spdm_request->req_session_id;
     557           33 :     rsp_session_id = libspdm_allocate_rsp_session_id(spdm_context, false);
     558           33 :     if (rsp_session_id == ((INVALID_SESSION_ID & 0xFFFF0000) >> 16)) {
     559            0 :         return libspdm_generate_error_response(
     560              :             spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
     561              :             response_size, response);
     562              :     }
     563           33 :     session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
     564           33 :     session_info = libspdm_assign_session_id(spdm_context, session_id, secured_message_version,
     565              :                                              false);
     566           33 :     if (session_info == NULL) {
     567            0 :         return libspdm_generate_error_response(
     568              :             spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
     569              :             response_size, response);
     570              :     }
     571              : 
     572              :     /* DSP0277 1.3: program the session's AEAD limit (min of local and peer) when secured message
     573              :      * version 1.3 was negotiated. */
     574           33 :     if (libspdm_get_version_from_version_number(secured_message_version) >=
     575              :         SECURED_SPDM_VERSION_13) {
     576            1 :         libspdm_apply_aead_limit_to_session(spdm_context, session_info,
     577              :                                             peer_aead_limit_exponent);
     578              :     }
     579              : 
     580           33 :     total_size = sizeof(spdm_key_exchange_response_t) + rsp_key_exchange_size +
     581           33 :                  measurement_summary_hash_size + sizeof(uint16_t) +
     582           33 :                  opaque_key_exchange_rsp_size + signature_size + hmac_size;
     583              : 
     584           33 :     LIBSPDM_ASSERT(*response_size >= total_size);
     585           33 :     *response_size = total_size;
     586           33 :     libspdm_zero_mem(response, *response_size);
     587           33 :     spdm_response = response;
     588              : 
     589           33 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     590           33 :     spdm_response->header.request_response_code = SPDM_KEY_EXCHANGE_RSP;
     591              : 
     592           33 :     if (libspdm_is_capabilities_flag_supported(
     593              :             spdm_context, false,
     594              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     595              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     596            0 :         spdm_response->header.param1 = spdm_context->local_context.heartbeat_period;
     597              :     } else {
     598           33 :         spdm_response->header.param1 = 0x00;
     599              :     }
     600              : 
     601           33 :     session_info->local_used_cert_chain_slot_id = slot_id;
     602              : 
     603           33 :     if (libspdm_is_capabilities_flag_supported(
     604              :             spdm_context, false,
     605              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     606              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     607            0 :         session_info->heartbeat_period = spdm_context->local_context.heartbeat_period;
     608              :     } else {
     609           33 :         session_info->heartbeat_period = 0x00;
     610              :     }
     611              : 
     612           33 :     spdm_response->rsp_session_id = rsp_session_id;
     613           33 :     spdm_response->mut_auth_requested = 0;
     614           33 :     spdm_response->req_slot_id_param = 0;
     615              : 
     616              :     #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
     617           33 :     if (libspdm_is_capabilities_flag_supported(
     618              :             spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP)) {
     619           22 :         req_slot_id = 0;
     620              : 
     621              :         mut_auth_requested =
     622           22 :             libspdm_key_exchange_start_mut_auth(spdm_context,
     623              :                                                 session_id,
     624           22 :                                                 spdm_context->connection_info.version,
     625              :                                                 slot_id,
     626              :                                                 &req_slot_id,
     627           22 :                                                 spdm_request->session_policy,
     628              :                                                 opaque_data_length,
     629              :                                                 req_opaque_data,
     630              :                                                 &mandatory_mut_auth);
     631           22 :         if (mut_auth_requested != 0) {
     632           21 :             const bool req_pub_key_id_cap = libspdm_is_capabilities_flag_supported(
     633              :                 spdm_context, false, SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP, 0);
     634           21 :             const bool req_mut_auth_cap = libspdm_is_capabilities_flag_supported(
     635              :                 spdm_context, false, SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP, 0);
     636           21 :             const bool req_encap_cap = libspdm_is_capabilities_flag_supported(
     637              :                 spdm_context, false, SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCAP_CAP, 0);
     638           21 :             const bool need_encap =
     639              :                 (mut_auth_requested ==
     640           21 :                  SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST) ||
     641              :                 (mut_auth_requested ==
     642              :                  SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS);
     643              : 
     644           21 :             switch (mut_auth_requested) {
     645           13 :             case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED:
     646              :             case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST:
     647              :             case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS:
     648           13 :                 break;
     649            8 :             default:
     650            8 :                 libspdm_free_session_id(spdm_context, session_id);
     651            8 :                 return libspdm_generate_error_response(spdm_context,
     652              :                                                        SPDM_ERROR_CODE_UNSPECIFIED, 0,
     653              :                                                        response_size, response);
     654              :             }
     655              : 
     656           13 :             if (req_pub_key_id_cap &&
     657              :                 (mut_auth_requested != SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED)) {
     658            1 :                 libspdm_free_session_id(spdm_context, session_id);
     659            1 :                 return libspdm_generate_error_response(spdm_context,
     660              :                                                        SPDM_ERROR_CODE_UNSPECIFIED, 0,
     661              :                                                        response_size, response);
     662              :             }
     663           12 :             if (!need_encap) {
     664            9 :                 if (req_pub_key_id_cap ?
     665              :                     (req_slot_id != 0xf) : (req_slot_id >= SPDM_MAX_SLOT_COUNT)) {
     666            3 :                     libspdm_free_session_id(spdm_context, session_id);
     667            3 :                     return libspdm_generate_error_response(spdm_context,
     668              :                                                            SPDM_ERROR_CODE_UNSPECIFIED, 0,
     669              :                                                            response_size, response);
     670              :                 }
     671            3 :             } else if (req_slot_id != 0) {
     672            2 :                 libspdm_free_session_id(spdm_context, session_id);
     673            2 :                 return libspdm_generate_error_response(spdm_context,
     674              :                                                        SPDM_ERROR_CODE_UNSPECIFIED, 0,
     675              :                                                        response_size, response);
     676              :             }
     677              : 
     678              :             /* If Integrator requires mutual authentication but Requester does not support mutual
     679              :              * authentication, or Integrator requires the encapsulated mutual authentication flow
     680              :              * and Requester does not support encapsulated messages, then return an error to
     681              :              * Requester. */
     682            7 :             if (mandatory_mut_auth && (!req_mut_auth_cap || (need_encap && !req_encap_cap))) {
     683            2 :                 if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
     684            1 :                     libspdm_free_session_id(spdm_context, session_id);
     685            1 :                     return libspdm_generate_error_response(spdm_context,
     686              :                                                            SPDM_ERROR_CODE_INVALID_POLICY, 0,
     687              :                                                            response_size, response);
     688              :                 } else {
     689            1 :                     libspdm_free_session_id(spdm_context, session_id);
     690            1 :                     return libspdm_generate_error_response(spdm_context,
     691              :                                                            SPDM_ERROR_CODE_UNSPECIFIED, 0,
     692              :                                                            response_size, response);
     693              :                 }
     694              :             }
     695              : 
     696            5 :             if (!need_encap) {
     697            4 :                 spdm_response->mut_auth_requested = mut_auth_requested;
     698            4 :                 spdm_response->req_slot_id_param = req_slot_id;
     699              :                 /* There is no encapsulated flow to retrieve the Requester's certificate chain,
     700              :                  * so the Responder already possesses it. Record the slot that the Requester is
     701              :                  * being told to sign FINISH with, as FINISH verification reads it.
     702              :                  * SlotIDParam carries 0xF for a provisioned public key, which libspdm
     703              :                  * records as 0xFF. */
     704            4 :                 session_info->peer_used_cert_chain_slot_id =
     705              :                     req_pub_key_id_cap ? 0xFF : req_slot_id;
     706              :             }
     707              :             #if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
     708            1 :             else if (need_encap && req_encap_cap) {
     709            1 :                 spdm_response->mut_auth_requested = mut_auth_requested;
     710            1 :                 session_info->peer_used_cert_chain_slot_id = req_slot_id;
     711            1 :                 init_encap_state(spdm_context, mut_auth_requested);
     712              :             }
     713              :             #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */
     714              :         }
     715              :     }
     716              :     #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
     717              : 
     718           17 :     if (!libspdm_get_random_number(SPDM_RANDOM_DATA_SIZE, spdm_response->random_data)) {
     719            0 :         libspdm_free_session_id(spdm_context, session_id);
     720            0 :         return libspdm_generate_error_response(spdm_context,
     721              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     722              :                                                response_size, response);
     723              :     }
     724              : 
     725           17 :     ptr = (void *)(spdm_response + 1);
     726           17 :     if (spdm_context->connection_info.algorithm.kem_alg != 0) {
     727            0 :         kem_context = libspdm_secured_message_kem_new(
     728            0 :             spdm_context->connection_info.version,
     729              :             spdm_context->connection_info.algorithm.kem_alg, false);
     730            0 :         if (kem_context == NULL) {
     731            0 :             libspdm_free_session_id(spdm_context, session_id);
     732            0 :             return libspdm_generate_error_response(spdm_context,
     733              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     734              :                                                    response_size, response);
     735              :         }
     736              : 
     737            0 :         result = libspdm_secured_message_kem_encapsulate(
     738              :             spdm_context->connection_info.algorithm.kem_alg,
     739              :             kem_context,
     740              :             (const uint8_t *)request + sizeof(spdm_key_exchange_request_t),
     741              :             kem_encap_key_size, ptr, &kem_cipher_text_size, session_info->secured_message_context);
     742            0 :         libspdm_secured_message_kem_free(
     743              :             spdm_context->connection_info.algorithm.kem_alg,
     744              :             kem_context);
     745            0 :         if (!result) {
     746            0 :             libspdm_free_session_id(spdm_context, session_id);
     747            0 :             return libspdm_generate_error_response(spdm_context,
     748              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     749              :                                                    response_size, response);
     750              :         }
     751              : 
     752            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc Self cipher_text (0x%zx):\n", kem_cipher_text_size));
     753            0 :         LIBSPDM_INTERNAL_DUMP_HEX(ptr, kem_cipher_text_size);
     754              : 
     755            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc peer encap_key (0x%zx):\n", kem_encap_key_size));
     756            0 :         LIBSPDM_INTERNAL_DUMP_HEX((const uint8_t *)request +
     757              :                                   sizeof(spdm_key_exchange_request_t),
     758              :                                   kem_encap_key_size);
     759              : 
     760            0 :         ptr += kem_cipher_text_size;
     761              :     } else {
     762           17 :         dhe_context = libspdm_secured_message_dhe_new(
     763           17 :             spdm_context->connection_info.version,
     764           17 :             spdm_context->connection_info.algorithm.dhe_named_group, false);
     765           17 :         if (dhe_context == NULL) {
     766            0 :             libspdm_free_session_id(spdm_context, session_id);
     767            0 :             return libspdm_generate_error_response(spdm_context,
     768              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     769              :                                                    response_size, response);
     770              :         }
     771              : 
     772           17 :         result = libspdm_secured_message_dhe_generate_key(
     773           17 :             spdm_context->connection_info.algorithm.dhe_named_group,
     774              :             dhe_context, ptr, &dhe_key_size);
     775           17 :         if (!result) {
     776            0 :             libspdm_secured_message_dhe_free(
     777            0 :                 spdm_context->connection_info.algorithm.dhe_named_group,
     778              :                 dhe_context);
     779            0 :             libspdm_free_session_id(spdm_context, session_id);
     780            0 :             return libspdm_generate_error_response(spdm_context,
     781              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     782              :                                                    response_size, response);
     783              :         }
     784              : 
     785           17 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc SelfKey (0x%zx):\n", dhe_key_size));
     786           17 :         LIBSPDM_INTERNAL_DUMP_HEX(ptr, dhe_key_size);
     787              : 
     788           17 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc peer_key (0x%zx):\n", dhe_key_size));
     789           17 :         LIBSPDM_INTERNAL_DUMP_HEX((const uint8_t *)request +
     790              :                                   sizeof(spdm_key_exchange_request_t),
     791              :                                   dhe_key_size);
     792              : 
     793           17 :         result = libspdm_secured_message_dhe_compute_key(
     794           17 :             spdm_context->connection_info.algorithm.dhe_named_group,
     795              :             dhe_context,
     796              :             (const uint8_t *)request + sizeof(spdm_key_exchange_request_t),
     797              :             dhe_key_size, session_info->secured_message_context);
     798           17 :         libspdm_secured_message_dhe_free(
     799           17 :             spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
     800           17 :         if (!result) {
     801            0 :             libspdm_free_session_id(spdm_context, session_id);
     802            0 :             return libspdm_generate_error_response(spdm_context,
     803              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     804              :                                                    response_size, response);
     805              :         }
     806              : 
     807           17 :         ptr += dhe_key_size;
     808              :     }
     809              : 
     810              : #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
     811           17 :     if (libspdm_is_capabilities_flag_supported(
     812            2 :             spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) &&
     813            2 :         ((spdm_request->header.param1 == SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH) ||
     814            1 :          (spdm_request->header.param1 == SPDM_REQUEST_ALL_MEASUREMENTS_HASH))) {
     815            2 :         result = libspdm_generate_measurement_summary_hash(
     816              :             spdm_context,
     817            2 :             spdm_context->connection_info.version,
     818              :             spdm_context->connection_info.algorithm.base_hash_algo,
     819            2 :             spdm_context->connection_info.algorithm.measurement_spec,
     820              :             spdm_context->connection_info.algorithm.measurement_hash_algo,
     821            2 :             spdm_request->header.param1,
     822              :             ptr,
     823              :             measurement_summary_hash_size);
     824              : 
     825            2 :         if (!result) {
     826            0 :             libspdm_free_session_id(spdm_context, session_id);
     827            0 :             return libspdm_generate_error_response(spdm_context,
     828              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     829              :                                                    response_size, response);
     830              :         }
     831              :     }
     832              : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP */
     833              : 
     834           17 :     ptr += measurement_summary_hash_size;
     835              : 
     836           17 :     libspdm_write_uint16(ptr, (uint16_t)opaque_key_exchange_rsp_size);
     837           17 :     ptr += sizeof(uint16_t);
     838              : 
     839           17 :     if (opaque_key_exchange_rsp_size != 0) {
     840           17 :         if (use_default_opaque_data) {
     841           16 :             size_t version_selection_size =
     842           16 :                 libspdm_get_opaque_data_version_selection_data_size(spdm_context);
     843           16 :             libspdm_build_opaque_data_version_selection_data(
     844              :                 spdm_context, secured_message_version, &version_selection_size, ptr);
     845              :             /* DSP0277 1.3: advertise this Responder's own AEAD limit. opaque_key_exchange_rsp_size
     846              :              * is the reserved opaque data capacity (version selection + AEAD limit); the append is a
     847              :              * no-op unless the negotiated secured message version is 1.3 or later. */
     848           16 :             libspdm_build_opaque_data_aead_limit_element(
     849              :                 spdm_context, secured_message_version, &opaque_key_exchange_rsp_size, ptr);
     850              :         } else {
     851            1 :             result = libspdm_key_exchange_rsp_opaque_data(
     852            1 :                 spdm_context, spdm_request->header.spdm_version,
     853            1 :                 spdm_request->header.param1, slot_id, spdm_request->session_policy,
     854              :                 req_opaque_data, opaque_data_length, ptr,
     855              :                 &opaque_key_exchange_rsp_size);
     856            1 :             if (!result) {
     857            0 :                 libspdm_free_session_id(spdm_context, session_id);
     858            0 :                 return libspdm_generate_error_response(spdm_context,
     859              :                                                        SPDM_ERROR_CODE_UNSPECIFIED, 0,
     860              :                                                        response_size, response);
     861              :             }
     862              :         }
     863           17 :         ptr += opaque_key_exchange_rsp_size;
     864              :     }
     865              : 
     866           17 :     status = libspdm_append_message_k(spdm_context, session_info, false, request, request_size);
     867           17 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     868            0 :         libspdm_free_session_id(spdm_context, session_id);
     869            0 :         return libspdm_generate_error_response(spdm_context,
     870              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     871              :                                                response_size, response);
     872              :     }
     873              : 
     874           17 :     status = libspdm_append_message_k(spdm_context, session_info, false, spdm_response,
     875           17 :                                       (size_t)ptr - (size_t)spdm_response);
     876           17 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     877            0 :         libspdm_free_session_id(spdm_context, session_id);
     878            0 :         return libspdm_generate_error_response(spdm_context,
     879              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     880              :                                                response_size, response);
     881              :     }
     882           17 :     result = libspdm_generate_key_exchange_rsp_signature(
     883              :         spdm_context, session_info, slot_id, ptr);
     884           17 :     if (!result) {
     885            0 :         libspdm_free_session_id(spdm_context, session_id);
     886            0 :         return libspdm_generate_error_response(
     887              :             spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
     888              :             0, response_size, response);
     889              :     }
     890              : 
     891           17 :     status = libspdm_append_message_k(spdm_context, session_info, false, ptr, signature_size);
     892           17 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     893            0 :         libspdm_free_session_id(spdm_context, session_id);
     894            0 :         return libspdm_generate_error_response(spdm_context,
     895              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     896              :                                                response_size, response);
     897              :     }
     898              : 
     899           17 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n", session_id));
     900           17 :     result = libspdm_calculate_th1_hash(spdm_context, session_info, false, th1_hash_data);
     901           17 :     if (!result) {
     902            0 :         libspdm_free_session_id(spdm_context, session_id);
     903            0 :         return libspdm_generate_error_response(spdm_context,
     904              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     905              :                                                response_size, response);
     906              :     }
     907           17 :     result = libspdm_generate_session_handshake_key(
     908              :         session_info->secured_message_context, th1_hash_data);
     909           17 :     if (!result) {
     910            0 :         libspdm_free_session_id(spdm_context, session_id);
     911            0 :         return libspdm_generate_error_response(spdm_context,
     912              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     913              :                                                response_size, response);
     914              :     }
     915              : 
     916           17 :     ptr += signature_size;
     917              : 
     918           17 :     if (!libspdm_is_capabilities_flag_supported(
     919              :             spdm_context, false,
     920              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     921              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     922           14 :         result = libspdm_generate_key_exchange_rsp_hmac(spdm_context, session_info, ptr);
     923           14 :         if (!result) {
     924            0 :             libspdm_free_session_id(spdm_context, session_id);
     925            0 :             return libspdm_generate_error_response(
     926              :                 spdm_context,
     927              :                 SPDM_ERROR_CODE_UNSPECIFIED,
     928              :                 0, response_size, response);
     929              :         }
     930           14 :         status = libspdm_append_message_k(spdm_context, session_info, false, ptr, hmac_size);
     931           14 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     932            0 :             libspdm_free_session_id(spdm_context, session_id);
     933            0 :             return libspdm_generate_error_response(
     934              :                 spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
     935              :                 0, response_size, response);
     936              :         }
     937              : 
     938           14 :         ptr += hmac_size;
     939              :     }
     940              : 
     941              :     #if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
     942           17 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     943            1 :         if ((spdm_request->session_policy &
     944              :              SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY) != 0) {
     945            1 :             if (!libspdm_event_subscribe(spdm_context, spdm_context->connection_info.version,
     946              :                                          session_id, LIBSPDM_EVENT_SUBSCRIBE_ALL, 0, 0, NULL)) {
     947            0 :                 libspdm_free_session_id(spdm_context, session_id);
     948            0 :                 return libspdm_generate_error_response(spdm_context,
     949              :                                                        SPDM_ERROR_CODE_UNSPECIFIED, 0,
     950              :                                                        response_size, response);
     951              :             }
     952              :         }
     953              :     }
     954              :     #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
     955              : 
     956           17 :     session_info->mut_auth_requested = spdm_response->mut_auth_requested;
     957           17 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     958            4 :         session_info->session_policy = spdm_request->session_policy;
     959              :     }
     960           17 :     libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_HANDSHAKING);
     961              : 
     962           17 :     return LIBSPDM_STATUS_SUCCESS;
     963              : }
     964              : 
     965              : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
        

Generated by: LCOV version 2.0-1