LCOV - code coverage report
Current view: top level - library/spdm_requester_lib - libspdm_req_get_version.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.2 % 108 92
Test Date: 2025-11-23 08:10:21 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2025 DMTF. All rights reserved.
       4              :  *  License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
       5              :  **/
       6              : 
       7              : #include "internal/libspdm_requester_lib.h"
       8              : 
       9              : #pragma pack(1)
      10              : typedef struct {
      11              :     spdm_message_header_t header;
      12              :     uint8_t reserved;
      13              :     uint8_t version_number_entry_count;
      14              :     spdm_version_number_t version_number_entry[LIBSPDM_MAX_VERSION_COUNT];
      15              : } libspdm_version_response_max_t;
      16              : #pragma pack()
      17              : 
      18              : /**
      19              :  * This function sends GET_VERSION and receives VERSION.
      20              :  *
      21              :  * @param  spdm_context         A pointer to the SPDM context.
      22              :  * @param  version_count        The number of SPDM versions that the Responder supports.
      23              :  * @param  VersionNumberEntries The list of SPDM versions that the Responder supports.
      24              :  *
      25              :  * @retval LIBSPDM_STATUS_SUCCESS
      26              :  *         GET_VERSION was sent and VERSION was received.
      27              :  * @retval LIBSPDM_STATUS_INVALID_MSG_SIZE
      28              :  *         The size of the VERSION response is invalid.
      29              :  * @retval LIBSPDM_STATUS_INVALID_MSG_FIELD
      30              :  *         The VERSION response contains one or more invalid fields.
      31              :  * @retval LIBSPDM_STATUS_ERROR_PEER
      32              :  *         The Responder returned an unexpected error.
      33              :  * @retval LIBSPDM_STATUS_BUSY_PEER
      34              :  *         The Responder continually returned Busy error messages.
      35              :  * @retval LIBSPDM_STATUS_RESYNCH_PEER
      36              :  *         The Responder returned a RequestResynch error message.
      37              :  * @retval LIBSPDM_STATUS_NEGOTIATION_FAIL
      38              :  *         The Requester and Responder do not support a common SPDM version.
      39              :  **/
      40           39 : static libspdm_return_t libspdm_try_get_version(libspdm_context_t *spdm_context,
      41              :                                                 uint8_t *version_number_entry_count,
      42              :                                                 spdm_version_number_t *version_number_entry)
      43              : {
      44              :     libspdm_return_t status;
      45              :     bool result;
      46              :     spdm_get_version_request_t *spdm_request;
      47              :     size_t spdm_request_size;
      48              :     libspdm_version_response_max_t *spdm_response;
      49              :     size_t spdm_response_size;
      50              :     spdm_version_number_t common_version;
      51              :     uint8_t *message;
      52              :     size_t message_size;
      53              :     size_t transport_header_size;
      54              : 
      55              :     /* -=[Set State Phase]=- */
      56           39 :     libspdm_reset_context(spdm_context);
      57              : 
      58              :     /* -=[Construct Request Phase]=- */
      59           39 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
      60           39 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
      61           39 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
      62            1 :         return status;
      63              :     }
      64           38 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
      65              :                     spdm_context->local_context.capability.transport_tail_size);
      66           38 :     spdm_request = (void *)(message + transport_header_size);
      67           38 :     spdm_request_size = message_size - transport_header_size -
      68           38 :                         spdm_context->local_context.capability.transport_tail_size;
      69              : 
      70           38 :     LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_version_request_t));
      71           38 :     spdm_request->header.spdm_version = SPDM_MESSAGE_VERSION_10;
      72           38 :     spdm_request->header.request_response_code = SPDM_GET_VERSION;
      73           38 :     spdm_request->header.param1 = 0;
      74           38 :     spdm_request->header.param2 = 0;
      75           38 :     spdm_request_size = sizeof(spdm_get_version_request_t);
      76              : 
      77              :     /* -=[Send Request Phase]=- */
      78           38 :     status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size, spdm_request);
      79           38 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
      80            1 :         libspdm_release_sender_buffer (spdm_context);
      81            1 :         return status;
      82              :     }
      83           37 :     libspdm_release_sender_buffer (spdm_context);
      84           37 :     spdm_request = (void *)spdm_context->last_spdm_request;
      85              : 
      86              :     /* -=[Receive Response Phase]=- */
      87           37 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
      88           37 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
      89            1 :         return status;
      90              :     }
      91           36 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
      92           36 :     spdm_response = (void *)(message);
      93           36 :     spdm_response_size = message_size;
      94              : 
      95           36 :     status = libspdm_receive_spdm_response(spdm_context, NULL, &spdm_response_size,
      96              :                                            (void **)&spdm_response);
      97           36 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
      98            1 :         goto receive_done;
      99              :     }
     100              : 
     101              :     /* -=[Validate Response Phase]=- */
     102           35 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     103            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     104            0 :         goto receive_done;
     105              :     }
     106           35 :     if (spdm_response->header.spdm_version != SPDM_MESSAGE_VERSION_10) {
     107            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     108            1 :         goto receive_done;
     109              :     }
     110           34 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     111              :         /* Responder shall not respond to the GET_VERSION request message with ErrorCode=ResponseNotReady.*/
     112           23 :         if (spdm_response->header.param1 == SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
     113              :             /* Received an unexpected error message. */
     114            1 :             status = LIBSPDM_STATUS_ERROR_PEER;
     115            1 :             goto receive_done;
     116              :         }
     117           22 :         status = libspdm_handle_simple_error_response(spdm_context, spdm_response->header.param1);
     118           22 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     119           22 :             goto receive_done;
     120              :         }
     121           11 :     } else if (spdm_response->header.request_response_code != SPDM_VERSION) {
     122            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     123            1 :         goto receive_done;
     124              :     }
     125           10 :     if (spdm_response_size < sizeof(spdm_version_response_t)) {
     126            1 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     127            1 :         goto receive_done;
     128              :     }
     129            9 :     if (spdm_response->version_number_entry_count > LIBSPDM_MAX_VERSION_COUNT) {
     130            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     131            1 :         goto receive_done;
     132              :     }
     133            8 :     if (spdm_response->version_number_entry_count == 0) {
     134            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     135            1 :         goto receive_done;
     136              :     }
     137            7 :     if (spdm_response_size < sizeof(spdm_version_response_t) +
     138            7 :         spdm_response->version_number_entry_count * sizeof(spdm_version_number_t)) {
     139            1 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     140            1 :         goto receive_done;
     141              :     }
     142            6 :     spdm_response_size = sizeof(spdm_version_response_t) +
     143            6 :                          spdm_response->version_number_entry_count * sizeof(spdm_version_number_t);
     144              : 
     145              :     /* -=[Process Response Phase]=- */
     146            6 :     status = libspdm_append_message_a(spdm_context, spdm_request, spdm_request_size);
     147            6 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     148            0 :         goto receive_done;
     149              :     }
     150              : 
     151            6 :     status = libspdm_append_message_a(spdm_context, spdm_response, spdm_response_size);
     152            6 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     153            0 :         libspdm_reset_message_a(spdm_context);
     154            0 :         goto receive_done;
     155              :     }
     156              : 
     157            6 :     result = libspdm_negotiate_connection_version (
     158              :         &common_version,
     159            6 :         spdm_context->local_context.version.spdm_version,
     160            6 :         spdm_context->local_context.version.spdm_version_count,
     161            6 :         spdm_response->version_number_entry,
     162            6 :         spdm_response->version_number_entry_count);
     163            6 :     if (result == false) {
     164            1 :         libspdm_reset_message_a(spdm_context);
     165            1 :         status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     166            1 :         goto receive_done;
     167              :     }
     168              : 
     169            5 :     libspdm_copy_mem(&(spdm_context->connection_info.version),
     170              :                      sizeof(spdm_context->connection_info.version),
     171              :                      &(common_version), sizeof(spdm_version_number_t));
     172              : 
     173            5 :     if (version_number_entry_count != NULL && version_number_entry != NULL) {
     174            0 :         if (*version_number_entry_count < spdm_response->version_number_entry_count) {
     175            0 :             *version_number_entry_count = spdm_response->version_number_entry_count;
     176            0 :             libspdm_reset_message_a(spdm_context);
     177            0 :             status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     178            0 :             goto receive_done;
     179              :         } else {
     180            0 :             *version_number_entry_count = spdm_response->version_number_entry_count;
     181            0 :             libspdm_copy_mem(version_number_entry,
     182            0 :                              spdm_response->version_number_entry_count *
     183              :                              sizeof(spdm_version_number_t),
     184            0 :                              spdm_response->version_number_entry,
     185            0 :                              spdm_response->version_number_entry_count *
     186              :                              sizeof(spdm_version_number_t));
     187            0 :             libspdm_version_number_sort (version_number_entry, *version_number_entry_count);
     188              :         }
     189              :     }
     190              : 
     191              :     /* -=[Update State Phase]=- */
     192            5 :     spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AFTER_VERSION;
     193            5 :     status = LIBSPDM_STATUS_SUCCESS;
     194              : 
     195              :     /* -=[Log Message Phase]=- */
     196              :     #if LIBSPDM_ENABLE_MSG_LOG
     197            5 :     libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     198              :     #endif /* LIBSPDM_ENABLE_MSG_LOG */
     199              : 
     200              :     /*Set the role of device*/
     201            5 :     spdm_context->local_context.is_requester = true;
     202              : 
     203           36 : receive_done:
     204           36 :     libspdm_release_receiver_buffer (spdm_context);
     205           36 :     return status;
     206              : }
     207              : 
     208           38 : libspdm_return_t libspdm_get_version(libspdm_context_t *spdm_context,
     209              :                                      uint8_t *version_number_entry_count,
     210              :                                      spdm_version_number_t *version_number_entry)
     211              : {
     212              :     size_t retry;
     213              :     uint64_t retry_delay_time;
     214              :     libspdm_return_t status;
     215              : 
     216           38 :     spdm_context->crypto_request = false;
     217           38 :     retry = spdm_context->retry_times;
     218           38 :     retry_delay_time = spdm_context->retry_delay_time;
     219              :     do {
     220           39 :         status = libspdm_try_get_version(spdm_context,
     221              :                                          version_number_entry_count, version_number_entry);
     222           39 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     223           37 :             return status;
     224              :         }
     225              : 
     226            2 :         libspdm_sleep(retry_delay_time);
     227            2 :     } while (retry-- != 0);
     228              : 
     229            1 :     return status;
     230              : }
        

Generated by: LCOV version 2.0-1