LCOV - code coverage report
Current view: top level - library/spdm_requester_lib - libspdm_req_get_csr.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 68.5 % 130 89
Test Date: 2025-10-12 08:10:56 Functions: 100.0 % 3 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              : 
       9              : #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP
      10              : 
      11              : /**
      12              :  * This function sends GET_CSR
      13              :  * to get csr from the device.
      14              :  *
      15              :  * @param[in]  context                      A pointer to the SPDM context.
      16              :  * @param[in]  session_id                   Indicates if it is a secured message protected via SPDM session.
      17              :  *                                          If session_id is NULL, it is a normal message.
      18              :  *                                          If session_id is NOT NULL, it is a secured message.
      19              :  * @param[in]  requester_info               requester info to gen CSR
      20              :  * @param[in]  requester_info_length        The len of requester info
      21              :  * @param[in]  opaque_data                  opaque data
      22              :  * @param[in]  opaque_data_length           The len of opaque data
      23              :  * @param[out] csr                          address to store CSR.
      24              :  * @param[in, out] csr_len                  on input, *csr_len indicates the max csr buffer size.
      25              :  *                                          on output, *csr_len indicates the actual csr buffer size.
      26              :  * @param[in]  request_attribute            Set certificate request attributes. This field is only used for SPDM 1.3 and above.
      27              :  * @param[in]  key_pair_id                  The value of this field shall be the unique key pair number identifying the desired
      28              :  *                                          asymmetric key pair to associate with SlotID .
      29              :  * @param[out] available_csr_tracking_tag   available CSRTrackingTag when the Responder sends a ResetRequired error message
      30              :  **/
      31            8 : static libspdm_return_t libspdm_try_get_csr(libspdm_context_t *spdm_context,
      32              :                                             const uint32_t *session_id,
      33              :                                             void *requester_info, uint16_t requester_info_length,
      34              :                                             void *opaque_data, uint16_t opaque_data_length,
      35              :                                             void *csr, size_t *csr_len,
      36              :                                             uint8_t request_attribute,
      37              :                                             uint8_t key_pair_id,
      38              :                                             uint8_t *available_csr_tracking_tag)
      39              : {
      40              :     libspdm_return_t status;
      41              :     libspdm_return_t warning;
      42              :     spdm_get_csr_request_t *spdm_request;
      43              :     size_t spdm_request_size;
      44              :     spdm_csr_response_t *spdm_response;
      45              :     size_t spdm_response_size;
      46              :     size_t transport_header_size;
      47              :     uint8_t *message;
      48              :     size_t message_size;
      49              :     libspdm_session_info_t *session_info;
      50              :     libspdm_session_state_t session_state;
      51              : 
      52            8 :     warning = LIBSPDM_STATUS_SUCCESS;
      53              : 
      54            8 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_12) {
      55            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
      56              :     }
      57            8 :     if (libspdm_get_connection_version(spdm_context) == SPDM_MESSAGE_VERSION_12) {
      58            5 :         if ((key_pair_id != 0) || (request_attribute != 0)) {
      59            0 :             return LIBSPDM_STATUS_INVALID_PARAMETER;
      60              :         }
      61              :     }
      62              : 
      63            8 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
      64            3 :         const uint8_t csr_cert_model = request_attribute &
      65              :                                        SPDM_GET_CSR_REQUEST_ATTRIBUTES_CERT_MODEL_MASK;
      66              : 
      67              :         /* CSR_CAP for a 1.2 Responder is not checked because it was not defined in SPDM 1.2.0. */
      68            3 :         if (!libspdm_is_capabilities_flag_supported(
      69              :                 spdm_context, true, 0,
      70              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CSR_CAP)) {
      71            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
      72              :         }
      73            3 :         if (spdm_context->connection_info.multi_key_conn_rsp) {
      74            1 :             if (key_pair_id == 0) {
      75            0 :                 return LIBSPDM_STATUS_INVALID_PARAMETER;
      76              :             }
      77            1 :             if ((csr_cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) ||
      78              :                 (csr_cert_model > SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
      79            1 :                 return LIBSPDM_STATUS_INVALID_PARAMETER;
      80              :             }
      81              :         } else {
      82            2 :             if ((key_pair_id != 0) || (csr_cert_model != 0)) {
      83            0 :                 return LIBSPDM_STATUS_INVALID_PARAMETER;
      84              :             }
      85              :         }
      86              :     }
      87              : 
      88            7 :     LIBSPDM_ASSERT(opaque_data_length < SPDM_MAX_OPAQUE_DATA_SIZE);
      89              : 
      90            7 :     if (spdm_context->connection_info.connection_state <
      91              :         LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
      92            0 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
      93              :     }
      94              : 
      95            7 :     if (session_id != NULL) {
      96            0 :         session_info = libspdm_get_session_info_via_session_id(
      97              :             spdm_context, *session_id);
      98            0 :         if (session_info == NULL) {
      99            0 :             LIBSPDM_ASSERT(false);
     100            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     101              :         }
     102            0 :         session_state = libspdm_secured_message_get_session_state(
     103              :             session_info->secured_message_context);
     104            0 :         if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
     105            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     106              :         }
     107              :     }
     108              : 
     109            7 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
     110            7 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     111            7 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     112            0 :         return status;
     113              :     }
     114            7 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
     115              :                     spdm_context->local_context.capability.transport_tail_size);
     116            7 :     spdm_request = (void *)(message + transport_header_size);
     117            7 :     spdm_request_size = message_size - transport_header_size -
     118            7 :                         spdm_context->local_context.capability.transport_tail_size;
     119              : 
     120            7 :     LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_csr_request_t) + opaque_data_length
     121              :                     + requester_info_length);
     122            7 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     123            7 :     spdm_request->header.request_response_code = SPDM_GET_CSR;
     124            7 :     spdm_request->header.param1 = key_pair_id;
     125            7 :     spdm_request->header.param2 = request_attribute;
     126              : 
     127            7 :     spdm_request->opaque_data_length = opaque_data_length;
     128            7 :     spdm_request->requester_info_length = requester_info_length;
     129              : 
     130            7 :     if (requester_info_length != 0) {
     131            2 :         libspdm_copy_mem(spdm_request + 1,
     132              :                          spdm_request_size - sizeof(spdm_get_csr_request_t),
     133              :                          (uint8_t *)requester_info, requester_info_length);
     134              :     }
     135              : 
     136            7 :     if (((spdm_context->connection_info.algorithm.other_params_support &
     137            4 :           SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE) &&
     138              :         (opaque_data_length != 0)) {
     139            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Overriding opaque_data_length to 0 since there is "
     140              :                        "no negotiated opaque data format.\n"));
     141            0 :         opaque_data_length = 0;
     142            0 :         warning = LIBSPDM_STATUS_OVERRIDDEN_PARAMETER;
     143              :     }
     144              : 
     145            7 :     if (opaque_data_length != 0) {
     146            2 :         libspdm_copy_mem((uint8_t *)(spdm_request + 1) + requester_info_length,
     147            2 :                          spdm_request_size - sizeof(spdm_get_csr_request_t) - requester_info_length,
     148              :                          (uint8_t *)opaque_data, opaque_data_length);
     149              :     }
     150              : 
     151            7 :     spdm_request_size = sizeof(spdm_get_csr_request_t) + opaque_data_length
     152            7 :                         + requester_info_length;
     153              : 
     154            7 :     status = libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request);
     155            7 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     156            1 :         libspdm_release_sender_buffer (spdm_context);
     157            1 :         return status;
     158              :     }
     159            6 :     libspdm_release_sender_buffer (spdm_context);
     160            6 :     spdm_request = (void *)spdm_context->last_spdm_request;
     161              : 
     162              :     /* receive */
     163            6 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     164            6 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     165            0 :         return status;
     166              :     }
     167            6 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
     168            6 :     spdm_response = (void *)(message);
     169            6 :     spdm_response_size = message_size;
     170              : 
     171            6 :     status = libspdm_receive_spdm_response(spdm_context, session_id,
     172              :                                            &spdm_response_size, (void **)&spdm_response);
     173              : 
     174            6 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     175            0 :         goto receive_done;
     176              :     }
     177            6 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     178            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     179            0 :         goto receive_done;
     180              :     }
     181            6 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     182            6 :         if ((spdm_response->header.param1 == SPDM_ERROR_CODE_RESET_REQUIRED) &&
     183            5 :             (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) &&
     184              :             (available_csr_tracking_tag != NULL)) {
     185            1 :             *available_csr_tracking_tag = spdm_response->header.param2;
     186              :         }
     187              : 
     188            3 :         status = libspdm_handle_error_response_main(
     189              :             spdm_context, session_id,
     190              :             &spdm_response_size,
     191              :             (void **)&spdm_response, SPDM_GET_CSR, SPDM_CSR);
     192            3 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     193            3 :             goto receive_done;
     194              :         }
     195            3 :     } else if (spdm_response->header.request_response_code != SPDM_CSR) {
     196            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     197            0 :         goto receive_done;
     198              :     }
     199            3 :     if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     200            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     201            0 :         goto receive_done;
     202              :     }
     203              : 
     204            3 :     if (spdm_response_size < sizeof(spdm_csr_response_t)) {
     205            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     206            0 :         goto receive_done;
     207              :     }
     208            3 :     if (spdm_response->csr_length == 0) {
     209            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     210            0 :         goto receive_done;
     211              :     }
     212              : 
     213            3 :     if (spdm_response_size < sizeof(spdm_csr_response_t) + spdm_response->csr_length) {
     214            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     215            0 :         goto receive_done;
     216              :     }
     217            3 :     if (*csr_len < spdm_response->csr_length) {
     218            0 :         *csr_len = spdm_response->csr_length;
     219            0 :         status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     220            0 :         goto receive_done;
     221              :     }
     222              : 
     223            3 :     libspdm_copy_mem(csr, *csr_len, spdm_response + 1, spdm_response->csr_length);
     224            3 :     *csr_len = spdm_response->csr_length;
     225              : 
     226            3 :     status = LIBSPDM_STATUS_SUCCESS;
     227              : 
     228            6 : receive_done:
     229            6 :     libspdm_release_receiver_buffer (spdm_context);
     230              : 
     231            6 :     if (LIBSPDM_STATUS_IS_SUCCESS(status) && LIBSPDM_STATUS_IS_WARNING(warning)) {
     232            0 :         status = warning;
     233              :     }
     234            6 :     return status;
     235              : }
     236              : 
     237            6 : libspdm_return_t libspdm_get_csr(void * spdm_context,
     238              :                                  const uint32_t *session_id,
     239              :                                  void * requester_info, uint16_t requester_info_length,
     240              :                                  void * opaque_data, uint16_t opaque_data_length,
     241              :                                  void *csr, size_t *csr_len)
     242              : {
     243              :     libspdm_context_t *context;
     244              :     size_t retry;
     245              :     uint64_t retry_delay_time;
     246              :     libspdm_return_t status;
     247              : 
     248            6 :     context = spdm_context;
     249            6 :     context->crypto_request = true;
     250            6 :     retry = context->retry_times;
     251            6 :     retry_delay_time = context->retry_delay_time;
     252              :     do {
     253            6 :         status = libspdm_try_get_csr(context, session_id,
     254              :                                      requester_info, requester_info_length,
     255              :                                      opaque_data, opaque_data_length,
     256              :                                      csr, csr_len,
     257              :                                      0, 0, NULL);
     258            6 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     259            6 :             return status;
     260              :         }
     261              : 
     262            0 :         libspdm_sleep(retry_delay_time);
     263            0 :     } while (retry-- != 0);
     264              : 
     265            0 :     return status;
     266              : }
     267              : 
     268              : #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX
     269            2 : libspdm_return_t libspdm_get_csr_ex(void * spdm_context,
     270              :                                     const uint32_t *session_id,
     271              :                                     void * requester_info, uint16_t requester_info_length,
     272              :                                     void * opaque_data, uint16_t opaque_data_length,
     273              :                                     void *csr, size_t *csr_len,
     274              :                                     uint8_t request_attribute,
     275              :                                     uint8_t key_pair_id,
     276              :                                     uint8_t *available_csr_tracking_tag
     277              :                                     )
     278              : {
     279              :     libspdm_context_t *context;
     280              :     size_t retry;
     281              :     uint64_t retry_delay_time;
     282              :     libspdm_return_t status;
     283              : 
     284            2 :     context = spdm_context;
     285            2 :     context->crypto_request = true;
     286            2 :     retry = context->retry_times;
     287            2 :     retry_delay_time = context->retry_delay_time;
     288              :     do {
     289            2 :         status = libspdm_try_get_csr(context, session_id,
     290              :                                      requester_info, requester_info_length,
     291              :                                      opaque_data, opaque_data_length,
     292              :                                      csr, csr_len,
     293              :                                      request_attribute, key_pair_id,
     294              :                                      available_csr_tracking_tag);
     295            2 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     296            2 :             return status;
     297              :         }
     298              : 
     299            0 :         libspdm_sleep(retry_delay_time);
     300            0 :     } while (retry-- != 0);
     301              : 
     302            0 :     return status;
     303              : }
     304              : #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX*/
     305              : 
     306              : #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP*/
        

Generated by: LCOV version 2.0-1