LCOV - code coverage report
Current view: top level - library/spdm_responder_lib - libspdm_rsp_encap_get_certificate.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 60.0 % 125 75
Test Date: 2025-06-29 08:09:00 Functions: 100.0 % 2 2

            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_responder_lib.h"
       8              : 
       9              : #if (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && \
      10              :     (LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT)
      11              : 
      12            2 : libspdm_return_t libspdm_get_encap_request_get_certificate(libspdm_context_t *spdm_context,
      13              :                                                            size_t *encap_request_size,
      14              :                                                            void *encap_request)
      15              : {
      16              :     spdm_get_certificate_request_t *spdm_request;
      17              :     libspdm_return_t status;
      18              : 
      19            2 :     spdm_context->encap_context.last_encap_request_size = 0;
      20              : 
      21            2 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
      22            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
      23              :     }
      24              : 
      25            2 :     if (!libspdm_is_capabilities_flag_supported(
      26              :             spdm_context, false,
      27              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP, 0)) {
      28            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
      29              :     }
      30              : 
      31            2 :     LIBSPDM_ASSERT(*encap_request_size >= sizeof(spdm_get_certificate_request_t));
      32            2 :     *encap_request_size = sizeof(spdm_get_certificate_request_t);
      33              : 
      34            2 :     spdm_request = encap_request;
      35              : 
      36            2 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
      37            2 :     spdm_request->header.request_response_code = SPDM_GET_CERTIFICATE;
      38            2 :     spdm_request->header.param1 = spdm_context->encap_context.req_slot_id;
      39            2 :     spdm_request->header.param2 = 0;
      40            2 :     spdm_request->offset = (uint16_t)spdm_context->mut_auth_cert_chain_buffer_size;
      41            2 :     spdm_request->length = LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN;
      42            2 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "request (offset 0x%x, size 0x%x):\n",
      43              :                    spdm_request->offset, spdm_request->length));
      44              : 
      45            2 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
      46            2 :                                                   spdm_request->header.request_response_code);
      47              : 
      48              :     /* Cache data*/
      49            2 :     status = libspdm_append_message_mut_b(spdm_context, spdm_request, *encap_request_size);
      50            2 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
      51            0 :         return LIBSPDM_STATUS_BUFFER_FULL;
      52              :     }
      53              : 
      54            2 :     libspdm_copy_mem(&spdm_context->encap_context.last_encap_request_header,
      55              :                      sizeof(spdm_context->encap_context.last_encap_request_header),
      56            2 :                      &spdm_request->header, sizeof(spdm_message_header_t));
      57            2 :     spdm_context->encap_context.last_encap_request_size = *encap_request_size;
      58              : 
      59            2 :     return LIBSPDM_STATUS_SUCCESS;
      60              : }
      61              : 
      62           12 : libspdm_return_t libspdm_process_encap_response_certificate(
      63              :     libspdm_context_t *spdm_context, size_t encap_response_size,
      64              :     const void *encap_response, bool *need_continue)
      65              : {
      66              :     const spdm_certificate_response_t *spdm_response;
      67              :     size_t spdm_response_size;
      68              :     bool result;
      69              :     libspdm_return_t status;
      70              :     uint16_t request_offset;
      71              :     uint8_t slot_id;
      72              :     uint8_t *cert_chain_buffer;
      73              :     size_t cert_chain_buffer_size;
      74              :     size_t cert_chain_buffer_max_size;
      75              :     uint8_t cert_model;
      76              : 
      77           12 :     spdm_response = encap_response;
      78           12 :     spdm_response_size = encap_response_size;
      79              : 
      80           12 :     cert_chain_buffer = (uint8_t *)spdm_context->mut_auth_cert_chain_buffer;
      81           12 :     cert_chain_buffer_size = spdm_context->mut_auth_cert_chain_buffer_size;
      82           12 :     cert_chain_buffer_max_size = spdm_context->mut_auth_cert_chain_buffer_max_size;
      83              : 
      84           12 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
      85            0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
      86              :     }
      87           12 :     if (spdm_response->header.spdm_version != libspdm_get_connection_version (spdm_context)) {
      88            0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
      89              :     }
      90           12 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
      91            2 :         status = libspdm_handle_encap_error_response_main(
      92            2 :             spdm_context, spdm_response->header.param1);
      93            2 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
      94            2 :             return status;
      95              :         }
      96           10 :     } else if (spdm_response->header.request_response_code != SPDM_CERTIFICATE) {
      97            0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
      98              :     }
      99           10 :     if (encap_response_size < sizeof(spdm_certificate_response_t)) {
     100            0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     101              :     }
     102           10 :     if ((spdm_response->portion_length > LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN) ||
     103            9 :         (spdm_response->portion_length == 0)) {
     104            2 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     105              :     }
     106              : 
     107            8 :     request_offset = (uint16_t)cert_chain_buffer_size;
     108              : 
     109            8 :     if (spdm_response->portion_length > 0xFFFF - request_offset) {
     110            0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     111              :     }
     112            8 :     if (spdm_response->remainder_length > 0xFFFF - request_offset - spdm_response->portion_length) {
     113            0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     114              :     }
     115            8 :     if (request_offset == 0) {
     116            8 :         spdm_context->encap_context.cert_chain_total_len = spdm_response->portion_length +
     117            8 :                                                            spdm_response->remainder_length;
     118            0 :     } else if (spdm_context->encap_context.cert_chain_total_len !=
     119            0 :                request_offset + spdm_response->portion_length + spdm_response->remainder_length) {
     120            0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     121              :     }
     122            8 :     slot_id = spdm_context->encap_context.req_slot_id;
     123            8 :     if ((spdm_response->header.param1 & SPDM_CERTIFICATE_RESPONSE_SLOT_ID_MASK) != slot_id) {
     124            0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     125              :     }
     126            8 :     if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     127            6 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "cert_info - 0x%02x\n",
     128              :                        spdm_response->header.param2));
     129            6 :         cert_model = spdm_response->header.param2 &
     130              :                      SPDM_CERTIFICATE_RESPONSE_ATTRIBUTES_CERTIFICATE_INFO_MASK;
     131            6 :         if (spdm_context->connection_info.multi_key_conn_req) {
     132            5 :             if (cert_model > SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT) {
     133            0 :                 return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     134              :             }
     135            5 :             if ((slot_id == 0) &&
     136              :                 (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
     137            1 :                 return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     138              :             }
     139            4 :             if ((cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) &&
     140            1 :                 (spdm_response->portion_length != 0)) {
     141            1 :                 return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     142              :             }
     143              :         } else {
     144            1 :             if (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) {
     145            0 :                 return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     146              :             }
     147              :         }
     148            4 :         if (spdm_context->connection_info.peer_cert_info[slot_id] ==
     149              :             SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) {
     150            4 :             spdm_context->connection_info.peer_cert_info[slot_id] = cert_model;
     151            0 :         } else if (spdm_context->connection_info.peer_cert_info[slot_id] != cert_model) {
     152            0 :             return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     153              :         }
     154              :     }
     155              : 
     156            6 :     if (spdm_response_size < sizeof(spdm_certificate_response_t) + spdm_response->portion_length) {
     157            0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     158              :     }
     159            6 :     spdm_response_size = sizeof(spdm_certificate_response_t) + spdm_response->portion_length;
     160              : 
     161              :     /* Cache data*/
     162              : 
     163            6 :     status = libspdm_append_message_mut_b(spdm_context, spdm_response, spdm_response_size);
     164            6 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     165            0 :         return LIBSPDM_STATUS_BUFFER_FULL;
     166              :     }
     167              : 
     168            6 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Certificate (offset 0x%x, size 0x%x):\n",
     169              :                    request_offset, spdm_response->portion_length));
     170            6 :     LIBSPDM_INTERNAL_DUMP_HEX((const void *)(spdm_response + 1), spdm_response->portion_length);
     171              : 
     172            6 :     if ((cert_chain_buffer_size + spdm_response->portion_length) > cert_chain_buffer_max_size) {
     173            0 :         return LIBSPDM_STATUS_BUFFER_FULL;
     174              :     }
     175              : 
     176            6 :     libspdm_copy_mem(cert_chain_buffer + cert_chain_buffer_size,
     177              :                      cert_chain_buffer_max_size - cert_chain_buffer_size,
     178            6 :                      (const void *)(spdm_response + 1), spdm_response->portion_length);
     179              : 
     180            6 :     cert_chain_buffer_size += spdm_response->portion_length;
     181            6 :     spdm_context->mut_auth_cert_chain_buffer_size = cert_chain_buffer_size;
     182              : 
     183            6 :     if (spdm_response->remainder_length != 0) {
     184            6 :         *need_continue = true;
     185              : 
     186            6 :         return LIBSPDM_STATUS_SUCCESS;
     187              :     }
     188              : 
     189            0 :     *need_continue = false;
     190              : 
     191            0 :     if (spdm_context->local_context.verify_peer_spdm_cert_chain != NULL) {
     192            0 :         result = spdm_context->local_context.verify_peer_spdm_cert_chain (
     193            0 :             spdm_context, spdm_context->encap_context.req_slot_id,
     194              :             cert_chain_buffer_size, cert_chain_buffer, NULL, NULL);
     195            0 :         if (!result) {
     196            0 :             return LIBSPDM_STATUS_VERIF_FAIL;
     197              :         }
     198              :     } else {
     199            0 :         result = libspdm_verify_peer_cert_chain_buffer_integrity(
     200              :             spdm_context, cert_chain_buffer, cert_chain_buffer_size);
     201            0 :         if (!result) {
     202            0 :             return LIBSPDM_STATUS_VERIF_FAIL;
     203              :         }
     204              : 
     205              :         /*verify peer cert chain authority*/
     206            0 :         result = libspdm_verify_peer_cert_chain_buffer_authority(
     207              :             spdm_context, cert_chain_buffer, cert_chain_buffer_size, NULL, NULL);
     208            0 :         if (!result) {
     209            0 :             status = LIBSPDM_STATUS_VERIF_NO_AUTHORITY;
     210              :         }
     211              :     }
     212              : 
     213            0 :     spdm_context->connection_info.peer_used_cert_chain_slot_id =
     214            0 :         spdm_context->encap_context.req_slot_id;
     215            0 :     slot_id = spdm_context->encap_context.req_slot_id;
     216            0 :     LIBSPDM_ASSERT(slot_id < SPDM_MAX_SLOT_COUNT);
     217              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     218              :     spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer_size =
     219              :         cert_chain_buffer_size;
     220              : 
     221              :     libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer,
     222              :                      sizeof(spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer),
     223              :                      cert_chain_buffer, cert_chain_buffer_size);
     224              : #else
     225            0 :     result = libspdm_hash_all(
     226              :         spdm_context->connection_info.algorithm.base_hash_algo,
     227              :         cert_chain_buffer, cert_chain_buffer_size,
     228            0 :         spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer_hash);
     229            0 :     if (!result) {
     230            0 :         return LIBSPDM_STATUS_CRYPTO_ERROR;
     231              :     }
     232            0 :     spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer_hash_size =
     233            0 :         libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     234              : 
     235            0 :     result = libspdm_get_leaf_cert_public_key_from_cert_chain(
     236              :         spdm_context->connection_info.algorithm.base_hash_algo,
     237            0 :         spdm_context->connection_info.algorithm.req_base_asym_alg,
     238              :         cert_chain_buffer, cert_chain_buffer_size,
     239            0 :         &spdm_context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key);
     240            0 :     if (!result) {
     241            0 :         return LIBSPDM_STATUS_INVALID_CERT;
     242              :     }
     243              : #endif
     244            0 :     if (status != LIBSPDM_STATUS_VERIF_NO_AUTHORITY) {
     245            0 :         return LIBSPDM_STATUS_SUCCESS;
     246              :     } else {
     247            0 :         return LIBSPDM_STATUS_VERIF_NO_AUTHORITY;
     248              :     }
     249              : }
     250              : 
     251              : #endif /* (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (...) */
        

Generated by: LCOV version 2.0-1