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_GET_KEY_PAIR_INFO_CAP
12 :
13 : spdm_get_key_pair_info_request_t m_libspdm_get_key_pair_info_request1 = {
14 : { SPDM_MESSAGE_VERSION_13, SPDM_GET_KEY_PAIR_INFO, 0, 0 },
15 : 4
16 : };
17 : size_t m_libspdm_get_key_pair_info_request1_size = sizeof(m_libspdm_get_key_pair_info_request1);
18 :
19 : /**
20 : * Test 1: Successful response to get key pair info with key pair id 4
21 : * Expected Behavior: get a LIBSPDM_STATUS_SUCCESS return code, and correct response message size and fields
22 : **/
23 1 : static void rsp_key_pair_info_case1(void **state)
24 : {
25 : libspdm_return_t status;
26 : libspdm_test_context_t *spdm_test_context;
27 : libspdm_context_t *spdm_context;
28 : size_t response_size;
29 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
30 : spdm_key_pair_info_response_t *spdm_response;
31 : uint8_t key_pair_id;
32 : uint16_t public_key_info_len;
33 1 : uint8_t public_key_info_ecp256[] = {0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
34 : 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
35 : 0x03, 0x01, 0x07};
36 :
37 1 : spdm_test_context = *state;
38 1 : spdm_context = spdm_test_context->spdm_context;
39 1 : spdm_test_context->case_id = 0x1;
40 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
41 : SPDM_VERSION_NUMBER_SHIFT_BIT;
42 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
43 1 : spdm_context->connection_info.algorithm.base_asym_algo = m_libspdm_use_asym_algo;
44 1 : spdm_context->local_context.capability.flags |=
45 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_GET_KEY_PAIR_INFO_CAP;
46 :
47 1 : key_pair_id = 4;
48 1 : public_key_info_len = sizeof(public_key_info_ecp256);
49 :
50 1 : response_size = sizeof(response);
51 :
52 1 : status = libspdm_get_response_key_pair_info(
53 : spdm_context, m_libspdm_get_key_pair_info_request1_size,
54 : &m_libspdm_get_key_pair_info_request1, &response_size, response);
55 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
56 1 : assert_int_equal(response_size, sizeof(spdm_key_pair_info_response_t) + public_key_info_len);
57 1 : spdm_response = (void *)response;
58 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_KEY_PAIR_INFO);
59 1 : assert_int_equal(spdm_response->key_pair_id, key_pair_id);
60 1 : }
61 :
62 : /**
63 : * Test 2:
64 : * An SPDM endpoint shall contain KeyPairID s starting from 1 to TotalKeyPairs inclusive and without gaps.
65 : * KeyPairID is set to 0.
66 : * Expected Behavior: Generate error response message
67 : **/
68 1 : static void rsp_key_pair_info_case2(void **state)
69 : {
70 : libspdm_return_t status;
71 : libspdm_test_context_t *spdm_test_context;
72 : libspdm_context_t *spdm_context;
73 : size_t response_size;
74 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
75 : spdm_key_pair_info_response_t *spdm_response;
76 : uint8_t key_pair_id;
77 :
78 1 : spdm_test_context = *state;
79 1 : spdm_context = spdm_test_context->spdm_context;
80 1 : spdm_test_context->case_id = 0x2;
81 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
82 : SPDM_VERSION_NUMBER_SHIFT_BIT;
83 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
84 1 : spdm_context->local_context.capability.flags |=
85 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_GET_KEY_PAIR_INFO_CAP;
86 :
87 : /* An SPDM endpoint shall contain KeyPairID s starting from 1 to TotalKeyPairs inclusive and without gaps.
88 : * KeyPairID is set to 0.*/
89 1 : key_pair_id = 0;
90 1 : m_libspdm_get_key_pair_info_request1.key_pair_id = key_pair_id;
91 :
92 1 : response_size = sizeof(response);
93 :
94 1 : status = libspdm_get_response_key_pair_info(
95 : spdm_context, m_libspdm_get_key_pair_info_request1_size,
96 : &m_libspdm_get_key_pair_info_request1, &response_size, response);
97 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
98 1 : spdm_response = (void *)response;
99 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
100 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_INVALID_REQUEST);
101 1 : assert_int_equal(spdm_response->header.param2, 0);
102 1 : }
103 :
104 : /**
105 : * Test 3: The key_pair_id is greater than the total key pairs
106 : * Expected Behavior: Generate error response message
107 : **/
108 1 : static void rsp_key_pair_info_case3(void **state)
109 : {
110 : libspdm_return_t status;
111 : libspdm_test_context_t *spdm_test_context;
112 : libspdm_context_t *spdm_context;
113 : size_t response_size;
114 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
115 : spdm_key_pair_info_response_t *spdm_response;
116 : uint8_t key_pair_id;
117 :
118 1 : spdm_test_context = *state;
119 1 : spdm_context = spdm_test_context->spdm_context;
120 1 : spdm_test_context->case_id = 0x3;
121 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
122 : SPDM_VERSION_NUMBER_SHIFT_BIT;
123 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
124 1 : spdm_context->local_context.capability.flags |=
125 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_GET_KEY_PAIR_INFO_CAP;
126 :
127 : /* key_pair_id > total_key_pairs (0xFF exceeds any possible TotalKeyPairs) */
128 1 : key_pair_id = 0xFF;
129 1 : m_libspdm_get_key_pair_info_request1.key_pair_id = key_pair_id;
130 :
131 1 : response_size = sizeof(response);
132 :
133 1 : status = libspdm_get_response_key_pair_info(
134 : spdm_context, m_libspdm_get_key_pair_info_request1_size,
135 : &m_libspdm_get_key_pair_info_request1, &response_size, response);
136 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
137 1 : spdm_response = (void *)response;
138 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
139 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_INVALID_REQUEST);
140 1 : assert_int_equal(spdm_response->header.param2, 0);
141 1 : }
142 :
143 : /**
144 : * Test 4: not set KEY_PAIR_INFO
145 : * Expected Behavior: Generate error response message
146 : **/
147 1 : static void rsp_key_pair_info_case4(void **state)
148 : {
149 : libspdm_return_t status;
150 : libspdm_test_context_t *spdm_test_context;
151 : libspdm_context_t *spdm_context;
152 : size_t response_size;
153 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
154 : spdm_key_pair_info_response_t *spdm_response;
155 : uint8_t key_pair_id;
156 :
157 1 : spdm_test_context = *state;
158 1 : spdm_context = spdm_test_context->spdm_context;
159 1 : spdm_test_context->case_id = 0x4;
160 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
161 : SPDM_VERSION_NUMBER_SHIFT_BIT;
162 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
163 : /* not set KEY_PAIR_INFO*/
164 1 : spdm_context->local_context.capability.flags &=
165 : ~SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_GET_KEY_PAIR_INFO_CAP;
166 :
167 1 : key_pair_id = 1;
168 1 : m_libspdm_get_key_pair_info_request1.key_pair_id = key_pair_id;
169 :
170 1 : response_size = sizeof(response);
171 :
172 1 : status = libspdm_get_response_key_pair_info(
173 : spdm_context, m_libspdm_get_key_pair_info_request1_size,
174 : &m_libspdm_get_key_pair_info_request1, &response_size, response);
175 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
176 1 : spdm_response = (void *)response;
177 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
178 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST);
179 1 : assert_int_equal(spdm_response->header.param2, SPDM_GET_KEY_PAIR_INFO);
180 1 : }
181 :
182 : /**
183 : * Test 5: Successful response to get key pair info with key pair id 4 in SPDM 1.4.
184 : * Expected Behavior: get a LIBSPDM_STATUS_SUCCESS return code, and the response carries the
185 : * SPDM 1.4 PQC tail (PqcAsymAlgoCapLen + PqcAsymAlgoCapabilities + CurrentPqcAsymAlgoLen +
186 : * CurrentPqcAsymAlgo = 10 bytes) exactly, with no extra trailing bytes.
187 : **/
188 1 : static void rsp_key_pair_info_case5(void **state)
189 : {
190 : libspdm_return_t status;
191 : libspdm_test_context_t *spdm_test_context;
192 : libspdm_context_t *spdm_context;
193 : size_t response_size;
194 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
195 : spdm_key_pair_info_response_t *spdm_response;
196 : uint8_t key_pair_id;
197 : uint16_t public_key_info_len;
198 : const uint8_t *ptr;
199 1 : const size_t pqc_tail_size = sizeof(uint8_t) + sizeof(uint32_t) +
200 : sizeof(uint8_t) + sizeof(uint32_t);
201 1 : uint8_t public_key_info_ecp256[] = {0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
202 : 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
203 : 0x03, 0x01, 0x07};
204 :
205 1 : spdm_test_context = *state;
206 1 : spdm_context = spdm_test_context->spdm_context;
207 1 : spdm_test_context->case_id = 0x5;
208 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_14 <<
209 : SPDM_VERSION_NUMBER_SHIFT_BIT;
210 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
211 1 : spdm_context->connection_info.algorithm.base_asym_algo = m_libspdm_use_asym_algo;
212 1 : spdm_context->local_context.capability.flags |=
213 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_GET_KEY_PAIR_INFO_CAP;
214 :
215 1 : key_pair_id = 4;
216 1 : public_key_info_len = sizeof(public_key_info_ecp256);
217 :
218 1 : m_libspdm_get_key_pair_info_request1.header.spdm_version = SPDM_MESSAGE_VERSION_14;
219 1 : m_libspdm_get_key_pair_info_request1.key_pair_id = key_pair_id;
220 :
221 1 : response_size = sizeof(response);
222 :
223 1 : status = libspdm_get_response_key_pair_info(
224 : spdm_context, m_libspdm_get_key_pair_info_request1_size,
225 : &m_libspdm_get_key_pair_info_request1, &response_size, response);
226 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
227 : /* The response shall be exactly the header + public key info + the 10-byte PQC tail. */
228 1 : assert_int_equal(response_size,
229 : sizeof(spdm_key_pair_info_response_t) + public_key_info_len + pqc_tail_size);
230 1 : spdm_response = (void *)response;
231 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_KEY_PAIR_INFO);
232 1 : assert_int_equal(spdm_response->key_pair_id, key_pair_id);
233 1 : assert_int_equal(spdm_response->public_key_info_len, public_key_info_len);
234 :
235 : /* Verify the PQC tail length prefixes are both 4 (sizeof(uint32_t)). */
236 1 : ptr = (const uint8_t *)spdm_response + sizeof(spdm_key_pair_info_response_t) +
237 : public_key_info_len;
238 1 : assert_int_equal(ptr[0], sizeof(uint32_t));
239 1 : assert_int_equal(ptr[sizeof(uint8_t) + sizeof(uint32_t)], sizeof(uint32_t));
240 :
241 : /* restore request version for subsequent runs */
242 1 : m_libspdm_get_key_pair_info_request1.header.spdm_version = SPDM_MESSAGE_VERSION_13;
243 1 : }
244 :
245 1 : int libspdm_rsp_key_pair_info_test(void)
246 : {
247 1 : const struct CMUnitTest test_cases[] = {
248 : /* Success Case to get key pair info*/
249 : cmocka_unit_test(rsp_key_pair_info_case1),
250 : /* The KeyPairID is at least 1 , KeyPairID is set to 0.*/
251 : cmocka_unit_test(rsp_key_pair_info_case2),
252 : /* KeyPairID > total_key_pairs*/
253 : cmocka_unit_test(rsp_key_pair_info_case3),
254 : /* capability not set KEY_PAIR_INFO*/
255 : cmocka_unit_test(rsp_key_pair_info_case4),
256 : /* Success Case to get key pair info in SPDM 1.4 (exact PQC tail size)*/
257 : cmocka_unit_test(rsp_key_pair_info_case5),
258 : };
259 :
260 1 : libspdm_test_context_t test_context = {
261 : LIBSPDM_TEST_CONTEXT_VERSION,
262 : false,
263 : };
264 1 : libspdm_setup_test_context(&test_context);
265 :
266 1 : return cmocka_run_group_tests(test_cases,
267 : libspdm_unit_test_group_setup,
268 : libspdm_unit_test_group_teardown);
269 : }
270 :
271 : #endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP*/
|