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