Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2025-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_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 |= SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP;
129 9 : spdm_context->connection_info.capability.flags |=
130 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP;
131 9 : spdm_context->connection_info.capability.flags |=
132 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCAP_CAP;
133 :
134 9 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP;
135 9 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP;
136 9 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP;
137 9 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCAP_CAP;
138 9 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EVENT_CAP;
139 :
140 9 : spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
141 9 : spdm_context->connection_info.algorithm.base_asym_algo = m_libspdm_use_asym_algo;
142 9 : spdm_context->connection_info.algorithm.dhe_named_group = m_libspdm_use_dhe_algo;
143 9 : spdm_context->connection_info.algorithm.aead_cipher_suite = m_libspdm_use_aead_algo;
144 :
145 9 : spdm_context->latest_session_id = m_session_id;
146 9 : spdm_context->last_spdm_request_session_id_valid = true;
147 9 : spdm_context->last_spdm_request_session_id = m_session_id;
148 9 : session_info = &spdm_context->session_info[0];
149 9 : libspdm_session_info_init(spdm_context, session_info, m_session_id,
150 : SECURED_SPDM_VERSION_11 << SPDM_VERSION_NUMBER_SHIFT_BIT, true);
151 9 : libspdm_secured_message_set_session_state(
152 : session_info->secured_message_context,
153 : LIBSPDM_SESSION_STATE_ESTABLISHED);
154 9 : }
155 :
156 : /**
157 : * Test 1: Requester has not set EVENT_CAP.
158 : * Expected behavior: returns with LIBSPDM_STATUS_UNSUPPORTED_CAP.
159 : **/
160 1 : static void req_send_event_err_case1(void **state)
161 : {
162 : libspdm_test_context_t *spdm_test_context;
163 : libspdm_context_t *spdm_context;
164 : libspdm_return_t status;
165 :
166 1 : spdm_test_context = *state;
167 1 : spdm_context = spdm_test_context->spdm_context;
168 1 : spdm_test_context->case_id = 0x1;
169 :
170 1 : set_standard_state(spdm_context);
171 :
172 : /* Clear EVENT_CAP. */
173 1 : spdm_context->local_context.capability.flags &= ~SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EVENT_CAP;
174 :
175 1 : m_test_params.event_count = 3;
176 1 : m_test_params.events_list_size = 100;
177 :
178 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
179 100 : m_test_params.events_list[index] = (uint8_t)index;
180 : }
181 :
182 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
183 : m_test_params.events_list_size, m_test_params.events_list);
184 :
185 1 : assert_int_equal(status, LIBSPDM_STATUS_UNSUPPORTED_CAP);
186 1 : }
187 :
188 : /**
189 : * Test 2: Connection version does not support SEND_EVENT.
190 : * Expected behavior: returns with LIBSPDM_STATUS_UNSUPPORTED_CAP.
191 : **/
192 1 : static void req_send_event_err_case2(void **state)
193 : {
194 : libspdm_test_context_t *spdm_test_context;
195 : libspdm_context_t *spdm_context;
196 : libspdm_return_t status;
197 :
198 1 : spdm_test_context = *state;
199 1 : spdm_context = spdm_test_context->spdm_context;
200 1 : spdm_test_context->case_id = 0x2;
201 :
202 1 : set_standard_state(spdm_context);
203 :
204 : /* Set version to 1.2, which does not support SEND_EVENT. */
205 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 <<
206 : SPDM_VERSION_NUMBER_SHIFT_BIT;
207 :
208 1 : m_test_params.event_count = 3;
209 1 : m_test_params.events_list_size = 100;
210 :
211 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
212 100 : m_test_params.events_list[index] = (uint8_t)index;
213 : }
214 :
215 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
216 : m_test_params.events_list_size, m_test_params.events_list);
217 :
218 1 : assert_int_equal(status, LIBSPDM_STATUS_UNSUPPORTED_CAP);
219 1 : }
220 :
221 : /**
222 : * Test 3: Unable to acquire send buffer.
223 : * Expected behavior: returns with LIBSPDM_STATUS_ACQUIRE_FAIL.
224 : **/
225 1 : static void req_send_event_err_case3(void **state)
226 : {
227 : libspdm_test_context_t *spdm_test_context;
228 : libspdm_context_t *spdm_context;
229 : libspdm_return_t status;
230 :
231 1 : spdm_test_context = *state;
232 1 : spdm_context = spdm_test_context->spdm_context;
233 1 : spdm_test_context->case_id = 0x3;
234 :
235 1 : set_standard_state(spdm_context);
236 :
237 1 : m_test_params.event_count = 3;
238 1 : m_test_params.events_list_size = 100;
239 :
240 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
241 100 : m_test_params.events_list[index] = (uint8_t)index;
242 : }
243 :
244 : /* Induce error when acquiring send buffer. */
245 1 : libspdm_force_error(LIBSPDM_ERR_ACQUIRE_SENDER_BUFFER);
246 :
247 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
248 : m_test_params.events_list_size, m_test_params.events_list);
249 :
250 1 : libspdm_release_error(LIBSPDM_ERR_ACQUIRE_SENDER_BUFFER);
251 :
252 1 : assert_int_equal(status, LIBSPDM_STATUS_ACQUIRE_FAIL);
253 1 : }
254 :
255 : /**
256 : * Test 4: Unable to acquire receive buffer.
257 : * Expected behavior: returns with LIBSPDM_STATUS_ACQUIRE_FAIL.
258 : **/
259 1 : static void req_send_event_err_case4(void **state)
260 : {
261 : libspdm_test_context_t *spdm_test_context;
262 : libspdm_context_t *spdm_context;
263 : libspdm_return_t status;
264 :
265 1 : spdm_test_context = *state;
266 1 : spdm_context = spdm_test_context->spdm_context;
267 1 : spdm_test_context->case_id = 0x4;
268 :
269 1 : set_standard_state(spdm_context);
270 :
271 1 : m_test_params.event_count = 3;
272 1 : m_test_params.events_list_size = 100;
273 :
274 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
275 100 : m_test_params.events_list[index] = (uint8_t)index;
276 : }
277 :
278 : /* Induce error when acquiring receive buffer. */
279 1 : libspdm_force_error(LIBSPDM_ERR_ACQUIRE_RECEIVER_BUFFER);
280 :
281 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
282 : m_test_params.events_list_size, m_test_params.events_list);
283 :
284 1 : libspdm_release_error(LIBSPDM_ERR_ACQUIRE_RECEIVER_BUFFER);
285 :
286 1 : assert_int_equal(status, LIBSPDM_STATUS_ACQUIRE_FAIL);
287 1 : }
288 :
289 : /**
290 : * Test 5: Unable to send message.
291 : * Expected behavior: returns with LIBSPDM_STATUS_SEND_FAIL.
292 : **/
293 1 : static void req_send_event_err_case5(void **state)
294 : {
295 : libspdm_test_context_t *spdm_test_context;
296 : libspdm_context_t *spdm_context;
297 : libspdm_return_t status;
298 :
299 1 : spdm_test_context = *state;
300 1 : spdm_context = spdm_test_context->spdm_context;
301 1 : spdm_test_context->case_id = 0x5;
302 :
303 1 : set_standard_state(spdm_context);
304 :
305 1 : m_test_params.event_count = 3;
306 1 : m_test_params.events_list_size = 100;
307 :
308 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
309 100 : m_test_params.events_list[index] = (uint8_t)index;
310 : }
311 :
312 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
313 : m_test_params.events_list_size, m_test_params.events_list);
314 :
315 1 : assert_int_equal(status, LIBSPDM_STATUS_SEND_FAIL);
316 1 : }
317 :
318 : /**
319 : * Test 6: Unable to receive message.
320 : * Expected behavior: returns with LIBSPDM_STATUS_RECEIVE_FAIL.
321 : **/
322 1 : static void req_send_event_err_case6(void **state)
323 : {
324 : libspdm_test_context_t *spdm_test_context;
325 : libspdm_context_t *spdm_context;
326 : libspdm_return_t status;
327 :
328 1 : spdm_test_context = *state;
329 1 : spdm_context = spdm_test_context->spdm_context;
330 1 : spdm_test_context->case_id = 0x6;
331 :
332 1 : set_standard_state(spdm_context);
333 :
334 1 : m_test_params.event_count = 3;
335 1 : m_test_params.events_list_size = 100;
336 :
337 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
338 100 : m_test_params.events_list[index] = (uint8_t)index;
339 : }
340 :
341 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
342 : m_test_params.events_list_size, m_test_params.events_list);
343 :
344 1 : assert_int_equal(status, LIBSPDM_STATUS_RECEIVE_FAIL);
345 1 : }
346 :
347 : /**
348 : * Test 7: Invalid size of EVENT_ACK response.
349 : * Expected behavior: returns with LIBSPDM_STATUS_INVALID_MSG_SIZE.
350 : **/
351 1 : static void req_send_event_err_case7(void **state)
352 : {
353 : libspdm_test_context_t *spdm_test_context;
354 : libspdm_context_t *spdm_context;
355 : libspdm_return_t status;
356 :
357 1 : spdm_test_context = *state;
358 1 : spdm_context = spdm_test_context->spdm_context;
359 1 : spdm_test_context->case_id = 0x7;
360 :
361 1 : set_standard_state(spdm_context);
362 :
363 1 : m_test_params.event_count = 3;
364 1 : m_test_params.events_list_size = 100;
365 :
366 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
367 100 : m_test_params.events_list[index] = (uint8_t)index;
368 : }
369 :
370 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
371 : m_test_params.events_list_size, m_test_params.events_list);
372 :
373 1 : assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_SIZE);
374 1 : }
375 :
376 : /**
377 : * Test 8: Invalid RequestResponseCode in response.
378 : * Expected behavior: returns with LIBSPDM_STATUS_INVALID_MSG_FIELD.
379 : **/
380 1 : static void req_send_event_err_case8(void **state)
381 : {
382 : libspdm_test_context_t *spdm_test_context;
383 : libspdm_context_t *spdm_context;
384 : libspdm_return_t status;
385 :
386 1 : spdm_test_context = *state;
387 1 : spdm_context = spdm_test_context->spdm_context;
388 1 : spdm_test_context->case_id = 0x8;
389 :
390 1 : set_standard_state(spdm_context);
391 :
392 1 : m_test_params.event_count = 3;
393 1 : m_test_params.events_list_size = 100;
394 :
395 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
396 100 : m_test_params.events_list[index] = (uint8_t)index;
397 : }
398 :
399 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
400 : m_test_params.events_list_size, m_test_params.events_list);
401 :
402 1 : assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
403 1 : }
404 :
405 : /**
406 : * Test 9: Invalid SPDMVersion in response.
407 : * Expected behavior: returns with LIBSPDM_STATUS_INVALID_MSG_FIELD.
408 : **/
409 1 : static void req_send_event_err_case9(void **state)
410 : {
411 : libspdm_test_context_t *spdm_test_context;
412 : libspdm_context_t *spdm_context;
413 : libspdm_return_t status;
414 :
415 1 : spdm_test_context = *state;
416 1 : spdm_context = spdm_test_context->spdm_context;
417 1 : spdm_test_context->case_id = 0x9;
418 :
419 1 : set_standard_state(spdm_context);
420 :
421 1 : m_test_params.event_count = 3;
422 1 : m_test_params.events_list_size = 100;
423 :
424 101 : for (int unsigned index = 0; index < m_test_params.events_list_size; index++) {
425 100 : m_test_params.events_list[index] = (uint8_t)index;
426 : }
427 :
428 1 : status = libspdm_send_event(spdm_context, m_session_id, m_test_params.event_count,
429 : m_test_params.events_list_size, m_test_params.events_list);
430 :
431 1 : assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
432 1 : }
433 :
434 1 : int libspdm_req_send_event_error_test(void)
435 : {
436 1 : const struct CMUnitTest test_cases[] = {
437 : cmocka_unit_test(req_send_event_err_case1),
438 : cmocka_unit_test(req_send_event_err_case2),
439 : cmocka_unit_test(req_send_event_err_case3),
440 : cmocka_unit_test(req_send_event_err_case4),
441 : cmocka_unit_test(req_send_event_err_case5),
442 : cmocka_unit_test(req_send_event_err_case6),
443 : cmocka_unit_test(req_send_event_err_case7),
444 : cmocka_unit_test(req_send_event_err_case8),
445 : cmocka_unit_test(req_send_event_err_case9),
446 : };
447 :
448 1 : libspdm_test_context_t test_context = {
449 : LIBSPDM_TEST_CONTEXT_VERSION,
450 : true,
451 : send_message,
452 : receive_message,
453 : };
454 :
455 1 : libspdm_setup_test_context(&test_context);
456 :
457 1 : return cmocka_run_group_tests(test_cases,
458 : libspdm_unit_test_group_setup,
459 : libspdm_unit_test_group_teardown);
460 : }
461 :
462 : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
|