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 : #include "spdm_unit_test.h"
7 : #include "internal/libspdm_requester_lib.h"
8 :
9 : #if (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && \
10 : (LIBSPDM_ENABLE_CAPABILITY_CERT_CAP)
11 :
12 : spdm_get_digest_request_t m_spdm_get_digests_request1 = {
13 : {
14 : SPDM_MESSAGE_VERSION_11,
15 : SPDM_GET_DIGESTS,
16 : },
17 : };
18 : size_t m_spdm_get_digests_request1_size = sizeof(m_spdm_get_digests_request1);
19 :
20 :
21 : spdm_get_digest_request_t m_spdm_get_digests_request2 = {
22 : {
23 : SPDM_MESSAGE_VERSION_13,
24 : SPDM_GET_DIGESTS,
25 : },
26 : };
27 : size_t m_spdm_get_digests_request2_size = sizeof(m_spdm_get_digests_request2);
28 :
29 : static uint8_t m_local_certificate_chain[LIBSPDM_MAX_CERT_CHAIN_SIZE];
30 :
31 : /**
32 : * Test 1: receives a valid GET_DIGESTS request message from Requester
33 : * Expected Behavior: produces a valid DIGESTS response message
34 : **/
35 1 : static void req_encap_digests_case1(void **state)
36 : {
37 : libspdm_return_t status;
38 : libspdm_test_context_t *spdm_test_context;
39 : libspdm_context_t *spdm_context;
40 : size_t response_size;
41 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
42 : spdm_digest_response_t *spdm_response;
43 :
44 1 : spdm_test_context = *state;
45 1 : spdm_context = spdm_test_context->spdm_context;
46 1 : spdm_test_context->case_id = 0x1;
47 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11
48 : << SPDM_VERSION_NUMBER_SHIFT_BIT;
49 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
50 1 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP;
51 1 : spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
52 1 : spdm_context->local_context.local_cert_chain_provision[0] = m_local_certificate_chain;
53 1 : spdm_context->local_context.local_cert_chain_provision_size[0] =
54 : sizeof(m_local_certificate_chain);
55 1 : libspdm_set_mem(m_local_certificate_chain, sizeof(m_local_certificate_chain), (uint8_t)(0xFF));
56 :
57 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
58 : spdm_context->transcript.message_m.buffer_size =
59 : spdm_context->transcript.message_m.max_buffer_size;
60 : #endif
61 :
62 1 : response_size = sizeof(response);
63 1 : status = libspdm_get_encap_response_digest(spdm_context,
64 : m_spdm_get_digests_request1_size,
65 : &m_spdm_get_digests_request1,
66 : &response_size, response);
67 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
68 1 : assert_int_equal(
69 : response_size,
70 : sizeof(spdm_digest_response_t) +
71 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo));
72 1 : spdm_response = (void *)response;
73 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_DIGESTS);
74 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
75 : assert_int_equal(spdm_context->transcript.message_m.buffer_size, 0);
76 : #endif
77 1 : }
78 :
79 : /**
80 : * Test 2:
81 : * Expected Behavior:
82 : **/
83 1 : static void req_encap_digests_case2(void **state)
84 : {
85 1 : }
86 :
87 : /**
88 : * Test 3: receives a valid GET_DIGESTS request message from Requester, but the request message cannot be appended to the internal cache since the internal cache is full
89 : * Expected Behavior: produces an ERROR response message with error code = Unspecified
90 : **/
91 1 : static void req_encap_digests_case3(void **state)
92 : {
93 : libspdm_return_t status;
94 : libspdm_test_context_t *spdm_test_context;
95 : libspdm_context_t *spdm_context;
96 : size_t response_size;
97 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
98 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
99 : spdm_digest_response_t *spdm_response;
100 : #endif
101 1 : spdm_test_context = *state;
102 1 : spdm_context = spdm_test_context->spdm_context;
103 1 : spdm_test_context->case_id = 0x3;
104 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11
105 : << SPDM_VERSION_NUMBER_SHIFT_BIT;
106 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
107 1 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP;
108 1 : spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
109 1 : spdm_context->local_context.local_cert_chain_provision[0] = m_local_certificate_chain;
110 1 : spdm_context->local_context.local_cert_chain_provision_size[0] =
111 : sizeof(m_local_certificate_chain);
112 1 : libspdm_set_mem(m_local_certificate_chain, sizeof(m_local_certificate_chain), (uint8_t)(0xFF));
113 :
114 1 : response_size = sizeof(response);
115 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
116 : spdm_context->transcript.message_b.buffer_size =
117 : spdm_context->transcript.message_b.max_buffer_size;
118 : #endif
119 1 : status = libspdm_get_encap_response_digest(spdm_context,
120 : m_spdm_get_digests_request1_size,
121 : &m_spdm_get_digests_request1,
122 : &response_size, response);
123 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
124 :
125 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
126 : assert_int_equal(
127 : response_size,
128 : sizeof(spdm_digest_response_t) +
129 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo));
130 : spdm_response = (void *)response;
131 : assert_int_equal(spdm_response->header.request_response_code, SPDM_DIGESTS);
132 : assert_int_equal(spdm_response->header.param1, 0);
133 : assert_int_equal(spdm_response->header.param2, SPDM_ERROR_CODE_INVALID_REQUEST);
134 : #endif
135 1 : }
136 :
137 : /**
138 : * Test 4: receives a valid GET_DIGESTS request message from Requester, but the response message cannot be appended to the internal cache since the internal cache is full
139 : * Expected Behavior: produces an ERROR response message with error code = Unspecified
140 : **/
141 1 : static void req_encap_digests_case4(void **state)
142 : {
143 : libspdm_test_context_t *spdm_test_context;
144 : libspdm_context_t *spdm_context;
145 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
146 : size_t response_size;
147 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
148 : libspdm_return_t status;
149 : spdm_digest_response_t *spdm_response;
150 : #endif
151 :
152 1 : spdm_test_context = *state;
153 1 : spdm_context = spdm_test_context->spdm_context;
154 1 : spdm_test_context->case_id = 0x4;
155 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11
156 : << SPDM_VERSION_NUMBER_SHIFT_BIT;
157 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
158 1 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP;
159 1 : spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
160 1 : spdm_context->local_context.local_cert_chain_provision[0] = m_local_certificate_chain;
161 1 : spdm_context->local_context.local_cert_chain_provision_size[0] =
162 : sizeof(m_local_certificate_chain);
163 1 : libspdm_set_mem(m_local_certificate_chain, sizeof(m_local_certificate_chain), (uint8_t)(0xFF));
164 :
165 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
166 : spdm_context->transcript.message_b.buffer_size =
167 : spdm_context->transcript.message_b.max_buffer_size -
168 : sizeof(spdm_get_digest_request_t);
169 : response_size = sizeof(response);
170 : status = libspdm_get_encap_response_digest(spdm_context,
171 : m_spdm_get_digests_request1_size,
172 : &m_spdm_get_digests_request1,
173 : &response_size, response);
174 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
175 : assert_int_equal(
176 : response_size,
177 : sizeof(spdm_digest_response_t) +
178 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo));
179 : spdm_response = (void *)response;
180 : assert_int_equal(spdm_response->header.request_response_code, SPDM_DIGESTS);
181 : assert_int_equal(spdm_response->header.param1, 0);
182 : assert_int_equal(spdm_response->header.param2, SPDM_ERROR_CODE_INVALID_REQUEST);
183 : #endif
184 1 : }
185 :
186 : /**
187 : * Test 5: receives a valid GET_DIGESTS request message from Requester ,
188 : * Set multi_key_conn_req to check if it responds correctly
189 : * Expected Behavior: produces a valid DIGESTS response message
190 : **/
191 1 : static void req_encap_digests_case5(void **state)
192 : {
193 : libspdm_return_t status;
194 : libspdm_test_context_t *spdm_test_context;
195 : libspdm_context_t *spdm_context;
196 : size_t response_size;
197 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
198 : spdm_digest_response_t *spdm_response;
199 : libspdm_session_info_t *session_info;
200 : uint32_t session_id;
201 :
202 1 : spdm_test_context = *state;
203 1 : spdm_context = spdm_test_context->spdm_context;
204 1 : spdm_test_context->case_id = 0x5;
205 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13
206 : << SPDM_VERSION_NUMBER_SHIFT_BIT;
207 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
208 1 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP;
209 1 : spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
210 1 : spdm_context->local_context.local_cert_chain_provision[0] = m_local_certificate_chain;
211 1 : spdm_context->local_context.local_cert_chain_provision_size[0] =
212 : sizeof(m_local_certificate_chain);
213 1 : libspdm_set_mem(m_local_certificate_chain, sizeof(m_local_certificate_chain), (uint8_t)(0xFF));
214 :
215 1 : session_id = 0xFFFFFFFF;
216 1 : spdm_context->latest_session_id = session_id;
217 1 : spdm_context->last_spdm_request_session_id_valid = true;
218 1 : spdm_context->last_spdm_request_session_id = session_id;
219 1 : session_info = &spdm_context->session_info[0];
220 1 : libspdm_session_info_init(spdm_context, session_info, session_id,
221 : SECURED_SPDM_VERSION_11 << SPDM_VERSION_NUMBER_SHIFT_BIT, true);
222 1 : libspdm_secured_message_set_session_state(
223 : session_info->secured_message_context,
224 : LIBSPDM_SESSION_STATE_ESTABLISHED);
225 :
226 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
227 : spdm_context->transcript.message_m.buffer_size =
228 : spdm_context->transcript.message_m.max_buffer_size;
229 : #endif
230 : /* Sub Case 1: Set multi_key_conn_req to true*/
231 1 : spdm_context->connection_info.multi_key_conn_req = true;
232 1 : libspdm_reset_message_encap_d(session_info);
233 :
234 1 : response_size = sizeof(response);
235 1 : status = libspdm_get_encap_response_digest(spdm_context,
236 : m_spdm_get_digests_request2_size,
237 : &m_spdm_get_digests_request2,
238 : &response_size, response);
239 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
240 1 : assert_int_equal(
241 : response_size,
242 : sizeof(spdm_digest_response_t) + sizeof(spdm_key_pair_id_t) +
243 : sizeof(spdm_certificate_info_t) +
244 : sizeof(spdm_key_usage_bit_mask_t) +
245 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo));
246 1 : spdm_response = (void *)response;
247 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_DIGESTS);
248 1 : assert_int_equal(session_info->session_transcript.message_encap_d.buffer_size,
249 : sizeof(spdm_digest_response_t) + sizeof(spdm_key_pair_id_t) +
250 : sizeof(spdm_certificate_info_t) +
251 : sizeof(spdm_key_usage_bit_mask_t) +
252 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo));
253 :
254 : /* Sub Case 2: Set multi_key_conn_req to false*/
255 1 : spdm_context->connection_info.multi_key_conn_req = false;
256 1 : libspdm_reset_message_encap_d(session_info);
257 :
258 1 : response_size = sizeof(response);
259 1 : status = libspdm_get_encap_response_digest(spdm_context,
260 : m_spdm_get_digests_request2_size,
261 : &m_spdm_get_digests_request2,
262 : &response_size, response);
263 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
264 1 : assert_int_equal(
265 : response_size,
266 : sizeof(spdm_digest_response_t) +
267 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo));
268 1 : spdm_response = (void *)response;
269 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_DIGESTS);
270 1 : assert_int_equal(session_info->session_transcript.message_encap_d.buffer_size, 0);
271 1 : }
272 :
273 : /**
274 : * Test 6: receives a valid GET_DIGESTS request message from Requester ,
275 : * Check KeyPairID CertificateInfo and KeyUsageMask
276 : * Expected Behavior: produces a valid DIGESTS response message
277 : **/
278 1 : static void req_encap_digests_case6(void **state)
279 : {
280 : libspdm_return_t status;
281 : libspdm_test_context_t *spdm_test_context;
282 : libspdm_context_t *spdm_context;
283 : size_t response_size;
284 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
285 : spdm_digest_response_t *spdm_response;
286 : libspdm_session_info_t *session_info;
287 : uint32_t session_id;
288 : uint8_t *digest;
289 : spdm_key_pair_id_t *key_pair_id;
290 : spdm_certificate_info_t *cert_info;
291 : spdm_key_usage_bit_mask_t *key_usage_bit_mask;
292 : uint32_t hash_size;
293 : uint8_t slot_count;
294 : size_t additional_size;
295 :
296 1 : spdm_test_context = *state;
297 1 : spdm_context = spdm_test_context->spdm_context;
298 1 : spdm_test_context->case_id = 0x6;
299 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13
300 : << SPDM_VERSION_NUMBER_SHIFT_BIT;
301 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
302 1 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP;
303 1 : spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
304 :
305 1 : slot_count = SPDM_MAX_SLOT_COUNT;
306 1 : additional_size = sizeof(spdm_key_pair_id_t) + sizeof(spdm_certificate_info_t) +
307 : sizeof(spdm_key_usage_bit_mask_t);
308 1 : hash_size = libspdm_get_hash_size(m_libspdm_use_hash_algo);
309 :
310 9 : for (uint8_t index = 0; index < SPDM_MAX_SLOT_COUNT; index++) {
311 8 : spdm_context->local_context.local_cert_chain_provision[index] =
312 8 : &m_local_certificate_chain[hash_size * index];
313 : spdm_context->local_context
314 8 : .local_cert_chain_provision_size[index] = hash_size;
315 : }
316 :
317 1 : libspdm_set_mem(m_local_certificate_chain, sizeof(m_local_certificate_chain), (uint8_t)(0xFF));
318 :
319 1 : session_id = 0xFFFFFFFF;
320 1 : spdm_context->latest_session_id = session_id;
321 1 : spdm_context->last_spdm_request_session_id_valid = true;
322 1 : spdm_context->last_spdm_request_session_id = session_id;
323 1 : session_info = &spdm_context->session_info[0];
324 1 : libspdm_session_info_init(spdm_context, session_info, session_id,
325 : SECURED_SPDM_VERSION_11 << SPDM_VERSION_NUMBER_SHIFT_BIT, true);
326 1 : libspdm_secured_message_set_session_state(
327 : session_info->secured_message_context,
328 : LIBSPDM_SESSION_STATE_ESTABLISHED);
329 :
330 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
331 : spdm_context->transcript.message_m.buffer_size =
332 : spdm_context->transcript.message_m.max_buffer_size;
333 : #endif
334 1 : spdm_context->connection_info.multi_key_conn_req = true;
335 1 : libspdm_reset_message_encap_d(session_info);
336 :
337 1 : response_size = sizeof(response);
338 1 : status = libspdm_get_encap_response_digest(spdm_context,
339 : m_spdm_get_digests_request2_size,
340 : &m_spdm_get_digests_request2,
341 : &response_size, response);
342 :
343 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
344 1 : assert_int_equal(response_size,
345 : sizeof(spdm_digest_response_t) + (hash_size + additional_size) * slot_count);
346 :
347 1 : spdm_response = (void *)response;
348 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_DIGESTS);
349 1 : assert_int_equal(session_info->session_transcript.message_encap_d.buffer_size,
350 : sizeof(spdm_digest_response_t) + (hash_size + additional_size) * slot_count);
351 :
352 1 : digest = (void *)(spdm_response + 1);
353 1 : libspdm_zero_mem (digest, hash_size * slot_count);
354 1 : key_pair_id = (spdm_key_pair_id_t *)((uint8_t *)digest + (hash_size * slot_count));
355 1 : cert_info = (spdm_certificate_info_t *)((uint8_t *)key_pair_id +
356 1 : sizeof(spdm_key_pair_id_t) * slot_count);
357 1 : key_usage_bit_mask = (spdm_key_usage_bit_mask_t *)((uint8_t *)cert_info +
358 1 : sizeof(spdm_certificate_info_t) *
359 : slot_count);
360 9 : for (uint8_t index = 0; index < SPDM_MAX_SLOT_COUNT; index++) {
361 8 : assert_memory_equal((void *)&key_pair_id[index],
362 : (void *)&spdm_context->local_context.local_key_pair_id[index],
363 : sizeof(spdm_key_pair_id_t));
364 8 : assert_memory_equal((void *)&cert_info[index],
365 : (void *)&spdm_context->local_context.local_cert_info[index],
366 : sizeof(spdm_certificate_info_t));
367 8 : assert_memory_equal((void *)&key_usage_bit_mask[index],
368 : (void *)&spdm_context->local_context.local_key_usage_bit_mask[index],
369 : sizeof(spdm_key_usage_bit_mask_t));
370 : }
371 1 : }
372 :
373 1 : int libspdm_req_encap_digests_test(void)
374 : {
375 1 : const struct CMUnitTest test_cases[] = {
376 : /* Success Case*/
377 : cmocka_unit_test(req_encap_digests_case1),
378 : /* Can be populated with new test.*/
379 : cmocka_unit_test(req_encap_digests_case2),
380 : /* Internal cache full (request message)*/
381 : cmocka_unit_test(req_encap_digests_case3),
382 : /* Internal cache full (response message)*/
383 : cmocka_unit_test(req_encap_digests_case4),
384 : /* Set multi_key_conn_req to check if it responds correctly */
385 : cmocka_unit_test(req_encap_digests_case5),
386 : /* Check KeyPairID CertificateInfo and KeyUsageMask*/
387 : cmocka_unit_test(req_encap_digests_case6),
388 : };
389 :
390 1 : libspdm_test_context_t test_context = {
391 : LIBSPDM_TEST_CONTEXT_VERSION,
392 : false,
393 : };
394 :
395 1 : libspdm_setup_test_context(&test_context);
396 :
397 1 : return cmocka_run_group_tests(test_cases,
398 : libspdm_unit_test_group_setup,
399 : libspdm_unit_test_group_teardown);
400 : }
401 :
402 : #endif /* (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (..) */
|