Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 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_EVENT_CAP
12 :
13 : static uint32_t m_session_id = 0xffffffff;
14 :
15 : static struct m_test_params {
16 : uint32_t event_count;
17 : size_t events_list_size;
18 : uint8_t events_list[0x1000];
19 : } m_test_params;
20 :
21 6 : static libspdm_return_t send_message(
22 : void *spdm_context, size_t request_size, const void *request, uint64_t timeout)
23 : {
24 6 : libspdm_test_context_t *spdm_test_context = libspdm_get_test_context();
25 :
26 6 : switch (spdm_test_context->case_id) {
27 5 : case 0x4:
28 : case 0x6:
29 : case 0x7:
30 : case 0x8:
31 : case 0x9:
32 5 : return LIBSPDM_STATUS_SUCCESS;
33 1 : case 0x5:
34 1 : return LIBSPDM_STATUS_SEND_FAIL;
35 0 : default:
36 0 : assert_true(false);
37 0 : return LIBSPDM_STATUS_SEND_FAIL;
38 : }
39 : }
40 :
41 4 : static libspdm_return_t receive_message(
42 : void *spdm_context, size_t *response_size, void **response, uint64_t timeout)
43 : {
44 4 : libspdm_test_context_t *spdm_test_context = libspdm_get_test_context();
45 : spdm_event_ack_response_t *spdm_response;
46 : size_t spdm_response_size;
47 : size_t transport_header_size;
48 : uint32_t session_id;
49 : libspdm_session_info_t *session_info;
50 : uint8_t *scratch_buffer;
51 : size_t scratch_buffer_size;
52 :
53 4 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
54 4 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
55 :
56 4 : session_id = m_session_id;
57 4 : session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
58 4 : LIBSPDM_ASSERT((session_info != NULL));
59 :
60 4 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
61 4 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
62 :
63 4 : spdm_response_size = sizeof(spdm_event_ack_response_t);
64 4 : libspdm_zero_mem(spdm_response, spdm_response_size);
65 :
66 4 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13;
67 4 : spdm_response->header.request_response_code = SPDM_EVENT_ACK;
68 4 : spdm_response->header.param1 = 0;
69 4 : spdm_response->header.param2 = 0;
70 :
71 4 : switch (spdm_test_context->case_id) {
72 1 : case 0x7:
73 : /* Invalid response message size. */
74 1 : spdm_response_size++;
75 1 : break;
76 1 : case 0x8:
77 : /* Invalid RequestResponseCode to SEND_EVENT request. */
78 1 : spdm_response->header.request_response_code = SPDM_KEY_UPDATE_ACK;
79 1 : break;
80 1 : case 0x9:
81 : /* Invalid SPDMVersion field value. */
82 1 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_14;
83 1 : break;
84 1 : default:
85 1 : break;
86 : }
87 :
88 : /* For secure message, message is in sender buffer, we need copy it to scratch buffer.
89 : * transport_message is always in sender buffer. */
90 4 : libspdm_get_scratch_buffer(spdm_context, (void **)&scratch_buffer, &scratch_buffer_size);
91 4 : libspdm_copy_mem(scratch_buffer + transport_header_size,
92 : scratch_buffer_size - transport_header_size,
93 : spdm_response, spdm_response_size);
94 :
95 4 : spdm_response = (void *)(scratch_buffer + transport_header_size);
96 :
97 4 : libspdm_transport_test_encode_message(spdm_context, &session_id,
98 : false, false, spdm_response_size,
99 : spdm_response, response_size, response);
100 :
101 : /* Workaround: Use single context to encode message and then decode message. */
102 4 : ((libspdm_secured_message_context_t *)(session_info->secured_message_context))->
103 4 : application_secret.response_data_sequence_number--;
104 :
105 4 : switch (spdm_test_context->case_id) {
106 1 : case 0x6:
107 1 : return LIBSPDM_STATUS_RECEIVE_FAIL;
108 3 : case 0x7:
109 : case 0x8:
110 : case 0x9:
111 3 : return LIBSPDM_STATUS_SUCCESS;
112 0 : default:
113 0 : assert_true(false);
114 0 : return LIBSPDM_STATUS_RECEIVE_FAIL;
115 : }
116 : }
117 :
118 9 : static void set_standard_state(libspdm_context_t *spdm_context)
119 : {
120 : libspdm_session_info_t *session_info;
121 :
122 9 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
123 : SPDM_VERSION_NUMBER_SHIFT_BIT;
124 9 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
125 :
126 9 : spdm_context->connection_info.capability.flags |=
127 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP;
128 9 : spdm_context->connection_info.capability.flags |=
129 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP;
130 9 : spdm_context->connection_info.capability.flags |=
131 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP;
132 9 : spdm_context->connection_info.capability.flags |=
133 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCAP_CAP;
134 :
135 9 : spdm_context->local_context.capability.flags |=
136 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP;
137 9 : spdm_context->local_context.capability.flags |=
138 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP;
139 9 : spdm_context->local_context.capability.flags |=
140 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP;
141 9 : spdm_context->local_context.capability.flags |=
142 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCAP_CAP;
143 9 : spdm_context->local_context.capability.flags |=
144 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EVENT_CAP;
145 :
146 9 : spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
147 9 : spdm_context->connection_info.algorithm.base_asym_algo = m_libspdm_use_asym_algo;
148 9 : spdm_context->connection_info.algorithm.dhe_named_group = m_libspdm_use_dhe_algo;
149 9 : spdm_context->connection_info.algorithm.aead_cipher_suite = m_libspdm_use_aead_algo;
150 :
151 9 : spdm_context->latest_session_id = m_session_id;
152 9 : spdm_context->last_spdm_request_session_id_valid = true;
153 9 : spdm_context->last_spdm_request_session_id = m_session_id;
154 9 : session_info = &spdm_context->session_info[0];
155 9 : libspdm_session_info_init(spdm_context, session_info, m_session_id,
156 : SECURED_SPDM_VERSION_11 << SPDM_VERSION_NUMBER_SHIFT_BIT, true);
157 9 : libspdm_secured_message_set_session_state(
158 : session_info->secured_message_context,
159 : LIBSPDM_SESSION_STATE_ESTABLISHED);
160 9 : }
161 :
162 : /**
163 : * Test 1: Requester has not set EVENT_CAP.
164 : * Expected behavior: returns with LIBSPDM_STATUS_UNSUPPORTED_CAP.
165 : **/
166 1 : static void req_send_event_err_case1(void **state)
167 : {
168 : libspdm_test_context_t *spdm_test_context;
169 : libspdm_context_t *spdm_context;
170 : libspdm_return_t status;
171 :
172 1 : spdm_test_context = *state;
173 1 : spdm_context = spdm_test_context->spdm_context;
174 1 : spdm_test_context->case_id = 0x1;
175 :
176 1 : set_standard_state(spdm_context);
177 :
178 : /* Clear EVENT_CAP. */
179 1 : spdm_context->local_context.capability.flags &=
180 : ~SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EVENT_CAP;
181 :
182 1 : m_test_params.event_count = 3;
183 1 : m_test_params.events_list_size = 100;
184 :
185 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
186 100 : m_test_params.events_list[index] = (uint8_t)index;
187 : }
188 :
189 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
190 : m_test_params.events_list_size, m_test_params.events_list);
191 :
192 1 : assert_int_equal(status, LIBSPDM_STATUS_UNSUPPORTED_CAP);
193 1 : }
194 :
195 : /**
196 : * Test 2: Connection version does not support SEND_EVENT.
197 : * Expected behavior: returns with LIBSPDM_STATUS_UNSUPPORTED_CAP.
198 : **/
199 1 : static void req_send_event_err_case2(void **state)
200 : {
201 : libspdm_test_context_t *spdm_test_context;
202 : libspdm_context_t *spdm_context;
203 : libspdm_return_t status;
204 :
205 1 : spdm_test_context = *state;
206 1 : spdm_context = spdm_test_context->spdm_context;
207 1 : spdm_test_context->case_id = 0x2;
208 :
209 1 : set_standard_state(spdm_context);
210 :
211 : /* Set version to 1.2, which does not support SEND_EVENT. */
212 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
213 : SPDM_VERSION_NUMBER_SHIFT_BIT;
214 :
215 1 : m_test_params.event_count = 3;
216 1 : m_test_params.events_list_size = 100;
217 :
218 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
219 100 : m_test_params.events_list[index] = (uint8_t)index;
220 : }
221 :
222 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
223 : m_test_params.events_list_size, m_test_params.events_list);
224 :
225 1 : assert_int_equal(status, LIBSPDM_STATUS_UNSUPPORTED_CAP);
226 1 : }
227 :
228 : /**
229 : * Test 3: Unable to acquire send buffer.
230 : * Expected behavior: returns with LIBSPDM_STATUS_ACQUIRE_FAIL.
231 : **/
232 1 : static void req_send_event_err_case3(void **state)
233 : {
234 : libspdm_test_context_t *spdm_test_context;
235 : libspdm_context_t *spdm_context;
236 : libspdm_return_t status;
237 :
238 1 : spdm_test_context = *state;
239 1 : spdm_context = spdm_test_context->spdm_context;
240 1 : spdm_test_context->case_id = 0x3;
241 :
242 1 : set_standard_state(spdm_context);
243 :
244 1 : m_test_params.event_count = 3;
245 1 : m_test_params.events_list_size = 100;
246 :
247 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
248 100 : m_test_params.events_list[index] = (uint8_t)index;
249 : }
250 :
251 : /* Induce error when acquiring send buffer. */
252 1 : libspdm_force_error(LIBSPDM_ERR_ACQUIRE_SENDER_BUFFER);
253 :
254 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
255 : m_test_params.events_list_size, m_test_params.events_list);
256 :
257 1 : libspdm_release_error(LIBSPDM_ERR_ACQUIRE_SENDER_BUFFER);
258 :
259 1 : assert_int_equal(status, LIBSPDM_STATUS_ACQUIRE_FAIL);
260 1 : }
261 :
262 : /**
263 : * Test 4: Unable to acquire receive buffer.
264 : * Expected behavior: returns with LIBSPDM_STATUS_ACQUIRE_FAIL.
265 : **/
266 1 : static void req_send_event_err_case4(void **state)
267 : {
268 : libspdm_test_context_t *spdm_test_context;
269 : libspdm_context_t *spdm_context;
270 : libspdm_return_t status;
271 :
272 1 : spdm_test_context = *state;
273 1 : spdm_context = spdm_test_context->spdm_context;
274 1 : spdm_test_context->case_id = 0x4;
275 :
276 1 : set_standard_state(spdm_context);
277 :
278 1 : m_test_params.event_count = 3;
279 1 : m_test_params.events_list_size = 100;
280 :
281 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
282 100 : m_test_params.events_list[index] = (uint8_t)index;
283 : }
284 :
285 : /* Induce error when acquiring receive buffer. */
286 1 : libspdm_force_error(LIBSPDM_ERR_ACQUIRE_RECEIVER_BUFFER);
287 :
288 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
289 : m_test_params.events_list_size, m_test_params.events_list);
290 :
291 1 : libspdm_release_error(LIBSPDM_ERR_ACQUIRE_RECEIVER_BUFFER);
292 :
293 1 : assert_int_equal(status, LIBSPDM_STATUS_ACQUIRE_FAIL);
294 1 : }
295 :
296 : /**
297 : * Test 5: Unable to send message.
298 : * Expected behavior: returns with LIBSPDM_STATUS_SEND_FAIL.
299 : **/
300 1 : static void req_send_event_err_case5(void **state)
301 : {
302 : libspdm_test_context_t *spdm_test_context;
303 : libspdm_context_t *spdm_context;
304 : libspdm_return_t status;
305 :
306 1 : spdm_test_context = *state;
307 1 : spdm_context = spdm_test_context->spdm_context;
308 1 : spdm_test_context->case_id = 0x5;
309 :
310 1 : set_standard_state(spdm_context);
311 :
312 1 : m_test_params.event_count = 3;
313 1 : m_test_params.events_list_size = 100;
314 :
315 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
316 100 : m_test_params.events_list[index] = (uint8_t)index;
317 : }
318 :
319 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
320 : m_test_params.events_list_size, m_test_params.events_list);
321 :
322 1 : assert_int_equal(status, LIBSPDM_STATUS_SEND_FAIL);
323 1 : }
324 :
325 : /**
326 : * Test 6: Unable to receive message.
327 : * Expected behavior: returns with LIBSPDM_STATUS_RECEIVE_FAIL.
328 : **/
329 1 : static void req_send_event_err_case6(void **state)
330 : {
331 : libspdm_test_context_t *spdm_test_context;
332 : libspdm_context_t *spdm_context;
333 : libspdm_return_t status;
334 :
335 1 : spdm_test_context = *state;
336 1 : spdm_context = spdm_test_context->spdm_context;
337 1 : spdm_test_context->case_id = 0x6;
338 :
339 1 : set_standard_state(spdm_context);
340 :
341 1 : m_test_params.event_count = 3;
342 1 : m_test_params.events_list_size = 100;
343 :
344 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
345 100 : m_test_params.events_list[index] = (uint8_t)index;
346 : }
347 :
348 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
349 : m_test_params.events_list_size, m_test_params.events_list);
350 :
351 1 : assert_int_equal(status, LIBSPDM_STATUS_RECEIVE_FAIL);
352 1 : }
353 :
354 : /**
355 : * Test 7: Invalid size of EVENT_ACK response.
356 : * Expected behavior: returns with LIBSPDM_STATUS_INVALID_MSG_SIZE.
357 : **/
358 1 : static void req_send_event_err_case7(void **state)
359 : {
360 : libspdm_test_context_t *spdm_test_context;
361 : libspdm_context_t *spdm_context;
362 : libspdm_return_t status;
363 :
364 1 : spdm_test_context = *state;
365 1 : spdm_context = spdm_test_context->spdm_context;
366 1 : spdm_test_context->case_id = 0x7;
367 :
368 1 : set_standard_state(spdm_context);
369 :
370 1 : m_test_params.event_count = 3;
371 1 : m_test_params.events_list_size = 100;
372 :
373 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
374 100 : m_test_params.events_list[index] = (uint8_t)index;
375 : }
376 :
377 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
378 : m_test_params.events_list_size, m_test_params.events_list);
379 :
380 1 : assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_SIZE);
381 1 : }
382 :
383 : /**
384 : * Test 8: Invalid RequestResponseCode in response.
385 : * Expected behavior: returns with LIBSPDM_STATUS_INVALID_MSG_FIELD.
386 : **/
387 1 : static void req_send_event_err_case8(void **state)
388 : {
389 : libspdm_test_context_t *spdm_test_context;
390 : libspdm_context_t *spdm_context;
391 : libspdm_return_t status;
392 :
393 1 : spdm_test_context = *state;
394 1 : spdm_context = spdm_test_context->spdm_context;
395 1 : spdm_test_context->case_id = 0x8;
396 :
397 1 : set_standard_state(spdm_context);
398 :
399 1 : m_test_params.event_count = 3;
400 1 : m_test_params.events_list_size = 100;
401 :
402 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
403 100 : m_test_params.events_list[index] = (uint8_t)index;
404 : }
405 :
406 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
407 : m_test_params.events_list_size, m_test_params.events_list);
408 :
409 1 : assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
410 1 : }
411 :
412 : /**
413 : * Test 9: Invalid SPDMVersion in response.
414 : * Expected behavior: returns with LIBSPDM_STATUS_INVALID_MSG_FIELD.
415 : **/
416 1 : static void req_send_event_err_case9(void **state)
417 : {
418 : libspdm_test_context_t *spdm_test_context;
419 : libspdm_context_t *spdm_context;
420 : libspdm_return_t status;
421 :
422 1 : spdm_test_context = *state;
423 1 : spdm_context = spdm_test_context->spdm_context;
424 1 : spdm_test_context->case_id = 0x9;
425 :
426 1 : set_standard_state(spdm_context);
427 :
428 1 : m_test_params.event_count = 3;
429 1 : m_test_params.events_list_size = 100;
430 :
431 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
432 100 : m_test_params.events_list[index] = (uint8_t)index;
433 : }
434 :
435 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
436 : m_test_params.events_list_size, m_test_params.events_list);
437 :
438 1 : assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
439 1 : }
440 :
441 1 : int libspdm_req_send_event_error_test(void)
442 : {
443 1 : const struct CMUnitTest test_cases[] = {
444 : cmocka_unit_test(req_send_event_err_case1),
445 : cmocka_unit_test(req_send_event_err_case2),
446 : cmocka_unit_test(req_send_event_err_case3),
447 : cmocka_unit_test(req_send_event_err_case4),
448 : cmocka_unit_test(req_send_event_err_case5),
449 : cmocka_unit_test(req_send_event_err_case6),
450 : cmocka_unit_test(req_send_event_err_case7),
451 : cmocka_unit_test(req_send_event_err_case8),
452 : cmocka_unit_test(req_send_event_err_case9),
453 : };
454 :
455 1 : libspdm_test_context_t test_context = {
456 : LIBSPDM_TEST_CONTEXT_VERSION,
457 : true,
458 : send_message,
459 : receive_message,
460 : };
461 :
462 1 : libspdm_setup_test_context(&test_context);
463 :
464 1 : return cmocka_run_group_tests(test_cases,
465 : libspdm_unit_test_group_setup,
466 : libspdm_unit_test_group_teardown);
467 : }
468 :
469 : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
|