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

Generated by: LCOV version 2.0-1