LCOV - code coverage report
Current view: top level - library/spdm_requester_lib - libspdm_req_get_certificate.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 68.4 % 291 199
Test Date: 2026-02-01 08:12:19 Functions: 100.0 % 4 4

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-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_requester_lib.h"
       8              : 
       9              : #if LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT
      10              : 
      11              : /**
      12              :  * This function sends GET_CERTIFICATE and receives CERTIFICATE.
      13              :  *
      14              :  * This function verify the integrity of the certificate chain.
      15              :  * root_hash -> Root certificate -> Intermediate certificate -> Leaf certificate.
      16              :  *
      17              :  * If the peer root certificate hash is deployed,
      18              :  * this function also verifies the digest with the root hash in the certificate chain.
      19              :  *
      20              :  * @param  spdm_context      A pointer to the SPDM context.
      21              :  * @param  slot_id           The number of slot for the certificate chain.
      22              :  * @param  cert_chain_size   On input, indicate the size in bytes of the destination buffer to store
      23              :  *                           the digest buffer.
      24              :  *                           On output, indicate the size in bytes of the certificate chain.
      25              :  * @param  cert_chain        A pointer to a destination buffer to store the certificate chain.
      26              :  * @param  trust_anchor      A buffer to hold the trust_anchor which is used to validate the peer
      27              :  *                           certificate, if not NULL.
      28              :  * @param  trust_anchor_size A buffer to hold the trust_anchor_size, if not NULL.
      29              :  *
      30              :  * @retval LIBSPDM_STATUS_SUCCESS
      31              :  *         GET_CERTIFICATE was sent and CERTIFICATE was received.
      32              :  * @retval LIBSPDM_STATUS_INVALID_STATE_LOCAL
      33              :  *         Cannot send GET_CERTIFICATE due to Requester's state.
      34              :  * @retval LIBSPDM_STATUS_UNSUPPORTED_CAP
      35              :  *         Cannot send GET_CERTIFICATE because the Requester's and/or Responder's CERT_CAP = 0.
      36              :  * @retval LIBSPDM_STATUS_INVALID_MSG_SIZE
      37              :  *         The size of the CERTIFICATE response is invalid.
      38              :  * @retval LIBSPDM_STATUS_INVALID_MSG_FIELD
      39              :  *         The CERTIFICATE response contains one or more invalid fields.
      40              :  * @retval LIBSPDM_STATUS_ERROR_PEER
      41              :  *         The Responder returned an unexpected error.
      42              :  * @retval LIBSPDM_STATUS_BUSY_PEER
      43              :  *         The Responder continually returned Busy error messages.
      44              :  * @retval LIBSPDM_STATUS_RESYNCH_PEER
      45              :  *         The Responder returned a RequestResynch error message.
      46              :  * @retval LIBSPDM_STATUS_BUFFER_FULL
      47              :  *         The buffer used to store transcripts is exhausted.
      48              :  * @retval LIBSPDM_STATUS_VERIF_FAIL
      49              :  *         Verification of the certificate chain failed.
      50              :  * @retval LIBSPDM_STATUS_INVALID_CERT
      51              :  *         The certificate is unable to be parsed or contains invalid field values.
      52              :  * @retval LIBSPDM_STATUS_CRYPTO_ERROR
      53              :  *         A generic cryptography error occurred.
      54              :  **/
      55           59 : static libspdm_return_t libspdm_try_get_large_certificate(libspdm_context_t *spdm_context,
      56              :                                                           const uint32_t *session_id,
      57              :                                                           uint8_t slot_id,
      58              :                                                           uint32_t length,
      59              :                                                           size_t *cert_chain_size,
      60              :                                                           void *cert_chain,
      61              :                                                           const void **trust_anchor,
      62              :                                                           size_t *trust_anchor_size,
      63              :                                                           bool slot_storage_size_requested,
      64              :                                                           uint32_t *slot_storage_size)
      65              : {
      66              :     bool result;
      67              :     libspdm_return_t status;
      68              :     spdm_get_certificate_large_request_t *spdm_request;
      69              :     size_t spdm_request_size;
      70              :     spdm_certificate_large_response_t *spdm_response;
      71              :     size_t spdm_response_size;
      72              :     uint32_t total_responder_cert_chain_buffer_length;
      73              :     size_t cert_chain_capacity;
      74              :     size_t cert_chain_size_internal;
      75              :     uint32_t remainder_length;
      76              :     uint8_t *message;
      77              :     size_t message_size;
      78              :     size_t transport_header_size;
      79              :     libspdm_session_info_t *session_info;
      80              :     libspdm_session_state_t session_state;
      81              :     bool chunk_enabled;
      82              :     uint8_t cert_model;
      83              :     uint32_t req_msg_length;
      84              :     uint32_t req_msg_offset;
      85              :     uint32_t rsp_msg_portion_length;
      86              :     uint32_t rsp_msg_remainder_length;
      87              :     bool use_large_cert_chain;
      88              :     uint32_t req_msg_header_size;
      89              :     uint32_t rsp_msg_header_size;
      90              :     uint32_t max_cert_chain_size;
      91              : 
      92              :     /* -=[Check Parameters Phase]=- */
      93           59 :     LIBSPDM_ASSERT(slot_id < SPDM_MAX_SLOT_COUNT);
      94           59 :     if (slot_storage_size_requested){
      95            2 :         LIBSPDM_ASSERT(slot_storage_size != NULL);
      96              :     } else {
      97           57 :         LIBSPDM_ASSERT(cert_chain_size != NULL);
      98           57 :         LIBSPDM_ASSERT(*cert_chain_size > 0);
      99           57 :         LIBSPDM_ASSERT(cert_chain != NULL);
     100              :     }
     101              : 
     102           59 :     if ((length > SPDM_MAX_CERTIFICATE_CHAIN_SIZE) &&
     103            0 :         (libspdm_get_connection_version (spdm_context) < SPDM_MESSAGE_VERSION_14)) {
     104            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     105              :     }
     106              : 
     107           59 :     if ((length == SPDM_MAX_CERTIFICATE_CHAIN_SIZE) &&
     108            0 :         (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_14)) {
     109              :         /* support compatibility */
     110            0 :         length = SPDM_MAX_CERTIFICATE_CHAIN_SIZE_14;
     111              :     }
     112              : 
     113           59 :     if ((libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_14) &&
     114            0 :         libspdm_is_capabilities_flag_supported(
     115              :             spdm_context, true, 0,
     116              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_LARGE_RESP_CAP)) {
     117            0 :         use_large_cert_chain = true;
     118              :     } else {
     119           59 :         use_large_cert_chain = false;
     120              :     }
     121              : 
     122           59 :     if (slot_storage_size_requested){
     123            2 :         if (libspdm_get_connection_version (spdm_context) < SPDM_MESSAGE_VERSION_13) {
     124            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     125              :         }
     126              : 
     127            2 :         if (!libspdm_is_capabilities_flag_supported(
     128              :                 spdm_context, true, 0,
     129              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_CERT_CAP)) {
     130            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     131              :         }
     132              :     }
     133              : 
     134           59 :     if (use_large_cert_chain) {
     135            0 :         max_cert_chain_size = SPDM_MAX_CERTIFICATE_CHAIN_SIZE_14;
     136            0 :         req_msg_header_size = sizeof(spdm_get_certificate_large_request_t);
     137            0 :         rsp_msg_header_size = sizeof(spdm_certificate_large_response_t);
     138              :     } else {
     139           59 :         max_cert_chain_size = SPDM_MAX_CERTIFICATE_CHAIN_SIZE;
     140           59 :         req_msg_header_size = sizeof(spdm_get_certificate_request_t);
     141           59 :         rsp_msg_header_size = sizeof(spdm_certificate_response_t);
     142              :     }
     143              : 
     144              :     /* use default max buffer length */
     145           59 :     if (length == 0) {
     146           58 :         length = spdm_context->local_context.capability.max_spdm_msg_size - rsp_msg_header_size;
     147              : 
     148           58 :         if (!use_large_cert_chain) {
     149           58 :             length = LIBSPDM_MIN(length, SPDM_MAX_CERTIFICATE_CHAIN_SIZE);
     150              :         }
     151              :     }
     152              : 
     153              :     /* -=[Verify State Phase]=- */
     154           59 :     if (!libspdm_is_capabilities_flag_supported(
     155              :             spdm_context, true, 0,
     156              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP)) {
     157            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     158              :     }
     159           59 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     160            1 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     161              :     }
     162              : 
     163           58 :     session_info = NULL;
     164           58 :     if (session_id != NULL) {
     165            1 :         session_info = libspdm_get_session_info_via_session_id(spdm_context, *session_id);
     166            1 :         if (session_info == NULL) {
     167            0 :             LIBSPDM_ASSERT(false);
     168            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     169              :         }
     170            1 :         session_state = libspdm_secured_message_get_session_state(
     171              :             session_info->secured_message_context);
     172            1 :         if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
     173            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     174              :         }
     175              :     }
     176              : 
     177           58 :     libspdm_reset_message_buffer_via_request_code(spdm_context, session_info, SPDM_GET_CERTIFICATE);
     178              : 
     179              :     chunk_enabled =
     180           58 :         libspdm_is_capabilities_flag_supported(spdm_context, true,
     181              :                                                SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP,
     182              :                                                SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP);
     183              : 
     184           58 :     remainder_length = 0;
     185           58 :     total_responder_cert_chain_buffer_length = 0;
     186           58 :     if (!slot_storage_size_requested){
     187           56 :         cert_chain_capacity = *cert_chain_size;
     188              :     }
     189           58 :     cert_chain_size_internal = 0;
     190              : 
     191           58 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
     192              : 
     193              :     do {
     194              :         /* -=[Construct Request Phase]=- */
     195         1470 :         status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     196         1470 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     197            0 :             return status;
     198              :         }
     199         1470 :         LIBSPDM_ASSERT (message_size >= transport_header_size +
     200              :                         spdm_context->local_context.capability.transport_tail_size);
     201         1470 :         spdm_request = (void *)(message + transport_header_size);
     202         1470 :         spdm_request_size = message_size - transport_header_size -
     203         1470 :                             spdm_context->local_context.capability.transport_tail_size;
     204              : 
     205         1470 :         LIBSPDM_ASSERT (spdm_request_size >= req_msg_header_size);
     206         1470 :         spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     207         1470 :         spdm_request->header.request_response_code = SPDM_GET_CERTIFICATE;
     208         1470 :         spdm_request->header.param1 = slot_id;
     209         1470 :         spdm_request->header.param2 = 0;
     210         1470 :         if (slot_storage_size_requested) {
     211            2 :             spdm_request->header.param2 |= SPDM_GET_CERTIFICATE_REQUEST_ATTRIBUTES_SLOT_SIZE_REQUESTED;
     212            2 :             req_msg_length = 0;
     213            2 :             req_msg_offset = 0;
     214              :         } else {
     215         1468 :             req_msg_offset = (uint32_t)cert_chain_size_internal;
     216         1468 :             if (req_msg_offset == 0) {
     217           56 :                 req_msg_length = length;
     218              :             } else {
     219         1412 :                 req_msg_length = LIBSPDM_MIN(length, remainder_length);
     220              :             }
     221              :         }
     222         1470 :         if (use_large_cert_chain) {
     223            0 :             spdm_request->header.param1 |= SPDM_GET_CERTIFICATE_REQUEST_LARGE_CERT_CHAIN;
     224            0 :             spdm_request->offset = 0;
     225            0 :             spdm_request->length = 0;
     226            0 :             spdm_request->large_offset = req_msg_offset;
     227            0 :             spdm_request->large_length = req_msg_length;
     228              :         } else {
     229         1470 :             spdm_request->offset = (uint16_t)req_msg_offset;
     230         1470 :             spdm_request->length = (uint16_t)req_msg_length;
     231              :         }
     232         1470 :         spdm_request_size = req_msg_header_size;
     233         1470 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "request (offset 0x%x, size 0x%x):\n",
     234              :                        req_msg_offset,req_msg_length));
     235              : 
     236              :         /* -=[Send Request Phase]=- */
     237              :         status =
     238         1470 :             libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request);
     239         1470 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     240            1 :             libspdm_release_sender_buffer (spdm_context);
     241            1 :             status = LIBSPDM_STATUS_SEND_FAIL;
     242            1 :             goto done;
     243              :         }
     244         1469 :         libspdm_release_sender_buffer (spdm_context);
     245         1469 :         spdm_request = (void *)spdm_context->last_spdm_request;
     246              : 
     247              :         /* -=[Receive Response Phase]=- */
     248         1469 :         status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     249         1469 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     250            0 :             return status;
     251              :         }
     252         1469 :         LIBSPDM_ASSERT (message_size >= transport_header_size);
     253         1469 :         spdm_response = (void *)(message);
     254         1469 :         spdm_response_size = message_size;
     255              : 
     256         1469 :         status = libspdm_receive_spdm_response(spdm_context, session_id,
     257              :                                                &spdm_response_size,
     258              :                                                (void **)&spdm_response);
     259         1469 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     260            0 :             libspdm_release_receiver_buffer (spdm_context);
     261            0 :             status = LIBSPDM_STATUS_RECEIVE_FAIL;
     262            0 :             goto done;
     263              :         }
     264              : 
     265              :         /* -=[Validate Response Phase]=- */
     266         1469 :         if (spdm_response_size < sizeof(spdm_message_header_t)) {
     267            0 :             libspdm_release_receiver_buffer (spdm_context);
     268            0 :             status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     269            0 :             goto done;
     270              :         }
     271         1469 :         if (spdm_response->header.request_response_code == SPDM_ERROR) {
     272           24 :             status = libspdm_handle_error_response_main(
     273              :                 spdm_context, session_id,
     274              :                 &spdm_response_size,
     275              :                 (void **)&spdm_response, SPDM_GET_CERTIFICATE,
     276              :                 SPDM_CERTIFICATE);
     277           24 :             if (LIBSPDM_STATUS_IS_ERROR(status)) {
     278           23 :                 libspdm_release_receiver_buffer (spdm_context);
     279           23 :                 goto done;
     280              :             }
     281         1445 :         } else if (spdm_response->header.request_response_code != SPDM_CERTIFICATE) {
     282            0 :             libspdm_release_receiver_buffer (spdm_context);
     283            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     284            0 :             goto done;
     285              :         }
     286         1446 :         if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     287            0 :             libspdm_release_receiver_buffer (spdm_context);
     288            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     289            0 :             goto done;
     290              :         }
     291         1446 :         if (spdm_response_size < rsp_msg_header_size) {
     292            0 :             libspdm_release_receiver_buffer (spdm_context);
     293            0 :             status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     294            0 :             goto done;
     295              :         }
     296         1446 :         if (use_large_cert_chain) {
     297            0 :             if ((spdm_response->header.param1 & SPDM_CERTIFICATE_RESPONSE_LARGE_CERT_CHAIN) == 0) {
     298            0 :                 libspdm_release_receiver_buffer (spdm_context);
     299            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     300            0 :                 goto done;
     301              :             }
     302              :         } else {
     303         1446 :             if ((spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_14) &&
     304            0 :                 ((spdm_response->header.param1 & SPDM_CERTIFICATE_RESPONSE_LARGE_CERT_CHAIN) != 0)) {
     305            0 :                 libspdm_release_receiver_buffer (spdm_context);
     306            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     307            0 :                 goto done;
     308              :             }
     309              :         }
     310         1446 :         if (use_large_cert_chain) {
     311            0 :             rsp_msg_portion_length = spdm_response->large_portion_length;
     312            0 :             rsp_msg_remainder_length = spdm_response->large_remainder_length;
     313              :         } else {
     314         1446 :             rsp_msg_portion_length = spdm_response->portion_length;
     315         1446 :             rsp_msg_remainder_length = spdm_response->remainder_length;
     316              :         }
     317              : 
     318         1446 :         if (slot_storage_size_requested) {
     319            2 :             if (rsp_msg_portion_length != 0) {
     320            1 :                 libspdm_release_receiver_buffer (spdm_context);
     321            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     322            1 :                 goto done;
     323              :             }
     324              :         } else {
     325         1444 :             if ((rsp_msg_portion_length > req_msg_length) ||
     326              :                 (rsp_msg_portion_length == 0)) {
     327            3 :                 libspdm_release_receiver_buffer (spdm_context);
     328            3 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     329            3 :                 goto done;
     330              :             }
     331         1441 :             if ((spdm_response->header.param1 & SPDM_CERTIFICATE_RESPONSE_SLOT_ID_MASK) != slot_id) {
     332            1 :                 libspdm_release_receiver_buffer (spdm_context);
     333            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     334            1 :                 goto done;
     335              :             }
     336         1440 :             if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     337           10 :                 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "cert_info - 0x%02x\n",
     338              :                                spdm_response->header.param2));
     339           10 :                 cert_model = spdm_response->header.param2 &
     340              :                              SPDM_CERTIFICATE_RESPONSE_ATTRIBUTES_CERTIFICATE_INFO_MASK;
     341           10 :                 if (spdm_context->connection_info.multi_key_conn_rsp) {
     342            8 :                     if (cert_model > SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT) {
     343            0 :                         libspdm_release_receiver_buffer (spdm_context);
     344            0 :                         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     345            0 :                         goto done;
     346              :                     }
     347            8 :                     if ((slot_id == 0) &&
     348              :                         (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
     349            1 :                         libspdm_release_receiver_buffer (spdm_context);
     350            1 :                         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     351            1 :                         goto done;
     352              :                     }
     353            7 :                     if ((cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) &&
     354              :                         (rsp_msg_portion_length != 0)) {
     355            1 :                         libspdm_release_receiver_buffer (spdm_context);
     356            1 :                         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     357            1 :                         goto done;
     358              :                     }
     359              :                 } else {
     360            2 :                     if (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) {
     361            0 :                         libspdm_release_receiver_buffer (spdm_context);
     362            0 :                         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     363            0 :                         goto done;
     364              :                     }
     365              :                 }
     366            8 :                 if (spdm_context->connection_info.peer_cert_info[slot_id] ==
     367              :                     SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) {
     368            5 :                     spdm_context->connection_info.peer_cert_info[slot_id] = cert_model;
     369            3 :                 } else if (spdm_context->connection_info.peer_cert_info[slot_id] != cert_model) {
     370            0 :                     libspdm_release_receiver_buffer (spdm_context);
     371            0 :                     status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     372            0 :                     goto done;
     373              :                 }
     374              :             }
     375         1438 :             if (spdm_response_size < rsp_msg_header_size +
     376              :                 rsp_msg_portion_length) {
     377            0 :                 libspdm_release_receiver_buffer (spdm_context);
     378            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     379            0 :                 goto done;
     380              :             }
     381         1438 :             if (rsp_msg_portion_length > max_cert_chain_size - req_msg_offset) {
     382            0 :                 libspdm_release_receiver_buffer (spdm_context);
     383            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     384            0 :                 goto done;
     385              :             }
     386         1438 :             if (rsp_msg_remainder_length > max_cert_chain_size - req_msg_offset -
     387              :                 rsp_msg_portion_length) {
     388            0 :                 libspdm_release_receiver_buffer (spdm_context);
     389            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     390            0 :                 goto done;
     391              :             }
     392         1438 :             if (req_msg_offset == 0) {
     393           27 :                 total_responder_cert_chain_buffer_length = rsp_msg_portion_length +
     394              :                                                            rsp_msg_remainder_length;
     395           27 :                 if (total_responder_cert_chain_buffer_length > cert_chain_capacity) {
     396            1 :                     libspdm_release_receiver_buffer (spdm_context);
     397            1 :                     status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     398            1 :                     goto done;
     399              :                 }
     400         1411 :             } else if (req_msg_offset + rsp_msg_portion_length +
     401              :                        rsp_msg_remainder_length != total_responder_cert_chain_buffer_length) {
     402            0 :                 libspdm_release_receiver_buffer (spdm_context);
     403            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     404            0 :                 goto done;
     405              :             }
     406         1437 :             if (chunk_enabled && (req_msg_offset == 0) && (req_msg_length == max_cert_chain_size) &&
     407              :                 (rsp_msg_remainder_length != 0)) {
     408            0 :                 libspdm_release_receiver_buffer (spdm_context);
     409            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     410            0 :                 goto done;
     411              :             }
     412              :         }
     413              : 
     414              :         /* -=[Process Response Phase]=- */
     415         1438 :         remainder_length = rsp_msg_remainder_length;
     416         1438 :         spdm_response_size = rsp_msg_header_size + rsp_msg_portion_length;
     417              : 
     418         1438 :         if (session_id == NULL) {
     419         1436 :             status = libspdm_append_message_b(spdm_context, spdm_request, spdm_request_size);
     420         1436 :             if (LIBSPDM_STATUS_IS_ERROR(status)) {
     421            0 :                 libspdm_release_receiver_buffer (spdm_context);
     422            0 :                 goto done;
     423              :             }
     424         1436 :             status = libspdm_append_message_b(spdm_context, spdm_response, spdm_response_size);
     425         1436 :             if (LIBSPDM_STATUS_IS_ERROR(status)) {
     426            0 :                 libspdm_release_receiver_buffer (spdm_context);
     427            0 :                 goto done;
     428              :             }
     429              :         }
     430              : 
     431         1438 :         if (slot_storage_size_requested) {
     432            1 :             *slot_storage_size = remainder_length;
     433            1 :             libspdm_release_receiver_buffer (spdm_context);
     434            1 :             status = LIBSPDM_STATUS_SUCCESS;
     435            1 :             goto done;
     436              :         }
     437              : 
     438         1437 :         if (cert_chain_size_internal + rsp_msg_portion_length > cert_chain_capacity) {
     439            0 :             libspdm_release_receiver_buffer (spdm_context);
     440            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "cert_chain_buffer full\n"));
     441            0 :             status = LIBSPDM_STATUS_BUFFER_FULL;
     442            0 :             goto done;
     443              :         }
     444              : 
     445         1437 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Certificate (offset 0x%x, size 0x%x):\n",
     446              :                        req_msg_offset, rsp_msg_portion_length));
     447         1437 :         LIBSPDM_INTERNAL_DUMP_HEX((uint8_t *)spdm_response + rsp_msg_header_size,
     448              :                                   rsp_msg_portion_length);
     449              : 
     450         1437 :         libspdm_copy_mem((uint8_t *)cert_chain + cert_chain_size_internal,
     451              :                          cert_chain_capacity - cert_chain_size_internal,
     452         1437 :                          (uint8_t *)spdm_response + rsp_msg_header_size,
     453              :                          rsp_msg_portion_length);
     454              : 
     455         1437 :         cert_chain_size_internal += rsp_msg_portion_length;
     456              : 
     457         1437 :         if (spdm_context->connection_info.connection_state <
     458              :             LIBSPDM_CONNECTION_STATE_AFTER_CERTIFICATE) {
     459           22 :             spdm_context->connection_info.connection_state =
     460              :                 LIBSPDM_CONNECTION_STATE_AFTER_CERTIFICATE;
     461              :         }
     462              : 
     463              :         /* -=[Log Message Phase]=- */
     464              :         #if LIBSPDM_ENABLE_MSG_LOG
     465         1437 :         libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     466              :         #endif /* LIBSPDM_ENABLE_MSG_LOG */
     467              : 
     468         1437 :         libspdm_release_receiver_buffer (spdm_context);
     469         1437 :     } while (remainder_length != 0);
     470              : 
     471           25 :     *cert_chain_size = cert_chain_size_internal;
     472           25 :     LIBSPDM_ASSERT(*cert_chain_size <= SPDM_MAX_CERTIFICATE_CHAIN_SIZE_14);
     473              : 
     474           25 :     if (spdm_context->local_context.verify_peer_spdm_cert_chain != NULL) {
     475            0 :         result = spdm_context->local_context.verify_peer_spdm_cert_chain (
     476              :             spdm_context, slot_id, cert_chain_size_internal, cert_chain,
     477              :             trust_anchor, trust_anchor_size);
     478            0 :         if (!result) {
     479            0 :             status = LIBSPDM_STATUS_VERIF_FAIL;
     480            0 :             goto done;
     481              :         }
     482              :     } else {
     483           25 :         result = libspdm_verify_peer_cert_chain_buffer_integrity(
     484              :             spdm_context, cert_chain, cert_chain_size_internal);
     485           25 :         if (!result) {
     486            5 :             status = LIBSPDM_STATUS_VERIF_FAIL;
     487            5 :             goto done;
     488              :         }
     489              : 
     490              :         /*verify peer cert chain authority*/
     491           20 :         result = libspdm_verify_peer_cert_chain_buffer_authority(
     492              :             spdm_context, cert_chain,cert_chain_size_internal,
     493              :             trust_anchor, trust_anchor_size);
     494           20 :         if (!result) {
     495            2 :             status = LIBSPDM_STATUS_VERIF_NO_AUTHORITY;
     496              :         }
     497              :     }
     498              : 
     499              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     500              :     spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer_size =
     501              :         cert_chain_size_internal;
     502              :     libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer,
     503              :                      sizeof(spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer),
     504              :                      cert_chain, cert_chain_size_internal);
     505              : #else
     506           20 :     result = libspdm_hash_all(
     507              :         spdm_context->connection_info.algorithm.base_hash_algo,
     508              :         cert_chain, cert_chain_size_internal,
     509           20 :         spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer_hash);
     510           20 :     if (!result) {
     511            0 :         status = LIBSPDM_STATUS_CRYPTO_ERROR;
     512            0 :         goto done;
     513              :     }
     514              : 
     515           40 :     spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer_hash_size =
     516           20 :         libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     517              : 
     518           20 :     if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
     519            0 :         result = libspdm_get_pqc_leaf_cert_public_key_from_cert_chain(
     520              :             spdm_context->connection_info.algorithm.base_hash_algo,
     521              :             spdm_context->connection_info.algorithm.pqc_asym_algo,
     522              :             cert_chain, cert_chain_size_internal,
     523            0 :             &spdm_context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key);
     524              :     } else {
     525           20 :         result = libspdm_get_leaf_cert_public_key_from_cert_chain(
     526              :             spdm_context->connection_info.algorithm.base_hash_algo,
     527              :             spdm_context->connection_info.algorithm.base_asym_algo,
     528              :             cert_chain, cert_chain_size_internal,
     529           20 :             &spdm_context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key);
     530              :     }
     531           20 :     if (!result) {
     532            0 :         status = LIBSPDM_STATUS_INVALID_CERT;
     533            0 :         goto done;
     534              :     }
     535              : #endif
     536              : 
     537           20 :     if (status != LIBSPDM_STATUS_VERIF_NO_AUTHORITY) {
     538           18 :         status = LIBSPDM_STATUS_SUCCESS;
     539              :     }
     540            2 : done:
     541           58 :     return status;
     542              : }
     543              : 
     544           56 : libspdm_return_t libspdm_get_certificate_ex(void *spdm_context, const uint32_t *session_id,
     545              :                                             uint8_t slot_id,
     546              :                                             uint32_t length,
     547              :                                             size_t *cert_chain_size,
     548              :                                             void *cert_chain,
     549              :                                             const void **trust_anchor,
     550              :                                             size_t *trust_anchor_size)
     551              : {
     552              :     libspdm_context_t *context;
     553              :     size_t retry;
     554              :     uint64_t retry_delay_time;
     555              :     libspdm_return_t status;
     556              : 
     557           56 :     context = spdm_context;
     558           56 :     context->crypto_request = true;
     559           56 :     retry = context->retry_times;
     560           56 :     retry_delay_time = context->retry_delay_time;
     561              :     do {
     562           57 :         status = libspdm_try_get_large_certificate(context, session_id, slot_id, length,
     563              :                                                    cert_chain_size, cert_chain, trust_anchor,
     564              :                                                    trust_anchor_size, false, NULL);
     565           57 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     566           55 :             return status;
     567              :         }
     568              : 
     569            2 :         libspdm_sleep(retry_delay_time);
     570            2 :     } while (retry-- != 0);
     571              : 
     572            1 :     return status;
     573              : }
     574              : 
     575           54 : libspdm_return_t libspdm_get_certificate(void *spdm_context, const uint32_t *session_id,
     576              :                                          uint8_t slot_id,
     577              :                                          size_t *cert_chain_size,
     578              :                                          void *cert_chain)
     579              : {
     580           54 :     return libspdm_get_certificate_ex(spdm_context, session_id, slot_id, 0,
     581              :                                       cert_chain_size, cert_chain,
     582              :                                       NULL, NULL);
     583              : }
     584              : 
     585            2 : libspdm_return_t libspdm_get_slot_storage_size(void *spdm_context, const uint32_t *session_id,
     586              :                                                uint8_t slot_id, uint32_t *slot_storage_size)
     587              : {
     588              :     libspdm_context_t *context;
     589              :     size_t retry;
     590              :     uint64_t retry_delay_time;
     591              :     libspdm_return_t status;
     592              : 
     593            2 :     context = spdm_context;
     594            2 :     context->crypto_request = true;
     595            2 :     retry = context->retry_times;
     596            2 :     retry_delay_time = context->retry_delay_time;
     597              :     do {
     598            2 :         status = libspdm_try_get_large_certificate(context, session_id, slot_id, 0,
     599              :                                                    NULL, NULL, NULL, NULL,
     600              :                                                    true, slot_storage_size);
     601            2 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     602            2 :             return status;
     603              :         }
     604              : 
     605            0 :         libspdm_sleep(retry_delay_time);
     606            0 :     } while (retry-- != 0);
     607              : 
     608            0 :     return status;
     609              : }
     610              : 
     611              : #endif /* LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT */
        

Generated by: LCOV version 2.0-1