Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2024-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_responder_lib.h"
9 : #include "internal/libspdm_requester_lib.h"
10 :
11 : #if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP
12 :
13 : /**
14 : * Test 1: Successful response to set key pair info with key pair id 4
15 : * Expected Behavior: get a LIBSPDM_STATUS_SUCCESS return code, and correct response message size and fields
16 : **/
17 1 : static void rsp_set_key_pair_info_ack_case1(void **state)
18 : {
19 : libspdm_return_t status;
20 : libspdm_test_context_t *spdm_test_context;
21 : libspdm_context_t *spdm_context;
22 : size_t response_size;
23 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
24 : spdm_set_key_pair_info_ack_response_t *spdm_response;
25 :
26 : uint8_t key_pair_id;
27 : size_t set_key_pair_info_request_size;
28 : spdm_set_key_pair_info_request_t *set_key_pair_info_request;
29 : uint8_t *ptr;
30 : uint16_t desired_key_usage;
31 : uint32_t desired_asym_algo;
32 : uint8_t desired_assoc_cert_slot_mask;
33 :
34 1 : set_key_pair_info_request = malloc(sizeof(spdm_set_key_pair_info_request_t) +
35 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) +
36 : sizeof(uint8_t));
37 :
38 1 : spdm_test_context = *state;
39 1 : spdm_context = spdm_test_context->spdm_context;
40 1 : spdm_test_context->case_id = 0x1;
41 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
42 : SPDM_VERSION_NUMBER_SHIFT_BIT;
43 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
44 1 : spdm_context->connection_info.algorithm.base_asym_algo = m_libspdm_use_asym_algo;
45 1 : spdm_context->local_context.capability.flags |=
46 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_INFO_CAP;
47 :
48 1 : key_pair_id = 4;
49 :
50 1 : response_size = sizeof(response);
51 :
52 : /*change: remove an association with slot*/
53 1 : set_key_pair_info_request_size =
54 : sizeof(spdm_set_key_pair_info_request_t) +
55 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t);
56 :
57 1 : libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size);
58 1 : set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_13;
59 1 : set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO;
60 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION;
61 1 : set_key_pair_info_request->header.param2 = 0;
62 1 : set_key_pair_info_request->key_pair_id = key_pair_id;
63 :
64 1 : status = libspdm_get_response_set_key_pair_info_ack(
65 : spdm_context, set_key_pair_info_request_size,
66 : set_key_pair_info_request, &response_size, response);
67 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
68 1 : assert_int_equal(response_size, sizeof(spdm_set_key_pair_info_ack_response_t));
69 1 : spdm_response = (void *)response;
70 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_SET_KEY_PAIR_INFO_ACK);
71 :
72 : /*erase: erase the keyusage and asymalgo*/
73 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION;
74 1 : set_key_pair_info_request_size = sizeof(spdm_set_key_pair_info_request_t);
75 1 : status = libspdm_get_response_set_key_pair_info_ack(
76 : spdm_context, set_key_pair_info_request_size,
77 : set_key_pair_info_request, &response_size, response);
78 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
79 1 : assert_int_equal(response_size, sizeof(spdm_set_key_pair_info_ack_response_t));
80 1 : spdm_response = (void *)response;
81 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_SET_KEY_PAIR_INFO_ACK);
82 :
83 : /*generate: generate a new key pair*/
84 1 : desired_key_usage = SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE;
85 1 : desired_asym_algo = SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC256;
86 1 : desired_assoc_cert_slot_mask = 0x08;
87 1 : set_key_pair_info_request_size =
88 : sizeof(spdm_set_key_pair_info_request_t) +
89 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t);
90 :
91 1 : libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size);
92 1 : set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_13;
93 1 : set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO;
94 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION;
95 1 : set_key_pair_info_request->header.param2 = 0;
96 1 : set_key_pair_info_request->key_pair_id = key_pair_id;
97 :
98 1 : ptr = (uint8_t*)(set_key_pair_info_request + 1);
99 1 : ptr += sizeof(uint8_t);
100 :
101 1 : libspdm_write_uint16(ptr, desired_key_usage);
102 1 : ptr += sizeof(uint16_t);
103 :
104 1 : libspdm_write_uint32(ptr, desired_asym_algo);
105 1 : ptr += sizeof(uint32_t);
106 :
107 1 : *ptr = desired_assoc_cert_slot_mask;
108 :
109 1 : status = libspdm_get_response_set_key_pair_info_ack(
110 : spdm_context, set_key_pair_info_request_size,
111 : set_key_pair_info_request, &response_size, response);
112 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
113 1 : assert_int_equal(response_size, sizeof(spdm_set_key_pair_info_ack_response_t));
114 1 : spdm_response = (void *)response;
115 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_SET_KEY_PAIR_INFO_ACK);
116 1 : free(set_key_pair_info_request);
117 1 : }
118 :
119 : /**
120 : * Test 2: Can be populated with new test.
121 : **/
122 1 : static void rsp_set_key_pair_info_ack_case2(void **state)
123 : {
124 1 : }
125 :
126 : /**
127 : * Test 3: The collection of multiple sub-cases.
128 : **/
129 1 : static void rsp_set_key_pair_info_ack_case3(void **state)
130 : {
131 : libspdm_return_t status;
132 : libspdm_test_context_t *spdm_test_context;
133 : libspdm_context_t *spdm_context;
134 : size_t response_size;
135 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
136 : spdm_set_key_pair_info_ack_response_t *spdm_response;
137 :
138 : uint8_t key_pair_id;
139 : size_t set_key_pair_info_request_size;
140 : spdm_set_key_pair_info_request_t *set_key_pair_info_request;
141 : uint8_t *ptr;
142 : uint16_t desired_key_usage;
143 : uint32_t desired_asym_algo;
144 : uint8_t desired_assoc_cert_slot_mask;
145 : uint8_t desired_pqc_asym_algo_len;
146 : uint32_t desired_pqc_asym_algo;
147 :
148 : uint8_t temp_buf[LIBSPDM_RECEIVER_BUFFER_SIZE];
149 1 : set_key_pair_info_request = (spdm_set_key_pair_info_request_t *)temp_buf;
150 :
151 1 : spdm_test_context = *state;
152 1 : spdm_context = spdm_test_context->spdm_context;
153 1 : spdm_test_context->case_id = 0x3;
154 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_14 <<
155 : SPDM_VERSION_NUMBER_SHIFT_BIT;
156 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
157 1 : spdm_context->connection_info.algorithm.base_asym_algo = m_libspdm_use_asym_algo;
158 1 : spdm_context->local_context.capability.flags |=
159 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_INFO_CAP;
160 :
161 1 : key_pair_id = 4;
162 :
163 : /*set responder need reset, spdm 1.4 */
164 1 : spdm_context->local_context.capability.flags |=
165 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_RESET_CAP;
166 :
167 : /*Before reset, change: remove an association with slot*/
168 1 : set_key_pair_info_request_size =
169 : sizeof(spdm_set_key_pair_info_request_t) +
170 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t) +
171 : sizeof(uint8_t);
172 :
173 1 : libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size);
174 1 : set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_14;
175 1 : set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO;
176 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION;
177 1 : set_key_pair_info_request->header.param2 = 0;
178 1 : set_key_pair_info_request->key_pair_id = key_pair_id;
179 :
180 1 : response_size = sizeof(response);
181 1 : status = libspdm_get_response_set_key_pair_info_ack(
182 : spdm_context, set_key_pair_info_request_size,
183 : set_key_pair_info_request, &response_size, response);
184 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
185 1 : assert_int_equal(response_size, sizeof(spdm_error_response_t));
186 1 : spdm_response = (void *)response;
187 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
188 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_RESET_REQUIRED);
189 1 : assert_int_equal(spdm_response->header.param2, 0);
190 :
191 : /* Sub Case 1: If KeyPairErase is set, all fields after the KeyPairID field in this request should not exist. */
192 1 : desired_key_usage = SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE;
193 1 : desired_asym_algo = SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC256;
194 1 : desired_pqc_asym_algo_len = sizeof(desired_pqc_asym_algo);
195 1 : desired_pqc_asym_algo = 0;
196 1 : desired_assoc_cert_slot_mask = 0x08;
197 1 : set_key_pair_info_request_size =
198 : sizeof(spdm_set_key_pair_info_request_t) +
199 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t) +
200 : sizeof(uint8_t) + sizeof(uint32_t);
201 :
202 1 : libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size);
203 1 : set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_14;
204 1 : set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO;
205 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION;
206 1 : set_key_pair_info_request->header.param2 = 0;
207 1 : set_key_pair_info_request->key_pair_id = key_pair_id;
208 :
209 1 : ptr = (uint8_t*)(set_key_pair_info_request + 1);
210 1 : ptr += sizeof(uint8_t);
211 :
212 1 : libspdm_write_uint16(ptr, desired_key_usage);
213 1 : ptr += sizeof(uint16_t);
214 :
215 1 : libspdm_write_uint32(ptr, desired_asym_algo);
216 1 : ptr += sizeof(uint32_t);
217 :
218 1 : *ptr = desired_assoc_cert_slot_mask;
219 1 : ptr += sizeof(uint8_t);
220 :
221 1 : *ptr = desired_pqc_asym_algo_len;
222 1 : ptr += sizeof(uint8_t);
223 :
224 1 : libspdm_write_uint32(ptr, desired_pqc_asym_algo);
225 :
226 1 : response_size = sizeof(response);
227 1 : status = libspdm_get_response_set_key_pair_info_ack(
228 : spdm_context, set_key_pair_info_request_size,
229 : set_key_pair_info_request, &response_size, response);
230 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
231 1 : assert_int_equal(response_size, sizeof(spdm_error_response_t));
232 1 : spdm_response = (void *)response;
233 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
234 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_OPERATION_FAILED);
235 1 : assert_int_equal(spdm_response->header.param2, 0);
236 :
237 : /*Sub Case 2: When GenerateKeyPair is set, the fields of DesiredKeyUsage, DesiredAsymAlgo and DesiredAssocCertSlotMask should exist. */
238 1 : set_key_pair_info_request_size = sizeof(spdm_set_key_pair_info_request_t);
239 :
240 1 : libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size);
241 1 : set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_14;
242 1 : set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO;
243 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION;
244 1 : set_key_pair_info_request->header.param2 = 0;
245 1 : set_key_pair_info_request->key_pair_id = key_pair_id;
246 :
247 1 : response_size = sizeof(response);
248 1 : status = libspdm_get_response_set_key_pair_info_ack(
249 : spdm_context, set_key_pair_info_request_size,
250 : set_key_pair_info_request, &response_size, response);
251 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
252 1 : assert_int_equal(response_size, sizeof(spdm_error_response_t));
253 1 : spdm_response = (void *)response;
254 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
255 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_INVALID_REQUEST);
256 1 : assert_int_equal(spdm_response->header.param2, 0);
257 :
258 : /*Sub Case 3: key_pair_id = 0 */
259 1 : set_key_pair_info_request_size = sizeof(spdm_set_key_pair_info_request_t);
260 :
261 1 : libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size);
262 1 : set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_14;
263 1 : set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO;
264 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION;
265 1 : set_key_pair_info_request->header.param2 = 0;
266 1 : set_key_pair_info_request->key_pair_id = 0;
267 :
268 1 : response_size = sizeof(response);
269 1 : status = libspdm_get_response_set_key_pair_info_ack(
270 : spdm_context, set_key_pair_info_request_size,
271 : set_key_pair_info_request, &response_size, response);
272 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
273 1 : assert_int_equal(response_size, sizeof(spdm_error_response_t));
274 1 : spdm_response = (void *)response;
275 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
276 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_INVALID_REQUEST);
277 1 : assert_int_equal(spdm_response->header.param2, 0);
278 :
279 : /* Sub Case 4: DesiredAsymAlgo must not have multiple bits set. */
280 1 : desired_key_usage = SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE;
281 1 : desired_asym_algo = SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC256 |
282 : SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC384;
283 1 : desired_pqc_asym_algo_len = sizeof(desired_pqc_asym_algo);
284 1 : desired_pqc_asym_algo = 0;
285 1 : desired_assoc_cert_slot_mask = 0x08;
286 1 : set_key_pair_info_request_size =
287 : sizeof(spdm_set_key_pair_info_request_t) +
288 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t) +
289 : sizeof(uint8_t) + sizeof(uint32_t);
290 :
291 1 : libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size);
292 1 : set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_14;
293 1 : set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO;
294 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION;
295 1 : set_key_pair_info_request->header.param2 = 0;
296 1 : set_key_pair_info_request->key_pair_id = key_pair_id;
297 :
298 1 : ptr = (uint8_t*)(set_key_pair_info_request + 1);
299 1 : ptr += sizeof(uint8_t);
300 :
301 1 : libspdm_write_uint16(ptr, desired_key_usage);
302 1 : ptr += sizeof(uint16_t);
303 :
304 1 : libspdm_write_uint32(ptr, desired_asym_algo);
305 1 : ptr += sizeof(uint32_t);
306 :
307 1 : *ptr = desired_assoc_cert_slot_mask;
308 1 : ptr += sizeof(uint8_t);
309 :
310 1 : *ptr = desired_pqc_asym_algo_len;
311 1 : ptr += sizeof(uint8_t);
312 :
313 1 : libspdm_write_uint32(ptr, desired_pqc_asym_algo);
314 :
315 1 : response_size = sizeof(response);
316 1 : status = libspdm_get_response_set_key_pair_info_ack(
317 : spdm_context, set_key_pair_info_request_size,
318 : set_key_pair_info_request, &response_size, response);
319 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
320 1 : assert_int_equal(response_size, sizeof(spdm_error_response_t));
321 1 : spdm_response = (void *)response;
322 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
323 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_INVALID_REQUEST);
324 1 : assert_int_equal(spdm_response->header.param2, 0);
325 :
326 : /* Sub Case 5: DesiredPqcAsymAlgo selects a bit outside PqcAsymAlgoCapabilities. Per
327 : * DSP0274 Table 115 this is the same class of malformed request as an out-of-capability
328 : * DesiredAsymAlgo, so the Responder shall answer with InvalidRequest (not
329 : * UnsupportedRequest). The sample HAL supports ML-DSA but not SLH-DSA for this key pair. */
330 1 : desired_key_usage = SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE;
331 1 : desired_asym_algo = 0;
332 1 : desired_pqc_asym_algo_len = sizeof(desired_pqc_asym_algo);
333 1 : desired_pqc_asym_algo = SPDM_KEY_PAIR_PQC_ASYM_ALGO_CAP_SLH_DSA_SHA2_128S;
334 1 : desired_assoc_cert_slot_mask = 0x08;
335 1 : set_key_pair_info_request_size =
336 : sizeof(spdm_set_key_pair_info_request_t) +
337 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t) +
338 : sizeof(uint8_t) + sizeof(uint32_t);
339 :
340 1 : libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size);
341 1 : set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_14;
342 1 : set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO;
343 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION;
344 1 : set_key_pair_info_request->header.param2 = 0;
345 1 : set_key_pair_info_request->key_pair_id = key_pair_id;
346 :
347 1 : ptr = (uint8_t*)(set_key_pair_info_request + 1);
348 1 : ptr += sizeof(uint8_t);
349 :
350 1 : libspdm_write_uint16(ptr, desired_key_usage);
351 1 : ptr += sizeof(uint16_t);
352 :
353 1 : libspdm_write_uint32(ptr, desired_asym_algo);
354 1 : ptr += sizeof(uint32_t);
355 :
356 1 : *ptr = desired_assoc_cert_slot_mask;
357 1 : ptr += sizeof(uint8_t);
358 :
359 1 : *ptr = desired_pqc_asym_algo_len;
360 1 : ptr += sizeof(uint8_t);
361 :
362 1 : libspdm_write_uint32(ptr, desired_pqc_asym_algo);
363 :
364 1 : response_size = sizeof(response);
365 1 : status = libspdm_get_response_set_key_pair_info_ack(
366 : spdm_context, set_key_pair_info_request_size,
367 : set_key_pair_info_request, &response_size, response);
368 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
369 1 : assert_int_equal(response_size, sizeof(spdm_error_response_t));
370 1 : spdm_response = (void *)response;
371 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
372 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_INVALID_REQUEST);
373 1 : assert_int_equal(spdm_response->header.param2, 0);
374 :
375 : /*Before reset, change: remove an association with slot*/
376 1 : set_key_pair_info_request_size =
377 : sizeof(spdm_set_key_pair_info_request_t) +
378 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t) +
379 : sizeof(uint8_t);
380 :
381 1 : libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size);
382 1 : set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_14;
383 1 : set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO;
384 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION;
385 1 : set_key_pair_info_request->header.param2 = 0;
386 1 : set_key_pair_info_request->key_pair_id = 0x1;
387 :
388 1 : response_size = sizeof(response);
389 1 : status = libspdm_get_response_set_key_pair_info_ack(
390 : spdm_context, set_key_pair_info_request_size,
391 : set_key_pair_info_request, &response_size, response);
392 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
393 1 : assert_int_equal(response_size, sizeof(spdm_error_response_t));
394 1 : spdm_response = (void *)response;
395 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
396 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_RESET_REQUIRED);
397 1 : assert_int_equal(spdm_response->header.param2, 0);
398 1 : }
399 :
400 : /**
401 : * Test 4: Successful response to set key pair info with key pair id 4: need reset, spdm 1.4
402 : * Expected Behavior: get a LIBSPDM_STATUS_SUCCESS return code, and correct response message size and fields
403 : **/
404 1 : static void rsp_set_key_pair_info_ack_case4(void **state)
405 : {
406 : /* reference case 2 */
407 : libspdm_return_t status;
408 : libspdm_test_context_t *spdm_test_context;
409 : libspdm_context_t *spdm_context;
410 : size_t response_size;
411 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
412 : spdm_set_key_pair_info_ack_response_t *spdm_response;
413 :
414 : uint8_t key_pair_id;
415 : size_t set_key_pair_info_request_size;
416 : spdm_set_key_pair_info_request_t *set_key_pair_info_request;
417 : uint8_t *ptr;
418 : uint16_t desired_key_usage;
419 : uint32_t desired_asym_algo;
420 : uint8_t desired_assoc_cert_slot_mask;
421 : uint8_t desired_pqc_asym_algo_len;
422 : uint32_t desired_pqc_asym_algo;
423 :
424 1 : set_key_pair_info_request = malloc(sizeof(spdm_set_key_pair_info_request_t) +
425 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) +
426 : sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint32_t));
427 :
428 1 : spdm_test_context = *state;
429 1 : spdm_context = spdm_test_context->spdm_context;
430 1 : spdm_test_context->case_id = 0x4;
431 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_14 <<
432 : SPDM_VERSION_NUMBER_SHIFT_BIT;
433 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
434 1 : spdm_context->connection_info.algorithm.base_asym_algo = m_libspdm_use_asym_algo;
435 1 : spdm_context->local_context.capability.flags = 0; /* clear flags */
436 1 : spdm_context->local_context.capability.flags |=
437 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_INFO_CAP;
438 :
439 1 : key_pair_id = 4;
440 :
441 : /*set responder need reset, spdm 1.4 */
442 1 : spdm_context->local_context.capability.flags |=
443 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_RESET_CAP;
444 :
445 1 : response_size = sizeof(response);
446 :
447 : /*Before reset, change: remove an association with slot*/
448 1 : set_key_pair_info_request_size =
449 : sizeof(spdm_set_key_pair_info_request_t) +
450 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t) +
451 : sizeof(uint8_t);
452 :
453 1 : libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size);
454 1 : set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_14;
455 1 : set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO;
456 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION;
457 1 : set_key_pair_info_request->header.param2 = 0;
458 1 : set_key_pair_info_request->key_pair_id = key_pair_id;
459 :
460 1 : status = libspdm_get_response_set_key_pair_info_ack(
461 : spdm_context, set_key_pair_info_request_size,
462 : set_key_pair_info_request, &response_size, response);
463 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
464 1 : assert_int_equal(response_size, sizeof(spdm_error_response_t));
465 1 : spdm_response = (void *)response;
466 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
467 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_RESET_REQUIRED);
468 1 : assert_int_equal(spdm_response->header.param2, 0);
469 :
470 : /*After reset, change: remove an association with slot*/
471 1 : status = libspdm_get_response_set_key_pair_info_ack(
472 : spdm_context, set_key_pair_info_request_size,
473 : set_key_pair_info_request, &response_size, response);
474 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
475 1 : assert_int_equal(response_size, sizeof(spdm_set_key_pair_info_ack_response_t));
476 1 : spdm_response = (void *)response;
477 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_SET_KEY_PAIR_INFO_ACK);
478 :
479 : /*Before reset, erase: erase the keyusage and asymalgo*/
480 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION;
481 1 : set_key_pair_info_request_size = sizeof(spdm_set_key_pair_info_request_t);
482 1 : status = libspdm_get_response_set_key_pair_info_ack(
483 : spdm_context, set_key_pair_info_request_size,
484 : set_key_pair_info_request, &response_size, response);
485 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
486 1 : assert_int_equal(response_size, sizeof(spdm_error_response_t));
487 1 : spdm_response = (void *)response;
488 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
489 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_RESET_REQUIRED);
490 1 : assert_int_equal(spdm_response->header.param2, 0);
491 :
492 : /*After reset, erase: erase the keyusage and asymalgo*/
493 1 : status = libspdm_get_response_set_key_pair_info_ack(
494 : spdm_context, set_key_pair_info_request_size,
495 : set_key_pair_info_request, &response_size, response);
496 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
497 1 : assert_int_equal(response_size, sizeof(spdm_set_key_pair_info_ack_response_t));
498 1 : spdm_response = (void *)response;
499 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_SET_KEY_PAIR_INFO_ACK);
500 :
501 :
502 : /*Before reset, generate: generate a new key pair*/
503 1 : desired_key_usage = SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE;
504 1 : desired_asym_algo = SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC256;
505 1 : desired_pqc_asym_algo_len = sizeof(desired_pqc_asym_algo);
506 1 : desired_pqc_asym_algo = 0;
507 1 : desired_assoc_cert_slot_mask = 0x08;
508 1 : set_key_pair_info_request_size =
509 : sizeof(spdm_set_key_pair_info_request_t) +
510 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t) +
511 : sizeof(uint8_t) + sizeof(uint32_t);
512 :
513 1 : libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size);
514 1 : set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_14;
515 1 : set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO;
516 1 : set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION;
517 1 : set_key_pair_info_request->header.param2 = 0;
518 1 : set_key_pair_info_request->key_pair_id = key_pair_id;
519 :
520 1 : ptr = (uint8_t*)(set_key_pair_info_request + 1);
521 1 : ptr += sizeof(uint8_t);
522 :
523 1 : libspdm_write_uint16(ptr, desired_key_usage);
524 1 : ptr += sizeof(uint16_t);
525 :
526 1 : libspdm_write_uint32(ptr, desired_asym_algo);
527 1 : ptr += sizeof(uint32_t);
528 :
529 1 : *ptr = desired_assoc_cert_slot_mask;
530 1 : ptr += sizeof(uint8_t);
531 :
532 1 : *ptr = desired_pqc_asym_algo_len;
533 1 : ptr += sizeof(uint8_t);
534 :
535 1 : libspdm_write_uint32(ptr, desired_pqc_asym_algo);
536 :
537 1 : status = libspdm_get_response_set_key_pair_info_ack(
538 : spdm_context, set_key_pair_info_request_size,
539 : set_key_pair_info_request, &response_size, response);
540 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
541 1 : assert_int_equal(response_size, sizeof(spdm_error_response_t));
542 1 : spdm_response = (void *)response;
543 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
544 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_RESET_REQUIRED);
545 1 : assert_int_equal(spdm_response->header.param2, 0);
546 :
547 : /*After reset, generate: generate a new key pair*/
548 1 : status = libspdm_get_response_set_key_pair_info_ack(
549 : spdm_context, set_key_pair_info_request_size,
550 : set_key_pair_info_request, &response_size, response);
551 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
552 1 : assert_int_equal(response_size, sizeof(spdm_set_key_pair_info_ack_response_t));
553 1 : spdm_response = (void *)response;
554 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_SET_KEY_PAIR_INFO_ACK);
555 1 : free(set_key_pair_info_request);
556 1 : }
557 :
558 : /**
559 : * Test 5: SET_KEY_PAIR_RESET replay where two requests differ only in DesiredPqcAsymAlgo.
560 : * This exercises the device_secret HAL (libspdm_write_key_pair_info) directly, since the
561 : * cached-request match that decides whether a post-reset replay is applied lives in the HAL.
562 : * Expected Behavior: a replay that changes only the PQC algorithm shall not be accepted as the
563 : * cached request; the correct PQC algorithm shall be applied only once the matching request is
564 : * replayed.
565 : **/
566 1 : static void rsp_set_key_pair_info_ack_case5(void **state)
567 : {
568 : libspdm_test_context_t *spdm_test_context;
569 : libspdm_context_t *spdm_context;
570 : uint8_t key_pair_id;
571 : bool need_reset;
572 : bool result;
573 : uint8_t total_key_pairs;
574 : uint16_t capabilities;
575 : uint16_t key_usage_capabilities;
576 : uint16_t current_key_usage;
577 : uint32_t asym_algo_capabilities;
578 : uint32_t current_asym_algo;
579 : uint32_t pqc_asym_algo_capabilities;
580 : uint32_t current_pqc_asym_algo;
581 : uint8_t assoc_cert_slot_mask;
582 :
583 1 : spdm_test_context = *state;
584 1 : spdm_context = spdm_test_context->spdm_context;
585 1 : spdm_test_context->case_id = 0x5;
586 :
587 1 : key_pair_id = 4;
588 :
589 : /* First request: GenerateKeyPair with ML-DSA-44. With need_reset = true the HAL caches the
590 : * request and reports that a reset is still required (not yet applied). */
591 1 : need_reset = true;
592 1 : result = libspdm_write_key_pair_info(
593 : spdm_context, key_pair_id, SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION,
594 : SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE, 0,
595 : SPDM_KEY_PAIR_PQC_ASYM_ALGO_CAP_ML_DSA_44, 0, &need_reset);
596 1 : assert_true(result);
597 1 : assert_true(need_reset);
598 :
599 : /* Post-reset replay that differs only in DesiredPqcAsymAlgo (ML-DSA-65). This must NOT be
600 : * treated as the cached request: the HAL caches the new request and again reports that a
601 : * reset is required, rather than applying the stale ML-DSA-44 value. */
602 1 : need_reset = true;
603 1 : result = libspdm_write_key_pair_info(
604 : spdm_context, key_pair_id, SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION,
605 : SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE, 0,
606 : SPDM_KEY_PAIR_PQC_ASYM_ALGO_CAP_ML_DSA_65, 0, &need_reset);
607 1 : assert_true(result);
608 1 : assert_true(need_reset);
609 :
610 : /* Replay the ML-DSA-65 request identically: now it matches the cached request and is
611 : * applied (need_reset cleared). */
612 1 : need_reset = true;
613 1 : result = libspdm_write_key_pair_info(
614 : spdm_context, key_pair_id, SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION,
615 : SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE, 0,
616 : SPDM_KEY_PAIR_PQC_ASYM_ALGO_CAP_ML_DSA_65, 0, &need_reset);
617 1 : assert_true(result);
618 1 : assert_false(need_reset);
619 :
620 : /* The applied PQC algorithm shall be ML-DSA-65 (the replayed value), not ML-DSA-44. */
621 1 : assert_true(libspdm_read_key_pair_info(
622 : spdm_context, key_pair_id, &total_key_pairs, &capabilities,
623 : &key_usage_capabilities, ¤t_key_usage, &asym_algo_capabilities,
624 : ¤t_asym_algo, &pqc_asym_algo_capabilities, ¤t_pqc_asym_algo,
625 : &assoc_cert_slot_mask, NULL, NULL));
626 1 : assert_int_equal(current_pqc_asym_algo, SPDM_KEY_PAIR_PQC_ASYM_ALGO_CAP_ML_DSA_65);
627 1 : }
628 :
629 1 : int libspdm_rsp_set_key_pair_info_ack_test(void)
630 : {
631 1 : const struct CMUnitTest test_cases[] = {
632 : /* Success Case to set key pair info*/
633 : cmocka_unit_test(rsp_set_key_pair_info_ack_case1),
634 : /* Can be populated with new test*/
635 : cmocka_unit_test(rsp_set_key_pair_info_ack_case2),
636 : /* The collection of multiple sub-cases.*/
637 : cmocka_unit_test(rsp_set_key_pair_info_ack_case3),
638 : /* Success Case to set key pair info with reset, spdm 1.4*/
639 : cmocka_unit_test(rsp_set_key_pair_info_ack_case4),
640 : /* Reset replay differing only in DesiredPqcAsymAlgo*/
641 : cmocka_unit_test(rsp_set_key_pair_info_ack_case5),
642 : };
643 :
644 1 : libspdm_test_context_t test_context = {
645 : LIBSPDM_TEST_CONTEXT_VERSION,
646 : false,
647 : };
648 1 : libspdm_setup_test_context(&test_context);
649 :
650 1 : return cmocka_run_group_tests(test_cases,
651 : libspdm_unit_test_group_setup,
652 : libspdm_unit_test_group_teardown);
653 : }
654 :
655 : #endif /* LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP*/
|