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: 66.8 % 271 181
Test Date: 2025-08-24 08:11:14 Functions: 100.0 % 6 6

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

Generated by: LCOV version 2.0-1