Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-2026 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 "spdm_unit_test.h"
8 : #include "internal/libspdm_responder_lib.h"
9 :
10 : #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
11 :
12 : #define CHUNK_GET_UNIT_TEST_OVERRIDE_DATA_TRANSFER_SIZE (64)
13 :
14 : typedef struct {
15 : spdm_message_header_t header;
16 : /* param1 == RSVD
17 : * param2 == RSVD*/
18 : uint16_t standard_id;
19 : uint8_t len;
20 : /*uint8_t vendor_id[len];*/
21 : uint16_t payload_length;
22 : /* uint8_t vendor_defined_payload[payload_length];*/
23 : } my_spdm_vendor_defined_request_msg_t;
24 :
25 :
26 1 : libspdm_return_t my_test_get_response_func(
27 : void *spdm_context, const uint32_t *session_id, bool is_app_message,
28 : size_t request_size, const void *request, size_t *response_size,
29 : void *response)
30 : {
31 : /* response message size is greater than the sending transmit buffer size of responder */
32 1 : *response_size = CHUNK_GET_UNIT_TEST_OVERRIDE_DATA_TRANSFER_SIZE + 1;
33 1 : return LIBSPDM_STATUS_SUCCESS;
34 : }
35 :
36 1 : libspdm_return_t my_test_get_response_func2(
37 : void *spdm_context,
38 : const uint32_t *session_id,
39 : uint16_t req_standard_id,
40 : uint8_t req_vendor_id_len,
41 : const void *req_vendor_id,
42 : uint32_t req_size,
43 : const void *req_data,
44 : uint32_t *resp_size,
45 : void *resp_data)
46 : {
47 : /* response message size is greater than the sending transmit buffer size of responder */
48 1 : *resp_size = CHUNK_GET_UNIT_TEST_OVERRIDE_DATA_TRANSFER_SIZE + 1;
49 1 : return LIBSPDM_STATUS_SUCCESS;
50 : }
51 :
52 : /**
53 : * Test 1: Test Responder Receive Send flow triggers chunk get mode
54 : * if response buffer is larger than requester data_transfer_size.
55 : **/
56 1 : void libspdm_test_responder_receive_send_rsp_case1(void** state)
57 : {
58 : #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
59 : /* This test case is partially copied from test_requester_get_measurement_case4 */
60 : libspdm_return_t status;
61 : libspdm_test_context_t* spdm_test_context;
62 : libspdm_context_t* spdm_context;
63 : size_t response_size;
64 : uint8_t* response;
65 : spdm_error_response_t* spdm_response;
66 : spdm_get_measurements_request_t spdm_request;
67 : void* message;
68 : size_t message_size;
69 : void* data;
70 : size_t data_size;
71 : void* hash;
72 : size_t hash_size;
73 : uint32_t transport_header_size;
74 : uint8_t chunk_handle;
75 :
76 1 : spdm_test_context = *state;
77 1 : spdm_context = spdm_test_context->spdm_context;
78 1 : spdm_test_context->case_id = 1;
79 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
80 : SPDM_VERSION_NUMBER_SHIFT_BIT;
81 :
82 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
83 :
84 1 : spdm_context->local_context.capability.flags |=
85 : (SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP
86 : | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP);
87 1 : spdm_context->connection_info.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP;
88 :
89 1 : if (!libspdm_read_responder_public_certificate_chain(
90 : m_libspdm_use_hash_algo,
91 : m_libspdm_use_asym_algo, &data,
92 : &data_size,
93 : &hash, &hash_size)) {
94 0 : return;
95 : }
96 :
97 1 : spdm_context->local_context.local_cert_chain_provision_size[0] = data_size;
98 1 : spdm_context->local_context.local_cert_chain_provision[0] = data;
99 :
100 1 : libspdm_reset_message_m(spdm_context, NULL);
101 :
102 1 : spdm_context->connection_info.algorithm.measurement_spec = m_libspdm_use_measurement_spec;
103 1 : spdm_context->connection_info.algorithm.measurement_hash_algo =
104 : m_libspdm_use_measurement_hash_algo;
105 1 : spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
106 1 : spdm_context->connection_info.algorithm.base_asym_algo = m_libspdm_use_asym_algo;
107 :
108 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
109 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = data_size;
110 : libspdm_copy_mem(
111 : spdm_context->connection_info.peer_used_cert_chain[0].buffer,
112 : sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer),
113 : data, data_size);
114 : #else
115 1 : libspdm_hash_all(
116 : spdm_context->connection_info.algorithm.base_hash_algo,
117 : data, data_size,
118 1 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash);
119 1 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size =
120 1 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
121 1 : libspdm_get_leaf_cert_public_key_from_cert_chain(
122 : spdm_context->connection_info.algorithm.base_hash_algo,
123 : spdm_context->connection_info.algorithm.base_asym_algo,
124 : data, data_size,
125 : &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key);
126 : #endif
127 :
128 1 : spdm_context->connection_info.capability.data_transfer_size =
129 : CHUNK_GET_UNIT_TEST_OVERRIDE_DATA_TRANSFER_SIZE;
130 :
131 1 : spdm_context->connection_info.capability.max_spdm_msg_size = LIBSPDM_MAX_SPDM_MSG_SIZE;
132 :
133 1 : libspdm_zero_mem(&spdm_request, sizeof(spdm_request));
134 1 : spdm_request.header.spdm_version = SPDM_MESSAGE_VERSION_12;
135 1 : spdm_request.header.request_response_code = SPDM_GET_MEASUREMENTS;
136 1 : spdm_request.header.param1 = SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE;
137 1 : spdm_request.header.param2 =
138 : SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_ALL_MEASUREMENTS;
139 1 : spdm_request.slot_id_param = 0;
140 :
141 1 : libspdm_copy_mem(spdm_context->last_spdm_request,
142 1 : libspdm_get_scratch_buffer_last_spdm_request_capacity(spdm_context),
143 : &spdm_request, sizeof(spdm_request));
144 1 : spdm_context->last_spdm_request_size = sizeof(spdm_request);
145 :
146 1 : assert_int_equal(spdm_context->chunk_context.get.chunk_in_use, false);
147 1 : libspdm_acquire_sender_buffer(spdm_context, &message_size, (void**) &message);
148 1 : response = message;
149 1 : response_size = message_size;
150 1 : libspdm_zero_mem(response, response_size);
151 :
152 1 : status = libspdm_build_response(spdm_context, NULL, false, &response_size, (void**)&response);
153 :
154 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
155 1 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
156 :
157 : /* Verify responder returned error large response with chunk_handle == 1
158 : * and responder is in chunking mode (get.chunk_in_use). */
159 1 : spdm_response = (spdm_error_response_t*) ((uint8_t*)message + transport_header_size);
160 1 : assert_int_equal(spdm_response->header.spdm_version, SPDM_MESSAGE_VERSION_12);
161 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
162 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_LARGE_RESPONSE);
163 1 : assert_int_equal(spdm_response->header.param2, 0);
164 :
165 1 : chunk_handle = *(uint8_t*)(spdm_response + 1);
166 1 : assert_int_equal(chunk_handle, spdm_context->chunk_context.get.chunk_handle);
167 1 : assert_int_equal(spdm_context->chunk_context.get.chunk_in_use, true);
168 1 : libspdm_release_sender_buffer(spdm_context);
169 :
170 1 : free(data);
171 1 : libspdm_reset_message_m(spdm_context, NULL);
172 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
173 : #else
174 1 : libspdm_asym_free(spdm_context->connection_info.algorithm.base_asym_algo,
175 : spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key);
176 : #endif
177 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP */
178 : }
179 :
180 : /**
181 : * Test 2: Test Responder Receive Send flow triggers chunk get mode
182 : * if response message size is larger than responder sending transmit buffer size.
183 : **/
184 1 : void libspdm_test_responder_receive_send_rsp_case2(void** state)
185 : {
186 : libspdm_return_t status;
187 : libspdm_test_context_t* spdm_test_context;
188 : libspdm_context_t* spdm_context;
189 : size_t response_size;
190 : uint8_t* response;
191 : spdm_error_response_t* spdm_response;
192 : my_spdm_vendor_defined_request_msg_t spdm_request;
193 : void* message;
194 : size_t message_size;
195 : uint32_t transport_header_size;
196 : uint8_t chunk_handle;
197 :
198 1 : spdm_test_context = *state;
199 1 : spdm_context = spdm_test_context->spdm_context;
200 1 : spdm_test_context->case_id = 2;
201 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
202 : SPDM_VERSION_NUMBER_SHIFT_BIT;
203 :
204 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
205 :
206 1 : spdm_context->local_context.capability.flags |=
207 : (SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP
208 : | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP);
209 1 : spdm_context->connection_info.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP;
210 :
211 : /* The local Responder transmit buffer size for sending a single and complete SPDM message */
212 1 : spdm_context->local_context.capability.sender_data_transfer_size =
213 : CHUNK_GET_UNIT_TEST_OVERRIDE_DATA_TRANSFER_SIZE;
214 : /* The peer Requester buffer size for receiving a single and complete SPDM message */
215 1 : spdm_context->connection_info.capability.data_transfer_size = LIBSPDM_DATA_TRANSFER_SIZE;
216 :
217 1 : spdm_context->connection_info.capability.max_spdm_msg_size = LIBSPDM_MAX_SPDM_MSG_SIZE;
218 :
219 1 : libspdm_zero_mem(&spdm_request, sizeof(spdm_request));
220 1 : spdm_request.header.spdm_version = SPDM_MESSAGE_VERSION_12;
221 1 : spdm_request.header.request_response_code = SPDM_VENDOR_DEFINED_REQUEST;
222 :
223 1 : libspdm_copy_mem(spdm_context->last_spdm_request,
224 1 : libspdm_get_scratch_buffer_last_spdm_request_capacity(spdm_context),
225 : &spdm_request, sizeof(spdm_request));
226 1 : spdm_context->last_spdm_request_size = sizeof(spdm_request);
227 :
228 1 : assert_int_equal(spdm_context->chunk_context.get.chunk_in_use, false);
229 1 : libspdm_acquire_sender_buffer(spdm_context, &message_size, (void**) &message);
230 :
231 1 : response = message;
232 1 : response_size = message_size;
233 1 : libspdm_zero_mem(response, response_size);
234 :
235 : /* Make response message size greater than the sending transmit buffer size of responder */
236 1 : spdm_context->get_response_func = (void *)my_test_get_response_func;
237 :
238 1 : status = libspdm_build_response(spdm_context, NULL, false, &response_size, (void**)&response);
239 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
240 1 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
241 :
242 : /* Verify responder returned error large response with chunk_handle == 1
243 : * and responder is in chunking mode (get.chunk_in_use). */
244 1 : spdm_response = (spdm_error_response_t*) ((uint8_t*)message + transport_header_size);
245 1 : assert_int_equal(spdm_response->header.spdm_version, SPDM_MESSAGE_VERSION_12);
246 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
247 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_LARGE_RESPONSE);
248 1 : assert_int_equal(spdm_response->header.param2, 0);
249 :
250 1 : chunk_handle = *(uint8_t*)(spdm_response + 1);
251 1 : assert_int_equal(chunk_handle, spdm_context->chunk_context.get.chunk_handle);
252 1 : assert_int_equal(spdm_context->chunk_context.get.chunk_in_use, true);
253 1 : libspdm_release_sender_buffer(spdm_context);
254 1 : }
255 :
256 :
257 : #if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
258 : /**
259 : * Test 3: Test Responder Receive Send flow triggers chunk get mode
260 : * if response message size is larger than responder sending transmit buffer size.
261 : **/
262 1 : void libspdm_test_responder_receive_send_rsp_case3(void** state)
263 : {
264 : libspdm_return_t status;
265 : libspdm_test_context_t* spdm_test_context;
266 : libspdm_context_t* spdm_context;
267 : size_t response_size;
268 : uint8_t* response;
269 : spdm_error_response_t* spdm_response;
270 : my_spdm_vendor_defined_request_msg_t spdm_request;
271 : void* message;
272 : size_t message_size;
273 : uint32_t transport_header_size;
274 : uint8_t chunk_handle;
275 :
276 1 : spdm_test_context = *state;
277 1 : spdm_context = spdm_test_context->spdm_context;
278 1 : spdm_test_context->case_id = 2;
279 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
280 : SPDM_VERSION_NUMBER_SHIFT_BIT;
281 :
282 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
283 :
284 1 : spdm_context->local_context.capability.flags |=
285 : (SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP
286 : | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP);
287 1 : spdm_context->connection_info.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP;
288 :
289 : /* The local Responder transmit buffer size for sending a single and complete SPDM message */
290 1 : spdm_context->local_context.capability.sender_data_transfer_size =
291 : CHUNK_GET_UNIT_TEST_OVERRIDE_DATA_TRANSFER_SIZE;
292 : /* The peer Requester buffer size for receiving a single and complete SPDM message */
293 1 : spdm_context->connection_info.capability.data_transfer_size = LIBSPDM_DATA_TRANSFER_SIZE;
294 :
295 1 : spdm_context->connection_info.capability.max_spdm_msg_size = LIBSPDM_MAX_SPDM_MSG_SIZE;
296 :
297 1 : libspdm_zero_mem(&spdm_request, sizeof(spdm_request));
298 1 : spdm_request.header.spdm_version = SPDM_MESSAGE_VERSION_12;
299 1 : spdm_request.header.request_response_code = SPDM_VENDOR_DEFINED_REQUEST;
300 :
301 1 : libspdm_copy_mem(spdm_context->last_spdm_request,
302 1 : libspdm_get_scratch_buffer_last_spdm_request_capacity(spdm_context),
303 : &spdm_request, sizeof(spdm_request));
304 1 : spdm_context->last_spdm_request_size = sizeof(spdm_request);
305 :
306 1 : assert_int_equal(spdm_context->chunk_context.get.chunk_in_use, false);
307 1 : libspdm_acquire_sender_buffer(spdm_context, &message_size, (void**) &message);
308 :
309 1 : response = message;
310 1 : response_size = message_size;
311 1 : libspdm_zero_mem(response, response_size);
312 :
313 : /* Make response message size greater than the sending transmit buffer size of responder */
314 1 : libspdm_register_vendor_callback_func(spdm_context, my_test_get_response_func2);
315 :
316 1 : status = libspdm_build_response(spdm_context, NULL, false, &response_size, (void**)&response);
317 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
318 1 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
319 :
320 : /* Verify responder returned error large response with chunk_handle == 1
321 : * and responder is in chunking mode (get.chunk_in_use). */
322 1 : spdm_response = (spdm_error_response_t*) ((uint8_t*)message + transport_header_size);
323 1 : assert_int_equal(spdm_response->header.spdm_version, SPDM_MESSAGE_VERSION_12);
324 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
325 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_LARGE_RESPONSE);
326 1 : assert_int_equal(spdm_response->header.param2, 0);
327 :
328 1 : chunk_handle = *(uint8_t*)(spdm_response + 1);
329 1 : assert_int_equal(chunk_handle, spdm_context->chunk_context.get.chunk_handle);
330 1 : assert_int_equal(spdm_context->chunk_context.get.chunk_in_use, true);
331 1 : libspdm_release_sender_buffer(spdm_context);
332 1 : }
333 : #endif /* LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES */
334 :
335 : /**
336 : * Test 4: Test Responder Receive Send flow triggers chunk get mode
337 : * if response buffer is larger than requester max_spdm_msg_size.
338 : * expect: SPDM_ERROR_CODE_RESPONSE_TOO_LARGE
339 : **/
340 1 : void libspdm_test_responder_receive_send_rsp_case4(void** state)
341 : {
342 : #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
343 : /* This test case is partially copied from test_requester_get_measurement_case4 */
344 : libspdm_return_t status;
345 : libspdm_test_context_t* spdm_test_context;
346 : libspdm_context_t* spdm_context;
347 : size_t response_size;
348 : uint8_t* response;
349 : spdm_error_response_t* spdm_response;
350 : spdm_get_measurements_request_t spdm_request;
351 : void* message;
352 : size_t message_size;
353 : void* data;
354 : size_t data_size;
355 : void* hash;
356 : size_t hash_size;
357 : uint32_t transport_header_size;
358 :
359 1 : spdm_test_context = *state;
360 1 : spdm_context = spdm_test_context->spdm_context;
361 1 : spdm_test_context->case_id = 3;
362 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
363 : SPDM_VERSION_NUMBER_SHIFT_BIT;
364 :
365 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
366 :
367 1 : spdm_context->local_context.capability.flags |=
368 : (SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP
369 : | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP);
370 1 : spdm_context->connection_info.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP;
371 :
372 1 : if (!libspdm_read_responder_public_certificate_chain(
373 : m_libspdm_use_hash_algo,
374 : m_libspdm_use_asym_algo, &data,
375 : &data_size,
376 : &hash, &hash_size)) {
377 0 : return;
378 : }
379 :
380 1 : spdm_context->local_context.local_cert_chain_provision_size[0] = data_size;
381 1 : spdm_context->local_context.local_cert_chain_provision[0] = data;
382 :
383 1 : libspdm_reset_message_m(spdm_context, NULL);
384 :
385 1 : spdm_context->connection_info.algorithm.measurement_spec = m_libspdm_use_measurement_spec;
386 1 : spdm_context->connection_info.algorithm.measurement_hash_algo =
387 : m_libspdm_use_measurement_hash_algo;
388 1 : spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
389 1 : spdm_context->connection_info.algorithm.base_asym_algo = m_libspdm_use_asym_algo;
390 :
391 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
392 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = data_size;
393 : libspdm_copy_mem(
394 : spdm_context->connection_info.peer_used_cert_chain[0].buffer,
395 : sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer),
396 : data, data_size);
397 : #else
398 1 : libspdm_hash_all(
399 : spdm_context->connection_info.algorithm.base_hash_algo,
400 : data, data_size,
401 1 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash);
402 1 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size =
403 1 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
404 1 : libspdm_get_leaf_cert_public_key_from_cert_chain(
405 : spdm_context->connection_info.algorithm.base_hash_algo,
406 : spdm_context->connection_info.algorithm.base_asym_algo,
407 : data, data_size,
408 : &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key);
409 : #endif
410 :
411 1 : spdm_context->connection_info.capability.data_transfer_size =
412 : CHUNK_GET_UNIT_TEST_OVERRIDE_DATA_TRANSFER_SIZE;
413 :
414 : /*set requester small max_spdm_msg_size*/
415 1 : spdm_context->connection_info.capability.max_spdm_msg_size = 100;
416 :
417 1 : libspdm_zero_mem(&spdm_request, sizeof(spdm_request));
418 1 : spdm_request.header.spdm_version = SPDM_MESSAGE_VERSION_12;
419 1 : spdm_request.header.request_response_code = SPDM_GET_MEASUREMENTS;
420 1 : spdm_request.header.param1 = SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE;
421 1 : spdm_request.header.param2 =
422 : SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_ALL_MEASUREMENTS;
423 1 : spdm_request.slot_id_param = 0;
424 :
425 1 : libspdm_copy_mem(spdm_context->last_spdm_request,
426 1 : libspdm_get_scratch_buffer_last_spdm_request_capacity(spdm_context),
427 : &spdm_request, sizeof(spdm_request));
428 1 : spdm_context->last_spdm_request_size = sizeof(spdm_request);
429 :
430 1 : assert_int_equal(spdm_context->chunk_context.get.chunk_in_use, false);
431 1 : libspdm_acquire_sender_buffer(spdm_context, &message_size, (void**) &message);
432 1 : response = message;
433 1 : response_size = message_size;
434 1 : libspdm_zero_mem(response, response_size);
435 :
436 1 : status = libspdm_build_response(spdm_context, NULL, false, &response_size, (void**)&response);
437 :
438 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
439 1 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
440 :
441 : /* Verify responder returned SPDM_ERROR_CODE_RESPONSE_TOO_LARGE response with chunk_handle == 0
442 : * and responder is not in chunking mode (get.chunk_in_use). */
443 1 : spdm_response = (spdm_error_response_t*) ((uint8_t*)message + transport_header_size);
444 1 : assert_int_equal(spdm_response->header.spdm_version, SPDM_MESSAGE_VERSION_12);
445 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
446 :
447 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_RESPONSE_TOO_LARGE);
448 1 : assert_int_equal(spdm_response->header.param2, 0);
449 1 : assert_int_equal(0, spdm_context->chunk_context.get.chunk_handle);
450 1 : assert_int_equal(spdm_context->chunk_context.get.chunk_in_use, false);
451 1 : libspdm_release_sender_buffer(spdm_context);
452 :
453 1 : free(data);
454 1 : libspdm_reset_message_m(spdm_context, NULL);
455 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
456 : #else
457 1 : libspdm_asym_free(spdm_context->connection_info.algorithm.base_asym_algo,
458 : spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key);
459 : #endif
460 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP */
461 : }
462 :
463 : /**
464 : * Test 5: During an active chunk GET transfer, a non-chunk, non-GET_VERSION
465 : * request should be rejected with UnexpectedRequest error, and
466 : * the chunk transfer sequence should NOT be terminated.
467 : **/
468 1 : void libspdm_test_responder_receive_send_rsp_case5(void** state)
469 : {
470 : libspdm_return_t status;
471 : libspdm_test_context_t *spdm_test_context;
472 : libspdm_context_t *spdm_context;
473 : size_t response_size;
474 : uint8_t *response;
475 : spdm_error_response_t *spdm_response;
476 : spdm_message_header_t spdm_request;
477 : void *message;
478 : size_t message_size;
479 : uint32_t transport_header_size;
480 : uint8_t saved_chunk_handle;
481 :
482 1 : spdm_test_context = *state;
483 1 : spdm_context = spdm_test_context->spdm_context;
484 1 : spdm_test_context->case_id = 5;
485 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
486 : SPDM_VERSION_NUMBER_SHIFT_BIT;
487 1 : spdm_context->connection_info.connection_state =
488 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
489 1 : spdm_context->local_context.capability.flags |=
490 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP;
491 1 : spdm_context->connection_info.capability.flags |=
492 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP;
493 1 : spdm_context->connection_info.capability.data_transfer_size =
494 : LIBSPDM_DATA_TRANSFER_SIZE;
495 1 : spdm_context->connection_info.capability.max_spdm_msg_size =
496 : LIBSPDM_MAX_SPDM_MSG_SIZE;
497 :
498 : /* Simulate an active chunk GET transfer. */
499 1 : spdm_context->chunk_context.get.chunk_in_use = true;
500 1 : spdm_context->chunk_context.get.chunk_handle = 1;
501 1 : spdm_context->chunk_context.get.chunk_seq_no = 2;
502 1 : saved_chunk_handle = spdm_context->chunk_context.get.chunk_handle;
503 :
504 : /* Send a GET_CAPABILITIES request (non-chunk, non-GET_VERSION). */
505 1 : libspdm_zero_mem(&spdm_request, sizeof(spdm_request));
506 1 : spdm_request.spdm_version = SPDM_MESSAGE_VERSION_12;
507 1 : spdm_request.request_response_code = SPDM_GET_CAPABILITIES;
508 :
509 1 : libspdm_copy_mem(spdm_context->last_spdm_request,
510 1 : libspdm_get_scratch_buffer_last_spdm_request_capacity(spdm_context),
511 : &spdm_request, sizeof(spdm_request));
512 1 : spdm_context->last_spdm_request_size = sizeof(spdm_request);
513 :
514 1 : libspdm_acquire_sender_buffer(spdm_context, &message_size, (void **)&message);
515 1 : response = message;
516 1 : response_size = message_size;
517 1 : libspdm_zero_mem(response, response_size);
518 :
519 1 : status = libspdm_build_response(spdm_context, NULL, false,
520 : &response_size, (void **)&response);
521 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
522 :
523 1 : transport_header_size =
524 : spdm_context->local_context.capability.transport_header_size;
525 1 : spdm_response = (spdm_error_response_t *)((uint8_t *)message + transport_header_size);
526 :
527 : /* Verify error UnexpectedRequest is returned. */
528 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
529 1 : assert_int_equal(spdm_response->header.param1,
530 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST);
531 :
532 : /* Verify chunk transfer sequence is NOT terminated. */
533 1 : assert_true(spdm_context->chunk_context.get.chunk_in_use);
534 1 : assert_int_equal(spdm_context->chunk_context.get.chunk_handle,
535 : saved_chunk_handle);
536 1 : assert_int_equal(spdm_context->chunk_context.get.chunk_seq_no, 2);
537 :
538 1 : libspdm_release_sender_buffer(spdm_context);
539 :
540 : /* Clean up chunk state for subsequent tests. */
541 1 : spdm_context->chunk_context.get.chunk_in_use = false;
542 1 : }
543 :
544 : /**
545 : * Test 6: During an active chunk GET transfer, a GET_VERSION request
546 : * should be allowed to interrupt: the chunk transfer should be
547 : * terminated and GET_VERSION processed normally.
548 : **/
549 1 : void libspdm_test_responder_receive_send_rsp_case6(void** state)
550 : {
551 : libspdm_return_t status;
552 : libspdm_test_context_t *spdm_test_context;
553 : libspdm_context_t *spdm_context;
554 : size_t response_size;
555 : uint8_t *response;
556 : spdm_message_header_t *spdm_response;
557 : spdm_get_version_request_t spdm_request;
558 : void *message;
559 : size_t message_size;
560 : uint32_t transport_header_size;
561 :
562 1 : spdm_test_context = *state;
563 1 : spdm_context = spdm_test_context->spdm_context;
564 1 : spdm_test_context->case_id = 6;
565 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
566 : SPDM_VERSION_NUMBER_SHIFT_BIT;
567 1 : spdm_context->connection_info.connection_state =
568 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
569 1 : spdm_context->local_context.capability.flags |=
570 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP;
571 1 : spdm_context->connection_info.capability.flags |=
572 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP;
573 1 : spdm_context->connection_info.capability.data_transfer_size =
574 : LIBSPDM_DATA_TRANSFER_SIZE;
575 1 : spdm_context->connection_info.capability.max_spdm_msg_size =
576 : LIBSPDM_MAX_SPDM_MSG_SIZE;
577 :
578 : /* Simulate an active chunk GET transfer. */
579 1 : spdm_context->chunk_context.get.chunk_in_use = true;
580 1 : spdm_context->chunk_context.get.chunk_handle = 1;
581 1 : spdm_context->chunk_context.get.chunk_seq_no = 2;
582 :
583 : /* Send a GET_VERSION request. */
584 1 : libspdm_zero_mem(&spdm_request, sizeof(spdm_request));
585 1 : spdm_request.header.spdm_version = SPDM_MESSAGE_VERSION_10;
586 1 : spdm_request.header.request_response_code = SPDM_GET_VERSION;
587 :
588 1 : libspdm_copy_mem(spdm_context->last_spdm_request,
589 1 : libspdm_get_scratch_buffer_last_spdm_request_capacity(spdm_context),
590 : &spdm_request, sizeof(spdm_request));
591 1 : spdm_context->last_spdm_request_size = sizeof(spdm_request);
592 :
593 1 : libspdm_acquire_sender_buffer(spdm_context, &message_size, (void **)&message);
594 1 : response = message;
595 1 : response_size = message_size;
596 1 : libspdm_zero_mem(response, response_size);
597 :
598 1 : status = libspdm_build_response(spdm_context, NULL, false,
599 : &response_size, (void **)&response);
600 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
601 :
602 1 : transport_header_size =
603 : spdm_context->local_context.capability.transport_header_size;
604 1 : spdm_response = (spdm_message_header_t *)((uint8_t *)message + transport_header_size);
605 :
606 : /* Verify GET_VERSION was processed: response should be VERSION. */
607 1 : assert_int_equal(spdm_response->request_response_code, SPDM_VERSION);
608 :
609 : /* Verify chunk transfer was terminated. */
610 1 : assert_false(spdm_context->chunk_context.get.chunk_in_use);
611 1 : assert_int_equal(spdm_context->chunk_context.get.chunk_seq_no, 0);
612 :
613 1 : libspdm_release_sender_buffer(spdm_context);
614 1 : }
615 :
616 : /**
617 : * Test 7: During an active chunk SEND transfer, a non-chunk, non-GET_VERSION
618 : * request should be rejected with UnexpectedRequest error, and
619 : * the chunk transfer sequence should NOT be terminated.
620 : **/
621 1 : void libspdm_test_responder_receive_send_rsp_case7(void** state)
622 : {
623 : libspdm_return_t status;
624 : libspdm_test_context_t *spdm_test_context;
625 : libspdm_context_t *spdm_context;
626 : size_t response_size;
627 : uint8_t *response;
628 : spdm_error_response_t *spdm_response;
629 : spdm_message_header_t spdm_request;
630 : void *message;
631 : size_t message_size;
632 : uint32_t transport_header_size;
633 :
634 1 : spdm_test_context = *state;
635 1 : spdm_context = spdm_test_context->spdm_context;
636 1 : spdm_test_context->case_id = 7;
637 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
638 : SPDM_VERSION_NUMBER_SHIFT_BIT;
639 1 : spdm_context->connection_info.connection_state =
640 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
641 1 : spdm_context->local_context.capability.flags |=
642 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP;
643 1 : spdm_context->connection_info.capability.flags |=
644 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP;
645 1 : spdm_context->connection_info.capability.data_transfer_size =
646 : LIBSPDM_DATA_TRANSFER_SIZE;
647 1 : spdm_context->connection_info.capability.max_spdm_msg_size =
648 : LIBSPDM_MAX_SPDM_MSG_SIZE;
649 :
650 : /* Simulate an active chunk SEND transfer. */
651 1 : spdm_context->chunk_context.send.chunk_in_use = true;
652 1 : spdm_context->chunk_context.send.chunk_handle = 1;
653 1 : spdm_context->chunk_context.send.chunk_seq_no = 3;
654 :
655 : /* Send a GET_CAPABILITIES request (non-chunk, non-GET_VERSION). */
656 1 : libspdm_zero_mem(&spdm_request, sizeof(spdm_request));
657 1 : spdm_request.spdm_version = SPDM_MESSAGE_VERSION_12;
658 1 : spdm_request.request_response_code = SPDM_GET_CAPABILITIES;
659 :
660 1 : libspdm_copy_mem(spdm_context->last_spdm_request,
661 1 : libspdm_get_scratch_buffer_last_spdm_request_capacity(spdm_context),
662 : &spdm_request, sizeof(spdm_request));
663 1 : spdm_context->last_spdm_request_size = sizeof(spdm_request);
664 :
665 1 : libspdm_acquire_sender_buffer(spdm_context, &message_size, (void **)&message);
666 1 : response = message;
667 1 : response_size = message_size;
668 1 : libspdm_zero_mem(response, response_size);
669 :
670 1 : status = libspdm_build_response(spdm_context, NULL, false,
671 : &response_size, (void **)&response);
672 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
673 :
674 1 : transport_header_size =
675 : spdm_context->local_context.capability.transport_header_size;
676 1 : spdm_response = (spdm_error_response_t *)((uint8_t *)message + transport_header_size);
677 :
678 : /* Verify error UnexpectedRequest is returned. */
679 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
680 1 : assert_int_equal(spdm_response->header.param1,
681 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST);
682 :
683 : /* Verify chunk SEND transfer sequence is NOT terminated. */
684 1 : assert_true(spdm_context->chunk_context.send.chunk_in_use);
685 1 : assert_int_equal(spdm_context->chunk_context.send.chunk_handle, 1);
686 1 : assert_int_equal(spdm_context->chunk_context.send.chunk_seq_no, 3);
687 :
688 1 : libspdm_release_sender_buffer(spdm_context);
689 :
690 : /* Clean up chunk state for subsequent tests. */
691 1 : spdm_context->chunk_context.send.chunk_in_use = false;
692 1 : }
693 :
694 : /**
695 : * Test 8: During an active chunk SEND transfer, a GET_VERSION request
696 : * should be allowed to interrupt: the chunk send transfer should be
697 : * terminated and GET_VERSION processed normally.
698 : **/
699 1 : void libspdm_test_responder_receive_send_rsp_case8(void** state)
700 : {
701 : libspdm_return_t status;
702 : libspdm_test_context_t *spdm_test_context;
703 : libspdm_context_t *spdm_context;
704 : size_t response_size;
705 : uint8_t *response;
706 : spdm_message_header_t *spdm_response;
707 : spdm_get_version_request_t spdm_request;
708 : void *message;
709 : size_t message_size;
710 : uint32_t transport_header_size;
711 :
712 1 : spdm_test_context = *state;
713 1 : spdm_context = spdm_test_context->spdm_context;
714 1 : spdm_test_context->case_id = 8;
715 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
716 : SPDM_VERSION_NUMBER_SHIFT_BIT;
717 1 : spdm_context->connection_info.connection_state =
718 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
719 1 : spdm_context->local_context.capability.flags |=
720 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP;
721 1 : spdm_context->connection_info.capability.flags |=
722 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP;
723 1 : spdm_context->connection_info.capability.data_transfer_size =
724 : LIBSPDM_DATA_TRANSFER_SIZE;
725 1 : spdm_context->connection_info.capability.max_spdm_msg_size =
726 : LIBSPDM_MAX_SPDM_MSG_SIZE;
727 :
728 : /* Simulate an active chunk SEND transfer. */
729 1 : spdm_context->chunk_context.send.chunk_in_use = true;
730 1 : spdm_context->chunk_context.send.chunk_handle = 1;
731 1 : spdm_context->chunk_context.send.chunk_seq_no = 3;
732 :
733 : /* Send a GET_VERSION request. */
734 1 : libspdm_zero_mem(&spdm_request, sizeof(spdm_request));
735 1 : spdm_request.header.spdm_version = SPDM_MESSAGE_VERSION_10;
736 1 : spdm_request.header.request_response_code = SPDM_GET_VERSION;
737 :
738 1 : libspdm_copy_mem(spdm_context->last_spdm_request,
739 1 : libspdm_get_scratch_buffer_last_spdm_request_capacity(spdm_context),
740 : &spdm_request, sizeof(spdm_request));
741 1 : spdm_context->last_spdm_request_size = sizeof(spdm_request);
742 :
743 1 : libspdm_acquire_sender_buffer(spdm_context, &message_size, (void **)&message);
744 1 : response = message;
745 1 : response_size = message_size;
746 1 : libspdm_zero_mem(response, response_size);
747 :
748 1 : status = libspdm_build_response(spdm_context, NULL, false,
749 : &response_size, (void **)&response);
750 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
751 :
752 1 : transport_header_size =
753 : spdm_context->local_context.capability.transport_header_size;
754 1 : spdm_response = (spdm_message_header_t *)((uint8_t *)message + transport_header_size);
755 :
756 : /* Verify GET_VERSION was processed: response should be VERSION. */
757 1 : assert_int_equal(spdm_response->request_response_code, SPDM_VERSION);
758 :
759 : /* Verify chunk send transfer was terminated. */
760 1 : assert_false(spdm_context->chunk_context.send.chunk_in_use);
761 1 : assert_int_equal(spdm_context->chunk_context.send.chunk_seq_no, 0);
762 :
763 1 : libspdm_release_sender_buffer(spdm_context);
764 1 : }
765 :
766 1 : int libspdm_rsp_receive_send_test(void)
767 : {
768 1 : const struct CMUnitTest test_cases[] = {
769 : /* response message size is larger than requester data_transfer_size */
770 : cmocka_unit_test(libspdm_test_responder_receive_send_rsp_case1),
771 : /* response message size is larger than responder sending transmit buffer size */
772 : cmocka_unit_test_setup(libspdm_test_responder_receive_send_rsp_case2,
773 : libspdm_unit_test_group_setup),
774 : #if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
775 : /* response message size is larger than responder sending transmit buffer size
776 : * using the new Vendor Defined Message API */
777 : cmocka_unit_test_setup(libspdm_test_responder_receive_send_rsp_case3,
778 : libspdm_unit_test_group_setup),
779 : #endif /* LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES */
780 : /* response message size is larger than requester max_spdm_msg_size */
781 : cmocka_unit_test_setup(libspdm_test_responder_receive_send_rsp_case4,
782 : libspdm_unit_test_group_setup),
783 : /* non-chunk request during active chunk GET transfer returns UnexpectedRequest
784 : * and does not terminate chunk transfer */
785 : cmocka_unit_test_setup(libspdm_test_responder_receive_send_rsp_case5,
786 : libspdm_unit_test_group_setup),
787 : /* GET_VERSION during active chunk GET transfer terminates chunk and proceeds */
788 : cmocka_unit_test_setup(libspdm_test_responder_receive_send_rsp_case6,
789 : libspdm_unit_test_group_setup),
790 : /* non-chunk request during active chunk SEND transfer returns UnexpectedRequest
791 : * and does not terminate chunk transfer */
792 : cmocka_unit_test_setup(libspdm_test_responder_receive_send_rsp_case7,
793 : libspdm_unit_test_group_setup),
794 : /* GET_VERSION during active chunk SEND transfer terminates chunk and proceeds */
795 : cmocka_unit_test_setup(libspdm_test_responder_receive_send_rsp_case8,
796 : libspdm_unit_test_group_setup),
797 : };
798 :
799 1 : libspdm_test_context_t test_context = {
800 : LIBSPDM_TEST_CONTEXT_VERSION,
801 : false,
802 : };
803 :
804 1 : libspdm_setup_test_context(&test_context);
805 :
806 1 : return cmocka_run_group_tests(test_cases,
807 : libspdm_unit_test_group_setup,
808 : libspdm_unit_test_group_teardown);
809 : }
810 :
811 : #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
|