LCOV - code coverage report
Current view: top level - spdm_responder_lib - libspdm_rsp_chunk_response.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.1 % 82 78
Test Date: 2026-10-01 20:56:25 Functions: 100.0 % 1 1
Branches: 84.1 % 44 37

             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_responder_lib.h"
       8                 :             : 
       9                 :             : #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
      10                 :             : 
      11                 :          19 : libspdm_return_t libspdm_get_response_chunk_get(
      12                 :             :     libspdm_context_t *spdm_context,
      13                 :             :     size_t request_size,
      14                 :             :     const void* request,
      15                 :             :     size_t* response_size,
      16                 :             :     void* response)
      17                 :             : {
      18                 :             :     libspdm_chunk_info_t* get_info;
      19                 :             :     uint32_t min_data_transfer_size;
      20                 :             :     uint64_t max_chunk_data_transfer_size;
      21                 :             : 
      22                 :             :     const spdm_chunk_get_request_t* spdm_request;
      23                 :             :     const spdm_chunk_get_request_14_t* spdm_request_14;
      24                 :             :     spdm_chunk_response_response_t* spdm_response;
      25                 :             :     spdm_chunk_response_response_14_t* spdm_response_14;
      26                 :             :     uint32_t chunk_seq_no;
      27                 :             : 
      28                 :             :     uint8_t* spdm_chunk;
      29                 :             : 
      30                 :          19 :     spdm_request = (const spdm_chunk_get_request_t*) request;
      31                 :          19 :     spdm_response = (spdm_chunk_response_response_t*) response;
      32                 :          19 :     get_info = &spdm_context->chunk_context.get;
      33                 :             : 
      34         [ -  + ]:          19 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_12) {
      35                 :           0 :         return libspdm_generate_error_response(spdm_context,
      36                 :             :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
      37                 :             :                                                SPDM_CHUNK_GET,
      38                 :             :                                                response_size, response);
      39                 :             :     }
      40                 :             : 
      41         [ +  + ]:          19 :     if (!libspdm_is_capabilities_flag_supported(
      42                 :             :             spdm_context, false, SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP,
      43                 :             :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP)) {
      44                 :           1 :         return libspdm_generate_error_response(
      45                 :             :             spdm_context,
      46                 :             :             SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
      47                 :             :             response_size, response);
      48                 :             :     }
      49                 :             : 
      50                 :             :     /*chunk mechanism can be used for normal or encap state*/
      51         [ +  + ]:          18 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
      52                 :           1 :         return libspdm_responder_handle_response_state(
      53                 :             :             spdm_context,
      54                 :           1 :             spdm_request->header.request_response_code,
      55                 :             :             response_size, response);
      56                 :             :     }
      57                 :             : 
      58         [ +  + ]:          17 :     if (spdm_context->connection_info.connection_state <
      59                 :             :         LIBSPDM_CONNECTION_STATE_AFTER_CAPABILITIES) {
      60                 :           1 :         return libspdm_generate_error_response(
      61                 :             :             spdm_context,
      62                 :             :             SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
      63                 :             :             response_size, response);
      64                 :             :     }
      65                 :             : 
      66         [ +  + ]:          16 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_14) {
      67         [ +  + ]:          12 :         if (request_size < sizeof(spdm_chunk_get_request_t)) {
      68                 :           1 :             return libspdm_generate_error_response(
      69                 :             :                 spdm_context,
      70                 :             :                 SPDM_ERROR_CODE_INVALID_REQUEST, 0,
      71                 :             :                 response_size, response);
      72                 :             :         }
      73                 :             :     } else {
      74         [ -  + ]:           4 :         if (request_size < sizeof(spdm_chunk_get_request_14_t)) {
      75                 :           0 :             return libspdm_generate_error_response(
      76                 :             :                 spdm_context,
      77                 :             :                 SPDM_ERROR_CODE_INVALID_REQUEST, 0,
      78                 :             :                 response_size, response);
      79                 :             :         }
      80                 :             :     }
      81                 :             : 
      82         [ +  + ]:          15 :     if (spdm_request->header.spdm_version < SPDM_MESSAGE_VERSION_12) {
      83                 :           1 :         return libspdm_generate_error_response(
      84                 :             :             spdm_context,
      85                 :             :             SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, SPDM_CHUNK_GET,
      86                 :             :             response_size, response);
      87                 :             :     }
      88                 :             : 
      89         [ -  + ]:          14 :     if (spdm_request->header.spdm_version
      90                 :          14 :         != libspdm_get_connection_version(spdm_context)) {
      91                 :           0 :         return libspdm_generate_error_response(
      92                 :             :             spdm_context,
      93                 :             :             SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
      94                 :             :             response_size, response);
      95                 :             :     }
      96                 :             : 
      97         [ +  + ]:          14 :     if (get_info->chunk_in_use == false) {
      98                 :           1 :         return libspdm_generate_error_response(
      99                 :             :             spdm_context,
     100                 :             :             SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     101                 :             :             response_size, response);
     102                 :             :     }
     103                 :             : 
     104         [ +  + ]:          13 :     if (spdm_request->header.param2 != get_info->chunk_handle) {
     105                 :           1 :         return libspdm_generate_error_response(
     106                 :             :             spdm_context,
     107                 :             :             SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     108                 :             :             response_size, response);
     109                 :             :     }
     110                 :             : 
     111         [ +  + ]:          12 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_14) {
     112         [ +  + ]:           8 :         if (spdm_request->chunk_seq_no != (uint16_t) get_info->chunk_seq_no) {
     113                 :           2 :             return libspdm_generate_error_response(
     114                 :             :                 spdm_context,
     115                 :             :                 SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     116                 :             :                 response_size, response);
     117                 :             :         }
     118                 :           6 :         chunk_seq_no = spdm_request->chunk_seq_no;
     119                 :             :     } else {
     120                 :           4 :         spdm_request_14 = (const spdm_chunk_get_request_14_t*) request;
     121         [ -  + ]:           4 :         if (spdm_request_14->chunk_seq_no != get_info->chunk_seq_no) {
     122                 :           0 :             return libspdm_generate_error_response(
     123                 :             :                 spdm_context,
     124                 :             :                 SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     125                 :             :                 response_size, response);
     126                 :             :         }
     127                 :           4 :         chunk_seq_no = spdm_request_14->chunk_seq_no;
     128                 :             :     }
     129                 :             : 
     130                 :          10 :     min_data_transfer_size = LIBSPDM_MIN(
     131                 :             :         spdm_context->connection_info.capability.data_transfer_size,
     132                 :             :         spdm_context->local_context.capability.sender_data_transfer_size);
     133                 :             : 
     134         [ +  + ]:          10 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_14) {
     135                 :             :         /* chunk seq no wrap not considered in spdm 1.4+ */
     136                 :             : 
     137                 :             :         /* Fail if exceed max chunks */
     138                 :           6 :         max_chunk_data_transfer_size =
     139                 :           6 :             ((size_t) min_data_transfer_size - sizeof(spdm_chunk_response_response_t)) * 65536 -
     140                 :             :             sizeof(uint32_t);
     141                 :             : 
     142                 :             :         /* max_spdm_msg_size already checked in caller */
     143         [ +  + ]:           6 :         if (get_info->large_message_size > max_chunk_data_transfer_size) {
     144                 :           1 :             return libspdm_generate_error_response(
     145                 :             :                 spdm_context,
     146                 :             :                 SPDM_ERROR_CODE_RESPONSE_TOO_LARGE, 0,
     147                 :             :                 response_size, response);
     148                 :             :         }
     149                 :             :     }
     150                 :             : 
     151                 :           9 :     libspdm_zero_mem(response, *response_size);
     152                 :             : 
     153                 :             :     /* Assert the data transfer size is smaller than the response size.
     154                 :             :      * Otherwise there is no reason to chunk this response. */
     155         [ -  + ]:           9 :     LIBSPDM_ASSERT(min_data_transfer_size < *response_size);
     156                 :             : 
     157                 :           9 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     158                 :           9 :     spdm_response->header.request_response_code = SPDM_CHUNK_RESPONSE;
     159                 :           9 :     spdm_response->header.param1 = 0;
     160                 :           9 :     spdm_response->header.param2 = get_info->chunk_handle;
     161         [ +  + ]:           9 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_14) {
     162                 :           5 :         spdm_response->chunk_seq_no = (uint16_t) get_info->chunk_seq_no;
     163                 :             :     } else {
     164                 :           4 :         spdm_response_14 = (spdm_chunk_response_response_14_t*) response;
     165                 :           4 :         spdm_response_14->chunk_seq_no = get_info->chunk_seq_no;
     166                 :             :     }
     167                 :             : 
     168                 :             :     LIBSPDM_ASSERT(sizeof(spdm_chunk_response_response_t) == sizeof(spdm_chunk_response_response_14_t));
     169                 :             : 
     170         [ +  + ]:           9 :     if (chunk_seq_no == 0) {
     171                 :           3 :         spdm_response->chunk_size =
     172                 :             :             min_data_transfer_size
     173                 :             :             - sizeof(spdm_chunk_response_response_t)
     174                 :           3 :             - sizeof(uint32_t);
     175                 :             : 
     176                 :             :         /* No reason to do chunking if message is smaller than largest chunk size. */
     177         [ -  + ]:           3 :         LIBSPDM_ASSERT(spdm_response->chunk_size < get_info->large_message_size);
     178                 :             : 
     179                 :           3 :         spdm_chunk = (uint8_t*) (spdm_response + 1);
     180                 :             : 
     181                 :             :         /* Set LargeMessageSize only in first chunk. */
     182                 :           3 :         libspdm_write_uint32(spdm_chunk, (uint32_t)get_info->large_message_size);
     183                 :           3 :         spdm_chunk += sizeof(uint32_t);
     184                 :             : 
     185                 :           3 :         *response_size = sizeof(spdm_chunk_response_response_t)
     186                 :             :                          + sizeof(uint32_t)
     187                 :           3 :                          + spdm_response->chunk_size;
     188                 :             :     } else {
     189                 :           6 :         spdm_response->chunk_size =
     190                 :           6 :             LIBSPDM_MIN(min_data_transfer_size
     191                 :             :                         - sizeof(spdm_chunk_response_response_t),
     192                 :             :                         (uint32_t) (get_info->large_message_size
     193                 :             :                                     - get_info->chunk_bytes_transferred));
     194                 :             : 
     195                 :           6 :         spdm_chunk = (uint8_t*) (spdm_response + 1);
     196                 :             : 
     197                 :           6 :         *response_size = sizeof(spdm_chunk_response_response_t)
     198                 :           6 :                          + spdm_response->chunk_size;
     199                 :             :     }
     200                 :             : 
     201                 :           9 :     libspdm_copy_mem(spdm_chunk, spdm_response->chunk_size,
     202                 :           9 :                      (uint8_t*) get_info->large_message + get_info->chunk_bytes_transferred,
     203                 :           9 :                      spdm_response->chunk_size);
     204                 :             : 
     205                 :           9 :     get_info->chunk_seq_no++;
     206                 :           9 :     get_info->chunk_bytes_transferred += spdm_response->chunk_size;
     207                 :             : 
     208         [ -  + ]:           9 :     LIBSPDM_ASSERT(get_info->chunk_bytes_transferred <= get_info->large_message_size);
     209         [ +  + ]:           9 :     if (get_info->chunk_bytes_transferred == get_info->large_message_size) {
     210                 :           4 :         libspdm_zero_mem(get_info->large_message, get_info->large_message_capacity);
     211                 :           4 :         get_info->chunk_in_use = false;
     212                 :           4 :         get_info->chunk_handle++; /* implicit wrap - around to 0. */
     213                 :           4 :         get_info->chunk_seq_no = 0;
     214                 :           4 :         get_info->large_message = NULL;
     215                 :           4 :         get_info->large_message_size = 0;
     216                 :           4 :         get_info->large_message_capacity = 0;
     217                 :           4 :         get_info->chunk_bytes_transferred = 0;
     218                 :             : 
     219                 :           4 :         spdm_response->header.param1 |= SPDM_CHUNK_GET_RESPONSE_ATTRIBUTE_LAST_CHUNK;
     220                 :             :     }
     221                 :             : 
     222                 :           9 :     return LIBSPDM_STATUS_SUCCESS;
     223                 :             : }
     224                 :             : 
     225                 :             : #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
        

Generated by: LCOV version 2.0-1