LCOV - code coverage report
Current view: top level - spdm_requester_lib - libspdm_req_get_version.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 98.1 % 108 106
Test Date: 2026-10-01 20:56:25 Functions: 100.0 % 2 2
Branches: 88.0 % 50 44

             Branch data     Line data    Source code
       1                 :             : /**
       2                 :             :  *  Copyright Notice:
       3                 :             :  *  Copyright 2021-2026 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_number_entry_count  The number of SPDM versions that the Responder supports.
      23                 :             :  * @param  version_number_entry        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                 :          84 : 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                 :          84 :     libspdm_reset_context(spdm_context);
      57                 :             : 
      58                 :             :     /* -=[Construct Request Phase]=- */
      59                 :          84 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
      60                 :          84 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
      61         [ +  + ]:          84 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
      62                 :           1 :         return status;
      63                 :             :     }
      64         [ -  + ]:          83 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
      65                 :             :                     spdm_context->local_context.capability.transport_tail_size);
      66                 :          83 :     spdm_request = (void *)(message + transport_header_size);
      67                 :          83 :     spdm_request_size = message_size - transport_header_size -
      68                 :          83 :                         spdm_context->local_context.capability.transport_tail_size;
      69                 :             : 
      70         [ -  + ]:          83 :     LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_version_request_t));
      71                 :          83 :     spdm_request->header.spdm_version = SPDM_MESSAGE_VERSION_10;
      72                 :          83 :     spdm_request->header.request_response_code = SPDM_GET_VERSION;
      73                 :          83 :     spdm_request->header.param1 = 0;
      74                 :          83 :     spdm_request->header.param2 = 0;
      75                 :          83 :     spdm_request_size = sizeof(spdm_get_version_request_t);
      76                 :             : 
      77                 :             :     /* -=[Send Request Phase]=- */
      78                 :          83 :     status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size, spdm_request);
      79         [ +  + ]:          83 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
      80                 :           1 :         libspdm_release_sender_buffer (spdm_context);
      81                 :           1 :         return status;
      82                 :             :     }
      83                 :          82 :     libspdm_release_sender_buffer (spdm_context);
      84                 :          82 :     spdm_request = (void *)spdm_context->last_spdm_request;
      85                 :             : 
      86                 :             :     /* -=[Receive Response Phase]=- */
      87                 :          82 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
      88         [ +  + ]:          82 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
      89                 :           1 :         return status;
      90                 :             :     }
      91         [ -  + ]:          81 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
      92                 :          81 :     spdm_response = (void *)(message);
      93                 :          81 :     spdm_response_size = message_size;
      94                 :             : 
      95                 :          81 :     status = libspdm_receive_spdm_response(spdm_context, NULL, &spdm_response_size,
      96                 :             :                                            (void **)&spdm_response);
      97         [ +  + ]:          81 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
      98                 :           4 :         goto receive_done;
      99                 :             :     }
     100                 :             : 
     101                 :             :     /* -=[Validate Response Phase]=- */
     102         [ -  + ]:          77 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     103                 :           0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     104                 :           0 :         goto receive_done;
     105                 :             :     }
     106         [ +  + ]:          77 :     if (spdm_response->header.spdm_version != SPDM_MESSAGE_VERSION_10) {
     107                 :           2 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     108                 :           2 :         goto receive_done;
     109                 :             :     }
     110         [ +  + ]:          75 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     111                 :             :         /* Responder shall not respond to the GET_VERSION request message with ErrorCode=ResponseNotReady.*/
     112         [ +  + ]:          45 :         if (spdm_response->header.param1 == SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
     113                 :             :             /* Received an unexpected error message. */
     114                 :           2 :             status = LIBSPDM_STATUS_ERROR_PEER;
     115                 :           2 :             goto receive_done;
     116                 :             :         }
     117                 :          43 :         status = libspdm_handle_simple_error_response(spdm_context, spdm_response->header.param1);
     118         [ +  - ]:          43 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     119                 :          43 :             goto receive_done;
     120                 :             :         }
     121         [ +  + ]:          30 :     } else if (spdm_response->header.request_response_code != SPDM_VERSION) {
     122                 :           2 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     123                 :           2 :         goto receive_done;
     124                 :             :     }
     125         [ +  + ]:          28 :     if (spdm_response_size < sizeof(spdm_version_response_t)) {
     126                 :           3 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     127                 :           3 :         goto receive_done;
     128                 :             :     }
     129         [ +  + ]:          25 :     if (spdm_response->version_number_entry_count > LIBSPDM_MAX_VERSION_COUNT) {
     130                 :           2 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     131                 :           2 :         goto receive_done;
     132                 :             :     }
     133         [ +  + ]:          23 :     if (spdm_response->version_number_entry_count == 0) {
     134                 :           2 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     135                 :           2 :         goto receive_done;
     136                 :             :     }
     137                 :          21 :     if (spdm_response_size < sizeof(spdm_version_response_t) +
     138         [ +  + ]:          21 :         spdm_response->version_number_entry_count * sizeof(spdm_version_number_t)) {
     139                 :           2 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     140                 :           2 :         goto receive_done;
     141                 :             :     }
     142                 :          19 :     spdm_response_size = sizeof(spdm_version_response_t) +
     143                 :          19 :                          spdm_response->version_number_entry_count * sizeof(spdm_version_number_t);
     144                 :             : 
     145                 :             :     /* -=[Process Response Phase]=- */
     146                 :          19 :     status = libspdm_append_message_a(spdm_context, spdm_request, spdm_request_size);
     147         [ +  + ]:          19 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     148                 :           1 :         goto receive_done;
     149                 :             :     }
     150                 :             : 
     151                 :          18 :     status = libspdm_append_message_a(spdm_context, spdm_response, spdm_response_size);
     152         [ +  + ]:          18 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     153                 :           1 :         libspdm_reset_message_a(spdm_context);
     154                 :           1 :         goto receive_done;
     155                 :             :     }
     156                 :             : 
     157                 :          17 :     result = libspdm_negotiate_connection_version (
     158                 :             :         &common_version,
     159                 :          17 :         spdm_context->local_context.version.spdm_version,
     160                 :          17 :         spdm_context->local_context.version.spdm_version_count,
     161                 :          17 :         spdm_response->version_number_entry,
     162                 :          17 :         spdm_response->version_number_entry_count);
     163         [ +  + ]:          17 :     if (result == false) {
     164                 :           2 :         libspdm_reset_message_a(spdm_context);
     165                 :           2 :         status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     166                 :           2 :         goto receive_done;
     167                 :             :     }
     168                 :             : 
     169                 :          15 :     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   [ +  +  +  - ]:          15 :     if (version_number_entry_count != NULL && version_number_entry != NULL) {
     174         [ +  + ]:           2 :         if (*version_number_entry_count < spdm_response->version_number_entry_count) {
     175                 :           1 :             *version_number_entry_count = spdm_response->version_number_entry_count;
     176                 :           1 :             libspdm_reset_message_a(spdm_context);
     177                 :           1 :             status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     178                 :           1 :             goto receive_done;
     179                 :             :         } else {
     180                 :           1 :             *version_number_entry_count = spdm_response->version_number_entry_count;
     181                 :           1 :             libspdm_copy_mem(version_number_entry,
     182                 :           1 :                              spdm_response->version_number_entry_count *
     183                 :             :                              sizeof(spdm_version_number_t),
     184                 :           1 :                              spdm_response->version_number_entry,
     185                 :           1 :                              spdm_response->version_number_entry_count *
     186                 :             :                              sizeof(spdm_version_number_t));
     187                 :           1 :             libspdm_version_number_sort (version_number_entry, *version_number_entry_count);
     188                 :             :         }
     189                 :             :     }
     190                 :             : 
     191                 :             :     /* -=[Update State Phase]=- */
     192                 :          14 :     spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AFTER_VERSION;
     193                 :          14 :     status = LIBSPDM_STATUS_SUCCESS;
     194                 :             : 
     195                 :             :     /* -=[Log Message Phase]=- */
     196                 :             :     #if LIBSPDM_ENABLE_MSG_LOG
     197                 :          14 :     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                 :          14 :     spdm_context->local_context.is_requester = true;
     202                 :             : 
     203                 :          81 : receive_done:
     204                 :          81 :     libspdm_release_receiver_buffer (spdm_context);
     205                 :          81 :     return status;
     206                 :             : }
     207                 :             : 
     208                 :          83 : 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                 :          83 :     spdm_context->crypto_request = false;
     217                 :          83 :     retry = spdm_context->retry_times;
     218                 :          83 :     retry_delay_time = spdm_context->retry_delay_time;
     219                 :             :     do {
     220                 :          84 :         status = libspdm_try_get_version(spdm_context,
     221                 :             :                                          version_number_entry_count, version_number_entry);
     222         [ +  + ]:          84 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     223                 :          81 :             return status;
     224                 :             :         }
     225                 :             : 
     226                 :           3 :         libspdm_sleep(retry_delay_time);
     227         [ +  + ]:           3 :     } while (retry-- != 0);
     228                 :             : 
     229                 :           2 :     return status;
     230                 :             : }
        

Generated by: LCOV version 2.0-1