LCOV - code coverage report
Current view: top level - library/spdm_responder_lib - libspdm_rsp_psk_exchange_rsp.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 73.8 % 233 172
Test Date: 2026-08-16 08:12:25 Functions: 100.0 % 2 2

            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_PSK_CAP
      11              : 
      12              : /**
      13              :  * This function generates the PSK exchange HMAC based upon TH.
      14              :  *
      15              :  * @param  spdm_context                  A pointer to the SPDM context.
      16              :  * @param  session_info                  The session info of an SPDM session.
      17              :  * @param  hmac                         The buffer to store the PSK exchange HMAC.
      18              :  *
      19              :  * @retval true  PSK exchange HMAC is generated.
      20              :  * @retval false PSK exchange HMAC is not generated.
      21              :  **/
      22           12 : static bool libspdm_generate_psk_exchange_rsp_hmac(libspdm_context_t *spdm_context,
      23              :                                                    libspdm_session_info_t *session_info,
      24              :                                                    uint8_t *hmac)
      25              : {
      26              :     uint8_t hmac_data[LIBSPDM_MAX_HASH_SIZE];
      27              :     size_t hash_size;
      28              :     bool result;
      29              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      30              :     uint8_t *th_curr_data;
      31              :     size_t th_curr_data_size;
      32              :     libspdm_th_managed_buffer_t th_curr;
      33              :     uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
      34              : #endif
      35              : 
      36           12 :     hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
      37              : 
      38              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      39              :     result = libspdm_calculate_th_for_exchange(spdm_context, session_info,
      40              :                                                NULL, 0, &th_curr);
      41              :     if (!result) {
      42              :         return false;
      43              :     }
      44              :     th_curr_data = libspdm_get_managed_buffer(&th_curr);
      45              :     th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
      46              : 
      47              :     result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
      48              :                                th_curr_data, th_curr_data_size, hash_data);
      49              :     if (!result) {
      50              :         return false;
      51              :     }
      52              : 
      53              :     result = libspdm_hmac_all_with_response_finished_key(
      54              :         session_info->secured_message_context, hash_data,
      55              :         hash_size, hmac_data);
      56              :     if (!result) {
      57              :         return false;
      58              :     }
      59              : #else
      60           12 :     result = libspdm_calculate_th_hmac_for_exchange_rsp(
      61              :         spdm_context, session_info, &hash_size, hmac_data);
      62           12 :     if (!result) {
      63            0 :         return false;
      64              :     }
      65              : #endif
      66           12 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
      67           12 :     LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
      68           12 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
      69              : 
      70           12 :     libspdm_copy_mem(hmac, hash_size, hmac_data, hash_size);
      71              : 
      72           12 :     return true;
      73              : }
      74              : 
      75           19 : libspdm_return_t libspdm_get_response_psk_exchange(libspdm_context_t *spdm_context,
      76              :                                                    size_t request_size,
      77              :                                                    const void *request,
      78              :                                                    size_t *response_size,
      79              :                                                    void *response)
      80              : {
      81              :     const spdm_psk_exchange_request_t *spdm_request;
      82              :     spdm_psk_exchange_response_t *spdm_response;
      83              :     bool result;
      84              :     uint32_t session_id;
      85              :     uint32_t measurement_summary_hash_size;
      86              :     uint32_t hmac_size;
      87              :     const uint8_t *req_opaque_data;
      88              :     uint8_t *rsp_opaque_data;
      89              :     uint8_t *ptr;
      90              :     libspdm_session_info_t *session_info;
      91              :     size_t total_size;
      92              :     uint16_t req_session_id;
      93              :     uint16_t rsp_session_id;
      94              :     libspdm_return_t status;
      95              :     size_t opaque_psk_exchange_rsp_size;
      96              :     bool use_default_opaque_data;
      97              :     uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
      98              :     uint8_t th2_hash_data[LIBSPDM_MAX_HASH_SIZE];
      99              :     uint32_t algo_size;
     100              :     uint16_t context_length;
     101              :     const void *psk_hint;
     102              :     size_t psk_hint_size;
     103              :     spdm_version_number_t secured_message_version;
     104           19 :     uint8_t peer_aead_limit_exponent = SECURED_MESSAGE_AEAD_LIMIT_EXPONENT_DEFAULT;
     105              : 
     106           19 :     spdm_request = request;
     107              : 
     108              :     /* -=[Check Parameters Phase]=- */
     109           19 :     LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_PSK_EXCHANGE);
     110              : 
     111           19 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     112            0 :         return libspdm_generate_error_response(spdm_context,
     113              :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     114              :                                                SPDM_PSK_EXCHANGE,
     115              :                                                response_size, response);
     116              :     }
     117              : 
     118           19 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
     119            0 :         return libspdm_generate_error_response(spdm_context,
     120              :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
     121              :                                                response_size, response);
     122              :     }
     123           19 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
     124            3 :         return libspdm_responder_handle_response_state(
     125              :             spdm_context,
     126            3 :             spdm_request->header.request_response_code,
     127              :             response_size, response);
     128              :     }
     129              :     /* Check capabilities even if GET_CAPABILITIES is not sent.
     130              :      * Assuming capabilities are provisioned.*/
     131           16 :     if (!libspdm_is_capabilities_flag_supported(
     132              :             spdm_context, false,
     133              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
     134              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
     135            0 :         return libspdm_generate_error_response(
     136              :             spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     137              :             SPDM_PSK_EXCHANGE, response_size, response);
     138              :     }
     139              : 
     140              :     /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
     141              :      * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
     142              :      */
     143           16 :     if (!libspdm_is_capabilities_flag_supported(
     144              :             spdm_context, false,
     145              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
     146              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
     147            0 :         return libspdm_generate_error_response(
     148              :             spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
     149              :             SPDM_KEY_EXCHANGE, response_size, response);
     150              :     }
     151              : 
     152           16 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     153            1 :         return libspdm_generate_error_response(spdm_context,
     154              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
     155              :                                                0, response_size, response);
     156              :     }
     157           15 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     158            3 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     159              :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
     160            0 :             return libspdm_generate_error_response(
     161              :                 spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
     162              :                 0, response_size, response);
     163              :         }
     164              :     }
     165           15 :     if (spdm_context->last_spdm_request_session_id_valid) {
     166            0 :         return libspdm_generate_error_response(spdm_context,
     167              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
     168              :                                                0, response_size, response);
     169              :     }
     170              : 
     171              :     {
     172              :         /* Double check if algorithm has been provisioned, because ALGORITHM might be skipped.*/
     173           15 :         if (libspdm_is_capabilities_flag_supported(
     174              :                 spdm_context, true, 0,
     175              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP)) {
     176            0 :             if (spdm_context->connection_info.algorithm
     177            0 :                 .measurement_spec != SPDM_MEASUREMENT_SPECIFICATION_DMTF) {
     178            0 :                 return libspdm_generate_error_response(
     179              :                     spdm_context,
     180              :                     SPDM_ERROR_CODE_INVALID_REQUEST,
     181              :                     0, response_size,
     182              :                     response);
     183              :             }
     184            0 :             algo_size = libspdm_get_measurement_hash_size(
     185              :                 spdm_context->connection_info.algorithm
     186              :                 .measurement_hash_algo);
     187            0 :             if (algo_size == 0) {
     188            0 :                 return libspdm_generate_error_response(
     189              :                     spdm_context,
     190              :                     SPDM_ERROR_CODE_INVALID_REQUEST,
     191              :                     0, response_size,
     192              :                     response);
     193              :             }
     194              :         }
     195           15 :         algo_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     196           15 :         if (algo_size == 0) {
     197            0 :             return libspdm_generate_error_response(
     198              :                 spdm_context,
     199              :                 SPDM_ERROR_CODE_INVALID_REQUEST,
     200              :                 0, response_size, response);
     201              :         }
     202           15 :         if (spdm_context->connection_info.algorithm.key_schedule !=
     203              :             SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM) {
     204            0 :             return libspdm_generate_error_response(
     205              :                 spdm_context,
     206              :                 SPDM_ERROR_CODE_INVALID_REQUEST,
     207              :                 0, response_size, response);
     208              :         }
     209              :     }
     210              : 
     211           15 :     if (spdm_request->header.param1 > 0) {
     212            4 :         if (!libspdm_is_capabilities_flag_supported(
     213              :                 spdm_context, false,
     214            3 :                 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) ||
     215            3 :             (spdm_context->connection_info.algorithm.measurement_spec == 0) ||
     216            3 :             (spdm_context->connection_info.algorithm.measurement_hash_algo == 0) ) {
     217            1 :             return libspdm_generate_error_response(
     218              :                 spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
     219              :                 0, response_size, response);
     220              :         }
     221              :     }
     222              : 
     223           14 :     measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
     224           14 :         spdm_context, false, spdm_request->header.param1);
     225           14 :     if ((measurement_summary_hash_size == 0) &&
     226           12 :         (spdm_request->header.param1 != SPDM_PSK_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH)) {
     227            1 :         return libspdm_generate_error_response(spdm_context,
     228              :                                                SPDM_ERROR_CODE_INVALID_REQUEST,
     229              :                                                0, response_size, response);
     230              :     }
     231              : 
     232           13 :     hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     233              : 
     234           13 :     if (request_size < sizeof(spdm_psk_exchange_request_t)) {
     235            0 :         return libspdm_generate_error_response(spdm_context,
     236              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     237              :                                                response_size, response);
     238              :     }
     239           13 :     if (request_size < sizeof(spdm_psk_exchange_request_t) +
     240           13 :         spdm_request->psk_hint_length +
     241           13 :         spdm_request->context_length +
     242           13 :         spdm_request->opaque_length) {
     243            1 :         return libspdm_generate_error_response(spdm_context,
     244              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     245              :                                                response_size, response);
     246              :     }
     247           12 :     request_size = sizeof(spdm_psk_exchange_request_t) +
     248           12 :                    spdm_request->psk_hint_length +
     249           12 :                    spdm_request->context_length +
     250           12 :                    spdm_request->opaque_length;
     251              : 
     252           12 :     if (libspdm_is_capabilities_flag_supported(
     253              :             spdm_context, false, 0,
     254              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
     255           12 :         context_length = LIBSPDM_PSK_CONTEXT_LENGTH;
     256              :     } else {
     257            0 :         context_length = 0;
     258              :     }
     259              : 
     260           12 :     if (spdm_request->psk_hint_length == 0) {
     261            2 :         psk_hint_size = 0;
     262            2 :         psk_hint = NULL;
     263           10 :     } else if (spdm_request->psk_hint_length <= LIBSPDM_PSK_MAX_HINT_LENGTH ) {
     264           10 :         psk_hint_size = spdm_request->psk_hint_length;
     265           10 :         psk_hint = (const uint8_t *)request +
     266              :                    sizeof(spdm_psk_exchange_request_t);
     267              :     } else {
     268            0 :         return libspdm_generate_error_response(
     269              :             spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     270              :             response_size, response);
     271              :     }
     272              : 
     273           12 :     secured_message_version = 0;
     274           12 :     opaque_psk_exchange_rsp_size = 0;
     275           12 :     if (spdm_request->opaque_length != 0) {
     276           10 :         req_opaque_data = (const uint8_t *)request + sizeof(spdm_psk_exchange_request_t) +
     277           10 :                           spdm_request->psk_hint_length + spdm_request->context_length;
     278              : 
     279              :         /*
     280              :          * Here allows integrator generate own opaque data for Key Exchange Response.
     281              :          * If libspdm_psk_exchange_rsp_opaque_data() returns false,
     282              :          * libspdm will generate version selection opaque data.
     283              :          */
     284           10 :         opaque_psk_exchange_rsp_size = *response_size - sizeof(spdm_psk_exchange_response_t) -
     285           10 :                                        measurement_summary_hash_size - context_length -
     286              :                                        hmac_size;
     287           10 :         use_default_opaque_data = false;
     288           10 :         result = libspdm_psk_exchange_rsp_opaque_data(
     289           10 :             spdm_context, psk_hint, spdm_request->psk_hint_length,
     290           10 :             spdm_request->header.spdm_version,
     291           10 :             spdm_request->header.param1,
     292           10 :             req_opaque_data, spdm_request->opaque_length, NULL,
     293              :             &opaque_psk_exchange_rsp_size);
     294           10 :         if (!result) {
     295            9 :             use_default_opaque_data = true;
     296            9 :             opaque_psk_exchange_rsp_size =
     297            9 :                 libspdm_get_opaque_data_version_selection_data_size(spdm_context);
     298              :         }
     299              : 
     300           10 :         if (use_default_opaque_data) {
     301            9 :             result = libspdm_process_general_opaque_data_check(spdm_context,
     302            9 :                                                                spdm_request->opaque_length, req_opaque_data);
     303            9 :             if (!result) {
     304            0 :                 return libspdm_generate_error_response(spdm_context,
     305              :                                                        SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     306              :                                                        response_size, response);
     307              :             }
     308            9 :             status = libspdm_process_opaque_data_supported_version_data(
     309            9 :                 spdm_context, spdm_request->opaque_length, req_opaque_data, &secured_message_version);
     310            9 :             if (LIBSPDM_STATUS_IS_ERROR(status)) {
     311            0 :                 return libspdm_generate_error_response(spdm_context,
     312              :                                                        SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     313              :                                                        response_size, response);
     314              :             }
     315              :             /* DSP0277 1.3: reserve room for this Responder's AEADlimitOE. The size helper returns 0
     316              :              * unless the negotiated secured message version is 1.3 or later. */
     317            9 :             opaque_psk_exchange_rsp_size +=
     318            9 :                 libspdm_get_opaque_data_aead_limit_element_size(spdm_context,
     319              :                                                                 secured_message_version);
     320              :         } else {
     321              :             /* use response buffer to temporarily store opaque data */
     322            1 :             rsp_opaque_data = (uint8_t *)response;
     323            1 :             result = libspdm_psk_exchange_rsp_opaque_data(
     324            1 :                 spdm_context, psk_hint, spdm_request->psk_hint_length,
     325            1 :                 spdm_request->header.spdm_version,
     326            1 :                 spdm_request->header.param1,
     327            1 :                 req_opaque_data, spdm_request->opaque_length, rsp_opaque_data,
     328              :                 &opaque_psk_exchange_rsp_size);
     329            1 :             if (!result) {
     330            0 :                 return libspdm_generate_error_response(spdm_context,
     331              :                                                        SPDM_ERROR_CODE_UNSPECIFIED, 0,
     332              :                                                        response_size, response);
     333              :             }
     334              :             /*
     335              :              * parse responder opaque data from integrator
     336              :              * to get secured_message_version.
     337              :              */
     338            1 :             status = libspdm_process_opaque_data_version_selection_data(
     339              :                 spdm_context, opaque_psk_exchange_rsp_size,
     340              :                 rsp_opaque_data, &secured_message_version);
     341            1 :             if (LIBSPDM_STATUS_IS_ERROR(status)) {
     342            0 :                 return libspdm_generate_error_response(spdm_context,
     343              :                                                        SPDM_ERROR_CODE_UNSPECIFIED, 0,
     344              :                                                        response_size, response);
     345              :             }
     346              :         }
     347              :         /* DSP0277 1.3: read the Requester's AEAD limit from the request (absent -> default 64).
     348              :          * This is independent of whether the Responder builds default or custom response opaque
     349              :          * data, so it runs for both paths. */
     350           10 :         status = libspdm_process_opaque_data_aead_limit(
     351           10 :             spdm_context, secured_message_version, spdm_request->opaque_length, req_opaque_data,
     352              :             &peer_aead_limit_exponent);
     353           10 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     354            0 :             return libspdm_generate_error_response(spdm_context,
     355              :                                                    SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     356              :                                                    response_size, response);
     357              :         }
     358              :     }
     359              : 
     360           12 :     total_size = sizeof(spdm_psk_exchange_response_t) +
     361           12 :                  measurement_summary_hash_size + context_length +
     362           12 :                  opaque_psk_exchange_rsp_size + hmac_size;
     363              : 
     364           12 :     LIBSPDM_ASSERT(*response_size >= total_size);
     365           12 :     *response_size = total_size;
     366           12 :     libspdm_zero_mem(response, *response_size);
     367           12 :     spdm_response = response;
     368              : 
     369           12 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     370           12 :     spdm_response->header.request_response_code = SPDM_PSK_EXCHANGE_RSP;
     371           12 :     if (libspdm_is_capabilities_flag_supported(
     372              :             spdm_context, false,
     373              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     374              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     375            0 :         spdm_response->header.param1 = spdm_context->local_context.heartbeat_period;
     376              :     } else {
     377           12 :         spdm_response->header.param1 = 0x00;
     378              :     }
     379              : 
     380           12 :     req_session_id = spdm_request->req_session_id;
     381           12 :     rsp_session_id = libspdm_allocate_rsp_session_id(spdm_context, true);
     382           12 :     if (rsp_session_id == ((INVALID_SESSION_ID & 0xFFFF0000) >> 16)) {
     383            0 :         return libspdm_generate_error_response(
     384              :             spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
     385              :             response_size, response);
     386              :     }
     387           12 :     session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
     388           12 :     session_info = libspdm_assign_session_id(spdm_context, session_id, secured_message_version,
     389              :                                              true);
     390           12 :     if (session_info == NULL) {
     391            0 :         return libspdm_generate_error_response(
     392              :             spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
     393              :             response_size, response);
     394              :     }
     395           12 :     libspdm_session_info_set_psk_hint(session_info, psk_hint, psk_hint_size);
     396              : 
     397              :     /* DSP0277 1.3: program the session's AEAD limit (min of local and peer) when secured message
     398              :      * version 1.3 was negotiated. */
     399           12 :     if (libspdm_get_version_from_version_number(secured_message_version) >=
     400              :         SECURED_SPDM_VERSION_13) {
     401            9 :         libspdm_apply_aead_limit_to_session(spdm_context, session_info,
     402              :                                             peer_aead_limit_exponent);
     403              :     }
     404              : 
     405           12 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
     406           12 :                                                   spdm_request->header.request_response_code);
     407              : 
     408           12 :     spdm_response->rsp_session_id = rsp_session_id;
     409           12 :     spdm_response->reserved = 0;
     410              : 
     411           12 :     spdm_response->context_length = context_length;
     412           12 :     spdm_response->opaque_length = (uint16_t)opaque_psk_exchange_rsp_size;
     413              : 
     414           12 :     ptr = (void *)(spdm_response + 1);
     415              : 
     416              : #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
     417           12 :     if (libspdm_is_capabilities_flag_supported(
     418            2 :             spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) &&
     419            2 :         ((spdm_request->header.param1 == SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH) ||
     420            1 :          (spdm_request->header.param1 == SPDM_REQUEST_ALL_MEASUREMENTS_HASH))) {
     421            2 :         result = libspdm_generate_measurement_summary_hash(
     422              :             spdm_context,
     423            2 :             spdm_context->connection_info.version,
     424              :             spdm_context->connection_info.algorithm.base_hash_algo,
     425            2 :             spdm_context->connection_info.algorithm.measurement_spec,
     426              :             spdm_context->connection_info.algorithm.measurement_hash_algo,
     427            2 :             spdm_request->header.param1,
     428              :             ptr,
     429              :             measurement_summary_hash_size);
     430              : 
     431            2 :         if (!result) {
     432            0 :             libspdm_free_session_id(spdm_context, session_id);
     433            0 :             return libspdm_generate_error_response(spdm_context,
     434              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     435              :                                                    response_size, response);
     436              :         }
     437              :     }
     438              : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP */
     439              : 
     440           12 :     ptr += measurement_summary_hash_size;
     441              : 
     442           12 :     if (context_length != 0) {
     443           12 :         if (!libspdm_get_random_number(context_length, ptr)) {
     444            0 :             libspdm_free_session_id(spdm_context, session_id);
     445            0 :             return libspdm_generate_error_response(spdm_context,
     446              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     447              :                                                    response_size, response);
     448              :         }
     449           12 :         ptr += context_length;
     450              :     }
     451              : 
     452           12 :     if (opaque_psk_exchange_rsp_size != 0) {
     453           10 :         if (use_default_opaque_data) {
     454            9 :             size_t version_selection_size =
     455            9 :                 libspdm_get_opaque_data_version_selection_data_size(spdm_context);
     456            9 :             libspdm_build_opaque_data_version_selection_data(
     457              :                 spdm_context, secured_message_version, &version_selection_size, ptr);
     458              :             /* DSP0277 1.3: advertise this Responder's own AEAD limit. opaque_psk_exchange_rsp_size
     459              :              * is the reserved opaque data capacity (version selection + AEAD limit); the append is a
     460              :              * no-op unless the negotiated secured message version is 1.3 or later. */
     461            9 :             libspdm_build_opaque_data_aead_limit_element(
     462              :                 spdm_context, secured_message_version, &opaque_psk_exchange_rsp_size, ptr);
     463              :         } else {
     464            1 :             result = libspdm_psk_exchange_rsp_opaque_data(
     465            1 :                 spdm_context, psk_hint, spdm_request->psk_hint_length,
     466            1 :                 spdm_request->header.spdm_version,
     467            1 :                 spdm_request->header.param1,
     468            1 :                 req_opaque_data, spdm_request->opaque_length, ptr,
     469              :                 &opaque_psk_exchange_rsp_size);
     470            1 :             if (!result) {
     471            0 :                 libspdm_free_session_id(spdm_context, session_id);
     472            0 :                 return libspdm_generate_error_response(spdm_context,
     473              :                                                        SPDM_ERROR_CODE_UNSPECIFIED, 0,
     474              :                                                        response_size, response);
     475              :             }
     476              :         }
     477           10 :         ptr += opaque_psk_exchange_rsp_size;
     478              :     }
     479              : 
     480           12 :     status = libspdm_append_message_k(spdm_context, session_info, false, request, request_size);
     481           12 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     482            0 :         libspdm_free_session_id(spdm_context, session_id);
     483            0 :         return libspdm_generate_error_response(spdm_context,
     484              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     485              :                                                response_size, response);
     486              :     }
     487              : 
     488           12 :     status = libspdm_append_message_k(spdm_context, session_info, false, spdm_response,
     489           12 :                                       (size_t)ptr - (size_t)spdm_response);
     490           12 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     491            0 :         libspdm_free_session_id(spdm_context, session_id);
     492            0 :         return libspdm_generate_error_response(spdm_context,
     493              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     494              :                                                response_size, response);
     495              :     }
     496              : 
     497           12 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
     498              :                    session_id));
     499           12 :     result = libspdm_calculate_th1_hash(spdm_context, session_info, false,
     500              :                                         th1_hash_data);
     501           12 :     if (!result) {
     502            0 :         libspdm_free_session_id(spdm_context, session_id);
     503            0 :         return libspdm_generate_error_response(spdm_context,
     504              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     505              :                                                response_size, response);
     506              :     }
     507           12 :     result = libspdm_generate_session_handshake_key(
     508              :         session_info->secured_message_context, th1_hash_data);
     509           12 :     if (!result) {
     510            0 :         libspdm_free_session_id(spdm_context, session_id);
     511            0 :         return libspdm_generate_error_response(spdm_context,
     512              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     513              :                                                response_size, response);
     514              :     }
     515              : 
     516           12 :     result = libspdm_generate_psk_exchange_rsp_hmac(spdm_context, session_info,
     517              :                                                     ptr);
     518           12 :     if (!result) {
     519            0 :         libspdm_free_session_id(spdm_context, session_id);
     520            0 :         return libspdm_generate_error_response(
     521              :             spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
     522              :             0, response_size, response);
     523              :     }
     524           12 :     status = libspdm_append_message_k(spdm_context, session_info, false, ptr, hmac_size);
     525           12 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     526            0 :         libspdm_free_session_id(spdm_context, session_id);
     527            0 :         return libspdm_generate_error_response(spdm_context,
     528              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     529              :                                                response_size, response);
     530              :     }
     531           12 :     ptr += hmac_size;
     532              : 
     533           12 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     534            3 :         session_info->session_policy = spdm_request->header.param2;
     535              :     }
     536           12 :     libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_HANDSHAKING);
     537              : 
     538           12 :     if (!libspdm_is_capabilities_flag_supported(
     539              :             spdm_context, false, 0,
     540              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
     541              :         /* No need to receive PSK_FINISH, enter application phase directly.*/
     542              : 
     543            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n",
     544              :                        session_id));
     545            0 :         result = libspdm_calculate_th2_hash(spdm_context, session_info,
     546              :                                             false, th2_hash_data);
     547            0 :         if (!result) {
     548            0 :             libspdm_free_session_id(spdm_context, session_id);
     549            0 :             return libspdm_generate_error_response(
     550              :                 spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
     551              :                 0, response_size, response);
     552              :         }
     553            0 :         result = libspdm_generate_session_data_key(
     554              :             session_info->secured_message_context, th2_hash_data);
     555            0 :         if (!result) {
     556            0 :             libspdm_free_session_id(spdm_context, session_id);
     557            0 :             return libspdm_generate_error_response(
     558              :                 spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
     559              :                 0, response_size, response);
     560              :         }
     561              : 
     562              :         #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
     563            0 :         if (libspdm_is_capabilities_flag_supported(
     564              :                 spdm_context, false,
     565              :                 SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     566              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     567            0 :             result = libspdm_start_watchdog(
     568            0 :                 session_id, spdm_context->local_context.heartbeat_period * 2);
     569            0 :             if (!result) {
     570            0 :                 libspdm_free_session_id(spdm_context, session_id);
     571            0 :                 return libspdm_generate_error_response(
     572              :                     spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
     573              :                     0, response_size, response);
     574              :             }
     575              :         }
     576              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
     577              : 
     578            0 :         libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_ESTABLISHED);
     579              :     }
     580              : 
     581           12 :     if (libspdm_is_capabilities_flag_supported(
     582              :             spdm_context, false,
     583              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     584              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     585            0 :         session_info->heartbeat_period = spdm_context->local_context.heartbeat_period;
     586              :     } else {
     587           12 :         session_info->heartbeat_period = 0x00;
     588              :     }
     589              : 
     590           12 :     return LIBSPDM_STATUS_SUCCESS;
     591              : }
     592              : 
     593              : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
        

Generated by: LCOV version 2.0-1