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: 72.5 % 233 169
Test Date: 2025-06-29 08:09:00 Functions: 100.0 % 5 5

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

Generated by: LCOV version 2.0-1