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 "spdm_unit_test.h"
8 : #include "internal/libspdm_requester_lib.h"
9 : #include "internal/libspdm_secured_message_lib.h"
10 :
11 : #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
12 :
13 : static bool m_libspdm_chunk_send_last_chunk = false;
14 : static uint8_t m_libspdm_chunk_send_chunk_handle = 0;
15 : static uint16_t m_libspdm_chunk_send_chunk_seq_no = 0;
16 : static uint32_t m_libspdm_chunk_send_chunk_seq_no_14 = 0;
17 :
18 : /* Override the LIBSPDM_DATA_TRANSFER_SIZE just for the unit tests in this file.
19 : * All other unit tests have the default data transfer size due to the specific
20 : * unit tests requests and responses hardcode for each test case. */
21 : #define CHUNK_SEND_REQUESTER_UNIT_TEST_DATA_TRANSFER_SIZE (42)
22 :
23 2 : void libspdm_requester_chunk_send_test_case1_build_algorithms_response(
24 : void* context, void* response, size_t* response_size)
25 : {
26 : spdm_algorithms_response_t* spdm_response;
27 :
28 2 : *response_size = sizeof(spdm_algorithms_response_t);
29 2 : spdm_response = (spdm_algorithms_response_t*) response;
30 :
31 2 : libspdm_zero_mem(spdm_response, *response_size);
32 2 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_12;
33 2 : spdm_response->header.request_response_code = SPDM_ALGORITHMS;
34 2 : spdm_response->header.param1 = 0;
35 2 : spdm_response->header.param2 = 0;
36 2 : spdm_response->length = sizeof(spdm_algorithms_response_t);
37 2 : spdm_response->measurement_specification_sel =
38 : SPDM_MEASUREMENT_SPECIFICATION_DMTF;
39 2 : spdm_response->measurement_hash_algo =
40 : m_libspdm_use_measurement_hash_algo;
41 2 : spdm_response->base_asym_sel = m_libspdm_use_asym_algo;
42 2 : spdm_response->base_hash_sel = m_libspdm_use_hash_algo;
43 2 : spdm_response->ext_asym_sel_count = 0;
44 2 : spdm_response->ext_hash_sel_count = 0;
45 2 : }
46 :
47 1 : void libspdm_requester_chunk_send_test_case15_build_algorithms_response(
48 : void* context, void* response, size_t* response_size)
49 : {
50 : spdm_algorithms_response_t* spdm_response;
51 :
52 1 : *response_size = sizeof(spdm_algorithms_response_t);
53 1 : spdm_response = (spdm_algorithms_response_t*) response;
54 :
55 1 : libspdm_zero_mem(spdm_response, *response_size);
56 1 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_14;
57 1 : spdm_response->header.request_response_code = SPDM_ALGORITHMS;
58 1 : spdm_response->header.param1 = 0;
59 1 : spdm_response->header.param2 = 0;
60 1 : spdm_response->length = sizeof(spdm_algorithms_response_t);
61 1 : spdm_response->measurement_specification_sel =
62 : SPDM_MEASUREMENT_SPECIFICATION_DMTF;
63 1 : spdm_response->measurement_hash_algo =
64 : m_libspdm_use_measurement_hash_algo;
65 1 : spdm_response->base_asym_sel = m_libspdm_use_asym_algo;
66 1 : spdm_response->base_hash_sel = m_libspdm_use_hash_algo;
67 1 : spdm_response->ext_asym_sel_count = 0;
68 1 : spdm_response->ext_hash_sel_count = 0;
69 1 : }
70 :
71 16 : static libspdm_return_t send_message(
72 : void *spdm_context, size_t request_size, const void *request, uint64_t timeout)
73 : {
74 : libspdm_test_context_t* spdm_test_context;
75 : const spdm_chunk_send_request_t* chunk_send;
76 : const spdm_chunk_send_request_14_t* chunk_send_14;
77 :
78 16 : spdm_test_context = libspdm_get_test_context();
79 :
80 16 : chunk_send = (const spdm_chunk_send_request_t*)
81 : ((const uint8_t*) request + sizeof(libspdm_test_message_header_t));
82 :
83 16 : chunk_send_14 = (const spdm_chunk_send_request_14_t*)
84 : ((const uint8_t*) request + sizeof(libspdm_test_message_header_t));
85 :
86 16 : m_libspdm_chunk_send_chunk_handle = chunk_send->header.param2;
87 16 : m_libspdm_chunk_send_chunk_seq_no = chunk_send->chunk_seq_no;
88 16 : m_libspdm_chunk_send_chunk_seq_no_14 = chunk_send_14->chunk_seq_no;
89 :
90 16 : if (chunk_send->header.param1 & SPDM_CHUNK_SEND_REQUEST_ATTRIBUTE_LAST_CHUNK) {
91 3 : m_libspdm_chunk_send_last_chunk = true;
92 : } else {
93 13 : m_libspdm_chunk_send_last_chunk = false;
94 : }
95 :
96 16 : if (spdm_test_context->case_id == 1) {
97 2 : return LIBSPDM_STATUS_SUCCESS;
98 : }
99 14 : if (spdm_test_context->case_id == 2) {
100 1 : return LIBSPDM_STATUS_SEND_FAIL;
101 : }
102 13 : if (spdm_test_context->case_id == 3) {
103 1 : return LIBSPDM_STATUS_SUCCESS;
104 : }
105 12 : if (spdm_test_context->case_id == 4) {
106 1 : return LIBSPDM_STATUS_SUCCESS;
107 : }
108 11 : if (spdm_test_context->case_id == 5) {
109 1 : return LIBSPDM_STATUS_SUCCESS;
110 : }
111 10 : if (spdm_test_context->case_id == 6) {
112 1 : return LIBSPDM_STATUS_SUCCESS;
113 : }
114 9 : if (spdm_test_context->case_id == 7) {
115 1 : return LIBSPDM_STATUS_SUCCESS;
116 : }
117 8 : if (spdm_test_context->case_id == 8) {
118 1 : return LIBSPDM_STATUS_SUCCESS;
119 : }
120 7 : if (spdm_test_context->case_id == 9) {
121 1 : return LIBSPDM_STATUS_SUCCESS;
122 : }
123 6 : if (spdm_test_context->case_id == 10) {
124 2 : if (chunk_send->header.request_response_code == SPDM_CHUNK_SEND) {
125 2 : return LIBSPDM_STATUS_SUCCESS;
126 : }
127 0 : return LIBSPDM_STATUS_SEND_FAIL;
128 : }
129 4 : if (spdm_test_context->case_id == 11) {
130 0 : return LIBSPDM_STATUS_SUCCESS;
131 : }
132 4 : if (spdm_test_context->case_id == 12) {
133 : /* Here the send request message should always be SPDM_CHUNK_SEND,
134 : * if not then something is wrong. */
135 1 : LIBSPDM_ASSERT(chunk_send->header.request_response_code == SPDM_CHUNK_SEND);
136 1 : return LIBSPDM_STATUS_SUCCESS;
137 : }
138 3 : if (spdm_test_context->case_id == 13) {
139 : /* Should never reach here since the test case is meant to fail before send */
140 0 : LIBSPDM_ASSERT(0);
141 : }
142 3 : if (spdm_test_context->case_id == 14) {
143 1 : return LIBSPDM_STATUS_SUCCESS;
144 : }
145 2 : if (spdm_test_context->case_id == 15) {
146 2 : return LIBSPDM_STATUS_SUCCESS;
147 : }
148 0 : return LIBSPDM_STATUS_SEND_FAIL;
149 : }
150 :
151 15 : static libspdm_return_t receive_message(
152 : void *spdm_context, size_t *response_size, void **response, uint64_t timeout)
153 : {
154 : libspdm_test_context_t *spdm_test_context;
155 : spdm_chunk_send_ack_response_t *chunk_send_ack_rsp;
156 : spdm_chunk_send_ack_response_14_t *chunk_send_ack_rsp_14;
157 : spdm_error_response_t *error_response;
158 : size_t chunk_rsp_size;
159 : uint8_t *chunk_copy_to;
160 : size_t chunk_size;
161 :
162 15 : spdm_test_context = libspdm_get_test_context();
163 :
164 15 : if ((spdm_test_context->case_id == 1) || (spdm_test_context->case_id == 10) ||
165 11 : (spdm_test_context->case_id == 11)) {
166 : /* Successful chunk send of algorithms request */
167 : chunk_send_ack_rsp
168 4 : = (void*) ((uint8_t*) *response + sizeof(libspdm_test_message_header_t));
169 :
170 4 : chunk_send_ack_rsp->header.spdm_version = SPDM_MESSAGE_VERSION_12;
171 4 : chunk_send_ack_rsp->header.request_response_code = SPDM_CHUNK_SEND_ACK;
172 4 : chunk_send_ack_rsp->header.param1 = 0;
173 4 : chunk_send_ack_rsp->header.param2 = m_libspdm_chunk_send_chunk_handle;
174 4 : chunk_send_ack_rsp->chunk_seq_no = m_libspdm_chunk_send_chunk_seq_no;
175 :
176 4 : if (m_libspdm_chunk_send_last_chunk) {
177 :
178 2 : chunk_copy_to = (uint8_t*) (chunk_send_ack_rsp + 1);
179 2 : chunk_size = *response_size - (chunk_copy_to - (uint8_t*) *response);
180 :
181 2 : libspdm_requester_chunk_send_test_case1_build_algorithms_response(
182 : spdm_context, chunk_copy_to, &chunk_size);
183 2 : chunk_rsp_size = sizeof(spdm_chunk_send_ack_response_t) + chunk_size;
184 :
185 2 : libspdm_transport_test_encode_message(
186 : spdm_context, NULL, false, false,
187 : chunk_rsp_size, chunk_send_ack_rsp,
188 : response_size, response);
189 : } else {
190 2 : chunk_rsp_size = sizeof(spdm_chunk_send_ack_response_t);
191 2 : libspdm_transport_test_encode_message(
192 : spdm_context, NULL, false, false,
193 : chunk_rsp_size, chunk_send_ack_rsp,
194 : response_size, response);
195 : }
196 4 : return LIBSPDM_STATUS_SUCCESS;
197 : }
198 11 : if (spdm_test_context->case_id == 2) {
199 : /* Request fail send
200 : * Should never reach here since the test case is meant to fail at send */
201 0 : LIBSPDM_ASSERT(0);
202 0 : return LIBSPDM_STATUS_RECEIVE_FAIL;
203 : }
204 11 : if (spdm_test_context->case_id == 3) {
205 : /* Response fail receive */
206 1 : return LIBSPDM_STATUS_RECEIVE_FAIL;
207 : }
208 10 : if (spdm_test_context->case_id == 4) {
209 : /* Response has bad SPDM version */
210 : chunk_send_ack_rsp
211 1 : = (void*) ((uint8_t*) *response + sizeof(libspdm_test_message_header_t));
212 :
213 1 : chunk_send_ack_rsp->header.spdm_version = SPDM_MESSAGE_VERSION_11; /* Bad SPDM version */
214 1 : chunk_send_ack_rsp->header.request_response_code = SPDM_CHUNK_SEND_ACK;
215 1 : chunk_send_ack_rsp->header.param1 = 0;
216 1 : chunk_send_ack_rsp->header.param2 = m_libspdm_chunk_send_chunk_handle;
217 1 : chunk_send_ack_rsp->chunk_seq_no = m_libspdm_chunk_send_chunk_seq_no;
218 :
219 1 : chunk_rsp_size = sizeof(spdm_chunk_send_ack_response_t);
220 1 : libspdm_transport_test_encode_message(
221 : spdm_context, NULL, false, false,
222 : chunk_rsp_size, chunk_send_ack_rsp,
223 : response_size, response);
224 :
225 1 : return LIBSPDM_STATUS_SUCCESS;
226 : }
227 9 : if (spdm_test_context->case_id == 5) {
228 : /* Response has bad request response code */
229 : chunk_send_ack_rsp
230 1 : = (void*) ((uint8_t*) *response + sizeof(libspdm_test_message_header_t));
231 :
232 1 : chunk_send_ack_rsp->header.spdm_version = SPDM_MESSAGE_VERSION_12;
233 1 : chunk_send_ack_rsp->header.request_response_code = SPDM_ERROR; /* Bad response code */
234 1 : chunk_send_ack_rsp->header.param1 = 0;
235 1 : chunk_send_ack_rsp->header.param2 = 0;
236 :
237 1 : chunk_rsp_size = sizeof(spdm_chunk_send_ack_response_t);
238 1 : libspdm_transport_test_encode_message(
239 : spdm_context, NULL, false, false,
240 : chunk_rsp_size, chunk_send_ack_rsp,
241 : response_size, response);
242 :
243 1 : return LIBSPDM_STATUS_SUCCESS;
244 : }
245 8 : if (spdm_test_context->case_id == 6) {
246 : /* Response has bad response size */
247 : chunk_send_ack_rsp
248 1 : = (void*) ((uint8_t*) *response + sizeof(libspdm_test_message_header_t));
249 :
250 1 : chunk_send_ack_rsp->header.spdm_version = SPDM_MESSAGE_VERSION_12;
251 1 : chunk_send_ack_rsp->header.request_response_code = SPDM_CHUNK_SEND_ACK;
252 1 : chunk_send_ack_rsp->header.param1 = 0;
253 1 : chunk_send_ack_rsp->header.param2 = m_libspdm_chunk_send_chunk_handle;
254 1 : chunk_send_ack_rsp->chunk_seq_no = m_libspdm_chunk_send_chunk_seq_no;
255 :
256 1 : chunk_rsp_size = 4; /* Bad response size */
257 :
258 1 : libspdm_transport_test_encode_message(
259 : spdm_context, NULL, false, false,
260 : chunk_rsp_size, chunk_send_ack_rsp,
261 : response_size, response);
262 :
263 :
264 1 : return LIBSPDM_STATUS_SUCCESS;
265 : }
266 7 : if (spdm_test_context->case_id == 7) {
267 : /* Response has early error detected */
268 : chunk_send_ack_rsp
269 1 : = (void*) ((uint8_t*) *response + sizeof(libspdm_test_message_header_t));
270 :
271 1 : chunk_send_ack_rsp->header.spdm_version = SPDM_MESSAGE_VERSION_12;
272 1 : chunk_send_ack_rsp->header.request_response_code = SPDM_CHUNK_SEND_ACK;
273 : chunk_send_ack_rsp->header.param1
274 1 : = SPDM_CHUNK_SEND_ACK_RESPONSE_ATTRIBUTE_EARLY_ERROR_DETECTED;
275 1 : chunk_send_ack_rsp->header.param2 = m_libspdm_chunk_send_chunk_handle;
276 1 : chunk_send_ack_rsp->chunk_seq_no = m_libspdm_chunk_send_chunk_seq_no;
277 :
278 1 : error_response = (void*) (chunk_send_ack_rsp + 1);
279 1 : error_response->header.spdm_version = SPDM_MESSAGE_VERSION_12;
280 1 : error_response->header.request_response_code = SPDM_ERROR;
281 1 : error_response->header.param1 = SPDM_ERROR_CODE_UNSPECIFIED;
282 1 : error_response->header.param2 = 0;
283 :
284 1 : chunk_rsp_size = sizeof(spdm_chunk_send_ack_response_t) + sizeof(spdm_error_response_t);
285 1 : libspdm_transport_test_encode_message(
286 : spdm_context, NULL, false, false,
287 : chunk_rsp_size, chunk_send_ack_rsp,
288 : response_size, response);
289 :
290 1 : return LIBSPDM_STATUS_SUCCESS;
291 : }
292 6 : if (spdm_test_context->case_id == 8) {
293 : /* Response has bad chunk handle */
294 : chunk_send_ack_rsp
295 1 : = (void*) ((uint8_t*) *response + sizeof(libspdm_test_message_header_t));
296 :
297 1 : chunk_send_ack_rsp->header.spdm_version = SPDM_MESSAGE_VERSION_12;
298 1 : chunk_send_ack_rsp->header.request_response_code = SPDM_CHUNK_SEND_ACK;
299 1 : chunk_send_ack_rsp->header.param1 = 0;
300 :
301 : /* Bad chunk handle */
302 1 : chunk_send_ack_rsp->header.param2 = m_libspdm_chunk_send_chunk_handle - 1;
303 1 : chunk_send_ack_rsp->chunk_seq_no = m_libspdm_chunk_send_chunk_seq_no;
304 :
305 1 : chunk_rsp_size = sizeof(spdm_chunk_send_ack_response_t);
306 1 : libspdm_transport_test_encode_message(
307 : spdm_context, NULL, false, false,
308 : chunk_rsp_size, chunk_send_ack_rsp,
309 : response_size, response);
310 :
311 1 : return LIBSPDM_STATUS_SUCCESS;
312 : }
313 5 : if (spdm_test_context->case_id == 9) {
314 : /* Response has bad chunk seq no */
315 : chunk_send_ack_rsp
316 1 : = (void*) ((uint8_t*) *response + sizeof(libspdm_test_message_header_t));
317 :
318 1 : chunk_send_ack_rsp->header.spdm_version = SPDM_MESSAGE_VERSION_12;
319 1 : chunk_send_ack_rsp->header.request_response_code = SPDM_CHUNK_SEND_ACK;
320 1 : chunk_send_ack_rsp->header.param1 = 0;
321 1 : chunk_send_ack_rsp->header.param2 = m_libspdm_chunk_send_chunk_handle;
322 :
323 : /* Bad Chunk Seq No */
324 1 : chunk_send_ack_rsp->chunk_seq_no = m_libspdm_chunk_send_chunk_seq_no - 1;
325 :
326 1 : chunk_rsp_size = sizeof(spdm_chunk_send_ack_response_t);
327 1 : libspdm_transport_test_encode_message(
328 : spdm_context, NULL, false, false,
329 : chunk_rsp_size, chunk_send_ack_rsp,
330 : response_size, response);
331 :
332 1 : return LIBSPDM_STATUS_SUCCESS;
333 : }
334 4 : if (spdm_test_context->case_id == 12) {
335 : /* ErrorCode == LargeResponse shall not be allowed in ResponseToLargeRequest */
336 : chunk_send_ack_rsp
337 1 : = (void*) ((uint8_t*) *response + sizeof(libspdm_test_message_header_t));
338 :
339 1 : chunk_send_ack_rsp->header.spdm_version = SPDM_MESSAGE_VERSION_12;
340 1 : chunk_send_ack_rsp->header.request_response_code = SPDM_CHUNK_SEND_ACK;
341 : chunk_send_ack_rsp->header.param1
342 1 : = SPDM_CHUNK_SEND_ACK_RESPONSE_ATTRIBUTE_EARLY_ERROR_DETECTED;
343 1 : chunk_send_ack_rsp->header.param2 = m_libspdm_chunk_send_chunk_handle;
344 1 : chunk_send_ack_rsp->chunk_seq_no = m_libspdm_chunk_send_chunk_seq_no;
345 :
346 1 : error_response = (void*) (chunk_send_ack_rsp + 1);
347 1 : error_response->header.spdm_version = SPDM_MESSAGE_VERSION_12;
348 1 : error_response->header.request_response_code = SPDM_ERROR;
349 :
350 : /* ErrorCode == LargeResponse in ResponseToLargeRequest */
351 1 : error_response->header.param1 = SPDM_ERROR_CODE_LARGE_RESPONSE;
352 1 : error_response->header.param2 = 0;
353 1 : *((uint8_t*) (error_response + 1)) = 0;
354 :
355 1 : chunk_rsp_size = sizeof(spdm_chunk_send_ack_response_t) + sizeof(spdm_error_response_t) +
356 : sizeof(uint8_t);
357 1 : libspdm_transport_test_encode_message(
358 : spdm_context, NULL, false, false,
359 : chunk_rsp_size, chunk_send_ack_rsp,
360 : response_size, response);
361 :
362 1 : return LIBSPDM_STATUS_SUCCESS;
363 : }
364 3 : if (spdm_test_context->case_id == 13) {
365 : /* Should never reach here since the test case is meant to fail before send */
366 0 : LIBSPDM_ASSERT(0);
367 : }
368 3 : if (spdm_test_context->case_id == 14) {
369 : /* Response an arror response with RequestResynch */
370 1 : error_response = (void*) ((uint8_t*) *response + sizeof(libspdm_test_message_header_t));
371 1 : error_response->header.spdm_version = SPDM_MESSAGE_VERSION_10;
372 1 : error_response->header.request_response_code = SPDM_ERROR;
373 1 : error_response->header.param1 = SPDM_ERROR_CODE_REQUEST_RESYNCH;
374 1 : error_response->header.param2 = 0;
375 :
376 1 : libspdm_transport_test_encode_message(
377 : spdm_context, NULL, false, false,
378 : sizeof(spdm_error_response_t), error_response,
379 : response_size, response);
380 :
381 1 : return LIBSPDM_STATUS_SUCCESS;
382 : }
383 2 : if (spdm_test_context->case_id == 15) {
384 : /* Successful chunk send of algorithms request with SPDM 1.4*/
385 : chunk_send_ack_rsp_14
386 2 : = (void*) ((uint8_t*) *response + sizeof(libspdm_test_message_header_t));
387 :
388 2 : chunk_send_ack_rsp_14->header.spdm_version = SPDM_MESSAGE_VERSION_14;
389 2 : chunk_send_ack_rsp_14->header.request_response_code = SPDM_CHUNK_SEND_ACK;
390 2 : chunk_send_ack_rsp_14->header.param1 = 0;
391 2 : chunk_send_ack_rsp_14->header.param2 = m_libspdm_chunk_send_chunk_handle;
392 2 : chunk_send_ack_rsp_14->chunk_seq_no = m_libspdm_chunk_send_chunk_seq_no_14;
393 :
394 2 : if (m_libspdm_chunk_send_last_chunk) {
395 :
396 1 : chunk_copy_to = (uint8_t*) (chunk_send_ack_rsp_14 + 1);
397 1 : chunk_size = *response_size - (chunk_copy_to - (uint8_t*) *response);
398 :
399 1 : libspdm_requester_chunk_send_test_case15_build_algorithms_response(
400 : spdm_context, chunk_copy_to, &chunk_size);
401 1 : chunk_rsp_size = sizeof(spdm_chunk_send_ack_response_14_t) + chunk_size;
402 :
403 1 : libspdm_transport_test_encode_message(
404 : spdm_context, NULL, false, false,
405 : chunk_rsp_size, chunk_send_ack_rsp_14,
406 : response_size, response);
407 : } else {
408 1 : chunk_rsp_size = sizeof(spdm_chunk_send_ack_response_14_t);
409 1 : libspdm_transport_test_encode_message(
410 : spdm_context, NULL, false, false,
411 : chunk_rsp_size, chunk_send_ack_rsp_14,
412 : response_size, response);
413 : }
414 2 : return LIBSPDM_STATUS_SUCCESS;
415 : }
416 0 : return LIBSPDM_STATUS_RECEIVE_FAIL;
417 : }
418 :
419 14 : libspdm_return_t libspdm_test_requester_chunk_send_generic_test_case(
420 : void** state, uint32_t case_id)
421 : {
422 : /* Copied from Neg. Algorithms test case 2 */
423 : libspdm_return_t status;
424 : libspdm_test_context_t* spdm_test_context;
425 : libspdm_context_t* spdm_context;
426 :
427 14 : spdm_test_context = *state;
428 14 : spdm_context = spdm_test_context->spdm_context;
429 14 : spdm_test_context->case_id = case_id;
430 14 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
431 : SPDM_VERSION_NUMBER_SHIFT_BIT;
432 14 : if (case_id == 15) {
433 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_14 <<
434 : SPDM_VERSION_NUMBER_SHIFT_BIT;
435 : }
436 14 : spdm_context->connection_info.capability.max_spdm_msg_size = LIBSPDM_MAX_SPDM_MSG_SIZE;
437 14 : spdm_context->connection_info.connection_state =
438 : LIBSPDM_CONNECTION_STATE_AFTER_CAPABILITIES;
439 14 : spdm_context->connection_info.capability.flags |=
440 : (SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP
441 : | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP);
442 14 : if (case_id != 10) {
443 : spdm_context->connection_info.capability.data_transfer_size
444 13 : = CHUNK_SEND_REQUESTER_UNIT_TEST_DATA_TRANSFER_SIZE;
445 : spdm_context->local_context.capability.sender_data_transfer_size
446 13 : = LIBSPDM_DATA_TRANSFER_SIZE;
447 : } else {
448 : spdm_context->connection_info.capability.data_transfer_size
449 1 : = LIBSPDM_DATA_TRANSFER_SIZE;
450 : spdm_context->local_context.capability.sender_data_transfer_size
451 1 : = CHUNK_SEND_REQUESTER_UNIT_TEST_DATA_TRANSFER_SIZE;
452 : }
453 :
454 14 : if (case_id == 11) {
455 1 : spdm_context->connection_info.capability.max_spdm_msg_size = 42;
456 : }
457 :
458 14 : spdm_context->local_context.capability.flags |=
459 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP;
460 14 : spdm_context->connection_info.capability.flags |= SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP;
461 14 : spdm_context->local_context.algorithm.measurement_spec = SPDM_MEASUREMENT_SPECIFICATION_DMTF;
462 :
463 14 : spdm_context->local_context.algorithm.measurement_hash_algo =
464 : m_libspdm_use_measurement_hash_algo;
465 14 : spdm_context->local_context.algorithm.base_asym_algo = m_libspdm_use_asym_algo;
466 14 : spdm_context->local_context.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
467 14 : spdm_context->local_context.algorithm.dhe_named_group = m_libspdm_use_dhe_algo;
468 14 : spdm_context->local_context.algorithm.aead_cipher_suite = m_libspdm_use_aead_algo;
469 14 : spdm_context->local_context.algorithm.req_base_asym_alg = m_libspdm_use_req_asym_algo;
470 14 : spdm_context->local_context.algorithm.key_schedule = m_libspdm_use_key_schedule_algo;
471 14 : libspdm_reset_message_a(spdm_context);
472 :
473 14 : status = libspdm_negotiate_algorithms(spdm_context);
474 14 : return status;
475 : }
476 :
477 : #if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
478 1 : libspdm_return_t libspdm_test_requester_chunk_send_vendor_specific_test_case(
479 : void** state, uint32_t case_id)
480 : {
481 : /* Use vendor specific request to generate a large request. */
482 : libspdm_return_t status;
483 : libspdm_test_context_t* spdm_test_context;
484 : libspdm_context_t* spdm_context;
485 :
486 1 : uint16_t standard_id = 6;
487 1 : uint8_t vendor_id_len = 2;
488 1 : uint8_t vendor_id[SPDM_MAX_VENDOR_ID_LENGTH] = {0xAA, 0xAA};
489 1 : uint32_t data_len = 65535;
490 1 : uint8_t data[65535] = {0};
491 :
492 1 : spdm_test_context = *state;
493 1 : spdm_context = spdm_test_context->spdm_context;
494 1 : spdm_test_context->case_id = case_id;
495 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
496 : SPDM_VERSION_NUMBER_SHIFT_BIT;
497 : /* Large request need a large scratch buffer. */
498 1 : spdm_context->connection_info.capability.max_spdm_msg_size = 0x12000;
499 1 : spdm_context->local_context.capability.max_spdm_msg_size = 0x12000;
500 1 : spdm_context->connection_info.connection_state =
501 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
502 1 : spdm_context->connection_info.capability.flags |=
503 : (SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP
504 : | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP);
505 : spdm_context->connection_info.capability.data_transfer_size
506 1 : = sizeof(spdm_chunk_send_request_t) + 1;
507 : spdm_context->local_context.capability.sender_data_transfer_size
508 1 : = CHUNK_SEND_REQUESTER_UNIT_TEST_DATA_TRANSFER_SIZE;
509 1 : spdm_context->local_context.is_requester = true;
510 :
511 1 : spdm_test_context->scratch_buffer_size =
512 1 : libspdm_get_sizeof_required_scratch_buffer(spdm_context);
513 1 : spdm_test_context->scratch_buffer = (void *)malloc(spdm_test_context->scratch_buffer_size);
514 1 : libspdm_set_scratch_buffer (spdm_context,
515 : spdm_test_context->scratch_buffer,
516 : spdm_test_context->scratch_buffer_size);
517 :
518 1 : libspdm_reset_message_a(spdm_context);
519 :
520 1 : status = libspdm_vendor_send_request_receive_response(spdm_context, NULL,
521 : standard_id, vendor_id_len, vendor_id,
522 : data_len, data,
523 : &standard_id, &vendor_id_len, vendor_id,
524 : &data_len, data);
525 1 : return status;
526 : }
527 : #endif /* LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES */
528 :
529 1 : static void req_chunk_send_case1(void** state)
530 : {
531 : libspdm_return_t status;
532 :
533 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 1);
534 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
535 1 : }
536 :
537 1 : static void req_chunk_send_case2(void** state)
538 : {
539 : libspdm_return_t status;
540 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 2);
541 1 : assert_int_equal(status, LIBSPDM_STATUS_SEND_FAIL);
542 1 : }
543 :
544 1 : static void req_chunk_send_case3(void** state)
545 : {
546 : libspdm_return_t status;
547 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 3);
548 1 : assert_int_equal(status, LIBSPDM_STATUS_RECEIVE_FAIL);
549 1 : }
550 :
551 1 : static void req_chunk_send_case4(void** state)
552 : {
553 : libspdm_return_t status;
554 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 4);
555 1 : assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
556 1 : }
557 :
558 1 : static void req_chunk_send_case5(void** state)
559 : {
560 : libspdm_return_t status;
561 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 5);
562 1 : assert_int_equal(status, LIBSPDM_STATUS_ERROR_PEER);
563 1 : }
564 :
565 1 : static void req_chunk_send_case6(void** state)
566 : {
567 : libspdm_return_t status;
568 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 6);
569 1 : assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_SIZE);
570 1 : }
571 :
572 1 : static void req_chunk_send_case7(void** state)
573 : {
574 : libspdm_return_t status;
575 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 7);
576 1 : assert_int_equal(status, LIBSPDM_STATUS_ERROR_PEER);
577 1 : }
578 :
579 1 : static void req_chunk_send_case8(void** state)
580 : {
581 : libspdm_return_t status;
582 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 8);
583 1 : assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
584 1 : }
585 :
586 1 : static void req_chunk_send_case9(void** state)
587 : {
588 : libspdm_return_t status;
589 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 9);
590 1 : assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
591 1 : }
592 :
593 1 : static void req_chunk_send_case10(void** state)
594 : {
595 : libspdm_return_t status;
596 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 10);
597 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
598 1 : }
599 :
600 1 : static void req_chunk_send_case11(void** state)
601 : {
602 : libspdm_return_t status;
603 :
604 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 11);
605 1 : assert_int_equal(status, LIBSPDM_STATUS_PEER_BUFFER_TOO_SMALL);
606 1 : }
607 :
608 : /**
609 : * Test 12: ErrorCode == LargeResponse shall not be allowed in ResponseToLargeRequest.
610 : * Expected behavior: returns a status of LIBSPDM_STATUS_ERROR_PEER,
611 : * Received an unexpected error message.
612 : **/
613 1 : static void req_chunk_send_case12(void** state)
614 : {
615 : libspdm_return_t status;
616 :
617 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 12);
618 1 : assert_int_equal(status, LIBSPDM_STATUS_ERROR_PEER);
619 1 : }
620 :
621 : #if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
622 : /**
623 : * Test 13: Request size shall not exceed max supported transfer size.
624 : * Expected behavior: returns a status of LIBSPDM_STATUS_SEND_FAIL,
625 : **/
626 1 : static void req_chunk_send_case13(void** state)
627 : {
628 : libspdm_return_t status;
629 :
630 1 : status = libspdm_test_requester_chunk_send_vendor_specific_test_case(state, 13);
631 1 : assert_int_equal(status, LIBSPDM_STATUS_SEND_FAIL);
632 1 : }
633 : #endif /* LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES */
634 :
635 : /**
636 : * Test 14: the requester is sending CHUNK_SEND, but receives an
637 : * ERROR message indicating the RequestResynch status of the responder
638 : * Expected behavior: client returns a Status of RETURN_DEVICE_ERROR, and the
639 : * communication is reset to expect a new GET_VERSION message.
640 : **/
641 1 : static void req_chunk_send_case14(void** state)
642 : {
643 : libspdm_return_t status;
644 : libspdm_test_context_t* spdm_test_context;
645 : libspdm_context_t* spdm_context;
646 :
647 1 : spdm_test_context = *state;
648 1 : spdm_context = spdm_test_context->spdm_context;
649 :
650 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 14);
651 1 : assert_int_equal(status, LIBSPDM_STATUS_RESYNCH_PEER);
652 1 : assert_int_equal(spdm_context->connection_info.connection_state,
653 : LIBSPDM_CONNECTION_STATE_NOT_STARTED);
654 1 : }
655 :
656 1 : static void req_chunk_send_case15(void** state)
657 : {
658 : libspdm_return_t status;
659 :
660 1 : status = libspdm_test_requester_chunk_send_generic_test_case(state, 15);
661 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
662 1 : }
663 :
664 1 : int libspdm_req_chunk_send_test(void)
665 : {
666 : /* Test the CHUNK_SEND handlers in various requester handlers */
667 1 : const struct CMUnitTest test_cases[] = {
668 : /* Request Algorithms successfully sent in chunks. */
669 : cmocka_unit_test(req_chunk_send_case1),
670 : /* Chunk Request fail send */
671 : cmocka_unit_test(req_chunk_send_case2),
672 : /* Chunk Response fail receive */
673 : cmocka_unit_test(req_chunk_send_case3),
674 : /* Chunk Response has bad SPDM version */
675 : cmocka_unit_test(req_chunk_send_case4),
676 : /* Chunk Response has bad request response code */
677 : cmocka_unit_test(req_chunk_send_case5),
678 : /* Chunk Response has bad response size */
679 : cmocka_unit_test(req_chunk_send_case6),
680 : /* Chunk Response has early error detected */
681 : cmocka_unit_test(req_chunk_send_case7),
682 : /* Chunk Response has bad chunk handle */
683 : cmocka_unit_test(req_chunk_send_case8),
684 : /* Chunk Response has bad chunk seq no */
685 : cmocka_unit_test(req_chunk_send_case9),
686 : /* sent in chunks due to greater than the sending transmit buffer size. */
687 : cmocka_unit_test(req_chunk_send_case10),
688 : /* requester message size greater than the responder max_spdm_msg_size, return LIBSPDM_STATUS_PEER_BUFFER_TOO_SMALL */
689 : cmocka_unit_test(req_chunk_send_case11),
690 : /* ErrorCode == LargeResponse shall not be allowed in ResponseToLargeRequest */
691 : cmocka_unit_test(req_chunk_send_case12),
692 : #if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
693 : /* Request size exceed max chunks */
694 : cmocka_unit_test(req_chunk_send_case13),
695 : #endif
696 : /* Recieved and error message indicating RequestResynch */
697 : cmocka_unit_test(req_chunk_send_case14),
698 : /* Request Algorithms successfully sent in chunks, with SPDM 1.4 */
699 : cmocka_unit_test(req_chunk_send_case15),
700 : };
701 :
702 1 : libspdm_test_context_t test_context = {
703 : LIBSPDM_TEST_CONTEXT_VERSION,
704 : true,
705 : send_message,
706 : receive_message,
707 : };
708 :
709 1 : libspdm_setup_test_context(&test_context);
710 :
711 1 : return cmocka_run_group_tests(test_cases,
712 : libspdm_unit_test_group_setup,
713 : libspdm_unit_test_group_teardown);
714 : }
715 :
716 : #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP*/
|