Skip to content

Commit a7b369b

Browse files
committed
Fix chunk_seq_no wrap in chunk send.
Fix #2875 Signed-off-by: Aaron Li <[email protected]>
1 parent 5ebe5e3 commit a7b369b

File tree

2 files changed

+99
-6
lines changed

2 files changed

+99
-6
lines changed

library/spdm_requester_lib/libspdm_req_send_receive.c

Lines changed: 22 additions & 5 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

@@ -316,6 +316,8 @@ libspdm_return_t libspdm_handle_large_request(
316316
size_t copy_size;
317317
libspdm_chunk_info_t *send_info;
318318
uint32_t min_data_transfer_size;
319+
size_t max_chunk_data_transfer_size;
320+
size_t max_spdm_msg_size;
319321
spdm_error_response_t *spdm_error;
320322

321323
if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_12) {
@@ -330,6 +332,25 @@ libspdm_return_t libspdm_handle_large_request(
330332
return LIBSPDM_STATUS_ERROR_PEER;
331333
}
332334

335+
/* Fail if exceed max chunks */
336+
min_data_transfer_size = LIBSPDM_MIN(
337+
spdm_context->connection_info.capability.data_transfer_size,
338+
spdm_context->local_context.capability.sender_data_transfer_size);
339+
340+
max_chunk_data_transfer_size =
341+
((size_t) min_data_transfer_size - sizeof(spdm_chunk_send_request_t)) * 65536 -
342+
sizeof(uint32_t);
343+
max_spdm_msg_size = spdm_context->local_context.capability.max_spdm_msg_size;
344+
if (spdm_context->connection_info.capability.max_spdm_msg_size != 0) {
345+
max_spdm_msg_size = LIBSPDM_MIN(max_spdm_msg_size,
346+
spdm_context->connection_info.capability.max_spdm_msg_size);
347+
}
348+
max_chunk_data_transfer_size = LIBSPDM_MIN(max_chunk_data_transfer_size, max_spdm_msg_size);
349+
350+
if (request_size > max_chunk_data_transfer_size) {
351+
return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
352+
}
353+
333354
/* now we can get sender buffer */
334355
transport_header_size = spdm_context->local_context.capability.transport_header_size;
335356

@@ -359,10 +380,6 @@ libspdm_return_t libspdm_handle_large_request(
359380
request = NULL; /* Invalidate to prevent accidental use. */
360381
request_size = 0;
361382

362-
min_data_transfer_size = LIBSPDM_MIN(
363-
spdm_context->connection_info.capability.data_transfer_size,
364-
spdm_context->local_context.capability.sender_data_transfer_size);
365-
366383
do {
367384
LIBSPDM_ASSERT(send_info->large_message_capacity >= transport_header_size);
368385
spdm_request = (spdm_chunk_send_request_t *)((uint8_t *)message + transport_header_size);

unit_test/test_spdm_requester/chunk_send.c

Lines changed: 77 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

@@ -105,6 +105,10 @@ libspdm_return_t libspdm_requester_chunk_send_test_send_message(
105105
LIBSPDM_ASSERT(chunk_send->header.request_response_code == SPDM_CHUNK_SEND);
106106
return LIBSPDM_STATUS_SUCCESS;
107107
}
108+
if (spdm_test_context->case_id == 13) {
109+
/* Should never reach here since the test case is meant to fail before send */
110+
LIBSPDM_ASSERT(0);
111+
}
108112
return LIBSPDM_STATUS_SEND_FAIL;
109113
}
110114

@@ -323,6 +327,10 @@ libspdm_return_t libspdm_requester_chunk_send_test_receive_message(
323327

324328
return LIBSPDM_STATUS_SUCCESS;
325329
}
330+
if (spdm_test_context->case_id == 13) {
331+
/* Should never reach here since the test case is meant to fail before send */
332+
LIBSPDM_ASSERT(0);
333+
}
326334
return LIBSPDM_STATUS_RECEIVE_FAIL;
327335
}
328336

@@ -380,6 +388,56 @@ libspdm_return_t libspdm_test_requester_chunk_send_generic_test_case(
380388
return status;
381389
}
382390

391+
libspdm_return_t libspdm_test_requester_chunk_send_vendor_specific_test_case(
392+
void** state, uint32_t case_id)
393+
{
394+
/* Use vendor specific request to generate a large request. */
395+
libspdm_return_t status;
396+
libspdm_test_context_t* spdm_test_context;
397+
libspdm_context_t* spdm_context;
398+
399+
uint16_t standard_id = 6;
400+
uint8_t vendor_id_len = 2;
401+
uint8_t vendor_id[SPDM_MAX_VENDOR_ID_LENGTH] = {0xAA, 0xAA};
402+
uint16_t data_len = 65535;
403+
uint8_t data[65535] = {0};
404+
405+
spdm_test_context = *state;
406+
spdm_context = spdm_test_context->spdm_context;
407+
spdm_test_context->case_id = case_id;
408+
spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
409+
SPDM_VERSION_NUMBER_SHIFT_BIT;
410+
/* Large request need a large scratch buffer. */
411+
spdm_context->connection_info.capability.max_spdm_msg_size = 0x12000;
412+
spdm_context->local_context.capability.max_spdm_msg_size = 0x12000;
413+
spdm_context->connection_info.connection_state =
414+
LIBSPDM_CONNECTION_STATE_NEGOTIATED;
415+
spdm_context->connection_info.capability.flags |=
416+
(SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP
417+
| SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP);
418+
spdm_context->connection_info.capability.data_transfer_size
419+
= sizeof(spdm_chunk_send_request_t) + 1;
420+
spdm_context->local_context.capability.sender_data_transfer_size
421+
= CHUNK_SEND_REQUESTER_UNIT_TEST_DATA_TRANSFER_SIZE;
422+
spdm_context->local_context.is_requester = true;
423+
424+
spdm_test_context->scratch_buffer_size =
425+
libspdm_get_sizeof_required_scratch_buffer(spdm_context);
426+
spdm_test_context->scratch_buffer = (void *)malloc(spdm_test_context->scratch_buffer_size);
427+
libspdm_set_scratch_buffer (spdm_context,
428+
spdm_test_context->scratch_buffer,
429+
spdm_test_context->scratch_buffer_size);
430+
431+
libspdm_reset_message_a(spdm_context);
432+
433+
status = libspdm_vendor_send_request_receive_response(spdm_context, NULL,
434+
standard_id, vendor_id_len, vendor_id,
435+
data_len, data,
436+
&standard_id, &vendor_id_len, vendor_id,
437+
&data_len, data);
438+
return status;
439+
}
440+
383441
void libspdm_test_requester_chunk_send_case1(void** state)
384442
{
385443
libspdm_return_t status;
@@ -472,6 +530,20 @@ void libspdm_test_requester_chunk_send_case12(void** state)
472530
assert_int_equal(status, LIBSPDM_STATUS_ERROR_PEER);
473531
}
474532

533+
#if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
534+
/**
535+
* Test 13: Request size shall not exceed max supported transfer size.
536+
* Expected behavior: returns a status of LIBSPDM_STATUS_SEND_FAIL,
537+
**/
538+
void libspdm_test_requester_chunk_send_case13(void** state)
539+
{
540+
libspdm_return_t status;
541+
542+
status = libspdm_test_requester_chunk_send_vendor_specific_test_case(state, 13);
543+
assert_int_equal(status, LIBSPDM_STATUS_SEND_FAIL);
544+
}
545+
#endif
546+
475547
int libspdm_requester_chunk_send_test_main(void)
476548
{
477549
/* Test the CHUNK_SEND handlers in various requester handlers */
@@ -500,6 +572,10 @@ int libspdm_requester_chunk_send_test_main(void)
500572
cmocka_unit_test(libspdm_test_requester_chunk_send_case11),
501573
/* ErrorCode == LargeResponse shall not be allowed in ResponseToLargeRequest */
502574
cmocka_unit_test(libspdm_test_requester_chunk_send_case12),
575+
#if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
576+
/* Request size exceed max chunks */
577+
cmocka_unit_test(libspdm_test_requester_chunk_send_case13),
578+
#endif
503579
};
504580

505581
libspdm_test_context_t test_context = {

0 commit comments

Comments
 (0)