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-06-29 08:09:00 Functions: 100.0 % 3 3

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2024 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              :  * @retval RETURN_SUCCESS               The measurement is got successfully.
      32              :  * @retval RETURN_DEVICE_ERROR          A device error occurs when communicates with the device.
      33              :  * @retval RETURN_SECURITY_VIOLATION    Any verification fails.
      34              :  **/
      35            8 : static libspdm_return_t libspdm_try_get_csr(libspdm_context_t *spdm_context,
      36              :                                             const uint32_t *session_id,
      37              :                                             void *requester_info, uint16_t requester_info_length,
      38              :                                             void *opaque_data, uint16_t opaque_data_length,
      39              :                                             void *csr, size_t *csr_len,
      40              :                                             uint8_t request_attribute,
      41              :                                             uint8_t key_pair_id,
      42              :                                             uint8_t *available_csr_tracking_tag)
      43              : {
      44              :     libspdm_return_t status;
      45              :     libspdm_return_t warning;
      46              :     spdm_get_csr_request_t *spdm_request;
      47              :     size_t spdm_request_size;
      48              :     spdm_csr_response_t *spdm_response;
      49              :     size_t spdm_response_size;
      50              :     size_t transport_header_size;
      51              :     uint8_t *message;
      52              :     size_t message_size;
      53              :     libspdm_session_info_t *session_info;
      54              :     libspdm_session_state_t session_state;
      55              : 
      56            8 :     warning = LIBSPDM_STATUS_SUCCESS;
      57              : 
      58            8 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_12) {
      59            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
      60              :     }
      61            8 :     if (libspdm_get_connection_version(spdm_context) == SPDM_MESSAGE_VERSION_12) {
      62            5 :         if ((key_pair_id != 0) || (request_attribute != 0)) {
      63            0 :             return LIBSPDM_STATUS_INVALID_PARAMETER;
      64              :         }
      65              :     }
      66              : 
      67            8 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
      68            3 :         const uint8_t csr_cert_model = request_attribute &
      69              :                                        SPDM_GET_CSR_REQUEST_ATTRIBUTES_CERT_MODEL_MASK;
      70              : 
      71              :         /* CSR_CAP for a 1.2 Responder is not checked because it was not defined in SPDM 1.2.0. */
      72            3 :         if (!libspdm_is_capabilities_flag_supported(
      73              :                 spdm_context, true, 0,
      74              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CSR_CAP)) {
      75            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
      76              :         }
      77            3 :         if (spdm_context->connection_info.multi_key_conn_rsp) {
      78            1 :             if (key_pair_id == 0) {
      79            0 :                 return LIBSPDM_STATUS_INVALID_PARAMETER;
      80              :             }
      81            1 :             if ((csr_cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) ||
      82              :                 (csr_cert_model > SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
      83            1 :                 return LIBSPDM_STATUS_INVALID_PARAMETER;
      84              :             }
      85              :         } else {
      86            2 :             if ((key_pair_id != 0) || (csr_cert_model != 0)) {
      87            0 :                 return LIBSPDM_STATUS_INVALID_PARAMETER;
      88              :             }
      89              :         }
      90              :     }
      91              : 
      92            7 :     LIBSPDM_ASSERT(opaque_data_length < SPDM_MAX_OPAQUE_DATA_SIZE);
      93              : 
      94            7 :     if (spdm_context->connection_info.connection_state <
      95              :         LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
      96            0 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
      97              :     }
      98              : 
      99            7 :     if (session_id != NULL) {
     100            0 :         session_info = libspdm_get_session_info_via_session_id(
     101              :             spdm_context, *session_id);
     102            0 :         if (session_info == NULL) {
     103            0 :             LIBSPDM_ASSERT(false);
     104            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     105              :         }
     106            0 :         session_state = libspdm_secured_message_get_session_state(
     107              :             session_info->secured_message_context);
     108            0 :         if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
     109            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     110              :         }
     111              :     }
     112              : 
     113            7 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
     114            7 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     115            7 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     116            0 :         return status;
     117              :     }
     118            7 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
     119              :                     spdm_context->local_context.capability.transport_tail_size);
     120            7 :     spdm_request = (void *)(message + transport_header_size);
     121            7 :     spdm_request_size = message_size - transport_header_size -
     122            7 :                         spdm_context->local_context.capability.transport_tail_size;
     123              : 
     124            7 :     LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_csr_request_t) + opaque_data_length
     125              :                     + requester_info_length);
     126            7 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     127            7 :     spdm_request->header.request_response_code = SPDM_GET_CSR;
     128            7 :     spdm_request->header.param1 = key_pair_id;
     129            7 :     spdm_request->header.param2 = request_attribute;
     130              : 
     131            7 :     spdm_request->opaque_data_length = opaque_data_length;
     132            7 :     spdm_request->requester_info_length = requester_info_length;
     133              : 
     134            7 :     if (requester_info_length != 0) {
     135            2 :         libspdm_copy_mem(spdm_request + 1,
     136              :                          spdm_request_size - sizeof(spdm_get_csr_request_t),
     137              :                          (uint8_t *)requester_info, requester_info_length);
     138              :     }
     139              : 
     140            7 :     if (((spdm_context->connection_info.algorithm.other_params_support &
     141            4 :           SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE) &&
     142              :         (opaque_data_length != 0)) {
     143            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Overriding opaque_data_length to 0 since there is "
     144              :                        "no negotiated opaque data format.\n"));
     145            0 :         opaque_data_length = 0;
     146            0 :         warning = LIBSPDM_STATUS_OVERRIDDEN_PARAMETER;
     147              :     }
     148              : 
     149            7 :     if (opaque_data_length != 0) {
     150            2 :         libspdm_copy_mem((uint8_t *)(spdm_request + 1) + requester_info_length,
     151            2 :                          spdm_request_size - sizeof(spdm_get_csr_request_t) - requester_info_length,
     152              :                          (uint8_t *)opaque_data, opaque_data_length);
     153              :     }
     154              : 
     155            7 :     spdm_request_size = sizeof(spdm_get_csr_request_t) + opaque_data_length
     156            7 :                         + requester_info_length;
     157              : 
     158            7 :     status = libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request);
     159            7 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     160            1 :         libspdm_release_sender_buffer (spdm_context);
     161            1 :         return status;
     162              :     }
     163            6 :     libspdm_release_sender_buffer (spdm_context);
     164            6 :     spdm_request = (void *)spdm_context->last_spdm_request;
     165              : 
     166              :     /* receive */
     167            6 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     168            6 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     169            0 :         return status;
     170              :     }
     171            6 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
     172            6 :     spdm_response = (void *)(message);
     173            6 :     spdm_response_size = message_size;
     174              : 
     175            6 :     status = libspdm_receive_spdm_response(spdm_context, session_id,
     176              :                                            &spdm_response_size, (void **)&spdm_response);
     177              : 
     178            6 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     179            0 :         goto receive_done;
     180              :     }
     181            6 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     182            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     183            0 :         goto receive_done;
     184              :     }
     185            6 :     if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     186            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     187            0 :         goto receive_done;
     188              :     }
     189            6 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     190            6 :         if ((spdm_response->header.param1 == SPDM_ERROR_CODE_RESET_REQUIRED) &&
     191            5 :             (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) &&
     192              :             (available_csr_tracking_tag != NULL)) {
     193            1 :             *available_csr_tracking_tag = spdm_response->header.param2;
     194              :         }
     195              : 
     196            3 :         status = libspdm_handle_error_response_main(
     197              :             spdm_context, session_id,
     198              :             &spdm_response_size,
     199              :             (void **)&spdm_response, SPDM_GET_CSR, SPDM_CSR);
     200            3 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     201            3 :             goto receive_done;
     202              :         }
     203            3 :     } else if (spdm_response->header.request_response_code != SPDM_CSR) {
     204            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     205            0 :         goto receive_done;
     206              :     }
     207              : 
     208            3 :     if (spdm_response_size < sizeof(spdm_csr_response_t)) {
     209            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     210            0 :         goto receive_done;
     211              :     }
     212            3 :     if (spdm_response->csr_length == 0) {
     213            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     214            0 :         goto receive_done;
     215              :     }
     216              : 
     217            3 :     if (spdm_response_size < sizeof(spdm_csr_response_t) + spdm_response->csr_length) {
     218            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     219            0 :         goto receive_done;
     220              :     }
     221            3 :     if (*csr_len < spdm_response->csr_length) {
     222            0 :         *csr_len = spdm_response->csr_length;
     223            0 :         status =  LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     224            0 :         goto receive_done;
     225              :     }
     226              : 
     227            3 :     libspdm_copy_mem(csr, *csr_len, spdm_response + 1, spdm_response->csr_length);
     228            3 :     *csr_len = spdm_response->csr_length;
     229              : 
     230            3 :     status = LIBSPDM_STATUS_SUCCESS;
     231              : 
     232            6 : receive_done:
     233            6 :     libspdm_release_receiver_buffer (spdm_context);
     234              : 
     235            6 :     if (LIBSPDM_STATUS_IS_SUCCESS(status) && LIBSPDM_STATUS_IS_WARNING(warning)) {
     236            0 :         status = warning;
     237              :     }
     238            6 :     return status;
     239              : }
     240              : 
     241            6 : libspdm_return_t libspdm_get_csr(void * spdm_context,
     242              :                                  const uint32_t *session_id,
     243              :                                  void * requester_info, uint16_t requester_info_length,
     244              :                                  void * opaque_data, uint16_t opaque_data_length,
     245              :                                  void *csr, size_t *csr_len)
     246              : {
     247              :     libspdm_context_t *context;
     248              :     size_t retry;
     249              :     uint64_t retry_delay_time;
     250              :     libspdm_return_t status;
     251              : 
     252            6 :     context = spdm_context;
     253            6 :     context->crypto_request = true;
     254            6 :     retry = context->retry_times;
     255            6 :     retry_delay_time = context->retry_delay_time;
     256              :     do {
     257            6 :         status = libspdm_try_get_csr(context, session_id,
     258              :                                      requester_info, requester_info_length,
     259              :                                      opaque_data, opaque_data_length,
     260              :                                      csr, csr_len,
     261              :                                      0, 0, NULL);
     262            6 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     263            6 :             return status;
     264              :         }
     265              : 
     266            0 :         libspdm_sleep(retry_delay_time);
     267            0 :     } while (retry-- != 0);
     268              : 
     269            0 :     return status;
     270              : }
     271              : 
     272              : #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX
     273            2 : libspdm_return_t libspdm_get_csr_ex(void * spdm_context,
     274              :                                     const uint32_t *session_id,
     275              :                                     void * requester_info, uint16_t requester_info_length,
     276              :                                     void * opaque_data, uint16_t opaque_data_length,
     277              :                                     void *csr, size_t *csr_len,
     278              :                                     uint8_t request_attribute,
     279              :                                     uint8_t key_pair_id,
     280              :                                     uint8_t *available_csr_tracking_tag
     281              :                                     )
     282              : {
     283              :     libspdm_context_t *context;
     284              :     size_t retry;
     285              :     uint64_t retry_delay_time;
     286              :     libspdm_return_t status;
     287              : 
     288            2 :     context = spdm_context;
     289            2 :     context->crypto_request = true;
     290            2 :     retry = context->retry_times;
     291            2 :     retry_delay_time = context->retry_delay_time;
     292              :     do {
     293            2 :         status = libspdm_try_get_csr(context, session_id,
     294              :                                      requester_info, requester_info_length,
     295              :                                      opaque_data, opaque_data_length,
     296              :                                      csr, csr_len,
     297              :                                      request_attribute, key_pair_id,
     298              :                                      available_csr_tracking_tag);
     299            2 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     300            2 :             return status;
     301              :         }
     302              : 
     303            0 :         libspdm_sleep(retry_delay_time);
     304            0 :     } while (retry-- != 0);
     305              : 
     306            0 :     return status;
     307              : }
     308              : #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX*/
     309              : 
     310              : #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP*/
        

Generated by: LCOV version 2.0-1