LCOV - code coverage report
Current view: top level - library/spdm_requester_lib - libspdm_req_get_measurement_extension_log.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 69.9 % 143 100
Test Date: 2025-12-21 08:10:27 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2024-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_ENABLE_CAPABILITY_MEL_CAP
      10              : 
      11              : /**
      12              :  * This function sends GET_MEASUREMENT_EXTENSION_LOG and receives MEASUREMENT_EXTENSION_LOG.
      13              :  *
      14              :  * @param  spdm_context               A pointer to the SPDM context.
      15              :  * @param  session_id                 Indicates if it is a secured message protected via SPDM session.
      16              :  *                                    If session_id is NULL, it is a normal message.
      17              :  *                                    If session_id is not NULL, it is a secured message.
      18              :  * @param  mel_size                   On input, indicate the size in bytes of the destination buffer to store.
      19              :  *                                    On output, indicate the size in bytes of the MEL.
      20              :  * @param  measure_exten_log          A pointer to a destination buffer to store the MEL.
      21              :  *
      22              :  **/
      23            9 : static libspdm_return_t libspdm_try_get_measurement_extension_log(libspdm_context_t *spdm_context,
      24              :                                                                   const uint32_t *session_id,
      25              :                                                                   size_t *mel_size,
      26              :                                                                   void *measure_exten_log)
      27              : {
      28              :     libspdm_return_t status;
      29              :     spdm_get_measurement_extension_log_request_t *spdm_request;
      30              :     size_t spdm_request_size;
      31              :     spdm_measurement_extension_log_response_t *spdm_response;
      32              :     size_t spdm_response_size;
      33              :     uint8_t *mel_block;
      34              :     uint32_t length;
      35              :     uint32_t total_responder_mel_buffer_length;
      36              :     size_t mel_capacity;
      37              :     size_t mel_size_internal;
      38              :     uint32_t remainder_length;
      39              :     uint8_t *message;
      40              :     size_t message_size;
      41              :     size_t transport_header_size;
      42              :     libspdm_session_info_t *session_info;
      43              :     libspdm_session_state_t session_state;
      44              :     spdm_measurement_extension_log_dmtf_t *measurement_extension_log;
      45              : 
      46              :     /* -=[Check Parameters Phase]=- */
      47            9 :     LIBSPDM_ASSERT(mel_size != NULL);
      48            9 :     LIBSPDM_ASSERT(*mel_size > 0);
      49            9 :     LIBSPDM_ASSERT(measure_exten_log != NULL);
      50              : 
      51              :     /* -=[Verify State Phase]=- */
      52            9 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) {
      53            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
      54              :     }
      55              : 
      56            9 :     if (!libspdm_is_capabilities_flag_supported(
      57              :             spdm_context, true, 0,
      58              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEL_CAP)) {
      59            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
      60              :     }
      61            9 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
      62            0 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
      63              :     }
      64              : 
      65            9 :     session_info = NULL;
      66            9 :     if (session_id != NULL) {
      67            0 :         session_info = libspdm_get_session_info_via_session_id(spdm_context, *session_id);
      68            0 :         if (session_info == NULL) {
      69            0 :             LIBSPDM_ASSERT(false);
      70            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
      71              :         }
      72            0 :         session_state = libspdm_secured_message_get_session_state(
      73              :             session_info->secured_message_context);
      74            0 :         if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
      75            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
      76              :         }
      77              :     }
      78              : 
      79            9 :     libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
      80              :                                                   SPDM_GET_MEASUREMENT_EXTENSION_LOG);
      81              : 
      82            9 :     remainder_length = 0;
      83            9 :     total_responder_mel_buffer_length = 0;
      84            9 :     mel_capacity = *mel_size;
      85            9 :     mel_size_internal = 0;
      86              : 
      87            9 :     length = LIBSPDM_MIN(SPDM_MAX_MEASUREMENT_EXTENSION_LOG_SIZE,
      88              :                          spdm_context->local_context.capability.max_spdm_msg_size -
      89              :                          sizeof(spdm_measurement_extension_log_response_t));
      90              : 
      91            9 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
      92              : 
      93              :     do {
      94              :         /* -=[Construct Request Phase]=- */
      95           15 :         status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
      96           15 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
      97            0 :             return status;
      98              :         }
      99           15 :         LIBSPDM_ASSERT (message_size >= transport_header_size +
     100              :                         spdm_context->local_context.capability.transport_tail_size);
     101           15 :         spdm_request = (void *)(message + transport_header_size);
     102           15 :         spdm_request_size = message_size - transport_header_size -
     103           15 :                             spdm_context->local_context.capability.transport_tail_size;
     104              : 
     105           15 :         spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     106           15 :         spdm_request->header.request_response_code = SPDM_GET_MEASUREMENT_EXTENSION_LOG;
     107           15 :         spdm_request->header.param1 = 0;
     108           15 :         spdm_request->header.param2 = 0;
     109           15 :         spdm_request->offset = (uint32_t)mel_size_internal;
     110           15 :         if (spdm_request->offset == 0) {
     111            9 :             spdm_request->length = length;
     112              :         } else {
     113            6 :             spdm_request->length = LIBSPDM_MIN(length, remainder_length);
     114              :         }
     115           15 :         spdm_request_size = sizeof(spdm_get_measurement_extension_log_request_t);
     116           15 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "request (offset 0x%x, size 0x%x):\n",
     117              :                        spdm_request->offset, spdm_request->length));
     118              : 
     119              :         /* -=[Send Request Phase]=- */
     120              :         status =
     121           15 :             libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request);
     122           15 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     123            1 :             libspdm_release_sender_buffer (spdm_context);
     124            1 :             status = LIBSPDM_STATUS_SEND_FAIL;
     125            1 :             goto done;
     126              :         }
     127           14 :         libspdm_release_sender_buffer (spdm_context);
     128           14 :         spdm_request = (void *)spdm_context->last_spdm_request;
     129              : 
     130              :         /* -=[Receive Response Phase]=- */
     131           14 :         status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     132           14 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     133            0 :             return status;
     134              :         }
     135           14 :         LIBSPDM_ASSERT (message_size >= transport_header_size);
     136           14 :         spdm_response = (void *)(message);
     137           14 :         spdm_response_size = message_size;
     138              : 
     139           14 :         status = libspdm_receive_spdm_response(spdm_context, session_id,
     140              :                                                &spdm_response_size,
     141              :                                                (void **)&spdm_response);
     142           14 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     143            0 :             libspdm_release_receiver_buffer (spdm_context);
     144            0 :             status = LIBSPDM_STATUS_RECEIVE_FAIL;
     145            0 :             goto done;
     146              :         }
     147              : 
     148              :         /* -=[Validate Response Phase]=- */
     149           14 :         if (spdm_response_size < sizeof(spdm_message_header_t)) {
     150            0 :             libspdm_release_receiver_buffer (spdm_context);
     151            0 :             status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     152            0 :             goto done;
     153              :         }
     154           14 :         if (spdm_response->header.request_response_code == SPDM_ERROR) {
     155            0 :             status = libspdm_handle_error_response_main(
     156              :                 spdm_context, session_id,
     157              :                 &spdm_response_size,
     158              :                 (void **)&spdm_response, SPDM_GET_MEASUREMENT_EXTENSION_LOG,
     159              :                 SPDM_MEASUREMENT_EXTENSION_LOG);
     160            0 :             if (LIBSPDM_STATUS_IS_ERROR(status)) {
     161            0 :                 libspdm_release_receiver_buffer (spdm_context);
     162            0 :                 goto done;
     163              :             }
     164           14 :         } else if (spdm_response->header.request_response_code != SPDM_MEASUREMENT_EXTENSION_LOG) {
     165            0 :             libspdm_release_receiver_buffer (spdm_context);
     166            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     167            0 :             goto done;
     168              :         }
     169           14 :         if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     170            0 :             libspdm_release_receiver_buffer (spdm_context);
     171            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     172            0 :             goto done;
     173              :         }
     174           14 :         if (spdm_response_size < sizeof(spdm_measurement_extension_log_response_t)) {
     175            0 :             libspdm_release_receiver_buffer (spdm_context);
     176            0 :             status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     177            0 :             goto done;
     178              :         }
     179           14 :         if ((spdm_response->portion_length > spdm_request->length) ||
     180           13 :             (spdm_response->portion_length == 0)) {
     181            1 :             libspdm_release_receiver_buffer (spdm_context);
     182            1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     183            1 :             goto done;
     184              :         }
     185           13 :         if (spdm_response_size < sizeof(spdm_measurement_extension_log_response_t) +
     186           13 :             spdm_response->portion_length) {
     187            0 :             libspdm_release_receiver_buffer (spdm_context);
     188            0 :             status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     189            0 :             goto done;
     190              :         }
     191           13 :         if (spdm_response->portion_length > 0xFFFFFFFF - spdm_request->offset) {
     192            0 :             libspdm_release_receiver_buffer (spdm_context);
     193            0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     194            0 :             goto done;
     195              :         }
     196           13 :         if (spdm_response->remainder_length > 0xFFFFFFFF - spdm_request->offset -
     197           13 :             spdm_response->portion_length) {
     198            1 :             libspdm_release_receiver_buffer (spdm_context);
     199            1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     200            1 :             goto done;
     201              :         }
     202           12 :         if (spdm_request->offset == 0) {
     203            6 :             total_responder_mel_buffer_length = spdm_response->portion_length +
     204            6 :                                                 spdm_response->remainder_length;
     205            6 :         } else if (spdm_request->offset + spdm_response->portion_length +
     206            6 :                    spdm_response->remainder_length < total_responder_mel_buffer_length) {
     207            1 :             libspdm_release_receiver_buffer (spdm_context);
     208            1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     209            1 :             goto done;
     210              :         }
     211              : 
     212              :         /* -=[Process Response Phase]=- */
     213           11 :         remainder_length = spdm_response->remainder_length;
     214           11 :         spdm_response_size = sizeof(spdm_measurement_extension_log_response_t) +
     215           11 :                              spdm_response->portion_length;
     216              : 
     217           11 :         if (mel_size_internal + spdm_response->portion_length > mel_capacity) {
     218            0 :             libspdm_release_receiver_buffer (spdm_context);
     219            0 :             status = LIBSPDM_STATUS_BUFFER_FULL;
     220            0 :             goto done;
     221              :         }
     222              : 
     223           11 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "MEL (offset 0x%x, size 0x%x):\n",
     224              :                        spdm_request->offset, spdm_response->portion_length));
     225           11 :         mel_block = (uint8_t *)(spdm_response + 1);
     226           11 :         LIBSPDM_INTERNAL_DUMP_HEX(mel_block, spdm_response->portion_length);
     227              : 
     228           11 :         libspdm_copy_mem((uint8_t *)measure_exten_log + mel_size_internal,
     229              :                          mel_capacity - mel_size_internal,
     230              :                          mel_block,
     231           11 :                          spdm_response->portion_length);
     232              : 
     233           11 :         mel_size_internal += spdm_response->portion_length;
     234              : 
     235              :         /* -=[Log Message Phase]=- */
     236              :         #if LIBSPDM_ENABLE_MSG_LOG
     237           11 :         libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     238              :         #endif /* LIBSPDM_ENABLE_MSG_LOG */
     239              : 
     240           11 :         libspdm_release_receiver_buffer (spdm_context);
     241           11 :         measurement_extension_log = (spdm_measurement_extension_log_dmtf_t *)measure_exten_log;
     242           11 :     } while (mel_size_internal < sizeof(spdm_measurement_extension_log_dmtf_t) +
     243           11 :              measurement_extension_log->mel_entries_len);
     244              : 
     245            5 :     *mel_size = mel_size_internal;
     246            5 :     LIBSPDM_ASSERT(*mel_size <= SPDM_MAX_MEASUREMENT_EXTENSION_LOG_SIZE);
     247              : 
     248            5 :     status = LIBSPDM_STATUS_SUCCESS;
     249              : 
     250            9 : done:
     251            9 :     return status;
     252              : }
     253              : 
     254            9 : libspdm_return_t libspdm_get_measurement_extension_log(void *spdm_context,
     255              :                                                        const uint32_t *session_id,
     256              :                                                        size_t *mel_size,
     257              :                                                        void *measure_exten_log)
     258              : {
     259              :     libspdm_context_t *context;
     260              :     size_t retry;
     261              :     uint64_t retry_delay_time;
     262              :     libspdm_return_t status;
     263              : 
     264            9 :     context = spdm_context;
     265            9 :     context->crypto_request = true;
     266            9 :     retry = context->retry_times;
     267            9 :     retry_delay_time = context->retry_delay_time;
     268              :     do {
     269            9 :         status = libspdm_try_get_measurement_extension_log(context, session_id,
     270              :                                                            mel_size, measure_exten_log);
     271            9 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     272            9 :             return status;
     273              :         }
     274              : 
     275            0 :         libspdm_sleep(retry_delay_time);
     276            0 :     } while (retry-- != 0);
     277              : 
     278            0 :     return status;
     279              : }
     280              : 
     281              : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEL_CAP */
        

Generated by: LCOV version 2.0-1