LCOV - code coverage report
Current view: top level - library/spdm_responder_lib - libspdm_rsp_certificate.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 75.5 % 98 74
Test Date: 2025-08-24 08:11:14 Functions: 100.0 % 1 1

            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              : #include "internal/libspdm_responder_lib.h"
       7              : 
       8              : #if LIBSPDM_ENABLE_CAPABILITY_CERT_CAP
       9              : 
      10         1650 : libspdm_return_t libspdm_get_response_certificate(libspdm_context_t *spdm_context,
      11              :                                                   size_t request_size,
      12              :                                                   const void *request,
      13              :                                                   size_t *response_size,
      14              :                                                   void *response)
      15              : {
      16              :     const spdm_get_certificate_large_request_t *spdm_request;
      17              :     spdm_certificate_large_response_t *spdm_response;
      18              :     uint32_t offset;
      19              :     uint32_t length;
      20              :     uint32_t remainder_length;
      21              :     uint8_t slot_id;
      22              :     libspdm_return_t status;
      23              :     size_t response_capacity;
      24              :     libspdm_session_info_t *session_info;
      25              :     libspdm_session_state_t session_state;
      26              :     bool use_large_cert_chain;
      27              :     uint32_t req_msg_header_size;
      28              :     uint32_t rsp_msg_header_size;
      29              :     size_t cert_chain_size;
      30              : 
      31         1650 :     spdm_request = request;
      32              : 
      33              :     /* -=[Check Parameters Phase]=- */
      34         1650 :     LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_GET_CERTIFICATE);
      35              : 
      36         1650 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
      37            0 :         return libspdm_generate_error_response(spdm_context,
      38              :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
      39              :                                                response_size, response);
      40              :     }
      41         1650 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
      42            3 :         return libspdm_responder_handle_response_state(
      43              :             spdm_context,
      44            3 :             spdm_request->header.request_response_code,
      45              :             response_size, response);
      46              :     }
      47         1647 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
      48            1 :         return libspdm_generate_error_response(spdm_context,
      49              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
      50              :                                                0, response_size, response);
      51              :     }
      52         1646 :     session_info = NULL;
      53         1646 :     if (spdm_context->last_spdm_request_session_id_valid) {
      54            6 :         session_info = libspdm_get_session_info_via_session_id(
      55              :             spdm_context,
      56              :             spdm_context->last_spdm_request_session_id);
      57            6 :         if (session_info == NULL) {
      58            0 :             return libspdm_generate_error_response(
      59              :                 spdm_context,
      60              :                 SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
      61              :                 response_size, response);
      62              :         }
      63            6 :         session_state = libspdm_secured_message_get_session_state(
      64              :             session_info->secured_message_context);
      65            6 :         if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
      66            0 :             return libspdm_generate_error_response(
      67              :                 spdm_context,
      68              :                 SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
      69              :                 response_size, response);
      70              :         }
      71              :     }
      72         1646 :     if (!libspdm_is_capabilities_flag_supported(
      73              :             spdm_context, false, 0,
      74              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP)) {
      75            0 :         return libspdm_generate_error_response(
      76              :             spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
      77              :             SPDM_GET_CERTIFICATE, response_size, response);
      78              :     }
      79              : 
      80         1646 :     if ((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_14) &&
      81            0 :         ((spdm_request->header.param1 & SPDM_GET_CERTIFICATE_REQUEST_LARGE_CERT_CHAIN) != 0)) {
      82            0 :         if (!libspdm_is_capabilities_flag_supported(
      83              :                 spdm_context, false, 0,
      84              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_LARGE_RESP_CAP)) {
      85            0 :             return libspdm_generate_error_response(
      86              :                 spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
      87              :                 SPDM_GET_CERTIFICATE, response_size, response);
      88              :         }
      89            0 :         use_large_cert_chain = true;
      90              :     } else {
      91         1646 :         use_large_cert_chain = false;
      92              :     }
      93              : 
      94         1646 :     if (use_large_cert_chain) {
      95            0 :         req_msg_header_size = sizeof(spdm_get_certificate_large_request_t);
      96            0 :         rsp_msg_header_size = sizeof(spdm_certificate_large_response_t);
      97              :     } else {
      98         1646 :         req_msg_header_size = sizeof(spdm_get_certificate_request_t);
      99         1646 :         rsp_msg_header_size = sizeof(spdm_certificate_response_t);
     100              :     }
     101              : 
     102         1646 :     if (request_size < req_msg_header_size) {
     103            0 :         return libspdm_generate_error_response(spdm_context,
     104              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     105              :                                                response_size, response);
     106              :     }
     107              : 
     108         1646 :     slot_id = spdm_request->header.param1 & SPDM_GET_CERTIFICATE_REQUEST_SLOT_ID_MASK;
     109              : 
     110         1646 :     if (slot_id >= SPDM_MAX_SLOT_COUNT) {
     111            1 :         return libspdm_generate_error_response(spdm_context,
     112              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     113              :                                                response_size, response);
     114              :     }
     115              : 
     116         1645 :     if ((spdm_context->local_context.cert_slot_reset_mask & (1 << slot_id)) != 0) {
     117            1 :         LIBSPDM_ASSERT(spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12);
     118            1 :         return libspdm_generate_error_response(spdm_context,
     119              :                                                SPDM_ERROR_CODE_RESET_REQUIRED, 0,
     120              :                                                response_size, response);
     121              :     }
     122              : 
     123         1644 :     if (spdm_context->local_context.local_cert_chain_provision[slot_id] == NULL) {
     124            0 :         return libspdm_generate_error_response(
     125              :             spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
     126              :             0, response_size, response);
     127              :     }
     128              : 
     129         1644 :     cert_chain_size = spdm_context->local_context.local_cert_chain_provision_size[slot_id];
     130              : 
     131         1644 :     if ((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_14) &&
     132            0 :         (!use_large_cert_chain) && (cert_chain_size > SPDM_MAX_CERTIFICATE_CHAIN_SIZE)) {
     133            0 :         return libspdm_generate_extended_error_response(
     134              :             spdm_context, SPDM_ERROR_CODE_DATA_TOO_LARGE, 0,
     135              :             sizeof(spdm_error_data_cert_chain_too_large_t),
     136              :             (const uint8_t *)&cert_chain_size,
     137              :             response_size, response);
     138              :     }
     139              : 
     140         1644 :     if (use_large_cert_chain) {
     141            0 :         offset = spdm_request->large_offset;
     142            0 :         length = spdm_request->large_length;
     143              :     } else {
     144         1644 :         offset = spdm_request->offset;
     145         1644 :         length = spdm_request->length;
     146              :     }
     147              : 
     148         1644 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     149            1 :         if (spdm_request->header.param2 &
     150              :             SPDM_GET_CERTIFICATE_REQUEST_ATTRIBUTES_SLOT_SIZE_REQUESTED) {
     151            1 :             offset = 0;
     152            1 :             length = 0;
     153              :         }
     154              :     }
     155              : 
     156         1644 :     if (offset >= cert_chain_size) {
     157          126 :         return libspdm_generate_error_response(spdm_context,
     158              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     159              :                                                response_size, response);
     160              :     }
     161              : 
     162         1518 :     if (!libspdm_is_capabilities_flag_supported(spdm_context, false,
     163              :                                                 SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP,
     164              :                                                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP)) {
     165         1515 :         if (length > LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN) {
     166           67 :             length = LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN;
     167              :         }
     168              :     }
     169         1518 :     if ((size_t)(offset + length) > cert_chain_size) {
     170           18 :         length = (uint32_t)(cert_chain_size - offset);
     171              :     }
     172         1518 :     remainder_length = (uint32_t)(cert_chain_size - (length + offset));
     173              : 
     174         1518 :     libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
     175         1518 :                                                   spdm_request->header.request_response_code);
     176              : 
     177         1518 :     LIBSPDM_ASSERT(*response_size >= rsp_msg_header_size + length);
     178         1518 :     response_capacity = *response_size;
     179         1518 :     *response_size = rsp_msg_header_size + length;
     180         1518 :     libspdm_zero_mem(response, *response_size);
     181         1518 :     spdm_response = response;
     182              : 
     183         1518 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     184         1518 :     spdm_response->header.request_response_code = SPDM_CERTIFICATE;
     185         1518 :     spdm_response->header.param1 = slot_id;
     186         1518 :     spdm_response->header.param2 = 0;
     187         1518 :     if ((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
     188            1 :         spdm_context->connection_info.multi_key_conn_rsp) {
     189            0 :         spdm_response->header.param2 = spdm_context->local_context.local_cert_info[slot_id];
     190              :     }
     191         1518 :     if (use_large_cert_chain) {
     192            0 :         spdm_response->header.param1 |= SPDM_CERTIFICATE_RESPONSE_LARGE_CERT_CHAIN;
     193              :     }
     194              : 
     195         1518 :     if (use_large_cert_chain) {
     196            0 :         spdm_response->portion_length = 0;
     197            0 :         spdm_response->remainder_length = 0;
     198            0 :         spdm_response->large_portion_length = length;
     199            0 :         spdm_response->large_remainder_length = remainder_length;
     200              :     } else {
     201         1518 :         spdm_response->portion_length = (uint16_t)length;
     202         1518 :         spdm_response->remainder_length = (uint16_t)remainder_length;
     203              :     }
     204              : 
     205         1518 :     libspdm_copy_mem((uint8_t *)spdm_response + rsp_msg_header_size,
     206              :                      response_capacity - rsp_msg_header_size,
     207              :                      (const uint8_t *)spdm_context->local_context
     208         1518 :                      .local_cert_chain_provision[slot_id] + offset, length);
     209              : 
     210         1518 :     if (session_info == NULL) {
     211              :         /* Log to transcript. */
     212         1514 :         const size_t spdm_request_size = req_msg_header_size;
     213              : 
     214         1514 :         status = libspdm_append_message_b(spdm_context, spdm_request, spdm_request_size);
     215         1514 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     216            0 :             return libspdm_generate_error_response(spdm_context,
     217              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     218              :                                                    response_size, response);
     219              :         }
     220              : 
     221         1514 :         status = libspdm_append_message_b(spdm_context, spdm_response, *response_size);
     222         1514 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     223            0 :             return libspdm_generate_error_response(spdm_context,
     224              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     225              :                                                    response_size, response);
     226              :         }
     227              :     }
     228              : 
     229         1518 :     if (spdm_context->connection_info.connection_state <
     230              :         LIBSPDM_CONNECTION_STATE_AFTER_CERTIFICATE) {
     231           13 :         libspdm_set_connection_state(spdm_context, LIBSPDM_CONNECTION_STATE_AFTER_CERTIFICATE);
     232              :     }
     233              : 
     234         1518 :     return LIBSPDM_STATUS_SUCCESS;
     235              : }
     236              : 
     237              : #endif /* LIBSPDM_ENABLE_CAPABILITY_CERT_CAP */
        

Generated by: LCOV version 2.0-1