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: 97.1 % 68 66
Test Date: 2025-06-29 08:09:00 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           14 : 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              :     spdm_chunk_response_response_t* spdm_response;
      24              : 
      25              :     uint8_t* spdm_chunk;
      26              : 
      27           14 :     spdm_request = (const spdm_chunk_get_request_t*) request;
      28           14 :     spdm_response = (spdm_chunk_response_response_t*) response;
      29           14 :     get_info = &spdm_context->chunk_context.get;
      30              : 
      31           14 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_12) {
      32            0 :         return libspdm_generate_error_response(spdm_context,
      33              :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
      34              :                                                SPDM_CHUNK_GET,
      35              :                                                response_size, response);
      36              :     }
      37              : 
      38           14 :     if (!libspdm_is_capabilities_flag_supported(
      39              :             spdm_context, false, SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP,
      40              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP)) {
      41            1 :         return libspdm_generate_error_response(
      42              :             spdm_context,
      43              :             SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
      44              :             response_size, response);
      45              :     }
      46              : 
      47              :     /*chunk mechanism can be used for normal or encap state*/
      48           13 :     if ((spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) &&
      49            1 :         (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP)) {
      50            1 :         return libspdm_responder_handle_response_state(
      51              :             spdm_context,
      52            1 :             spdm_request->header.request_response_code,
      53              :             response_size, response);
      54              :     }
      55              : 
      56           12 :     if (spdm_context->connection_info.connection_state <
      57              :         LIBSPDM_CONNECTION_STATE_AFTER_CAPABILITIES) {
      58            1 :         return libspdm_generate_error_response(
      59              :             spdm_context,
      60              :             SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
      61              :             response_size, response);
      62              :     }
      63              : 
      64           11 :     if (request_size < sizeof(spdm_chunk_get_request_t)) {
      65            1 :         return libspdm_generate_error_response(
      66              :             spdm_context,
      67              :             SPDM_ERROR_CODE_INVALID_REQUEST, 0,
      68              :             response_size, response);
      69              :     }
      70              : 
      71           10 :     if (spdm_request->header.spdm_version < SPDM_MESSAGE_VERSION_12) {
      72            1 :         return libspdm_generate_error_response(
      73              :             spdm_context,
      74              :             SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, SPDM_CHUNK_GET,
      75              :             response_size, response);
      76              :     }
      77              : 
      78            9 :     if (spdm_request->header.spdm_version
      79            9 :         != libspdm_get_connection_version(spdm_context)) {
      80            0 :         return libspdm_generate_error_response(
      81              :             spdm_context,
      82              :             SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
      83              :             response_size, response);
      84              :     }
      85              : 
      86            9 :     if (get_info->chunk_in_use == false) {
      87            1 :         return libspdm_generate_error_response(
      88              :             spdm_context,
      89              :             SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
      90              :             response_size, response);
      91              :     }
      92              : 
      93            8 :     if (spdm_request->header.param2 != get_info->chunk_handle) {
      94            1 :         return libspdm_generate_error_response(
      95              :             spdm_context,
      96              :             SPDM_ERROR_CODE_INVALID_REQUEST, 0,
      97              :             response_size, response);
      98              :     }
      99              : 
     100            7 :     if (spdm_request->chunk_seq_no != get_info->chunk_seq_no) {
     101            2 :         return libspdm_generate_error_response(
     102              :             spdm_context,
     103              :             SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     104              :             response_size, response);
     105              :     }
     106              : 
     107            5 :     min_data_transfer_size = LIBSPDM_MIN(
     108              :         spdm_context->connection_info.capability.data_transfer_size,
     109              :         spdm_context->local_context.capability.sender_data_transfer_size);
     110              : 
     111              :     /* Fail if exceed max chunks */
     112            5 :     max_chunk_data_transfer_size =
     113            5 :         ((size_t) min_data_transfer_size - sizeof(spdm_chunk_response_response_t)) * 65536 -
     114              :         sizeof(uint32_t);
     115              :     /* max_spdm_msg_size already checked in caller */
     116              : 
     117            5 :     if (get_info->large_message_size > max_chunk_data_transfer_size) {
     118            1 :         return libspdm_generate_error_response(
     119              :             spdm_context,
     120              :             SPDM_ERROR_CODE_RESPONSE_TOO_LARGE, 0,
     121              :             response_size, response);
     122              :     }
     123              : 
     124            4 :     libspdm_zero_mem(response, *response_size);
     125              : 
     126              :     /* Assert the data transfer size is smaller than the response size.
     127              :      * Otherwise there is no reason to chunk this response. */
     128            4 :     LIBSPDM_ASSERT(min_data_transfer_size < *response_size);
     129              : 
     130            4 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     131            4 :     spdm_response->header.request_response_code = SPDM_CHUNK_RESPONSE;
     132            4 :     spdm_response->header.param1 = 0;
     133            4 :     spdm_response->header.param2 = get_info->chunk_handle;
     134            4 :     spdm_response->chunk_seq_no = get_info->chunk_seq_no;
     135              : 
     136            4 :     if (spdm_request->chunk_seq_no == 0) {
     137            1 :         spdm_response->chunk_size =
     138              :             min_data_transfer_size
     139              :             - sizeof(spdm_chunk_response_response_t)
     140            1 :             - sizeof(uint32_t);
     141              : 
     142              :         /* No reason to do chunking if message is smaller than largest chunk size. */
     143            1 :         LIBSPDM_ASSERT(spdm_response->chunk_size < get_info->large_message_size);
     144              : 
     145            1 :         spdm_chunk = (uint8_t*) (spdm_response + 1);
     146              : 
     147              :         /* Set LargeMessageSize only in first chunk. */
     148            1 :         *((uint32_t*) (spdm_chunk)) = (uint32_t)get_info->large_message_size;
     149            1 :         spdm_chunk += sizeof(uint32_t);
     150              : 
     151            1 :         *response_size = sizeof(spdm_chunk_response_response_t)
     152              :                          + sizeof(uint32_t)
     153            1 :                          + spdm_response->chunk_size;
     154              :     } else {
     155            3 :         spdm_response->chunk_size =
     156            3 :             LIBSPDM_MIN(min_data_transfer_size
     157              :                         - sizeof(spdm_chunk_response_response_t),
     158              :                         (uint32_t) (get_info->large_message_size
     159              :                                     - get_info->chunk_bytes_transferred));
     160              : 
     161            3 :         spdm_chunk = (uint8_t*) (spdm_response + 1);
     162              : 
     163            3 :         *response_size = sizeof(spdm_chunk_response_response_t)
     164            3 :                          + spdm_response->chunk_size;
     165              :     }
     166              : 
     167            4 :     libspdm_copy_mem(spdm_chunk, spdm_response->chunk_size,
     168            4 :                      (uint8_t*) get_info->large_message + get_info->chunk_bytes_transferred,
     169            4 :                      spdm_response->chunk_size);
     170              : 
     171            4 :     get_info->chunk_seq_no++;
     172            4 :     get_info->chunk_bytes_transferred += spdm_response->chunk_size;
     173              : 
     174            4 :     LIBSPDM_ASSERT(get_info->chunk_bytes_transferred <= get_info->large_message_size);
     175            4 :     if (get_info->chunk_bytes_transferred == get_info->large_message_size) {
     176            2 :         get_info->chunk_in_use = false;
     177            2 :         get_info->chunk_handle++; /* implicit wrap - around to 0. */
     178            2 :         get_info->chunk_seq_no = 0;
     179            2 :         get_info->large_message = NULL;
     180            2 :         get_info->large_message_size = 0;
     181            2 :         get_info->chunk_bytes_transferred = 0;
     182              : 
     183            2 :         spdm_response->header.param1 |= SPDM_CHUNK_GET_RESPONSE_ATTRIBUTE_LAST_CHUNK;
     184              :     }
     185              : 
     186            4 :     return LIBSPDM_STATUS_SUCCESS;
     187              : }
     188              : 
     189              : #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
        

Generated by: LCOV version 2.0-1