Skip to content

Commit

Permalink
Fix chunk_seq_no wrap in chunk get response.
Browse files Browse the repository at this point in the history
Fix DMTF#2875

Signed-off-by: Aaron Li <[email protected]>
  • Loading branch information
Li-Aaron committed Jan 13, 2025
1 parent 630d92a commit 75f0128
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 4 deletions.
17 changes: 14 additions & 3 deletions library/spdm_responder_lib/libspdm_rsp_chunk_get.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Copyright Notice:
* Copyright 2021-2024 DMTF. All rights reserved.
* Copyright 2021-2025 DMTF. All rights reserved.
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
**/

Expand All @@ -17,6 +17,7 @@ libspdm_return_t libspdm_get_response_chunk_get(
{
libspdm_chunk_info_t* get_info;
uint32_t min_data_transfer_size;
size_t max_chunk_data_transfer_size;

const spdm_chunk_get_request_t* spdm_request;
spdm_chunk_response_response_t* spdm_response;
Expand Down Expand Up @@ -103,12 +104,22 @@ libspdm_return_t libspdm_get_response_chunk_get(
response_size, response);
}

libspdm_zero_mem(response, *response_size);

min_data_transfer_size = LIBSPDM_MIN(
spdm_context->connection_info.capability.data_transfer_size,
spdm_context->local_context.capability.sender_data_transfer_size);

/* Fail if exceed max chunks */
max_chunk_data_transfer_size = ((size_t) min_data_transfer_size - sizeof(spdm_chunk_response_response_t)) * 65536 - sizeof(uint32_t);

if (get_info->large_message_size > max_chunk_data_transfer_size) {
return libspdm_generate_error_response(
spdm_context,
SPDM_ERROR_CODE_RESPONSE_TOO_LARGE, 0,
response_size, response);
}

libspdm_zero_mem(response, *response_size);

/* Assert the data transfer size is smaller than the response size.
* Otherwise there is no reason to chunk this response. */
LIBSPDM_ASSERT(min_data_transfer_size < *response_size);
Expand Down
99 changes: 98 additions & 1 deletion unit_test/test_spdm_responder/chunk_get.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Copyright Notice:
* Copyright 2021-2022 DMTF. All rights reserved.
* Copyright 2021-2025 DMTF. All rights reserved.
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
**/

Expand Down Expand Up @@ -996,6 +996,101 @@ void libspdm_test_responder_chunk_get_rsp_case13(void** state)
}
}


/**
* Test 14: Responder has reponse exceed chunk seq no
**/
void libspdm_test_responder_chunk_get_rsp_case14(void** state)
{
libspdm_return_t status;
libspdm_test_context_t* spdm_test_context;
libspdm_context_t* spdm_context;
size_t response_size;
uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
spdm_error_response_t* spdm_response;
spdm_chunk_get_request_t spdm_request;
void* scratch_buffer;
size_t scratch_buffer_size;

uint8_t chunk_handle;
uint32_t data_transfer_size;
uint32_t total_chunk_size;

spdm_test_context = *state;
spdm_context = spdm_test_context->spdm_context;
spdm_test_context->case_id = 10;
spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
SPDM_VERSION_NUMBER_SHIFT_BIT;

spdm_context->connection_info.connection_state =
LIBSPDM_CONNECTION_STATE_NEGOTIATED;
spdm_context->connection_info.algorithm.base_hash_algo =
m_libspdm_use_hash_algo;

data_transfer_size = CHUNK_GET_RESPONDER_UNIT_TEST_DATA_TRANSFER_SIZE;
spdm_context->local_context.capability.data_transfer_size = data_transfer_size;
spdm_context->local_context.capability.flags |=
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP;
spdm_context->connection_info.capability.flags |=
SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP;

/* large response need a large scratch buffer */
spdm_context->connection_info.capability.max_spdm_msg_size = data_transfer_size * 65536;
spdm_context->local_context.capability.max_spdm_msg_size = data_transfer_size * 65536;
spdm_test_context->scratch_buffer_size =
libspdm_get_sizeof_required_scratch_buffer(spdm_context);
spdm_test_context->scratch_buffer = (void *)malloc(spdm_test_context->scratch_buffer_size);
libspdm_set_scratch_buffer (spdm_context,
spdm_test_context->scratch_buffer,
spdm_test_context->scratch_buffer_size);


libspdm_get_scratch_buffer(spdm_context, &scratch_buffer, &scratch_buffer_size);

scratch_buffer = (uint8_t*)scratch_buffer +
libspdm_get_scratch_buffer_large_message_offset(spdm_context);
scratch_buffer_size = scratch_buffer_size -
libspdm_get_scratch_buffer_large_message_offset(spdm_context);
libspdm_zero_mem(scratch_buffer, scratch_buffer_size);

/* a huge chunk size to cause the chunk seq no wrap */
total_chunk_size = data_transfer_size * 65536;

LIBSPDM_ASSERT(total_chunk_size <= scratch_buffer_size);

chunk_handle = (uint8_t) spdm_test_context->case_id; /* Any number is fine */
spdm_context->chunk_context.get.chunk_in_use = true;
spdm_context->chunk_context.get.chunk_handle = chunk_handle;
spdm_context->chunk_context.get.chunk_seq_no = 0;
spdm_context->chunk_context.get.large_message = scratch_buffer;
spdm_context->chunk_context.get.large_message_size = total_chunk_size;
spdm_context->chunk_context.get.chunk_bytes_transferred = 0;

libspdm_zero_mem(&spdm_request, sizeof(spdm_request));
spdm_request.header.spdm_version = SPDM_MESSAGE_VERSION_12;
spdm_request.header.request_response_code = SPDM_CHUNK_GET;
spdm_request.header.param1 = 0;
spdm_request.header.param2 = chunk_handle;
spdm_request.chunk_seq_no = 0;

response_size = sizeof(response);
status = libspdm_get_response_chunk_get(
spdm_context,
sizeof(spdm_request), &spdm_request,
&response_size, response);

assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
assert_int_equal(response_size, sizeof(spdm_error_response_t));

spdm_response = (spdm_error_response_t*) response;

assert_int_equal(spdm_response->header.spdm_version, SPDM_MESSAGE_VERSION_12);
assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_RESPONSE_TOO_LARGE);
assert_int_equal(spdm_response->header.param2, 0);
}


int libspdm_responder_chunk_get_rsp_test_main(void)
{
const struct CMUnitTest spdm_responder_chunk_get_tests[] = {
Expand Down Expand Up @@ -1025,6 +1120,8 @@ int libspdm_responder_chunk_get_rsp_test_main(void)
cmocka_unit_test(libspdm_test_responder_chunk_get_rsp_case12),
/* Successful request of last chunk where chunk size is exactly 1 byte */
cmocka_unit_test(libspdm_test_responder_chunk_get_rsp_case13),
/* Responder has reponse exceed chunk seq no */
cmocka_unit_test(libspdm_test_responder_chunk_get_rsp_case14),
};

libspdm_test_context_t test_context = {
Expand Down

0 comments on commit 75f0128

Please sign in to comment.