LCOV - code coverage report
Current view: top level - library/spdm_requester_lib - libspdm_req_psk_exchange.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 70.8 % 284 201
Test Date: 2026-08-16 08:12:25 Functions: 75.0 % 4 3

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2026 DMTF. All rights reserved.
       4              :  *  License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
       5              :  **/
       6              : 
       7              : #include "internal/libspdm_requester_lib.h"
       8              : #include "internal/libspdm_secured_message_lib.h"
       9              : 
      10              : #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
      11              : 
      12              : #pragma pack(1)
      13              : typedef struct {
      14              :     spdm_message_header_t header;
      15              :     uint16_t req_session_id;
      16              :     uint16_t psk_hint_length;
      17              :     uint16_t context_length;
      18              :     uint16_t opaque_length;
      19              :     uint8_t psk_hint[LIBSPDM_PSK_MAX_HINT_LENGTH];
      20              :     uint8_t context[LIBSPDM_PSK_CONTEXT_LENGTH];
      21              :     uint8_t opaque_data[SPDM_MAX_OPAQUE_DATA_SIZE];
      22              : } libspdm_psk_exchange_request_mine_t;
      23              : 
      24              : typedef struct {
      25              :     spdm_message_header_t header;
      26              :     uint16_t rsp_session_id;
      27              :     uint16_t reserved;
      28              :     uint16_t context_length;
      29              :     uint16_t opaque_length;
      30              :     uint8_t measurement_summary_hash[LIBSPDM_MAX_HASH_SIZE];
      31              :     uint8_t context[LIBSPDM_PSK_CONTEXT_LENGTH];
      32              :     uint8_t opaque_data[SPDM_MAX_OPAQUE_DATA_SIZE];
      33              :     uint8_t verify_data[LIBSPDM_MAX_HASH_SIZE];
      34              : } libspdm_psk_exchange_response_max_t;
      35              : #pragma pack()
      36              : 
      37           16 : bool libspdm_verify_psk_exchange_rsp_hmac(libspdm_context_t *spdm_context,
      38              :                                           libspdm_session_info_t *session_info,
      39              :                                           const void *hmac_data,
      40              :                                           size_t hmac_data_size)
      41              : {
      42              :     size_t hash_size;
      43              :     uint8_t calc_hmac_data[LIBSPDM_MAX_HASH_SIZE];
      44              :     bool result;
      45              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      46              :     uint8_t *th_curr_data;
      47              :     size_t th_curr_data_size;
      48              :     libspdm_th_managed_buffer_t th_curr;
      49              :     uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
      50              : #endif
      51              : 
      52           16 :     hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
      53           16 :     LIBSPDM_ASSERT(hash_size == hmac_data_size);
      54              : 
      55              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      56              :     result = libspdm_calculate_th_for_exchange(spdm_context, session_info,
      57              :                                                NULL, 0, &th_curr);
      58              :     if (!result) {
      59              :         return false;
      60              :     }
      61              :     th_curr_data = libspdm_get_managed_buffer(&th_curr);
      62              :     th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
      63              : 
      64              :     result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
      65              :                                th_curr_data, th_curr_data_size, hash_data);
      66              :     if (!result) {
      67              :         return false;
      68              :     }
      69              : 
      70              :     result = libspdm_hmac_all_with_response_finished_key(
      71              :         session_info->secured_message_context, hash_data,
      72              :         hash_size, calc_hmac_data);
      73              :     if (!result) {
      74              :         return false;
      75              :     }
      76              : #else
      77           16 :     result = libspdm_calculate_th_hmac_for_exchange_rsp(
      78              :         spdm_context, session_info, &hash_size, calc_hmac_data);
      79           16 :     if (!result) {
      80            0 :         return false;
      81              :     }
      82              : #endif
      83           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
      84           16 :     LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
      85           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
      86              : 
      87           16 :     if (!libspdm_consttime_is_mem_equal(calc_hmac_data, hmac_data, hash_size)) {
      88            1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_psk_exchange_rsp_hmac - FAIL !!!\n"));
      89            1 :         return false;
      90              :     }
      91           15 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_psk_exchange_rsp_hmac - PASS !!!\n"));
      92              : 
      93           15 :     return true;
      94              : }
      95              : 
      96              : /**
      97              :  * This function sends PSK_EXCHANGE and receives PSK_EXCHANGE_RSP for SPDM PSK exchange.
      98              :  *
      99              :  * @param  spdm_context              A pointer to the SPDM context.
     100              :  * @param  measurement_hash_type     measurement_hash_type to the PSK_EXCHANGE request.
     101              :  * @param  session_policy            The policy for the session.
     102              :  * @param  session_id                session_id from the PSK_EXCHANGE_RSP response.
     103              :  * @param  heartbeat_period          heartbeat_period from the PSK_EXCHANGE_RSP response.
     104              :  * @param  measurement_hash          measurement_hash from the PSK_EXCHANGE_RSP response.
     105              :  * @param  requester_context_in      A buffer to hold the requester context as input, if not NULL.
     106              :  * @param  requester_context_in_size The size of requester_context_in.
     107              :  *                                   It must be 32 bytes at least, but not exceed LIBSPDM_PSK_CONTEXT_LENGTH.
     108              :  * @param  requester_context         A buffer to hold the requester context, if not NULL.
     109              :  * @param  requester_context_size    On input, the size of requester_context buffer.
     110              :  *                                   On output, the size of data returned in requester_context buffer.
     111              :  *                                   It must be 32 bytes at least.
     112              :  * @param  responder_context         A buffer to hold the responder context, if not NULL.
     113              :  * @param  responder_context_size    On input, the size of requester_context buffer.
     114              :  *                                   On output, the size of data returned in requester_context buffer.
     115              :  *                                   It could be 0 if device does not support context.
     116              :  * @param  opaque_data               A buffer to hold the responder opaque data, if not NULL.
     117              :  * @param  responder_opaque_data_size          On input, the size of the opaque data buffer.
     118              :  *                                   Responder opaque data should be less than 1024 bytes.
     119              :  *                                   On output, the size of the opaque data.
     120              :  **/
     121           45 : static libspdm_return_t libspdm_try_send_receive_psk_exchange(
     122              :     libspdm_context_t *spdm_context,
     123              :     const void *psk_hint, uint16_t psk_hint_size,
     124              :     uint8_t measurement_hash_type,
     125              :     uint8_t session_policy,
     126              :     uint32_t *session_id, uint8_t *heartbeat_period,
     127              :     void *measurement_hash,
     128              :     const void *requester_context_in,
     129              :     size_t requester_context_in_size,
     130              :     void *requester_context,
     131              :     size_t *requester_context_size,
     132              :     void *responder_context,
     133              :     size_t *responder_context_size,
     134              :     const void *requester_opaque_data,
     135              :     size_t requester_opaque_data_size,
     136              :     void *responder_opaque_data,
     137              :     size_t *responder_opaque_data_size)
     138              : {
     139              :     bool result;
     140              :     libspdm_return_t status;
     141              :     libspdm_psk_exchange_request_mine_t *spdm_request;
     142              :     size_t spdm_request_size;
     143              :     libspdm_psk_exchange_response_max_t *spdm_response;
     144              :     size_t spdm_response_size;
     145              :     uint32_t measurement_summary_hash_size;
     146              :     uint32_t hmac_size;
     147              :     uint8_t *ptr;
     148              :     void *measurement_summary_hash;
     149              :     uint8_t *verify_data;
     150              :     uint16_t req_session_id;
     151              :     uint16_t rsp_session_id;
     152              :     libspdm_session_info_t *session_info;
     153              :     size_t opaque_psk_exchange_req_size;
     154              :     uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
     155              :     uint8_t th2_hash_data[LIBSPDM_MAX_HASH_SIZE];
     156              :     uint32_t algo_size;
     157              :     uint8_t *message;
     158              :     size_t message_size;
     159              :     size_t transport_header_size;
     160              :     spdm_version_number_t secured_message_version;
     161              :     spdm_version_number_t local_max_secured_version;
     162           45 :     uint8_t peer_aead_limit_exponent = SECURED_MESSAGE_AEAD_LIMIT_EXPONENT_DEFAULT;
     163              : 
     164           45 :     LIBSPDM_ASSERT(measurement_hash_type == SPDM_PSK_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH ||
     165              :                    measurement_hash_type == SPDM_PSK_EXCHANGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH ||
     166              :                    measurement_hash_type == SPDM_PSK_EXCHANGE_REQUEST_ALL_MEASUREMENTS_HASH);
     167              : 
     168           45 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     169            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     170              :     }
     171              : 
     172              :     /* Check capabilities even if GET_CAPABILITIES is not sent.
     173              :      * Assuming capabilities are provisioned.*/
     174           45 :     if (!libspdm_is_capabilities_flag_supported(
     175              :             spdm_context, true,
     176              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
     177              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
     178            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     179              :     }
     180              : 
     181              :     /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
     182              :      * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
     183              :      */
     184           45 :     if (!libspdm_is_capabilities_flag_supported(
     185              :             spdm_context, true,
     186              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
     187              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
     188            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     189              :     }
     190              : 
     191           45 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     192            1 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     193              :     }
     194           44 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     195            2 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     196              :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
     197            0 :             return LIBSPDM_STATUS_INVALID_STATE_PEER;
     198              :         }
     199              :     }
     200              : 
     201           44 :     req_session_id = libspdm_allocate_req_session_id(spdm_context, true);
     202           44 :     if (req_session_id == (INVALID_SESSION_ID & 0xFFFF)) {
     203            0 :         return LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     204              :     }
     205              : 
     206           44 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL, SPDM_PSK_EXCHANGE);
     207              :     {
     208              :         /* Double check if algorithm has been provisioned, because ALGORITHM might be skipped.*/
     209           44 :         if (libspdm_is_capabilities_flag_supported(
     210              :                 spdm_context, true, 0,
     211              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP)) {
     212           14 :             if (spdm_context->connection_info.algorithm
     213           14 :                 .measurement_spec !=
     214              :                 SPDM_MEASUREMENT_SPECIFICATION_DMTF) {
     215            0 :                 return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     216              :             }
     217           14 :             algo_size = libspdm_get_measurement_hash_size(
     218              :                 spdm_context->connection_info.algorithm.measurement_hash_algo);
     219           14 :             if (algo_size == 0) {
     220            0 :                 return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     221              :             }
     222              :         }
     223           44 :         algo_size = libspdm_get_hash_size(
     224              :             spdm_context->connection_info.algorithm.base_hash_algo);
     225           44 :         if (algo_size == 0) {
     226            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     227              :         }
     228           44 :         if (spdm_context->connection_info.algorithm.key_schedule !=
     229              :             SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM) {
     230            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     231              :         }
     232              :     }
     233              : 
     234           44 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
     235           44 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     236           44 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     237            0 :         return status;
     238              :     }
     239           44 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
     240              :                     spdm_context->local_context.capability.transport_tail_size);
     241           44 :     spdm_request = (void *)(message + transport_header_size);
     242           44 :     spdm_request_size = message_size - transport_header_size -
     243           44 :                         spdm_context->local_context.capability.transport_tail_size;
     244              : 
     245           44 :     LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_psk_exchange_request_t) + psk_hint_size);
     246           44 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     247           44 :     spdm_request->header.request_response_code = SPDM_PSK_EXCHANGE;
     248           44 :     spdm_request->header.param1 = measurement_hash_type;
     249           44 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     250            2 :         spdm_request->header.param2 = session_policy;
     251              :     } else {
     252           42 :         spdm_request->header.param2 = 0;
     253              :     }
     254           44 :     spdm_request->psk_hint_length = psk_hint_size;
     255           44 :     if (requester_context_in == NULL) {
     256           44 :         spdm_request->context_length = LIBSPDM_PSK_CONTEXT_LENGTH;
     257              :     } else {
     258            0 :         LIBSPDM_ASSERT (requester_context_in_size <= LIBSPDM_PSK_CONTEXT_LENGTH);
     259            0 :         spdm_request->context_length = (uint16_t)requester_context_in_size;
     260              :     }
     261              : 
     262              :     /* No secured message version is negotiated yet at request time, so the AEADlimitOE element is
     263              :      * gated on the highest secured message version this endpoint offers. */
     264           44 :     local_max_secured_version = libspdm_local_max_secured_message_version(spdm_context);
     265              : 
     266           44 :     if (requester_opaque_data != NULL) {
     267            0 :         LIBSPDM_ASSERT(requester_opaque_data_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
     268              : 
     269            0 :         opaque_psk_exchange_req_size = (uint16_t)requester_opaque_data_size;
     270              :     } else {
     271              :         /* DSP0277 1.3: also advertise this endpoint's AEAD limit in the request opaque data. */
     272           44 :         opaque_psk_exchange_req_size =
     273           88 :             libspdm_get_opaque_data_supported_version_data_size(spdm_context) +
     274           44 :             libspdm_get_opaque_data_aead_limit_element_size(spdm_context,
     275              :                                                             local_max_secured_version);
     276              :     }
     277              : 
     278           44 :     LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_psk_exchange_request_t) + psk_hint_size +
     279              :                    spdm_request->context_length + opaque_psk_exchange_req_size);
     280           44 :     spdm_request->opaque_length = (uint16_t)opaque_psk_exchange_req_size;
     281              : 
     282           44 :     spdm_request->req_session_id = req_session_id;
     283              : 
     284           44 :     ptr = spdm_request->psk_hint;
     285           44 :     if ((psk_hint != NULL) && (psk_hint_size > 0)) {
     286           43 :         libspdm_copy_mem(ptr, sizeof(spdm_request->psk_hint),
     287              :                          psk_hint,
     288              :                          psk_hint_size);
     289              :     }
     290           44 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "psk_hint (0x%x) - ", spdm_request->psk_hint_length));
     291           44 :     LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_request->psk_hint_length);
     292           44 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     293           44 :     ptr += spdm_request->psk_hint_length;
     294              : 
     295           44 :     if (requester_context_in == NULL) {
     296           44 :         if (!libspdm_get_random_number(LIBSPDM_PSK_CONTEXT_LENGTH, ptr)) {
     297            0 :             libspdm_release_sender_buffer (spdm_context);
     298            0 :             return LIBSPDM_STATUS_LOW_ENTROPY;
     299              :         }
     300              :     } else {
     301            0 :         libspdm_copy_mem(ptr, sizeof(spdm_request->context),
     302            0 :                          requester_context_in, spdm_request->context_length);
     303              :     }
     304           44 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterContextData (0x%x) - ",
     305              :                    spdm_request->context_length));
     306           44 :     LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_request->context_length);
     307           44 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     308           44 :     if (requester_context != NULL) {
     309            0 :         if (*requester_context_size > spdm_request->context_length) {
     310            0 :             *requester_context_size = spdm_request->context_length;
     311              :         }
     312            0 :         libspdm_copy_mem(requester_context, *requester_context_size,
     313              :                          ptr, *requester_context_size);
     314              :     }
     315           44 :     ptr += spdm_request->context_length;
     316              : 
     317           44 :     if (requester_opaque_data != NULL) {
     318            0 :         libspdm_copy_mem(ptr, opaque_psk_exchange_req_size,
     319              :                          requester_opaque_data, opaque_psk_exchange_req_size);
     320              :     } else {
     321           44 :         size_t supported_version_size =
     322           44 :             libspdm_get_opaque_data_supported_version_data_size(spdm_context);
     323           44 :         libspdm_build_opaque_data_supported_version_data(
     324              :             spdm_context, &supported_version_size, ptr);
     325              :         /* opaque_psk_exchange_req_size holds the reserved opaque data capacity (supported version +
     326              :          * AEAD limit); it is the capacity passed to the append below. */
     327           44 :         libspdm_build_opaque_data_aead_limit_element(
     328              :             spdm_context, local_max_secured_version, &opaque_psk_exchange_req_size, ptr);
     329              :     }
     330           44 :     ptr += opaque_psk_exchange_req_size;
     331              : 
     332           44 :     spdm_request_size = (size_t)ptr - (size_t)spdm_request;
     333           44 :     status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size,
     334              :                                        spdm_request);
     335           44 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     336            1 :         libspdm_release_sender_buffer (spdm_context);
     337            1 :         return status;
     338              :     }
     339           43 :     libspdm_release_sender_buffer (spdm_context);
     340           43 :     spdm_request = (void *)spdm_context->last_spdm_request;
     341              : 
     342              :     /* receive */
     343              : 
     344           43 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     345           43 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     346            0 :         return status;
     347              :     }
     348           43 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
     349           43 :     spdm_response = (void *)(message);
     350           43 :     spdm_response_size = message_size;
     351              : 
     352           43 :     status = libspdm_receive_spdm_response(
     353              :         spdm_context, NULL, &spdm_response_size, (void **)&spdm_response);
     354           43 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     355            0 :         goto receive_done;
     356              :     }
     357           43 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     358            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     359            0 :         goto receive_done;
     360              :     }
     361           43 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     362           24 :         status = libspdm_handle_error_response_main(
     363              :             spdm_context, NULL, &spdm_response_size,
     364              :             (void **)&spdm_response, SPDM_PSK_EXCHANGE,
     365              :             SPDM_PSK_EXCHANGE_RSP);
     366           24 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     367           23 :             goto receive_done;
     368              :         }
     369           19 :     } else if (spdm_response->header.request_response_code != SPDM_PSK_EXCHANGE_RSP) {
     370            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     371            0 :         goto receive_done;
     372              :     }
     373           20 :     if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     374            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     375            0 :         goto receive_done;
     376              :     }
     377           20 :     if (spdm_response_size < sizeof(spdm_psk_exchange_response_t)) {
     378            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     379            0 :         goto receive_done;
     380              :     }
     381              : 
     382           20 :     if (!libspdm_is_capabilities_flag_supported(
     383              :             spdm_context, true,
     384              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     385              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     386           18 :         if (spdm_response->header.param1 != 0) {
     387            1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     388            1 :             goto receive_done;
     389              :         }
     390              :     }
     391           19 :     if (heartbeat_period != NULL) {
     392           19 :         *heartbeat_period = spdm_response->header.param1;
     393              :     }
     394              : 
     395           19 :     measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
     396              :         spdm_context, true, measurement_hash_type);
     397           19 :     hmac_size = libspdm_get_hash_size(
     398              :         spdm_context->connection_info.algorithm.base_hash_algo);
     399              : 
     400           19 :     if (spdm_response_size <
     401              :         sizeof(spdm_psk_exchange_response_t) +
     402           19 :         spdm_response->context_length + spdm_response->opaque_length +
     403           19 :         measurement_summary_hash_size + hmac_size) {
     404            2 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     405            2 :         goto receive_done;
     406              :     }
     407              : 
     408           17 :     ptr = (uint8_t *)spdm_response + sizeof(spdm_psk_exchange_response_t) +
     409           17 :           measurement_summary_hash_size + spdm_response->context_length;
     410           17 :     if (spdm_response->opaque_length != 0) {
     411           15 :         result = libspdm_process_general_opaque_data_check(spdm_context,
     412           15 :                                                            spdm_response->opaque_length, ptr);
     413           15 :         if (!result) {
     414            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     415            0 :             goto receive_done;
     416              :         }
     417           15 :         status = libspdm_process_opaque_data_version_selection_data(
     418           15 :             spdm_context, spdm_response->opaque_length, ptr, &secured_message_version);
     419           15 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     420            1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     421            1 :             goto receive_done;
     422              :         }
     423              :         /* DSP0277 1.3: read the Responder's AEAD limit (absent -> default 64). */
     424           14 :         status = libspdm_process_opaque_data_aead_limit(
     425           14 :             spdm_context, secured_message_version, spdm_response->opaque_length, ptr,
     426              :             &peer_aead_limit_exponent);
     427           14 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     428            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     429            0 :             goto receive_done;
     430              :         }
     431              :     }
     432              : 
     433           16 :     spdm_response_size = sizeof(spdm_psk_exchange_response_t) +
     434           16 :                          spdm_response->context_length +
     435           16 :                          spdm_response->opaque_length +
     436           16 :                          measurement_summary_hash_size + hmac_size;
     437              : 
     438           16 :     ptr = (uint8_t *)(spdm_response->measurement_summary_hash);
     439           16 :     measurement_summary_hash = ptr;
     440           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "measurement_summary_hash (0x%x) - ",
     441              :                    measurement_summary_hash_size));
     442           16 :     LIBSPDM_INTERNAL_DUMP_DATA(measurement_summary_hash,
     443              :                                measurement_summary_hash_size);
     444           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     445              : 
     446           16 :     ptr += measurement_summary_hash_size;
     447              : 
     448           16 :     if (spdm_response->opaque_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
     449            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     450            0 :         goto receive_done;
     451              :     }
     452              : 
     453           16 :     if (libspdm_is_capabilities_flag_supported(
     454              :             spdm_context, true, 0,
     455              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER)) {
     456            2 :         if (spdm_response->context_length != 0) {
     457            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     458            0 :             goto receive_done;
     459              :         }
     460              :     } else {
     461           14 :         if (spdm_response->context_length == 0) {
     462            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     463            0 :             goto receive_done;
     464              :         }
     465              :     }
     466              : 
     467           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderContextData (0x%x) - ",
     468              :                    spdm_response->context_length));
     469           16 :     LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_response->context_length);
     470           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     471           16 :     if (responder_context != NULL) {
     472            0 :         if (*responder_context_size > spdm_response->context_length) {
     473            0 :             *responder_context_size = spdm_response->context_length;
     474              :         }
     475            0 :         libspdm_copy_mem(responder_context, *responder_context_size,
     476              :                          ptr, *responder_context_size);
     477              :     }
     478              : 
     479           16 :     ptr += spdm_response->context_length;
     480              : 
     481           16 :     if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
     482            0 :         if (spdm_response->opaque_length >= *responder_opaque_data_size) {
     483            0 :             status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     484            0 :             goto receive_done;
     485              :         }
     486            0 :         libspdm_copy_mem(responder_opaque_data, *responder_opaque_data_size,
     487            0 :                          ptr, spdm_response->opaque_length);
     488            0 :         *responder_opaque_data_size = spdm_response->opaque_length;
     489              :     }
     490              : 
     491           16 :     ptr += spdm_response->opaque_length;
     492              : 
     493           16 :     rsp_session_id = spdm_response->rsp_session_id;
     494           16 :     *session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
     495           16 :     session_info = libspdm_assign_session_id(spdm_context, *session_id, secured_message_version,
     496              :                                              true);
     497           16 :     if (session_info == NULL) {
     498            0 :         status = LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     499            0 :         goto receive_done;
     500              :     }
     501           16 :     libspdm_session_info_set_psk_hint(session_info,
     502              :                                       psk_hint,
     503              :                                       psk_hint_size);
     504              : 
     505              :     /* DSP0277 1.3: program the session's AEAD limit (min of local and peer) when secured message
     506              :      * version 1.3 was negotiated. */
     507           16 :     if (libspdm_get_version_from_version_number(secured_message_version) >=
     508              :         SECURED_SPDM_VERSION_13) {
     509            0 :         libspdm_apply_aead_limit_to_session(spdm_context, session_info,
     510              :                                             peer_aead_limit_exponent);
     511              :     }
     512              : 
     513              :     /* Cache session data*/
     514              : 
     515           16 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_request,
     516              :                                       spdm_request_size);
     517           16 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     518            0 :         libspdm_free_session_id(spdm_context, *session_id);
     519            0 :         goto receive_done;
     520              :     }
     521              : 
     522           16 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_response,
     523              :                                       spdm_response_size - hmac_size);
     524           16 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     525            0 :         libspdm_free_session_id(spdm_context, *session_id);
     526            0 :         goto receive_done;
     527              :     }
     528              : 
     529           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
     530              :                    *session_id));
     531           16 :     result = libspdm_calculate_th1_hash(spdm_context, session_info, true,
     532              :                                         th1_hash_data);
     533           16 :     if (!result) {
     534            0 :         libspdm_free_session_id(spdm_context, *session_id);
     535            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     536            0 :         goto receive_done;
     537              :     }
     538           16 :     result = libspdm_generate_session_handshake_key(
     539              :         session_info->secured_message_context, th1_hash_data);
     540           16 :     if (!result) {
     541            0 :         libspdm_free_session_id(spdm_context, *session_id);
     542            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     543            0 :         goto receive_done;
     544              :     }
     545              : 
     546           16 :     verify_data = ptr;
     547           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%x):\n", hmac_size));
     548           16 :     LIBSPDM_INTERNAL_DUMP_HEX(verify_data, hmac_size);
     549           16 :     result = libspdm_verify_psk_exchange_rsp_hmac(spdm_context, session_info,
     550              :                                                   verify_data, hmac_size);
     551           16 :     if (!result) {
     552            1 :         libspdm_free_session_id(spdm_context, *session_id);
     553            1 :         status = LIBSPDM_STATUS_VERIF_FAIL;
     554            1 :         goto receive_done;
     555              :     }
     556              : 
     557           15 :     status = libspdm_append_message_k(spdm_context, session_info, true, verify_data, hmac_size);
     558           15 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     559            0 :         libspdm_free_session_id(spdm_context, *session_id);
     560            0 :         goto receive_done;
     561              :     }
     562              : 
     563           15 :     if (measurement_hash != NULL) {
     564           15 :         libspdm_copy_mem(measurement_hash, measurement_summary_hash_size,
     565              :                          measurement_summary_hash, measurement_summary_hash_size);
     566              :     }
     567              : 
     568           15 :     session_info->session_policy = session_policy;
     569              : 
     570           15 :     libspdm_secured_message_set_session_state(
     571              :         session_info->secured_message_context,
     572              :         LIBSPDM_SESSION_STATE_HANDSHAKING);
     573              : 
     574           15 :     if (!libspdm_is_capabilities_flag_supported(
     575              :             spdm_context, true, 0,
     576              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
     577              :         /* No need to send PSK_FINISH, enter application phase directly.*/
     578              : 
     579            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n",
     580              :                        *session_id));
     581            2 :         result = libspdm_calculate_th2_hash(spdm_context, session_info,
     582              :                                             true, th2_hash_data);
     583            2 :         if (!result) {
     584            0 :             libspdm_free_session_id(spdm_context, *session_id);
     585            0 :             status = LIBSPDM_STATUS_CRYPTO_ERROR;
     586            0 :             goto receive_done;
     587              :         }
     588            2 :         result = libspdm_generate_session_data_key(
     589              :             session_info->secured_message_context, th2_hash_data);
     590            2 :         if (!result) {
     591            0 :             libspdm_free_session_id(spdm_context, *session_id);
     592            0 :             status = LIBSPDM_STATUS_CRYPTO_ERROR;
     593            0 :             goto receive_done;
     594              :         }
     595              : 
     596            2 :         libspdm_secured_message_set_session_state(
     597              :             session_info->secured_message_context,
     598              :             LIBSPDM_SESSION_STATE_ESTABLISHED);
     599              :     }
     600              : 
     601           15 :     session_info->heartbeat_period = spdm_response->header.param1;
     602              : 
     603              :     /* -=[Log Message Phase]=- */
     604              :     #if LIBSPDM_ENABLE_MSG_LOG
     605           15 :     libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     606              :     #endif /* LIBSPDM_ENABLE_MSG_LOG */
     607              : 
     608           15 :     status = LIBSPDM_STATUS_SUCCESS;
     609              : 
     610           43 : receive_done:
     611           43 :     libspdm_release_receiver_buffer (spdm_context);
     612           43 :     return status;
     613              : }
     614              : 
     615           44 : libspdm_return_t libspdm_send_receive_psk_exchange(libspdm_context_t *spdm_context,
     616              :                                                    const void *psk_hint,
     617              :                                                    uint16_t psk_hint_size,
     618              :                                                    uint8_t measurement_hash_type,
     619              :                                                    uint8_t session_policy,
     620              :                                                    uint32_t *session_id,
     621              :                                                    uint8_t *heartbeat_period,
     622              :                                                    void *measurement_hash)
     623              : {
     624              :     size_t retry;
     625              :     uint64_t retry_delay_time;
     626              :     libspdm_return_t status;
     627              : 
     628           44 :     spdm_context->crypto_request = true;
     629           44 :     retry = spdm_context->retry_times;
     630           44 :     retry_delay_time = spdm_context->retry_delay_time;
     631              :     do {
     632           45 :         status = libspdm_try_send_receive_psk_exchange(
     633              :             spdm_context, psk_hint, psk_hint_size,
     634              :             measurement_hash_type, session_policy, session_id,
     635              :             heartbeat_period, measurement_hash,
     636              :             NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL);
     637           45 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     638           43 :             return status;
     639              :         }
     640              : 
     641            2 :         libspdm_sleep(retry_delay_time);
     642            2 :     } while (retry-- != 0);
     643              : 
     644            1 :     return status;
     645              : }
     646              : 
     647            0 : libspdm_return_t libspdm_send_receive_psk_exchange_ex(libspdm_context_t *spdm_context,
     648              :                                                       const void *psk_hint,
     649              :                                                       uint16_t psk_hint_size,
     650              :                                                       uint8_t measurement_hash_type,
     651              :                                                       uint8_t session_policy,
     652              :                                                       uint32_t *session_id,
     653              :                                                       uint8_t *heartbeat_period,
     654              :                                                       void *measurement_hash,
     655              :                                                       const void *requester_context_in,
     656              :                                                       size_t requester_context_in_size,
     657              :                                                       void *requester_context,
     658              :                                                       size_t *requester_context_size,
     659              :                                                       void *responder_context,
     660              :                                                       size_t *responder_context_size,
     661              :                                                       const void *requester_opaque_data,
     662              :                                                       size_t requester_opaque_data_size,
     663              :                                                       void *responder_opaque_data,
     664              :                                                       size_t *responder_opaque_data_size)
     665              : {
     666              :     size_t retry;
     667              :     uint64_t retry_delay_time;
     668              :     libspdm_return_t status;
     669              : 
     670            0 :     spdm_context->crypto_request = true;
     671            0 :     retry = spdm_context->retry_times;
     672            0 :     retry_delay_time = spdm_context->retry_delay_time;
     673              :     do {
     674            0 :         status = libspdm_try_send_receive_psk_exchange(
     675              :             spdm_context, psk_hint, psk_hint_size,
     676              :             measurement_hash_type, session_policy, session_id,
     677              :             heartbeat_period, measurement_hash,
     678              :             requester_context_in, requester_context_in_size,
     679              :             requester_context, requester_context_size,
     680              :             responder_context, responder_context_size,
     681              :             requester_opaque_data, requester_opaque_data_size,
     682              :             responder_opaque_data, responder_opaque_data_size);
     683            0 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     684            0 :             return status;
     685              :         }
     686              : 
     687            0 :         libspdm_sleep(retry_delay_time);
     688            0 :     } while (retry-- != 0);
     689              : 
     690            0 :     return status;
     691              : }
     692              : 
     693              : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
        

Generated by: LCOV version 2.0-1