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.7 % 261 174
Test Date: 2025-12-21 08:10:27 Functions: 100.0 % 4 4

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

Generated by: LCOV version 2.0-1