LCOV - code coverage report
Current view: top level - library/spdm_responder_lib - libspdm_rsp_chunk_get.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.1 % 81 77
Test Date: 2025-10-12 08:10:56 Functions: 100.0 % 1 1

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

Generated by: LCOV version 2.0-1