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