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.5 % 271 191
Test Date: 2025-10-12 08:10:56 Functions: 75.0 % 4 3

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2025 DMTF. All rights reserved.
       4              :  *  License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
       5              :  **/
       6              : 
       7              : #include "internal/libspdm_requester_lib.h"
       8              : #include "internal/libspdm_secured_message_lib.h"
       9              : 
      10              : #if LIBSPDM_ENABLE_CAPABILITY_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              : 
     162           45 :     LIBSPDM_ASSERT(measurement_hash_type == SPDM_PSK_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH ||
     163              :                    measurement_hash_type == SPDM_PSK_EXCHANGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH ||
     164              :                    measurement_hash_type == SPDM_PSK_EXCHANGE_REQUEST_ALL_MEASUREMENTS_HASH);
     165              : 
     166           45 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     167            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     168              :     }
     169              : 
     170              :     /* Check capabilities even if GET_CAPABILITIES is not sent.
     171              :      * Assuming capabilities are provisioned.*/
     172           45 :     if (!libspdm_is_capabilities_flag_supported(
     173              :             spdm_context, true,
     174              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
     175              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
     176            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     177              :     }
     178              : 
     179              :     /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
     180              :      * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
     181              :      */
     182           45 :     if (!libspdm_is_capabilities_flag_supported(
     183              :             spdm_context, true,
     184              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
     185              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
     186            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     187              :     }
     188              : 
     189           45 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     190            1 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     191              :     }
     192           44 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     193            2 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     194              :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
     195            0 :             return LIBSPDM_STATUS_INVALID_STATE_PEER;
     196              :         }
     197              :     }
     198              : 
     199           44 :     req_session_id = libspdm_allocate_req_session_id(spdm_context, true);
     200           44 :     if (req_session_id == (INVALID_SESSION_ID & 0xFFFF)) {
     201            0 :         return LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     202              :     }
     203              : 
     204           44 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL, SPDM_PSK_EXCHANGE);
     205              :     {
     206              :         /* Double check if algorithm has been provisioned, because ALGORITHM might be skipped.*/
     207           44 :         if (libspdm_is_capabilities_flag_supported(
     208              :                 spdm_context, true, 0,
     209              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP)) {
     210           14 :             if (spdm_context->connection_info.algorithm
     211           14 :                 .measurement_spec !=
     212              :                 SPDM_MEASUREMENT_SPECIFICATION_DMTF) {
     213            0 :                 return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     214              :             }
     215           14 :             algo_size = libspdm_get_measurement_hash_size(
     216              :                 spdm_context->connection_info.algorithm.measurement_hash_algo);
     217           14 :             if (algo_size == 0) {
     218            0 :                 return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     219              :             }
     220              :         }
     221           44 :         algo_size = libspdm_get_hash_size(
     222              :             spdm_context->connection_info.algorithm.base_hash_algo);
     223           44 :         if (algo_size == 0) {
     224            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     225              :         }
     226           44 :         if (spdm_context->connection_info.algorithm.key_schedule !=
     227              :             SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM) {
     228            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     229              :         }
     230              :     }
     231              : 
     232           44 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
     233           44 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     234           44 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     235            0 :         return status;
     236              :     }
     237           44 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
     238              :                     spdm_context->local_context.capability.transport_tail_size);
     239           44 :     spdm_request = (void *)(message + transport_header_size);
     240           44 :     spdm_request_size = message_size - transport_header_size -
     241           44 :                         spdm_context->local_context.capability.transport_tail_size;
     242              : 
     243           44 :     LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_psk_exchange_request_t) + psk_hint_size);
     244           44 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     245           44 :     spdm_request->header.request_response_code = SPDM_PSK_EXCHANGE;
     246           44 :     spdm_request->header.param1 = measurement_hash_type;
     247           44 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     248            2 :         spdm_request->header.param2 = session_policy;
     249              :     } else {
     250           42 :         spdm_request->header.param2 = 0;
     251              :     }
     252           44 :     spdm_request->psk_hint_length = psk_hint_size;
     253           44 :     if (requester_context_in == NULL) {
     254           44 :         spdm_request->context_length = LIBSPDM_PSK_CONTEXT_LENGTH;
     255              :     } else {
     256            0 :         LIBSPDM_ASSERT (requester_context_in_size <= LIBSPDM_PSK_CONTEXT_LENGTH);
     257            0 :         spdm_request->context_length = (uint16_t)requester_context_in_size;
     258              :     }
     259              : 
     260           44 :     if (requester_opaque_data != NULL) {
     261            0 :         LIBSPDM_ASSERT(requester_opaque_data_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
     262              : 
     263            0 :         opaque_psk_exchange_req_size = (uint16_t)requester_opaque_data_size;
     264              :     } else {
     265           44 :         opaque_psk_exchange_req_size =
     266           44 :             libspdm_get_opaque_data_supported_version_data_size(spdm_context);
     267              :     }
     268              : 
     269           44 :     LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_psk_exchange_request_t) + psk_hint_size +
     270              :                    spdm_request->context_length + opaque_psk_exchange_req_size);
     271           44 :     spdm_request->opaque_length = (uint16_t)opaque_psk_exchange_req_size;
     272              : 
     273           44 :     spdm_request->req_session_id = req_session_id;
     274              : 
     275           44 :     ptr = spdm_request->psk_hint;
     276           44 :     if ((psk_hint != NULL) && (psk_hint_size > 0)) {
     277           43 :         libspdm_copy_mem(ptr, sizeof(spdm_request->psk_hint),
     278              :                          psk_hint,
     279              :                          psk_hint_size);
     280              :     }
     281           44 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "psk_hint (0x%x) - ", spdm_request->psk_hint_length));
     282           44 :     LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_request->psk_hint_length);
     283           44 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     284           44 :     ptr += spdm_request->psk_hint_length;
     285              : 
     286           44 :     if (requester_context_in == NULL) {
     287           44 :         if (!libspdm_get_random_number(LIBSPDM_PSK_CONTEXT_LENGTH, ptr)) {
     288            0 :             libspdm_release_sender_buffer (spdm_context);
     289            0 :             return LIBSPDM_STATUS_LOW_ENTROPY;
     290              :         }
     291              :     } else {
     292            0 :         libspdm_copy_mem(ptr, sizeof(spdm_request->context),
     293            0 :                          requester_context_in, spdm_request->context_length);
     294              :     }
     295           44 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterContextData (0x%x) - ",
     296              :                    spdm_request->context_length));
     297           44 :     LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_request->context_length);
     298           44 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     299           44 :     if (requester_context != NULL) {
     300            0 :         if (*requester_context_size > spdm_request->context_length) {
     301            0 :             *requester_context_size = spdm_request->context_length;
     302              :         }
     303            0 :         libspdm_copy_mem(requester_context, *requester_context_size,
     304              :                          ptr, *requester_context_size);
     305              :     }
     306           44 :     ptr += spdm_request->context_length;
     307              : 
     308           44 :     if (requester_opaque_data != NULL) {
     309            0 :         libspdm_copy_mem(ptr, opaque_psk_exchange_req_size,
     310              :                          requester_opaque_data, opaque_psk_exchange_req_size);
     311              :     } else {
     312           44 :         libspdm_build_opaque_data_supported_version_data(
     313              :             spdm_context, &opaque_psk_exchange_req_size, ptr);
     314              :     }
     315           44 :     ptr += opaque_psk_exchange_req_size;
     316              : 
     317           44 :     spdm_request_size = (size_t)ptr - (size_t)spdm_request;
     318           44 :     status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size,
     319              :                                        spdm_request);
     320           44 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     321            1 :         libspdm_release_sender_buffer (spdm_context);
     322            1 :         return status;
     323              :     }
     324           43 :     libspdm_release_sender_buffer (spdm_context);
     325           43 :     spdm_request = (void *)spdm_context->last_spdm_request;
     326              : 
     327              :     /* receive */
     328              : 
     329           43 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     330           43 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     331            0 :         return status;
     332              :     }
     333           43 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
     334           43 :     spdm_response = (void *)(message);
     335           43 :     spdm_response_size = message_size;
     336              : 
     337           43 :     status = libspdm_receive_spdm_response(
     338              :         spdm_context, NULL, &spdm_response_size, (void **)&spdm_response);
     339           43 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     340            0 :         goto receive_done;
     341              :     }
     342           43 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     343            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     344            0 :         goto receive_done;
     345              :     }
     346           43 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     347           24 :         status = libspdm_handle_error_response_main(
     348              :             spdm_context, NULL, &spdm_response_size,
     349              :             (void **)&spdm_response, SPDM_PSK_EXCHANGE,
     350              :             SPDM_PSK_EXCHANGE_RSP);
     351           24 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     352           23 :             goto receive_done;
     353              :         }
     354           19 :     } else if (spdm_response->header.request_response_code != SPDM_PSK_EXCHANGE_RSP) {
     355            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     356            0 :         goto receive_done;
     357              :     }
     358           20 :     if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     359            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     360            0 :         goto receive_done;
     361              :     }
     362           20 :     if (spdm_response_size < sizeof(spdm_psk_exchange_response_t)) {
     363            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     364            0 :         goto receive_done;
     365              :     }
     366              : 
     367           20 :     if (!libspdm_is_capabilities_flag_supported(
     368              :             spdm_context, true,
     369              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     370              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     371           18 :         if (spdm_response->header.param1 != 0) {
     372            1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     373            1 :             goto receive_done;
     374              :         }
     375              :     }
     376           19 :     if (heartbeat_period != NULL) {
     377           19 :         *heartbeat_period = spdm_response->header.param1;
     378              :     }
     379              : 
     380           19 :     measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
     381              :         spdm_context, true, measurement_hash_type);
     382           19 :     hmac_size = libspdm_get_hash_size(
     383              :         spdm_context->connection_info.algorithm.base_hash_algo);
     384              : 
     385           19 :     if (spdm_response_size <
     386              :         sizeof(spdm_psk_exchange_response_t) +
     387           19 :         spdm_response->context_length + spdm_response->opaque_length +
     388           19 :         measurement_summary_hash_size + hmac_size) {
     389            2 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     390            2 :         goto receive_done;
     391              :     }
     392              : 
     393           17 :     ptr = (uint8_t *)spdm_response + sizeof(spdm_psk_exchange_response_t) +
     394           17 :           measurement_summary_hash_size + spdm_response->context_length;
     395           17 :     if (spdm_response->opaque_length != 0) {
     396           15 :         result = libspdm_process_general_opaque_data_check(spdm_context,
     397           15 :                                                            spdm_response->opaque_length, ptr);
     398           15 :         if (!result) {
     399            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     400            0 :             goto receive_done;
     401              :         }
     402           15 :         status = libspdm_process_opaque_data_version_selection_data(
     403           15 :             spdm_context, spdm_response->opaque_length, ptr, &secured_message_version);
     404           15 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     405            1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     406            1 :             goto receive_done;
     407              :         }
     408              :     }
     409              : 
     410           16 :     spdm_response_size = sizeof(spdm_psk_exchange_response_t) +
     411           16 :                          spdm_response->context_length +
     412           16 :                          spdm_response->opaque_length +
     413           16 :                          measurement_summary_hash_size + hmac_size;
     414              : 
     415           16 :     ptr = (uint8_t *)(spdm_response->measurement_summary_hash);
     416           16 :     measurement_summary_hash = ptr;
     417           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "measurement_summary_hash (0x%x) - ",
     418              :                    measurement_summary_hash_size));
     419           16 :     LIBSPDM_INTERNAL_DUMP_DATA(measurement_summary_hash,
     420              :                                measurement_summary_hash_size);
     421           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     422              : 
     423           16 :     ptr += measurement_summary_hash_size;
     424              : 
     425           16 :     if (spdm_response->opaque_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
     426            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     427            0 :         goto receive_done;
     428              :     }
     429              : 
     430           16 :     if (libspdm_is_capabilities_flag_supported(
     431              :             spdm_context, true, 0,
     432              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER)) {
     433            2 :         if (spdm_response->context_length != 0) {
     434            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     435            0 :             goto receive_done;
     436              :         }
     437              :     } else {
     438           14 :         if (spdm_response->context_length == 0) {
     439            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     440            0 :             goto receive_done;
     441              :         }
     442              :     }
     443              : 
     444           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderContextData (0x%x) - ",
     445              :                    spdm_response->context_length));
     446           16 :     LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_response->context_length);
     447           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     448           16 :     if (responder_context != NULL) {
     449            0 :         if (*responder_context_size > spdm_response->context_length) {
     450            0 :             *responder_context_size = spdm_response->context_length;
     451              :         }
     452            0 :         libspdm_copy_mem(responder_context, *responder_context_size,
     453              :                          ptr, *responder_context_size);
     454              :     }
     455              : 
     456           16 :     ptr += spdm_response->context_length;
     457              : 
     458           16 :     if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
     459            0 :         if (spdm_response->opaque_length >= *responder_opaque_data_size) {
     460            0 :             status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     461            0 :             goto receive_done;
     462              :         }
     463            0 :         libspdm_copy_mem(responder_opaque_data, *responder_opaque_data_size,
     464            0 :                          ptr, spdm_response->opaque_length);
     465            0 :         *responder_opaque_data_size = spdm_response->opaque_length;
     466              :     }
     467              : 
     468           16 :     ptr += spdm_response->opaque_length;
     469              : 
     470           16 :     rsp_session_id = spdm_response->rsp_session_id;
     471           16 :     *session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
     472           16 :     session_info = libspdm_assign_session_id(spdm_context, *session_id, secured_message_version,
     473              :                                              true);
     474           16 :     if (session_info == NULL) {
     475            0 :         status = LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
     476            0 :         goto receive_done;
     477              :     }
     478           16 :     libspdm_session_info_set_psk_hint(session_info,
     479              :                                       psk_hint,
     480              :                                       psk_hint_size);
     481              : 
     482              :     /* Cache session data*/
     483              : 
     484           16 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_request,
     485              :                                       spdm_request_size);
     486           16 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     487            0 :         libspdm_free_session_id(spdm_context, *session_id);
     488            0 :         goto receive_done;
     489              :     }
     490              : 
     491           16 :     status = libspdm_append_message_k(spdm_context, session_info, true, spdm_response,
     492              :                                       spdm_response_size - hmac_size);
     493           16 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     494            0 :         libspdm_free_session_id(spdm_context, *session_id);
     495            0 :         goto receive_done;
     496              :     }
     497              : 
     498           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
     499              :                    *session_id));
     500           16 :     result = libspdm_calculate_th1_hash(spdm_context, session_info, true,
     501              :                                         th1_hash_data);
     502           16 :     if (!result) {
     503            0 :         libspdm_free_session_id(spdm_context, *session_id);
     504            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     505            0 :         goto receive_done;
     506              :     }
     507           16 :     result = libspdm_generate_session_handshake_key(
     508              :         session_info->secured_message_context, th1_hash_data);
     509           16 :     if (!result) {
     510            0 :         libspdm_free_session_id(spdm_context, *session_id);
     511            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     512            0 :         goto receive_done;
     513              :     }
     514              : 
     515           16 :     verify_data = ptr;
     516           16 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%x):\n", hmac_size));
     517           16 :     LIBSPDM_INTERNAL_DUMP_HEX(verify_data, hmac_size);
     518           16 :     result = libspdm_verify_psk_exchange_rsp_hmac(spdm_context, session_info,
     519              :                                                   verify_data, hmac_size);
     520           16 :     if (!result) {
     521            1 :         libspdm_free_session_id(spdm_context, *session_id);
     522            1 :         status = LIBSPDM_STATUS_VERIF_FAIL;
     523            1 :         goto receive_done;
     524              :     }
     525              : 
     526           15 :     status = libspdm_append_message_k(spdm_context, session_info, true, verify_data, hmac_size);
     527           15 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     528            0 :         libspdm_free_session_id(spdm_context, *session_id);
     529            0 :         goto receive_done;
     530              :     }
     531              : 
     532           15 :     if (measurement_hash != NULL) {
     533           15 :         libspdm_copy_mem(measurement_hash, measurement_summary_hash_size,
     534              :                          measurement_summary_hash, measurement_summary_hash_size);
     535              :     }
     536              : 
     537           15 :     session_info->session_policy = session_policy;
     538              : 
     539           15 :     libspdm_secured_message_set_session_state(
     540              :         session_info->secured_message_context,
     541              :         LIBSPDM_SESSION_STATE_HANDSHAKING);
     542              : 
     543           15 :     if (!libspdm_is_capabilities_flag_supported(
     544              :             spdm_context, true, 0,
     545              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
     546              :         /* No need to send PSK_FINISH, enter application phase directly.*/
     547              : 
     548            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n",
     549              :                        *session_id));
     550            2 :         result = libspdm_calculate_th2_hash(spdm_context, session_info,
     551              :                                             true, th2_hash_data);
     552            2 :         if (!result) {
     553            0 :             libspdm_free_session_id(spdm_context, *session_id);
     554            0 :             status = LIBSPDM_STATUS_CRYPTO_ERROR;
     555            0 :             goto receive_done;
     556              :         }
     557            2 :         result = libspdm_generate_session_data_key(
     558              :             session_info->secured_message_context, th2_hash_data);
     559            2 :         if (!result) {
     560            0 :             libspdm_free_session_id(spdm_context, *session_id);
     561            0 :             status = LIBSPDM_STATUS_CRYPTO_ERROR;
     562            0 :             goto receive_done;
     563              :         }
     564              : 
     565            2 :         libspdm_secured_message_set_session_state(
     566              :             session_info->secured_message_context,
     567              :             LIBSPDM_SESSION_STATE_ESTABLISHED);
     568              :     }
     569              : 
     570           15 :     session_info->heartbeat_period = spdm_response->header.param1;
     571              : 
     572              :     /* -=[Log Message Phase]=- */
     573              :     #if LIBSPDM_ENABLE_MSG_LOG
     574           15 :     libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     575              :     #endif /* LIBSPDM_ENABLE_MSG_LOG */
     576              : 
     577           15 :     status = LIBSPDM_STATUS_SUCCESS;
     578              : 
     579           43 : receive_done:
     580           43 :     libspdm_release_receiver_buffer (spdm_context);
     581           43 :     return status;
     582              : }
     583              : 
     584           44 : libspdm_return_t libspdm_send_receive_psk_exchange(libspdm_context_t *spdm_context,
     585              :                                                    const void *psk_hint,
     586              :                                                    uint16_t psk_hint_size,
     587              :                                                    uint8_t measurement_hash_type,
     588              :                                                    uint8_t session_policy,
     589              :                                                    uint32_t *session_id,
     590              :                                                    uint8_t *heartbeat_period,
     591              :                                                    void *measurement_hash)
     592              : {
     593              :     size_t retry;
     594              :     uint64_t retry_delay_time;
     595              :     libspdm_return_t status;
     596              : 
     597           44 :     spdm_context->crypto_request = true;
     598           44 :     retry = spdm_context->retry_times;
     599           44 :     retry_delay_time = spdm_context->retry_delay_time;
     600              :     do {
     601           45 :         status = libspdm_try_send_receive_psk_exchange(
     602              :             spdm_context, psk_hint, psk_hint_size,
     603              :             measurement_hash_type, session_policy, session_id,
     604              :             heartbeat_period, measurement_hash,
     605              :             NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL);
     606           45 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     607           43 :             return status;
     608              :         }
     609              : 
     610            2 :         libspdm_sleep(retry_delay_time);
     611            2 :     } while (retry-- != 0);
     612              : 
     613            1 :     return status;
     614              : }
     615              : 
     616            0 : libspdm_return_t libspdm_send_receive_psk_exchange_ex(libspdm_context_t *spdm_context,
     617              :                                                       const void *psk_hint,
     618              :                                                       uint16_t psk_hint_size,
     619              :                                                       uint8_t measurement_hash_type,
     620              :                                                       uint8_t session_policy,
     621              :                                                       uint32_t *session_id,
     622              :                                                       uint8_t *heartbeat_period,
     623              :                                                       void *measurement_hash,
     624              :                                                       const void *requester_context_in,
     625              :                                                       size_t requester_context_in_size,
     626              :                                                       void *requester_context,
     627              :                                                       size_t *requester_context_size,
     628              :                                                       void *responder_context,
     629              :                                                       size_t *responder_context_size,
     630              :                                                       const void *requester_opaque_data,
     631              :                                                       size_t requester_opaque_data_size,
     632              :                                                       void *responder_opaque_data,
     633              :                                                       size_t *responder_opaque_data_size)
     634              : {
     635              :     size_t retry;
     636              :     uint64_t retry_delay_time;
     637              :     libspdm_return_t status;
     638              : 
     639            0 :     spdm_context->crypto_request = true;
     640            0 :     retry = spdm_context->retry_times;
     641            0 :     retry_delay_time = spdm_context->retry_delay_time;
     642              :     do {
     643            0 :         status = libspdm_try_send_receive_psk_exchange(
     644              :             spdm_context, psk_hint, psk_hint_size,
     645              :             measurement_hash_type, session_policy, session_id,
     646              :             heartbeat_period, measurement_hash,
     647              :             requester_context_in, requester_context_in_size,
     648              :             requester_context, requester_context_size,
     649              :             responder_context, responder_context_size,
     650              :             requester_opaque_data, requester_opaque_data_size,
     651              :             responder_opaque_data, responder_opaque_data_size);
     652            0 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     653            0 :             return status;
     654              :         }
     655              : 
     656            0 :         libspdm_sleep(retry_delay_time);
     657            0 :     } while (retry-- != 0);
     658              : 
     659            0 :     return status;
     660              : }
     661              : 
     662              : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
        

Generated by: LCOV version 2.0-1