LCOV - code coverage report
Current view: top level - library/spdm_responder_lib - libspdm_rsp_encap_get_endpoint_info.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 79.7 % 128 102
Test Date: 2026-02-22 08:11:49 Functions: 66.7 % 3 2

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2025-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              : 
       9              : #if (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT)
      10              : 
      11            0 : libspdm_return_t libspdm_register_get_endpoint_info_callback_func(
      12              :     void *spdm_context, libspdm_get_endpoint_info_callback_func get_endpoint_info_callback)
      13              : {
      14            0 :     libspdm_context_t *context = (libspdm_context_t *)spdm_context;
      15            0 :     context->get_endpoint_info_callback = get_endpoint_info_callback;
      16            0 :     return LIBSPDM_STATUS_SUCCESS;
      17              : }
      18              : 
      19            1 : libspdm_return_t libspdm_get_encap_request_get_endpoint_info(
      20              :     libspdm_context_t *spdm_context,
      21              :     size_t *encap_request_size,
      22              :     void *encap_request)
      23              : {
      24              :     libspdm_return_t status;
      25              :     spdm_get_endpoint_info_request_t *spdm_request;
      26              :     uint32_t session_id;
      27              :     libspdm_session_info_t *session_info;
      28              :     libspdm_session_state_t session_state;
      29              :     uint8_t *spdm_nonce;
      30              : 
      31            1 :     LIBSPDM_ASSERT(spdm_context->get_endpoint_info_callback != NULL);
      32              : 
      33            1 :     spdm_context->encap_context.last_encap_request_size = 0;
      34              : 
      35            1 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) {
      36            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
      37              :     }
      38              : 
      39            1 :     if (!libspdm_is_capabilities_flag_supported(
      40              :             spdm_context, false,
      41              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP, 0)) {
      42            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
      43              :     }
      44              : 
      45            1 :     if (spdm_context->last_spdm_request_session_id_valid) {
      46            1 :         session_id = spdm_context->last_spdm_request_session_id;
      47            1 :         session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
      48            1 :         if (session_info == NULL) {
      49            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
      50              :         }
      51            1 :         session_state = libspdm_secured_message_get_session_state(
      52              :             session_info->secured_message_context);
      53            1 :         if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
      54            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
      55              :         }
      56              :     } else {
      57            0 :         session_info = NULL;
      58              :     }
      59              : 
      60            1 :     LIBSPDM_ASSERT(*encap_request_size >= sizeof(spdm_get_endpoint_info_request_t));
      61              : 
      62            1 :     spdm_request = encap_request;
      63              : 
      64            1 :     libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
      65            1 :                                                   spdm_request->header.request_response_code);
      66              : 
      67            1 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
      68            1 :     spdm_request->header.request_response_code = SPDM_GET_ENDPOINT_INFO;
      69            1 :     spdm_request->header.param1 = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER;
      70            1 :     spdm_request->header.param2 =
      71            1 :         spdm_context->encap_context.req_slot_id & SPDM_GET_ENDPOINT_INFO_REQUEST_SLOT_ID_MASK;
      72              : 
      73              :     /* request signature if requester support */
      74            1 :     if (libspdm_is_capabilities_flag_supported(
      75              :             spdm_context, false,
      76              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP_SIG, 0)) {
      77            1 :         LIBSPDM_ASSERT(
      78              :             *encap_request_size >= sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE);
      79            1 :         *encap_request_size = sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE;
      80              : 
      81            1 :         spdm_request->request_attributes =
      82              :             SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED;
      83            1 :         libspdm_write_uint24(spdm_request->reserved, 0);
      84              : 
      85            1 :         spdm_nonce = (uint8_t *)(spdm_request + 1);
      86            1 :         if (!libspdm_get_random_number(SPDM_NONCE_SIZE, spdm_nonce)) {
      87            0 :             libspdm_release_sender_buffer (spdm_context);
      88            0 :             return LIBSPDM_STATUS_LOW_ENTROPY;
      89              :         }
      90            1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Encap RequesterNonce - "));
      91            1 :         LIBSPDM_INTERNAL_DUMP_DATA(spdm_nonce, SPDM_NONCE_SIZE);
      92            1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
      93              : 
      94            1 :         status = libspdm_append_message_encap_e(spdm_context, session_info,
      95              :                                                 spdm_request, *encap_request_size);
      96            1 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
      97            0 :             return status;
      98              :         }
      99              : 
     100              :     } else {
     101            0 :         *encap_request_size = sizeof(spdm_get_endpoint_info_request_t);
     102            0 :         spdm_request->request_attributes = 0;
     103            0 :         libspdm_write_uint24(spdm_request->reserved, 0);
     104              :     }
     105              : 
     106            1 :     libspdm_copy_mem(&spdm_context->encap_context.last_encap_request_header,
     107              :                      sizeof(spdm_context->encap_context.last_encap_request_header),
     108            1 :                      &spdm_request->header, sizeof(spdm_message_header_t));
     109            1 :     spdm_context->encap_context.last_encap_request_size =
     110            1 :         *encap_request_size;
     111              : 
     112            1 :     return LIBSPDM_STATUS_SUCCESS;
     113              : }
     114              : 
     115           16 : libspdm_return_t libspdm_process_encap_response_endpoint_info(
     116              :     libspdm_context_t *spdm_context, size_t encap_response_size,
     117              :     const void *encap_response, bool *need_continue)
     118              : {
     119              :     libspdm_return_t status;
     120              :     spdm_get_endpoint_info_request_t *spdm_request;
     121              :     const spdm_endpoint_info_response_t *spdm_response;
     122              :     size_t spdm_response_size;
     123              :     uint32_t session_id;
     124              :     libspdm_session_info_t *session_info;
     125              :     libspdm_session_state_t session_state;
     126              :     const uint8_t *ptr;
     127              :     const uint8_t *ep_info_data;
     128              :     uint32_t ep_info_data_len;
     129              :     size_t signature_size;
     130              :     const void *signature;
     131              :     uint8_t slot_id;
     132              :     bool result;
     133              :     uint8_t request_attributes;
     134              : 
     135           16 :     LIBSPDM_ASSERT(spdm_context->get_endpoint_info_callback != NULL);
     136              : 
     137           16 :     if (spdm_context->last_spdm_request_session_id_valid) {
     138            0 :         session_id = spdm_context->last_spdm_request_session_id;
     139            0 :         session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
     140            0 :         if (session_info == NULL) {
     141            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     142              :         }
     143            0 :         session_state = libspdm_secured_message_get_session_state(
     144              :             session_info->secured_message_context);
     145            0 :         if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
     146            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     147              :         }
     148              :     } else {
     149           16 :         session_info = NULL;
     150              :     }
     151              : 
     152           16 :     spdm_request =
     153              :         (void *)&spdm_context->encap_context.last_encap_request_header;
     154              : 
     155           16 :     spdm_response = encap_response;
     156           16 :     spdm_response_size = encap_response_size;
     157              : 
     158           16 :     if (spdm_response->header.spdm_version != libspdm_get_connection_version (spdm_context)) {
     159            1 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     160              :     }
     161              : 
     162           15 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     163            2 :         status = libspdm_handle_encap_error_response_main(spdm_response->header.param1);
     164            2 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     165            2 :             return status;
     166              :         }
     167           13 :     } else if (spdm_response->header.request_response_code != SPDM_ENDPOINT_INFO) {
     168            1 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     169              :     }
     170              : 
     171           12 :     if (spdm_response_size < sizeof(spdm_endpoint_info_response_t) + sizeof(uint32_t)) {
     172            0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     173              :     }
     174              : 
     175           12 :     slot_id = spdm_context->encap_context.req_slot_id & SPDM_GET_ENDPOINT_INFO_REQUEST_SLOT_ID_MASK;
     176              : 
     177              :     /* request signature if requester support */
     178           12 :     if (libspdm_is_capabilities_flag_supported(
     179              :             spdm_context, false,
     180              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP_SIG, 0)) {
     181            8 :         if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
     182            0 :             signature_size = libspdm_get_req_pqc_asym_signature_size(
     183              :                 spdm_context->connection_info.algorithm.req_pqc_asym_alg);
     184              :         } else {
     185            8 :             signature_size = libspdm_get_req_asym_signature_size(
     186            8 :                 spdm_context->connection_info.algorithm.req_base_asym_alg);
     187              :         }
     188            8 :         request_attributes = SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED;
     189              : 
     190            8 :         if ((spdm_response->header.param2 & SPDM_ENDPOINT_INFO_RESPONSE_SLOT_ID_MASK) != slot_id) {
     191            1 :             return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     192              :         }
     193              : 
     194            7 :         if (spdm_response_size <
     195            7 :             sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE + signature_size) {
     196            1 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     197              :         }
     198              : 
     199            6 :         ptr = (const uint8_t *)(spdm_response + 1);
     200            6 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Encap ResponderNonce (0x%x) - ", SPDM_NONCE_SIZE));
     201            6 :         LIBSPDM_INTERNAL_DUMP_DATA(ptr, SPDM_NONCE_SIZE);
     202            6 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     203              : 
     204            6 :         ptr += SPDM_NONCE_SIZE;
     205            6 :         ep_info_data_len = *(const uint32_t *) ptr;
     206              : 
     207            6 :         if (spdm_response_size !=
     208              :             sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE +
     209            6 :             signature_size + ep_info_data_len + sizeof(uint32_t)) {
     210            1 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     211              :         }
     212            5 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ep_info_data_len - 0x%06x\n",
     213              :                        ep_info_data_len));
     214            5 :         ptr += sizeof(uint32_t);
     215            5 :         ep_info_data = ptr;
     216              : 
     217            5 :         status = libspdm_append_message_encap_e(spdm_context, session_info, spdm_response,
     218              :                                                 spdm_response_size - signature_size);
     219            5 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     220            0 :             return status;
     221              :         }
     222              : 
     223            5 :         ptr += ep_info_data_len;
     224            5 :         signature = ptr;
     225            5 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature (0x%zx):\n", signature_size));
     226            5 :         LIBSPDM_INTERNAL_DUMP_HEX(signature, signature_size);
     227              : 
     228            5 :         result = libspdm_verify_endpoint_info_signature(
     229              :             spdm_context, session_info, false, slot_id, signature, signature_size);
     230            5 :         if (!result) {
     231            1 :             return LIBSPDM_STATUS_VERIF_FAIL;
     232              :         }
     233              : 
     234            4 :         libspdm_reset_message_encap_e(spdm_context, session_info);
     235              :     } else {
     236            4 :         request_attributes = 0;
     237              : 
     238              :         /* responder's slot_id should be 0 */
     239            4 :         if ((spdm_response->header.param2 & SPDM_ENDPOINT_INFO_RESPONSE_SLOT_ID_MASK) != 0) {
     240            1 :             return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     241              :         }
     242              : 
     243              :         /* nonce and signature not present */
     244            3 :         ptr = (const uint8_t *)(spdm_response + 1);
     245            3 :         ep_info_data_len = *(const uint32_t *) ptr;
     246            3 :         if (spdm_response_size <
     247            3 :             sizeof(spdm_endpoint_info_response_t) + ep_info_data_len + sizeof(uint32_t)) {
     248            2 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     249              :         }
     250              : 
     251            1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ep_info_data_len - 0x%06x\n",
     252              :                        ep_info_data_len));
     253            1 :         ptr += sizeof(uint32_t);
     254            1 :         ep_info_data = ptr;
     255              :     }
     256              : 
     257            5 :     *need_continue = false;
     258              : 
     259            5 :     status = spdm_context->get_endpoint_info_callback(
     260            5 :         spdm_context, spdm_request->header.param1, spdm_request->header.param2,
     261              :         request_attributes, ep_info_data_len, ep_info_data);
     262              : 
     263            5 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     264            0 :         return status;
     265              :     }
     266              : 
     267            5 :     return LIBSPDM_STATUS_SUCCESS;
     268              : }
     269              : 
     270              : #endif /* (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (...) */
        

Generated by: LCOV version 2.0-1