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: 70.1 % 144 101
Test Date: 2025-06-29 08:09:00 Functions: 100.0 % 3 3

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

Generated by: LCOV version 2.0-1