Skip to content

Commit dd31020

Browse files
committed
Fix chunk_seq_no wrap in chunk get response.
Fix #2875 Signed-off-by: Aaron Li <[email protected]>
1 parent a4b9fa9 commit dd31020

File tree

2 files changed

+121
-4
lines changed

2 files changed

+121
-4
lines changed

library/spdm_responder_lib/libspdm_rsp_chunk_get.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* Copyright Notice:
3-
* Copyright 2021-2024 DMTF. All rights reserved.
3+
* Copyright 2021-2025 DMTF. All rights reserved.
44
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
55
**/
66

@@ -17,6 +17,8 @@ libspdm_return_t libspdm_get_response_chunk_get(
1717
{
1818
libspdm_chunk_info_t* get_info;
1919
uint32_t min_data_transfer_size;
20+
uint64_t max_chunk_data_transfer_size;
21+
size_t max_spdm_msg_size;
2022

2123
const spdm_chunk_get_request_t* spdm_request;
2224
spdm_chunk_response_response_t* spdm_response;
@@ -103,12 +105,30 @@ libspdm_return_t libspdm_get_response_chunk_get(
103105
response_size, response);
104106
}
105107

106-
libspdm_zero_mem(response, *response_size);
107-
108108
min_data_transfer_size = LIBSPDM_MIN(
109109
spdm_context->connection_info.capability.data_transfer_size,
110110
spdm_context->local_context.capability.sender_data_transfer_size);
111111

112+
/* Fail if exceed max chunks */
113+
max_chunk_data_transfer_size =
114+
((size_t) min_data_transfer_size - sizeof(spdm_chunk_response_response_t)) * 65536 -
115+
sizeof(uint32_t);
116+
max_spdm_msg_size = spdm_context->local_context.capability.max_spdm_msg_size;
117+
if (spdm_context->connection_info.capability.max_spdm_msg_size != 0) {
118+
max_spdm_msg_size = LIBSPDM_MIN(max_spdm_msg_size,
119+
spdm_context->connection_info.capability.max_spdm_msg_size);
120+
}
121+
max_chunk_data_transfer_size = LIBSPDM_MIN(max_chunk_data_transfer_size, max_spdm_msg_size);
122+
123+
if (get_info->large_message_size > max_chunk_data_transfer_size) {
124+
return libspdm_generate_error_response(
125+
spdm_context,
126+
SPDM_ERROR_CODE_RESPONSE_TOO_LARGE, 0,
127+
response_size, response);
128+
}
129+
130+
libspdm_zero_mem(response, *response_size);
131+
112132
/* Assert the data transfer size is smaller than the response size.
113133
* Otherwise there is no reason to chunk this response. */
114134
LIBSPDM_ASSERT(min_data_transfer_size < *response_size);

unit_test/test_spdm_responder/chunk_get.c

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* Copyright Notice:
3-
* Copyright 2021-2022 DMTF. All rights reserved.
3+
* Copyright 2021-2025 DMTF. All rights reserved.
44
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
55
**/
66

@@ -996,6 +996,101 @@ void libspdm_test_responder_chunk_get_rsp_case13(void** state)
996996
}
997997
}
998998

999+
1000+
/**
1001+
* Test 14: Responder has reponse exceed chunk seq no
1002+
**/
1003+
void libspdm_test_responder_chunk_get_rsp_case14(void** state)
1004+
{
1005+
libspdm_return_t status;
1006+
libspdm_test_context_t* spdm_test_context;
1007+
libspdm_context_t* spdm_context;
1008+
size_t response_size;
1009+
uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
1010+
spdm_error_response_t* spdm_response;
1011+
spdm_chunk_get_request_t spdm_request;
1012+
void* scratch_buffer;
1013+
size_t scratch_buffer_size;
1014+
1015+
uint8_t chunk_handle;
1016+
uint32_t data_transfer_size;
1017+
uint32_t total_chunk_size;
1018+
1019+
spdm_test_context = *state;
1020+
spdm_context = spdm_test_context->spdm_context;
1021+
spdm_test_context->case_id = 10;
1022+
spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
1023+
SPDM_VERSION_NUMBER_SHIFT_BIT;
1024+
1025+
spdm_context->connection_info.connection_state =
1026+
LIBSPDM_CONNECTION_STATE_NEGOTIATED;
1027+
spdm_context->connection_info.algorithm.base_hash_algo =
1028+
m_libspdm_use_hash_algo;
1029+
1030+
data_transfer_size = CHUNK_GET_RESPONDER_UNIT_TEST_DATA_TRANSFER_SIZE;
1031+
spdm_context->local_context.capability.data_transfer_size = data_transfer_size;
1032+
spdm_context->local_context.capability.flags |=
1033+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP;
1034+
spdm_context->connection_info.capability.flags |=
1035+
SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP;
1036+
1037+
/* large response need a large scratch buffer */
1038+
spdm_context->connection_info.capability.max_spdm_msg_size = data_transfer_size * 65536;
1039+
spdm_context->local_context.capability.max_spdm_msg_size = data_transfer_size * 65536;
1040+
spdm_test_context->scratch_buffer_size =
1041+
libspdm_get_sizeof_required_scratch_buffer(spdm_context);
1042+
spdm_test_context->scratch_buffer = (void *)malloc(spdm_test_context->scratch_buffer_size);
1043+
libspdm_set_scratch_buffer (spdm_context,
1044+
spdm_test_context->scratch_buffer,
1045+
spdm_test_context->scratch_buffer_size);
1046+
1047+
1048+
libspdm_get_scratch_buffer(spdm_context, &scratch_buffer, &scratch_buffer_size);
1049+
1050+
scratch_buffer = (uint8_t*)scratch_buffer +
1051+
libspdm_get_scratch_buffer_large_message_offset(spdm_context);
1052+
scratch_buffer_size = scratch_buffer_size -
1053+
libspdm_get_scratch_buffer_large_message_offset(spdm_context);
1054+
libspdm_zero_mem(scratch_buffer, scratch_buffer_size);
1055+
1056+
/* a huge chunk size to cause the chunk seq no wrap */
1057+
total_chunk_size = data_transfer_size * 65536;
1058+
1059+
LIBSPDM_ASSERT(total_chunk_size <= scratch_buffer_size);
1060+
1061+
chunk_handle = (uint8_t) spdm_test_context->case_id; /* Any number is fine */
1062+
spdm_context->chunk_context.get.chunk_in_use = true;
1063+
spdm_context->chunk_context.get.chunk_handle = chunk_handle;
1064+
spdm_context->chunk_context.get.chunk_seq_no = 0;
1065+
spdm_context->chunk_context.get.large_message = scratch_buffer;
1066+
spdm_context->chunk_context.get.large_message_size = total_chunk_size;
1067+
spdm_context->chunk_context.get.chunk_bytes_transferred = 0;
1068+
1069+
libspdm_zero_mem(&spdm_request, sizeof(spdm_request));
1070+
spdm_request.header.spdm_version = SPDM_MESSAGE_VERSION_12;
1071+
spdm_request.header.request_response_code = SPDM_CHUNK_GET;
1072+
spdm_request.header.param1 = 0;
1073+
spdm_request.header.param2 = chunk_handle;
1074+
spdm_request.chunk_seq_no = 0;
1075+
1076+
response_size = sizeof(response);
1077+
status = libspdm_get_response_chunk_get(
1078+
spdm_context,
1079+
sizeof(spdm_request), &spdm_request,
1080+
&response_size, response);
1081+
1082+
assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
1083+
assert_int_equal(response_size, sizeof(spdm_error_response_t));
1084+
1085+
spdm_response = (spdm_error_response_t*) response;
1086+
1087+
assert_int_equal(spdm_response->header.spdm_version, SPDM_MESSAGE_VERSION_12);
1088+
assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
1089+
assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_RESPONSE_TOO_LARGE);
1090+
assert_int_equal(spdm_response->header.param2, 0);
1091+
}
1092+
1093+
9991094
int libspdm_responder_chunk_get_rsp_test_main(void)
10001095
{
10011096
const struct CMUnitTest spdm_responder_chunk_get_tests[] = {
@@ -1025,6 +1120,8 @@ int libspdm_responder_chunk_get_rsp_test_main(void)
10251120
cmocka_unit_test(libspdm_test_responder_chunk_get_rsp_case12),
10261121
/* Successful request of last chunk where chunk size is exactly 1 byte */
10271122
cmocka_unit_test(libspdm_test_responder_chunk_get_rsp_case13),
1123+
/* Responder has reponse exceed chunk seq no */
1124+
cmocka_unit_test(libspdm_test_responder_chunk_get_rsp_case14),
10281125
};
10291126

10301127
libspdm_test_context_t test_context = {

0 commit comments

Comments
 (0)