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: 80.5 % 128 103
Test Date: 2025-06-29 08:09:00 Functions: 66.7 % 3 2

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 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_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(
     164            2 :             spdm_context, spdm_response->header.param1);
     165            2 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     166            2 :             return status;
     167              :         }
     168           13 :     } else if (spdm_response->header.request_response_code != SPDM_ENDPOINT_INFO) {
     169            1 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     170              :     }
     171              : 
     172           12 :     if (spdm_response_size < sizeof(spdm_endpoint_info_response_t) + sizeof(uint32_t)) {
     173            0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     174              :     }
     175              : 
     176           12 :     slot_id = spdm_context->encap_context.req_slot_id & SPDM_GET_ENDPOINT_INFO_REQUEST_SLOT_ID_MASK;
     177           12 :     spdm_context->connection_info.peer_used_cert_chain_slot_id = slot_id;
     178              : 
     179              :     /* request signature if requester support */
     180           12 :     if (libspdm_is_capabilities_flag_supported(
     181              :             spdm_context, false,
     182              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP_SIG, 0)) {
     183           16 :         signature_size = libspdm_get_req_asym_signature_size(
     184            8 :             spdm_context->connection_info.algorithm.req_base_asym_alg);
     185            8 :         request_attributes = SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED;
     186              : 
     187            8 :         if ((spdm_response->header.param2 & SPDM_ENDPOINT_INFO_RESPONSE_SLOT_ID_MASK) != slot_id) {
     188            1 :             return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     189              :         }
     190              : 
     191            7 :         if (spdm_response_size <
     192            7 :             sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE + signature_size) {
     193            1 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     194              :         }
     195              : 
     196            6 :         ptr = (const uint8_t *)(spdm_response + 1);
     197            6 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Encap ResponderNonce (0x%x) - ", SPDM_NONCE_SIZE));
     198            6 :         LIBSPDM_INTERNAL_DUMP_DATA(ptr, SPDM_NONCE_SIZE);
     199            6 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     200              : 
     201            6 :         ptr += SPDM_NONCE_SIZE;
     202            6 :         ep_info_data_len = *(const uint32_t *) ptr;
     203              : 
     204            6 :         if (spdm_response_size !=
     205              :             sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE +
     206            6 :             signature_size + ep_info_data_len + sizeof(uint32_t)) {
     207            1 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     208              :         }
     209            5 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ep_info_data_len - 0x%06x\n",
     210              :                        ep_info_data_len));
     211            5 :         ptr += sizeof(uint32_t);
     212            5 :         ep_info_data = ptr;
     213              : 
     214            5 :         status = libspdm_append_message_encap_e(spdm_context, session_info, spdm_response,
     215              :                                                 spdm_response_size - signature_size);
     216            5 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     217            0 :             return status;
     218              :         }
     219              : 
     220            5 :         ptr += ep_info_data_len;
     221            5 :         signature = ptr;
     222            5 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature (0x%zx):\n", signature_size));
     223            5 :         LIBSPDM_INTERNAL_DUMP_HEX(signature, signature_size);
     224              : 
     225            5 :         result = libspdm_verify_endpoint_info_signature(
     226              :             spdm_context, session_info, false, signature, signature_size);
     227            5 :         if (!result) {
     228            1 :             return LIBSPDM_STATUS_VERIF_FAIL;
     229              :         }
     230              : 
     231            4 :         libspdm_reset_message_encap_e(spdm_context, session_info);
     232              :     } else {
     233            4 :         request_attributes = 0;
     234              : 
     235              :         /* responder's slot_id should be 0 */
     236            4 :         if ((spdm_response->header.param2 & SPDM_ENDPOINT_INFO_RESPONSE_SLOT_ID_MASK) != 0) {
     237            1 :             return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     238              :         }
     239              : 
     240              :         /* nonce and signature not present */
     241            3 :         ptr = (const uint8_t *)(spdm_response + 1);
     242            3 :         ep_info_data_len = *(const uint32_t *) ptr;
     243            3 :         if (spdm_response_size <
     244            3 :             sizeof(spdm_endpoint_info_response_t) + ep_info_data_len + sizeof(uint32_t)) {
     245            2 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     246              :         }
     247              : 
     248            1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ep_info_data_len - 0x%06x\n",
     249              :                        ep_info_data_len));
     250            1 :         ptr += sizeof(uint32_t);
     251            1 :         ep_info_data = ptr;
     252              :     }
     253              : 
     254            5 :     *need_continue = false;
     255              : 
     256            5 :     status = spdm_context->get_endpoint_info_callback(
     257            5 :         spdm_context, spdm_request->header.param1, spdm_request->header.param2,
     258              :         request_attributes, ep_info_data_len, ep_info_data);
     259              : 
     260            5 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     261            0 :         return status;
     262              :     }
     263              : 
     264            5 :     return LIBSPDM_STATUS_SUCCESS;
     265              : }
     266              : 
     267              : #endif /* (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (...) */
        

Generated by: LCOV version 2.0-1