LCOV - code coverage report
Current view: top level - library/spdm_responder_lib - libspdm_rsp_psk_finish_rsp.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 79.3 % 111 88
Test Date: 2026-03-15 08:15:47 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2026 DMTF. All rights reserved.
       4              :  *  License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
       5              :  **/
       6              : 
       7              : #include "internal/libspdm_responder_lib.h"
       8              : #include "internal/libspdm_secured_message_lib.h"
       9              : 
      10              : #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
      11              : 
      12            8 : bool libspdm_verify_psk_finish_req_hmac(libspdm_context_t *spdm_context,
      13              :                                         libspdm_session_info_t *session_info,
      14              :                                         const uint8_t *hmac, size_t hmac_size)
      15              : {
      16              :     uint8_t hmac_data[LIBSPDM_MAX_HASH_SIZE];
      17              :     size_t hash_size;
      18              :     bool result;
      19              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      20              :     uint8_t *th_curr_data;
      21              :     size_t th_curr_data_size;
      22              :     libspdm_th_managed_buffer_t th_curr;
      23              :     uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
      24              : #endif
      25              : 
      26            8 :     hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
      27            8 :     LIBSPDM_ASSERT(hmac_size == hash_size);
      28              : 
      29              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      30              :     result = libspdm_calculate_th_for_finish(spdm_context, session_info, NULL,
      31              :                                              0, NULL, 0, &th_curr);
      32              :     if (!result) {
      33              :         return false;
      34              :     }
      35              :     th_curr_data = libspdm_get_managed_buffer(&th_curr);
      36              :     th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
      37              : 
      38              :     result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
      39              :                                th_curr_data, th_curr_data_size, hash_data);
      40              :     if (!result) {
      41              :         return false;
      42              :     }
      43              : 
      44              :     result = libspdm_hmac_all_with_request_finished_key(
      45              :         session_info->secured_message_context, hash_data,
      46              :         hash_size, hmac_data);
      47              :     if (!result) {
      48              :         return false;
      49              :     }
      50              : #else
      51            8 :     result = libspdm_calculate_th_hmac_for_finish_req(
      52              :         spdm_context, session_info, &hash_size, hmac_data);
      53            8 :     if (!result) {
      54            0 :         return false;
      55              :     }
      56              : #endif
      57            8 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc th_curr hmac - "));
      58            8 :     LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
      59            8 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
      60              : 
      61            8 :     if (!libspdm_consttime_is_mem_equal(hmac, hmac_data, hash_size)) {
      62            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_psk_finish_req_hmac - FAIL !!!\n"));
      63            2 :         return false;
      64              :     }
      65            6 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_psk_finish_req_hmac - PASS !!!\n"));
      66            6 :     return true;
      67              : }
      68              : 
      69           17 : libspdm_return_t libspdm_get_response_psk_finish(libspdm_context_t *spdm_context,
      70              :                                                  size_t request_size,
      71              :                                                  const void *request,
      72              :                                                  size_t *response_size,
      73              :                                                  void *response)
      74              : {
      75              :     uint32_t session_id;
      76              :     bool result;
      77              :     uint32_t hmac_size;
      78              :     spdm_psk_finish_response_t *spdm_response;
      79              :     libspdm_session_info_t *session_info;
      80              :     uint8_t th2_hash_data[LIBSPDM_MAX_HASH_SIZE];
      81              :     const spdm_psk_finish_request_t *spdm_request;
      82              :     libspdm_return_t status;
      83              :     libspdm_session_state_t session_state;
      84              :     uint8_t *ptr;
      85              :     size_t opaque_data_entry_size;
      86              :     const uint8_t *req_opaque_data;
      87              :     size_t req_opaque_data_size;
      88              :     uint8_t *opaque_data;
      89              :     size_t opaque_data_size;
      90              : 
      91           17 :     spdm_request = request;
      92              : 
      93              :     /* -=[Check Parameters Phase]=- */
      94           17 :     LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_PSK_FINISH);
      95              : 
      96           17 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
      97            0 :         return libspdm_generate_error_response(spdm_context,
      98              :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
      99              :                                                SPDM_PSK_FINISH,
     100              :                                                response_size, response);
     101              :     }
     102              : 
     103           17 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
     104            0 :         return libspdm_generate_error_response(spdm_context,
     105              :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
     106              :                                                response_size, response);
     107              :     }
     108           17 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
     109            3 :         return libspdm_responder_handle_response_state(
     110              :             spdm_context,
     111            3 :             spdm_request->header.request_response_code,
     112              :             response_size, response);
     113              :     }
     114           14 :     if (!libspdm_is_capabilities_flag_supported(
     115              :             spdm_context, false,
     116              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
     117              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
     118            1 :         return libspdm_generate_error_response(
     119              :             spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     120              :             SPDM_PSK_FINISH, response_size, response);
     121              :     }
     122           13 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     123            1 :         return libspdm_generate_error_response(spdm_context,
     124              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
     125              :                                                0, response_size, response);
     126              :     }
     127              : 
     128           12 :     if (!spdm_context->last_spdm_request_session_id_valid) {
     129            0 :         if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     130            0 :             return libspdm_generate_error_response(spdm_context,
     131              :                                                    SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
     132              :                                                    response_size, response);
     133              :         } else {
     134            0 :             return libspdm_generate_error_response(spdm_context,
     135              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     136              :                                                    response_size, response);
     137              :         }
     138              :     }
     139           12 :     session_id = spdm_context->last_spdm_request_session_id;
     140              :     session_info =
     141           12 :         libspdm_get_session_info_via_session_id(spdm_context, session_id);
     142           12 :     if (session_info == NULL) {
     143            0 :         if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     144            0 :             return libspdm_generate_error_response(spdm_context,
     145              :                                                    SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
     146              :                                                    response_size, response);
     147              :         } else {
     148            0 :             return libspdm_generate_error_response(spdm_context,
     149              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     150              :                                                    response_size, response);
     151              :         }
     152              :     }
     153           12 :     if (!session_info->use_psk) {
     154            0 :         return libspdm_generate_error_response(spdm_context,
     155              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     156              :                                                response_size, response);
     157              :     }
     158           12 :     session_state = libspdm_secured_message_get_session_state(
     159              :         session_info->secured_message_context);
     160           12 :     if (session_state != LIBSPDM_SESSION_STATE_HANDSHAKING) {
     161            1 :         return libspdm_generate_error_response(spdm_context,
     162              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     163              :                                                response_size, response);
     164              :     }
     165              : 
     166              :     /* remove HMAC*/
     167           11 :     hmac_size = libspdm_get_hash_size(
     168              :         spdm_context->connection_info.algorithm.base_hash_algo);
     169              : 
     170           11 :     ptr = (uint8_t *)(size_t)spdm_request + sizeof(spdm_psk_finish_request_t);
     171           11 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
     172            2 :         req_opaque_data_size = libspdm_read_uint16((const uint8_t *)request +
     173              :                                                    sizeof(spdm_psk_finish_request_t));
     174            2 :         ptr += sizeof(uint16_t);
     175            2 :         if (request_size < sizeof(spdm_psk_finish_request_t) +
     176            2 :             sizeof(uint16_t) + req_opaque_data_size) {
     177            0 :             return libspdm_generate_error_response(spdm_context,
     178              :                                                    SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     179              :                                                    response_size, response);
     180              :         }
     181            2 :         req_opaque_data = ptr;
     182            2 :         ptr += req_opaque_data_size;
     183            2 :         opaque_data_entry_size = sizeof(uint16_t) + req_opaque_data_size;
     184              :     } else {
     185            9 :         opaque_data_entry_size = 0;
     186              :     }
     187              : 
     188              :     /* this message can only be in secured session
     189              :      * thus don't need to consider transport layer padding, just check its exact size */
     190           11 :     if (request_size != sizeof(spdm_psk_finish_request_t) + opaque_data_entry_size + hmac_size) {
     191            3 :         return libspdm_generate_error_response(spdm_context,
     192              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     193              :                                                response_size, response);
     194              :     }
     195              : 
     196            8 :     libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
     197            8 :                                                   spdm_request->header.request_response_code);
     198              : 
     199            8 :     status = libspdm_append_message_f(spdm_context, session_info, false, request,
     200              :                                       request_size - hmac_size);
     201            8 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     202            0 :         return libspdm_generate_error_response(spdm_context,
     203              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     204              :                                                response_size, response);
     205              :     }
     206              : 
     207            8 :     result = libspdm_verify_psk_finish_req_hmac(
     208              :         spdm_context, session_info,
     209              :         ptr, hmac_size);
     210            8 :     if (!result) {
     211            2 :         if ((spdm_context->handle_error_return_policy &
     212              :              LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY_DROP_ON_DECRYPT_ERROR) == 0) {
     213            2 :             return libspdm_generate_error_response(
     214              :                 spdm_context, SPDM_ERROR_CODE_DECRYPT_ERROR, 0,
     215              :                 response_size, response);
     216              :         } else {
     217              :             /**
     218              :              * just ignore this message
     219              :              * return UNSUPPORTED and clear response_size to continue the dispatch without send response
     220              :              **/
     221            0 :             *response_size = 0;
     222            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     223              :         }
     224              :     }
     225            6 :     status = libspdm_append_message_f(
     226              :         spdm_context, session_info, false,
     227              :         ptr, hmac_size);
     228            6 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     229            0 :         return libspdm_generate_error_response(spdm_context,
     230              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     231              :                                                response_size, response);
     232              :     }
     233              : 
     234            6 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
     235            2 :         opaque_data_entry_size = sizeof(uint16_t);
     236              :     } else {
     237            4 :         opaque_data_entry_size = 0;
     238              :     }
     239              : 
     240              :     /* response_size should be large enough to hold a psk finish response without opaque data. */
     241            6 :     LIBSPDM_ASSERT(*response_size >= sizeof(spdm_psk_finish_response_t) + opaque_data_entry_size);
     242            6 :     libspdm_zero_mem(response, *response_size);
     243            6 :     spdm_response = response;
     244              : 
     245            6 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     246            6 :     spdm_response->header.request_response_code = SPDM_PSK_FINISH_RSP;
     247            6 :     spdm_response->header.param1 = 0;
     248            6 :     spdm_response->header.param2 = 0;
     249              : 
     250            6 :     ptr = (uint8_t *)spdm_response + sizeof(spdm_psk_finish_response_t);
     251            6 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
     252            2 :         opaque_data_size = *response_size - sizeof(spdm_psk_finish_response_t) -
     253              :                            opaque_data_entry_size;
     254            2 :         opaque_data = ptr + opaque_data_entry_size;
     255              : 
     256            2 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     257              :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE) {
     258            1 :             opaque_data_size = 0;
     259              :         } else {
     260            2 :             status = libspdm_psk_finish_rsp_opaque_data(
     261            1 :                 spdm_context, session_id, spdm_request->header.spdm_version,
     262              :                 req_opaque_data, req_opaque_data_size,
     263              :                 opaque_data, &opaque_data_size);
     264            1 :             if (LIBSPDM_STATUS_IS_ERROR(status)) {
     265            0 :                 return libspdm_generate_error_response(spdm_context,
     266              :                                                        SPDM_ERROR_CODE_UNSPECIFIED, 0,
     267              :                                                        response_size, response);
     268              :             }
     269              :         }
     270            2 :         libspdm_write_uint16(ptr, (uint16_t)opaque_data_size);
     271            2 :         opaque_data_entry_size = sizeof(uint16_t) + opaque_data_size;
     272            2 :         ptr += opaque_data_entry_size;
     273              :     }
     274              : 
     275            6 :     *response_size = sizeof(spdm_psk_finish_response_t) + opaque_data_entry_size;
     276              : 
     277            6 :     status = libspdm_append_message_f(spdm_context, session_info, false, spdm_response,
     278              :                                       *response_size);
     279            6 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     280            0 :         return libspdm_generate_error_response(spdm_context,
     281              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     282              :                                                response_size, response);
     283              :     }
     284              : 
     285            6 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n", session_id));
     286            6 :     result = libspdm_calculate_th2_hash(spdm_context, session_info, false,
     287              :                                         th2_hash_data);
     288            6 :     if (!result) {
     289            0 :         return libspdm_generate_error_response(spdm_context,
     290              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     291              :                                                response_size, response);
     292              :     }
     293            6 :     result = libspdm_generate_session_data_key(
     294              :         session_info->secured_message_context, th2_hash_data);
     295            6 :     if (!result) {
     296            0 :         return libspdm_generate_error_response(spdm_context,
     297              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     298              :                                                response_size, response);
     299              :     }
     300              : 
     301              :     #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
     302            6 :     if (libspdm_is_capabilities_flag_supported(
     303              :             spdm_context, false,
     304              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     305              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     306            0 :         result = libspdm_start_watchdog(
     307            0 :             session_id, spdm_context->local_context.heartbeat_period * 2);
     308            0 :         if (!result) {
     309            0 :             return libspdm_generate_error_response(spdm_context,
     310              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     311              :                                                    response_size, response);
     312              :         }
     313              :     }
     314              :     #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
     315              : 
     316            6 :     return LIBSPDM_STATUS_SUCCESS;
     317              : }
     318              : 
     319              : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP */
        

Generated by: LCOV version 2.0-1