LCOV - code coverage report
Current view: top level - library/spdm_requester_lib - libspdm_req_get_measurements.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 75.3 % 388 292
Test Date: 2025-06-29 08:09:00 Functions: 100.0 % 5 5

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2024 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_ENABLE_CAPABILITY_MEAS_CAP
      10              : 
      11           23 : bool libspdm_verify_measurement_signature(libspdm_context_t *spdm_context,
      12              :                                           libspdm_session_info_t *session_info,
      13              :                                           const void *sign_data,
      14              :                                           size_t sign_data_size)
      15              : {
      16              :     bool result;
      17              :     void *context;
      18              :     uint8_t slot_id;
      19              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      20              :     libspdm_l1l2_managed_buffer_t l1l2;
      21              :     uint8_t *l1l2_buffer;
      22              :     size_t l1l2_buffer_size;
      23              :     const uint8_t *cert_chain_data;
      24              :     size_t cert_chain_data_size;
      25              :     const uint8_t *cert_buffer;
      26              :     size_t cert_buffer_size;
      27              : #else
      28              :     uint8_t l1l2_hash[LIBSPDM_MAX_HASH_SIZE];
      29              :     size_t l1l2_hash_size;
      30              : #endif
      31              : 
      32              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      33              :     result = libspdm_calculate_l1l2(spdm_context, session_info, &l1l2);
      34              :     l1l2_buffer = libspdm_get_managed_buffer(&l1l2);
      35              :     l1l2_buffer_size = libspdm_get_managed_buffer_size(&l1l2);
      36              : #else
      37           23 :     l1l2_hash_size = sizeof(l1l2_hash);
      38           23 :     result = libspdm_calculate_l1l2_hash(spdm_context, session_info, &l1l2_hash_size, l1l2_hash);
      39              : #endif
      40           23 :     libspdm_reset_message_m(spdm_context, session_info);
      41           23 :     if (!result) {
      42            0 :         return false;
      43              :     }
      44              : 
      45           23 :     slot_id = spdm_context->connection_info.peer_used_cert_chain_slot_id;
      46           23 :     LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xF));
      47              : 
      48           23 :     if (slot_id == 0xF) {
      49            1 :         result = libspdm_asym_get_public_key_from_der(
      50              :             spdm_context->connection_info.algorithm.base_asym_algo,
      51            1 :             spdm_context->local_context.peer_public_key_provision,
      52              :             spdm_context->local_context.peer_public_key_provision_size,
      53              :             &context);
      54            1 :         if (!result) {
      55            0 :             return false;
      56              :         }
      57              :     } else {
      58              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      59              :         result = libspdm_get_peer_cert_chain_data(
      60              :             spdm_context, (const void **)&cert_chain_data, &cert_chain_data_size);
      61              :         if (!result) {
      62              :             return false;
      63              :         }
      64              : 
      65              :         /* Get leaf cert from cert chain*/
      66              :         result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
      67              :                                                        cert_chain_data_size, -1,
      68              :                                                        &cert_buffer, &cert_buffer_size);
      69              :         if (!result) {
      70              :             return false;
      71              :         }
      72              : 
      73              :         result = libspdm_asym_get_public_key_from_x509(
      74              :             spdm_context->connection_info.algorithm.base_asym_algo,
      75              :             cert_buffer, cert_buffer_size, &context);
      76              :         if (!result) {
      77              :             return false;
      78              :         }
      79              : #else
      80           22 :         context = spdm_context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key;
      81           22 :         LIBSPDM_ASSERT(context != NULL);
      82              : #endif
      83              :     }
      84              : 
      85              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      86              :     result = libspdm_asym_verify_ex(
      87              :         spdm_context->connection_info.version, SPDM_MEASUREMENTS,
      88              :         spdm_context->connection_info.algorithm.base_asym_algo,
      89              :         spdm_context->connection_info.algorithm.base_hash_algo,
      90              :         context, l1l2_buffer, l1l2_buffer_size, sign_data, sign_data_size,
      91              :         &spdm_context->spdm_10_11_verify_signature_endian);
      92              :     libspdm_asym_free(spdm_context->connection_info.algorithm.base_asym_algo, context);
      93              : #else
      94           23 :     result = libspdm_asym_verify_hash_ex(
      95           23 :         spdm_context->connection_info.version, SPDM_MEASUREMENTS,
      96              :         spdm_context->connection_info.algorithm.base_asym_algo,
      97              :         spdm_context->connection_info.algorithm.base_hash_algo,
      98              :         context, l1l2_hash, l1l2_hash_size, sign_data, sign_data_size,
      99              :         &spdm_context->spdm_10_11_verify_signature_endian);
     100           23 :     if (slot_id == 0xF) {
     101            1 :         libspdm_asym_free(spdm_context->connection_info.algorithm.base_asym_algo, context);
     102              :     }
     103              : #endif
     104           23 :     if (!result) {
     105            8 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_measurement_signature - FAIL !!!\n"));
     106            8 :         return false;
     107              :     }
     108              : 
     109           15 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_measurement_signature - PASS !!!\n"));
     110           15 :     return true;
     111              : }
     112              : 
     113              : /**
     114              :  * This function sends GET_MEASUREMENT to get measurement from the device.
     115              :  * If the signature is requested this function verifies the signature of the measurement.
     116              :  *
     117              :  * @param  context                    A pointer to the SPDM context.
     118              :  * @param  session_id                 Indicates if it is a secured message protected via SPDM session.
     119              :  *                                    If session_id is NULL, it is a normal message.
     120              :  *                                    If session_id is not NULL, it is a secured message.
     121              :  * @param  request_attribute          The request attribute of the request message.
     122              :  * @param  measurement_operation      The measurement operation of the request message.
     123              :  * @param  slot_id                    The number of slot for the certificate chain.
     124              :  * @param  requester_context          If not NULL, a buffer to hold the requester context (8 bytes).
     125              :  *                                    It is used only if the negotiated version >= 1.3.
     126              :  * @param  content_changed            The measurement content changed output param.
     127              :  * @param  number_of_blocks           The number of blocks of the measurement record.
     128              :  * @param  measurement_record_length  On input, indicate the size in bytes of the destination buffer
     129              :  *                                    to store the measurement record.
     130              :  *                                    On output, indicate the size in bytes of the measurement record.
     131              :  * @param  measurement_record         A pointer to a destination buffer to store the measurement record.
     132              :  * @param  requester_nonce_in         If not NULL, a buffer that holds the requester nonce (32 bytes)
     133              :  * @param  requester_nonce            If not NULL, a buffer to hold the requester nonce (32 bytes).
     134              :  * @param  responder_nonce            If not NULL, a buffer to hold the responder nonce (32 bytes).
     135              :  *
     136              :  **/
     137          306 : static libspdm_return_t libspdm_try_get_measurement(libspdm_context_t *spdm_context,
     138              :                                                     const uint32_t *session_id,
     139              :                                                     uint8_t request_attribute,
     140              :                                                     uint8_t measurement_operation,
     141              :                                                     uint8_t slot_id_param,
     142              :                                                     const void *requester_context,
     143              :                                                     uint8_t *content_changed,
     144              :                                                     uint8_t *number_of_blocks,
     145              :                                                     uint32_t *measurement_record_length,
     146              :                                                     void *measurement_record,
     147              :                                                     const void *requester_nonce_in,
     148              :                                                     void *requester_nonce,
     149              :                                                     void *responder_nonce,
     150              :                                                     void *opaque_data,
     151              :                                                     size_t *opaque_data_size)
     152              : {
     153              :     bool result;
     154              :     libspdm_return_t status;
     155              :     spdm_get_measurements_request_t *spdm_request;
     156              :     size_t spdm_request_size;
     157              :     spdm_measurements_response_t *spdm_response;
     158              :     size_t spdm_response_size;
     159              :     uint32_t measurement_record_data_length;
     160              :     uint8_t *measurement_record_data;
     161              :     spdm_measurement_block_common_header_t *measurement_block_header;
     162              :     uint32_t measurement_block_size;
     163              :     uint8_t measurement_block_count;
     164              :     uint8_t *ptr;
     165              :     void *nonce;
     166              :     uint16_t opaque_length;
     167              :     void *signature;
     168              :     size_t signature_size;
     169              :     libspdm_session_info_t *session_info;
     170              :     libspdm_session_state_t session_state;
     171              :     uint8_t *message;
     172              :     size_t message_size;
     173              :     size_t transport_header_size;
     174              : 
     175              :     /* -=[Check Parameters Phase]=- */
     176          306 :     LIBSPDM_ASSERT((slot_id_param < SPDM_MAX_SLOT_COUNT) || (slot_id_param == 0xF));
     177          306 :     LIBSPDM_ASSERT((slot_id_param != 0xf) ||
     178              :                    (spdm_context->local_context.peer_public_key_provision_size != 0));
     179              : 
     180              :     /* -=[Verify State Phase]=- */
     181          306 :     if (!libspdm_is_capabilities_flag_supported(
     182              :             spdm_context, true, 0,
     183              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP)) {
     184            1 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     185              :     }
     186              : 
     187          305 :     LIBSPDM_ASSERT(spdm_context->local_context.algorithm.measurement_spec != 0);
     188              : 
     189          305 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     190            2 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     191              :     }
     192              : 
     193          303 :     if (session_id == NULL) {
     194          302 :         session_info = NULL;
     195              :     } else {
     196            1 :         session_info = libspdm_get_session_info_via_session_id(spdm_context, *session_id);
     197            1 :         if (session_info == NULL) {
     198            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     199              :         }
     200            1 :         session_state = libspdm_secured_message_get_session_state(
     201              :             session_info->secured_message_context);
     202            1 :         if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
     203            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     204              :         }
     205              :     }
     206              : 
     207          303 :     if (libspdm_is_capabilities_flag_supported(
     208              :             spdm_context, true, 0,
     209            3 :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP_NO_SIG) &&
     210            3 :         ((request_attribute & SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE) != 0)) {
     211            1 :         return LIBSPDM_STATUS_INVALID_PARAMETER;
     212              :     }
     213              : 
     214          302 :     if ((request_attribute & SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE) != 0) {
     215           75 :         signature_size = libspdm_get_asym_signature_size(
     216              :             spdm_context->connection_info.algorithm.base_asym_algo);
     217              :     } else {
     218          227 :         signature_size = 0;
     219              :     }
     220              : 
     221          302 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL, SPDM_GET_MEASUREMENTS);
     222              : 
     223              :     /* -=[Construct Request Phase]=- */
     224          302 :     spdm_context->connection_info.peer_used_cert_chain_slot_id = slot_id_param;
     225          302 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
     226          302 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     227          302 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     228            1 :         return status;
     229              :     }
     230          301 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
     231              :                     spdm_context->local_context.capability.transport_tail_size);
     232          301 :     spdm_request = (void *)(message + transport_header_size);
     233          301 :     spdm_request_size = message_size - transport_header_size -
     234          301 :                         spdm_context->local_context.capability.transport_tail_size;
     235              : 
     236          301 :     LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_request->header));
     237          301 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     238          301 :     spdm_request->header.request_response_code = SPDM_GET_MEASUREMENTS;
     239          301 :     spdm_request->header.param1 = request_attribute;
     240          301 :     spdm_request->header.param2 = measurement_operation;
     241          301 :     if ((request_attribute & SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE) != 0) {
     242           75 :         if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     243            0 :             LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_measurements_request_t) +
     244              :                             SPDM_REQ_CONTEXT_SIZE);
     245            0 :             spdm_request_size = sizeof(spdm_get_measurements_request_t) + SPDM_REQ_CONTEXT_SIZE;
     246           75 :         } else if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
     247           75 :             LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_measurements_request_t));
     248           75 :             spdm_request_size = sizeof(spdm_get_measurements_request_t);
     249              :         } else {
     250            0 :             LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_measurements_request_t) -
     251              :                             sizeof(spdm_request->slot_id_param));
     252            0 :             spdm_request_size = sizeof(spdm_get_measurements_request_t) -
     253              :                                 sizeof(spdm_request->slot_id_param);
     254              :         }
     255              : 
     256           75 :         if (requester_nonce_in == NULL) {
     257           73 :             if(!libspdm_get_random_number(SPDM_NONCE_SIZE, spdm_request->nonce)) {
     258            0 :                 libspdm_release_sender_buffer (spdm_context);
     259            0 :                 return LIBSPDM_STATUS_LOW_ENTROPY;
     260              :             }
     261              :         } else {
     262            2 :             libspdm_copy_mem(spdm_request->nonce, sizeof(spdm_request->nonce),
     263              :                              requester_nonce_in, SPDM_NONCE_SIZE);
     264              :         }
     265           75 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterNonce - "));
     266           75 :         LIBSPDM_INTERNAL_DUMP_DATA(spdm_request->nonce, SPDM_NONCE_SIZE);
     267           75 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     268           75 :         spdm_request->slot_id_param = slot_id_param;
     269              : 
     270           75 :         if (requester_nonce != NULL) {
     271            2 :             libspdm_copy_mem(requester_nonce, SPDM_NONCE_SIZE,
     272            2 :                              spdm_request->nonce, SPDM_NONCE_SIZE);
     273              :         }
     274              :     } else {
     275          226 :         if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     276            2 :             LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_request->header) +
     277              :                             SPDM_REQ_CONTEXT_SIZE);
     278            2 :             spdm_request_size = sizeof(spdm_request->header) + SPDM_REQ_CONTEXT_SIZE;
     279              :         } else {
     280          224 :             spdm_request_size = sizeof(spdm_request->header);
     281              :         }
     282              : 
     283          226 :         if (requester_nonce != NULL) {
     284            0 :             libspdm_zero_mem (requester_nonce, SPDM_NONCE_SIZE);
     285              :         }
     286              :     }
     287          301 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     288            2 :         if (requester_context == NULL) {
     289            0 :             libspdm_zero_mem((uint8_t *)spdm_request + spdm_request_size - SPDM_REQ_CONTEXT_SIZE,
     290              :                              SPDM_REQ_CONTEXT_SIZE);
     291              :         } else {
     292            2 :             libspdm_copy_mem((uint8_t *)spdm_request + spdm_request_size - SPDM_REQ_CONTEXT_SIZE,
     293              :                              SPDM_REQ_CONTEXT_SIZE,
     294              :                              requester_context, SPDM_REQ_CONTEXT_SIZE);
     295              :         }
     296            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterContext - "));
     297            2 :         LIBSPDM_INTERNAL_DUMP_DATA((uint8_t *)spdm_request + spdm_request_size -
     298              :                                    SPDM_REQ_CONTEXT_SIZE,
     299              :                                    SPDM_REQ_CONTEXT_SIZE);
     300            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     301              :     }
     302              : 
     303              :     /* -=[Send Request Phase]=- */
     304          301 :     status = libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request);
     305          301 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     306            2 :         libspdm_release_sender_buffer (spdm_context);
     307            2 :         return status;
     308              :     }
     309          299 :     libspdm_release_sender_buffer (spdm_context);
     310          299 :     spdm_request = (void *)spdm_context->last_spdm_request;
     311              : 
     312              :     /* -=[Receive Response Phase]=- */
     313          299 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     314          299 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     315            1 :         return status;
     316              :     }
     317          298 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
     318          298 :     spdm_response = (void *)(message);
     319          298 :     spdm_response_size = message_size;
     320              : 
     321          298 :     status = libspdm_receive_spdm_response(
     322              :         spdm_context, session_id, &spdm_response_size, (void **)&spdm_response);
     323          298 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     324            1 :         goto receive_done;
     325              :     }
     326              : 
     327              :     /* -=[Validate Response Phase]=- */
     328          297 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     329            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     330            0 :         goto receive_done;
     331              :     }
     332          297 :     if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     333            0 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     334            0 :         goto receive_done;
     335              :     }
     336          297 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     337           46 :         status = libspdm_handle_error_response_main(
     338              :             spdm_context, session_id,
     339              :             &spdm_response_size, (void **)&spdm_response,
     340              :             SPDM_GET_MEASUREMENTS, SPDM_MEASUREMENTS);
     341           46 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     342           45 :             goto receive_done;
     343              :         }
     344          251 :     } else if (spdm_response->header.request_response_code != SPDM_MEASUREMENTS) {
     345            2 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     346            2 :         goto receive_done;
     347              :     }
     348          250 :     if (spdm_response_size < sizeof(spdm_measurements_response_t)) {
     349            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     350            0 :         goto receive_done;
     351              :     }
     352          250 :     if (measurement_operation ==
     353              :         SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_TOTAL_NUMBER_OF_MEASUREMENTS) {
     354            8 :         if (spdm_response->number_of_blocks != 0) {
     355            4 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     356            4 :             goto receive_done;
     357              :         }
     358          242 :     } else if (measurement_operation ==
     359              :                SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_ALL_MEASUREMENTS) {
     360            2 :         if ((spdm_response->number_of_blocks == 0) || (spdm_response->number_of_blocks == 0xff)) {
     361            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     362            0 :             goto receive_done;
     363              :         }
     364              :     } else {
     365          240 :         if (spdm_response->number_of_blocks != 1) {
     366            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     367            0 :             goto receive_done;
     368              :         }
     369              :     }
     370              : 
     371          246 :     measurement_record_data_length = libspdm_read_uint24(spdm_response->measurement_record_length);
     372          246 :     if (measurement_operation ==
     373              :         SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_TOTAL_NUMBER_OF_MEASUREMENTS) {
     374            4 :         if (measurement_record_data_length != 0) {
     375            2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     376            2 :             goto receive_done;
     377              :         }
     378              :     } else {
     379          242 :         if (spdm_response_size <
     380          242 :             sizeof(spdm_measurements_response_t) +
     381              :             measurement_record_data_length) {
     382            0 :             status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     383            0 :             goto receive_done;
     384              :         }
     385          242 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "measurement_record_length - 0x%06x\n",
     386              :                        measurement_record_data_length));
     387              :     }
     388              : 
     389          244 :     measurement_record_data = (void *)(spdm_response + 1);
     390              : 
     391          244 :     if ((request_attribute & SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE) != 0) {
     392           25 :         if (spdm_response_size <
     393              :             sizeof(spdm_measurements_response_t) +
     394           25 :             measurement_record_data_length + SPDM_NONCE_SIZE + sizeof(uint16_t)) {
     395            0 :             status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     396            0 :             goto receive_done;
     397              :         }
     398           25 :         if ((spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_11) &&
     399           25 :             ((spdm_response->header.param2 & SPDM_MEASUREMENTS_RESPONSE_SLOT_ID_MASK)
     400           25 :              != slot_id_param)) {
     401            3 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     402            3 :             goto receive_done;
     403              :         }
     404           22 :         ptr = measurement_record_data + measurement_record_data_length;
     405           22 :         nonce = ptr;
     406           22 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "nonce (0x%x) - ", SPDM_NONCE_SIZE));
     407           22 :         LIBSPDM_INTERNAL_DUMP_DATA(nonce, SPDM_NONCE_SIZE);
     408           22 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     409           22 :         ptr += SPDM_NONCE_SIZE;
     410           22 :         if (responder_nonce != NULL) {
     411            2 :             libspdm_copy_mem(responder_nonce, SPDM_NONCE_SIZE, nonce, SPDM_NONCE_SIZE);
     412              :         }
     413              : 
     414           22 :         opaque_length = libspdm_read_uint16((const uint8_t *)ptr);
     415           22 :         if (opaque_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
     416            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     417            0 :             goto receive_done;
     418              :         }
     419           22 :         if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     420            3 :             if (((spdm_context->connection_info.algorithm.other_params_support &
     421              :                   SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) ==
     422              :                  SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE)
     423            2 :                 && (opaque_length != 0)) {
     424            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     425            0 :                 goto receive_done;
     426              :             }
     427              :         }
     428           22 :         ptr += sizeof(uint16_t);
     429           22 :         if (opaque_length != 0) {
     430            9 :             result = libspdm_process_general_opaque_data_check(spdm_context, opaque_length, ptr);
     431            9 :             if (!result) {
     432            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     433            0 :                 goto receive_done;
     434              :             }
     435              :         }
     436              : 
     437           22 :         if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     438            0 :             if (spdm_response_size <
     439              :                 sizeof(spdm_measurements_response_t) +
     440              :                 measurement_record_data_length + SPDM_NONCE_SIZE +
     441            0 :                 sizeof(uint16_t) + opaque_length + SPDM_REQ_CONTEXT_SIZE + signature_size) {
     442            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     443            0 :                 goto receive_done;
     444              :             }
     445            0 :             spdm_response_size = sizeof(spdm_measurements_response_t) +
     446              :                                  measurement_record_data_length +
     447            0 :                                  SPDM_NONCE_SIZE + sizeof(uint16_t) +
     448            0 :                                  opaque_length + SPDM_REQ_CONTEXT_SIZE + signature_size;
     449              :         } else {
     450           22 :             if (spdm_response_size <
     451              :                 sizeof(spdm_measurements_response_t) +
     452              :                 measurement_record_data_length + SPDM_NONCE_SIZE +
     453           22 :                 sizeof(uint16_t) + opaque_length + signature_size) {
     454            6 :                 status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     455            6 :                 goto receive_done;
     456              :             }
     457           16 :             spdm_response_size = sizeof(spdm_measurements_response_t) +
     458              :                                  measurement_record_data_length +
     459           16 :                                  SPDM_NONCE_SIZE + sizeof(uint16_t) +
     460           16 :                                  opaque_length + signature_size;
     461              :         }
     462              : 
     463           16 :         if ((opaque_data != NULL) && (opaque_data_size != NULL)) {
     464            2 :             if (opaque_length >= *opaque_data_size) {
     465            0 :                 status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     466            0 :                 goto receive_done;
     467              :             }
     468            2 :             libspdm_copy_mem(opaque_data, *opaque_data_size, ptr, opaque_length);
     469            2 :             *opaque_data_size = opaque_length;
     470              :         }
     471           16 :         ptr += opaque_length;
     472           16 :         if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     473            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterContext - "));
     474            0 :             LIBSPDM_INTERNAL_DUMP_DATA(ptr, SPDM_REQ_CONTEXT_SIZE);
     475            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     476            0 :             if (!libspdm_consttime_is_mem_equal((uint8_t *)spdm_request +
     477            0 :                                                 spdm_request_size - SPDM_REQ_CONTEXT_SIZE,
     478              :                                                 ptr, SPDM_REQ_CONTEXT_SIZE)) {
     479            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     480            0 :                 goto receive_done;
     481              :             }
     482            0 :             ptr += SPDM_REQ_CONTEXT_SIZE;
     483              :         }
     484              : 
     485              :         /* -=[Process Response Phase]=- */
     486           16 :         status = libspdm_append_message_m(spdm_context, session_info, spdm_request,
     487              :                                           spdm_request_size);
     488           16 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     489            0 :             goto receive_done;
     490              :         }
     491              : 
     492           16 :         status = libspdm_append_message_m(spdm_context, session_info, spdm_response,
     493              :                                           spdm_response_size - signature_size);
     494           16 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     495            0 :             goto receive_done;
     496              :         }
     497              : 
     498           16 :         signature = ptr;
     499           16 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature (0x%zx):\n", signature_size));
     500           16 :         LIBSPDM_INTERNAL_DUMP_HEX(signature, signature_size);
     501              : 
     502           16 :         result = libspdm_verify_measurement_signature(
     503              :             spdm_context, session_info, signature, signature_size);
     504           16 :         if (!result) {
     505            6 :             status = LIBSPDM_STATUS_VERIF_FAIL;
     506            6 :             goto receive_done;
     507              :         }
     508              : 
     509           10 :         libspdm_reset_message_m(spdm_context, session_info);
     510              :     } else {
     511          219 :         if (spdm_response_size <
     512              :             sizeof(spdm_measurements_response_t) +
     513          219 :             measurement_record_data_length + sizeof(uint16_t)) {
     514            0 :             status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     515            0 :             goto receive_done;
     516              :         }
     517          219 :         ptr = measurement_record_data + measurement_record_data_length;
     518              : 
     519          219 :         nonce = ptr;
     520          219 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "nonce (0x%x) - ", SPDM_NONCE_SIZE));
     521          219 :         LIBSPDM_INTERNAL_DUMP_DATA(nonce, SPDM_NONCE_SIZE);
     522          219 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     523          219 :         ptr += SPDM_NONCE_SIZE;
     524          219 :         if (responder_nonce != NULL) {
     525            0 :             libspdm_copy_mem(responder_nonce, SPDM_NONCE_SIZE, nonce, SPDM_NONCE_SIZE);
     526              :         }
     527              : 
     528          219 :         opaque_length = libspdm_read_uint16((const uint8_t *)ptr);
     529          219 :         if (opaque_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
     530            2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     531            2 :             goto receive_done;
     532              :         }
     533          217 :         ptr += sizeof(uint16_t);
     534          217 :         if (opaque_length != 0) {
     535            3 :             result = libspdm_process_general_opaque_data_check(spdm_context, opaque_length, ptr);
     536            3 :             if (!result) {
     537            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     538            0 :                 goto receive_done;
     539              :             }
     540              :         }
     541              : 
     542          217 :         if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     543            2 :             if (spdm_response_size <
     544              :                 sizeof(spdm_measurements_response_t) +
     545              :                 measurement_record_data_length + SPDM_NONCE_SIZE +
     546            2 :                 sizeof(uint16_t) + opaque_length + SPDM_REQ_CONTEXT_SIZE) {
     547            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     548            0 :                 goto receive_done;
     549              :             }
     550            2 :             spdm_response_size = sizeof(spdm_measurements_response_t) +
     551              :                                  measurement_record_data_length +
     552            2 :                                  SPDM_NONCE_SIZE + sizeof(uint16_t) +
     553            2 :                                  opaque_length + SPDM_REQ_CONTEXT_SIZE;
     554              :         } else {
     555          215 :             if (spdm_response_size <
     556              :                 sizeof(spdm_measurements_response_t) +
     557              :                 measurement_record_data_length + SPDM_NONCE_SIZE +
     558          215 :                 sizeof(uint16_t) + opaque_length) {
     559            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     560            0 :                 goto receive_done;
     561              :             }
     562          215 :             spdm_response_size = sizeof(spdm_measurements_response_t) +
     563              :                                  measurement_record_data_length +
     564          215 :                                  SPDM_NONCE_SIZE + sizeof(uint16_t) +
     565              :                                  opaque_length;
     566              :         }
     567              : 
     568          217 :         if ((opaque_data != NULL) && (opaque_data_size != NULL)) {
     569            0 :             if (opaque_length >= *opaque_data_size) {
     570            0 :                 status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     571            0 :                 goto receive_done;
     572              :             }
     573            0 :             libspdm_copy_mem(opaque_data, *opaque_data_size, ptr, opaque_length);
     574            0 :             *opaque_data_size = opaque_length;
     575              :         }
     576          217 :         ptr += opaque_length;
     577          217 :         if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     578            2 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterContext - "));
     579            2 :             LIBSPDM_INTERNAL_DUMP_DATA(ptr, SPDM_REQ_CONTEXT_SIZE);
     580            2 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     581            2 :             if (!libspdm_consttime_is_mem_equal((uint8_t *)spdm_request +
     582            2 :                                                 spdm_request_size - SPDM_REQ_CONTEXT_SIZE,
     583              :                                                 ptr, SPDM_REQ_CONTEXT_SIZE)) {
     584            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     585            1 :                 goto receive_done;
     586              :             }
     587            1 :             ptr += SPDM_REQ_CONTEXT_SIZE;
     588              :         }
     589              : 
     590              :         /* If a signature is not requested then content_changed must be 0. */
     591          216 :         if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     592            4 :             if ((spdm_response->header.param2 & SPDM_MEASUREMENTS_RESPONSE_CONTENT_CHANGE_MASK)
     593              :                 != 0) {
     594            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     595            1 :                 goto receive_done;
     596              :             }
     597              :         }
     598              : 
     599          215 :         status = libspdm_append_message_m(spdm_context, session_info, spdm_request,
     600              :                                           spdm_request_size);
     601          215 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     602            0 :             goto receive_done;
     603              :         }
     604              : 
     605          215 :         status = libspdm_append_message_m(spdm_context, session_info, spdm_response,
     606              :                                           spdm_response_size);
     607          215 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     608            0 :             goto receive_done;
     609              :         }
     610              :     }
     611              : 
     612          225 :     if (content_changed != NULL) {
     613            0 :         *content_changed = 0;
     614            0 :         if ((spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) &&
     615            0 :             ((request_attribute &
     616              :               SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE) != 0)) {
     617            0 :             *content_changed =
     618            0 :                 (spdm_response->header.param2 & SPDM_MEASUREMENTS_RESPONSE_CONTENT_CHANGE_MASK);
     619              :         }
     620              :     }
     621          225 :     if (measurement_operation ==
     622              :         SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_TOTAL_NUMBER_OF_MEASUREMENTS) {
     623            2 :         *number_of_blocks = spdm_response->header.param1;
     624            2 :         if (*number_of_blocks == 0xFF) {
     625              :             /* the number of block cannot be 0xFF, because index 0xFF will brings confusing.*/
     626            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     627            0 :             goto receive_done;
     628              :         }
     629            2 :         if (*number_of_blocks == 0x0) {
     630              :             /* the number of block cannot be 0x0, because a responder without measurement should clear capability flags.*/
     631            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     632            0 :             goto receive_done;
     633              :         }
     634              :     } else {
     635          223 :         *number_of_blocks = spdm_response->number_of_blocks;
     636          223 :         if (*measurement_record_length < measurement_record_data_length) {
     637            0 :             status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     638            0 :             goto receive_done;
     639              :         }
     640          223 :         if (measurement_record_data_length < sizeof(spdm_measurement_block_common_header_t)) {
     641            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     642            0 :             goto receive_done;
     643              :         }
     644              : 
     645          223 :         measurement_block_size = 0;
     646          223 :         measurement_block_count = 1;
     647          442 :         while (measurement_block_size < measurement_record_data_length) {
     648          225 :             measurement_block_header =
     649          225 :                 (spdm_measurement_block_common_header_t *)&measurement_record_data
     650              :                 [measurement_block_size];
     651          225 :             if (measurement_block_header->measurement_size >
     652          225 :                 measurement_record_data_length -
     653          225 :                 ((uint8_t *)measurement_block_header -
     654              :                  (uint8_t *)measurement_record_data)) {
     655            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     656            0 :                 goto receive_done;
     657              :             }
     658          225 :             if (measurement_block_header->measurement_specification == 0 ||
     659          225 :                 (measurement_block_header->measurement_specification &
     660          225 :                  (measurement_block_header->measurement_specification - 1))) {
     661            4 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     662            4 :                 goto receive_done;
     663              :             }
     664          221 :             if (measurement_block_header->measurement_specification !=
     665          221 :                 spdm_context->connection_info.algorithm.measurement_spec) {
     666            2 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     667            2 :                 goto receive_done;
     668              :             }
     669          219 :             if (measurement_block_header->index == 0 || measurement_block_header->index == 0xFF) {
     670            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     671            0 :                 goto receive_done;
     672              :             }
     673          219 :             if (measurement_operation !=
     674              :                 SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_ALL_MEASUREMENTS) {
     675          215 :                 if (measurement_block_header->index != measurement_operation) {
     676            0 :                     status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     677            0 :                     goto receive_done;
     678              :                 }
     679              :             }
     680          219 :             if (measurement_block_count > *number_of_blocks) {
     681            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     682            0 :                 goto receive_done;
     683              :             }
     684          219 :             measurement_block_count++;
     685          219 :             measurement_block_size = (uint32_t)(
     686              :                 measurement_block_size +
     687          219 :                 sizeof(spdm_measurement_block_common_header_t) +
     688          219 :                 measurement_block_header->measurement_size);
     689              :         }
     690              : 
     691          217 :         if (measurement_block_size != measurement_record_data_length) {
     692            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     693            0 :             goto receive_done;
     694              :         }
     695              : 
     696          217 :         *measurement_record_length = measurement_record_data_length;
     697          217 :         libspdm_copy_mem(measurement_record,
     698              :                          measurement_record_data_length,
     699              :                          measurement_record_data,
     700              :                          measurement_record_data_length);
     701              :     }
     702              : 
     703          219 :     status = LIBSPDM_STATUS_SUCCESS;
     704              : 
     705              :     /* -=[Log Message Phase]=- */
     706              :     #if LIBSPDM_ENABLE_MSG_LOG
     707          219 :     libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     708              :     #endif /* LIBSPDM_ENABLE_MSG_LOG */
     709              : 
     710          298 : receive_done:
     711          298 :     if ((status != LIBSPDM_STATUS_SUCCESS) &&
     712              :         (status != LIBSPDM_STATUS_NOT_READY_PEER)) {
     713           77 :         libspdm_reset_message_m(spdm_context, session_info);
     714              :     }
     715          298 :     libspdm_release_receiver_buffer (spdm_context);
     716          298 :     return status;
     717              : }
     718              : 
     719          301 : libspdm_return_t libspdm_get_measurement(void *spdm_context, const uint32_t *session_id,
     720              :                                          uint8_t request_attribute,
     721              :                                          uint8_t measurement_operation,
     722              :                                          uint8_t slot_id_param,
     723              :                                          uint8_t *content_changed,
     724              :                                          uint8_t *number_of_blocks,
     725              :                                          uint32_t *measurement_record_length,
     726              :                                          void *measurement_record)
     727              : {
     728              :     libspdm_context_t *context;
     729              :     size_t retry;
     730              :     uint64_t retry_delay_time;
     731              :     libspdm_return_t status;
     732              : 
     733          301 :     context = spdm_context;
     734          301 :     context->crypto_request = true;
     735          301 :     retry = context->retry_times;
     736          301 :     retry_delay_time = context->retry_delay_time;
     737              :     do {
     738          302 :         status = libspdm_try_get_measurement(
     739              :             context, session_id, request_attribute,
     740              :             measurement_operation, slot_id_param, NULL, content_changed, number_of_blocks,
     741              :             measurement_record_length, measurement_record,
     742              :             NULL, NULL, NULL, NULL, NULL);
     743          302 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     744          299 :             return status;
     745              :         }
     746              : 
     747            3 :         libspdm_sleep(retry_delay_time);
     748            3 :     } while (retry-- != 0);
     749              : 
     750            2 :     return status;
     751              : }
     752              : 
     753            2 : libspdm_return_t libspdm_get_measurement_ex(void *spdm_context, const uint32_t *session_id,
     754              :                                             uint8_t request_attribute,
     755              :                                             uint8_t measurement_operation,
     756              :                                             uint8_t slot_id_param,
     757              :                                             uint8_t *content_changed,
     758              :                                             uint8_t *number_of_blocks,
     759              :                                             uint32_t *measurement_record_length,
     760              :                                             void *measurement_record,
     761              :                                             const void *requester_nonce_in,
     762              :                                             void *requester_nonce,
     763              :                                             void *responder_nonce,
     764              :                                             void *opaque_data,
     765              :                                             size_t *opaque_data_size)
     766              : {
     767              :     libspdm_context_t *context;
     768              :     size_t retry;
     769              :     uint64_t retry_delay_time;
     770              :     libspdm_return_t status;
     771              : 
     772            2 :     context = spdm_context;
     773            2 :     context->crypto_request = true;
     774            2 :     retry = context->retry_times;
     775            2 :     retry_delay_time = context->retry_delay_time;
     776              :     do {
     777            2 :         status = libspdm_try_get_measurement(
     778              :             context, session_id, request_attribute,
     779              :             measurement_operation, slot_id_param, NULL, content_changed, number_of_blocks,
     780              :             measurement_record_length, measurement_record,
     781              :             requester_nonce_in,
     782              :             requester_nonce, responder_nonce,
     783              :             opaque_data, opaque_data_size);
     784            2 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     785            2 :             return status;
     786              :         }
     787              : 
     788            0 :         libspdm_sleep(retry_delay_time);
     789            0 :     } while (retry-- != 0);
     790              : 
     791            0 :     return status;
     792              : }
     793              : 
     794            2 : libspdm_return_t libspdm_get_measurement_ex2(void *spdm_context, const uint32_t *session_id,
     795              :                                              uint8_t request_attribute,
     796              :                                              uint8_t measurement_operation,
     797              :                                              uint8_t slot_id_param,
     798              :                                              const void *requester_context,
     799              :                                              uint8_t *content_changed,
     800              :                                              uint8_t *number_of_blocks,
     801              :                                              uint32_t *measurement_record_length,
     802              :                                              void *measurement_record,
     803              :                                              const void *requester_nonce_in,
     804              :                                              void *requester_nonce,
     805              :                                              void *responder_nonce,
     806              :                                              void *opaque_data,
     807              :                                              size_t *opaque_data_size)
     808              : {
     809              :     libspdm_context_t *context;
     810              :     size_t retry;
     811              :     uint64_t retry_delay_time;
     812              :     libspdm_return_t status;
     813              : 
     814            2 :     context = spdm_context;
     815            2 :     context->crypto_request = true;
     816            2 :     retry = context->retry_times;
     817            2 :     retry_delay_time = context->retry_delay_time;
     818              :     do {
     819            2 :         status = libspdm_try_get_measurement(
     820              :             context, session_id, request_attribute,
     821              :             measurement_operation, slot_id_param, requester_context,
     822              :             content_changed, number_of_blocks,
     823              :             measurement_record_length, measurement_record,
     824              :             requester_nonce_in,
     825              :             requester_nonce, responder_nonce,
     826              :             opaque_data, opaque_data_size);
     827            2 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     828            2 :             return status;
     829              :         }
     830              : 
     831            0 :         libspdm_sleep(retry_delay_time);
     832            0 :     } while (retry-- != 0);
     833              : 
     834            0 :     return status;
     835              : }
     836              : 
     837              : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP*/
        

Generated by: LCOV version 2.0-1