Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2024-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 "internal/libspdm_responder_lib.h"
8 :
9 : #if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP
10 :
11 21 : libspdm_return_t libspdm_get_response_set_key_pair_info_ack(libspdm_context_t *spdm_context,
12 : size_t request_size,
13 : const void *request,
14 : size_t *response_size,
15 : void *response)
16 : {
17 : const spdm_set_key_pair_info_request_t *spdm_request;
18 : spdm_set_key_pair_info_ack_response_t *spdm_response;
19 :
20 : libspdm_session_info_t *session_info;
21 : libspdm_session_state_t session_state;
22 :
23 : uint16_t capabilities;
24 : uint16_t key_usage_capabilities;
25 : uint16_t current_key_usage;
26 : uint32_t asym_algo_capabilities;
27 : uint32_t current_asym_algo;
28 : uint32_t pqc_asym_algo_capabilities;
29 : uint32_t current_pqc_asym_algo;
30 : uint8_t assoc_cert_slot_mask;
31 : uint8_t key_pair_id;
32 : uint8_t total_key_pairs;
33 : bool result;
34 :
35 : uint16_t desired_key_usage;
36 : uint32_t desired_asym_algo;
37 : uint8_t desired_assoc_cert_slot_mask;
38 : uint8_t desired_pqc_asym_algo_len;
39 : uint32_t desired_pqc_asym_algo;
40 : uint8_t operation;
41 : bool need_reset;
42 : const uint8_t *ptr;
43 :
44 21 : spdm_request = request;
45 :
46 : /* -=[Check Parameters Phase]=- */
47 21 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_SET_KEY_PAIR_INFO);
48 :
49 21 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) {
50 0 : return libspdm_generate_error_response(spdm_context,
51 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
52 : SPDM_SET_KEY_PAIR_INFO,
53 : response_size, response);
54 : }
55 :
56 21 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
57 0 : return libspdm_generate_error_response(spdm_context,
58 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
59 : response_size, response);
60 : }
61 :
62 21 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
63 0 : return libspdm_responder_handle_response_state(spdm_context,
64 0 : spdm_request->header.request_response_code,
65 : response_size, response);
66 : }
67 :
68 21 : if (request_size < sizeof(spdm_set_key_pair_info_request_t)) {
69 0 : return libspdm_generate_error_response(spdm_context,
70 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
71 : response_size, response);
72 : }
73 :
74 21 : if (spdm_context->connection_info.connection_state <
75 : LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
76 0 : return libspdm_generate_error_response(
77 : spdm_context,
78 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
79 : response_size, response);
80 : }
81 :
82 21 : if (spdm_context->last_spdm_request_session_id_valid) {
83 0 : session_info = libspdm_get_session_info_via_session_id(
84 : spdm_context,
85 : spdm_context->last_spdm_request_session_id);
86 0 : if (session_info == NULL) {
87 0 : return libspdm_generate_error_response(
88 : spdm_context,
89 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
90 : response_size, response);
91 : }
92 0 : session_state = libspdm_secured_message_get_session_state(
93 : session_info->secured_message_context);
94 0 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
95 0 : return libspdm_generate_error_response(
96 : spdm_context,
97 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
98 : response_size, response);
99 : }
100 : }
101 :
102 21 : if (!libspdm_is_capabilities_flag_supported(
103 : spdm_context, false, 0,
104 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_INFO_CAP)) {
105 0 : return libspdm_generate_error_response(
106 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
107 : SPDM_SET_KEY_PAIR_INFO, response_size, response);
108 : }
109 :
110 21 : total_key_pairs = spdm_context->local_context.total_key_pairs;
111 21 : key_pair_id = spdm_request->key_pair_id;
112 21 : if ((key_pair_id == 0) || (key_pair_id > total_key_pairs)) {
113 1 : return libspdm_generate_error_response(spdm_context,
114 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
115 : response_size, response);
116 : }
117 :
118 20 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_set_key_pair_info_ack_response_t));
119 :
120 20 : libspdm_zero_mem(response, *response_size);
121 :
122 20 : result = libspdm_read_key_pair_info(
123 : spdm_context,
124 : key_pair_id,
125 : &capabilities,
126 : &key_usage_capabilities,
127 : ¤t_key_usage,
128 : &asym_algo_capabilities,
129 : ¤t_asym_algo,
130 : &pqc_asym_algo_capabilities,
131 : ¤t_pqc_asym_algo,
132 : &assoc_cert_slot_mask,
133 : NULL, NULL);
134 20 : if (!result) {
135 0 : return libspdm_generate_error_response(spdm_context,
136 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
137 : response_size, response);
138 : }
139 :
140 20 : operation = spdm_request->header.param1;
141 :
142 20 : if (operation != SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION) {
143 14 : if (request_size < sizeof(spdm_set_key_pair_info_request_t) +
144 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t)) {
145 1 : return libspdm_generate_error_response(spdm_context,
146 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
147 : response_size, response);
148 : }
149 :
150 13 : ptr = (const uint8_t*)(spdm_request + 1);
151 13 : ptr += sizeof(uint8_t);
152 :
153 13 : desired_key_usage = libspdm_read_uint16((const uint8_t *)ptr);
154 13 : ptr += sizeof(uint16_t);
155 :
156 13 : desired_asym_algo = libspdm_read_uint32((const uint8_t *)ptr);
157 13 : ptr += sizeof(uint32_t);
158 :
159 13 : desired_assoc_cert_slot_mask = *ptr;
160 13 : ptr += sizeof(uint8_t);
161 :
162 13 : desired_pqc_asym_algo = 0;
163 13 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_14) {
164 4 : if (request_size < sizeof(spdm_set_key_pair_info_request_t) +
165 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t) +
166 : sizeof(uint8_t)) {
167 0 : return libspdm_generate_error_response(spdm_context,
168 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
169 : response_size, response);
170 : }
171 :
172 4 : desired_pqc_asym_algo_len = *ptr;
173 4 : ptr += sizeof(uint8_t);
174 :
175 4 : if (request_size < sizeof(spdm_set_key_pair_info_request_t) +
176 : sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t) +
177 4 : sizeof(uint8_t) + desired_pqc_asym_algo_len) {
178 0 : return libspdm_generate_error_response(spdm_context,
179 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
180 : response_size, response);
181 : }
182 :
183 4 : if (desired_pqc_asym_algo_len > sizeof(uint32_t)) {
184 0 : desired_pqc_asym_algo_len = sizeof(uint32_t);
185 : }
186 4 : libspdm_copy_mem (&desired_pqc_asym_algo, sizeof(desired_pqc_asym_algo),
187 : ptr, desired_pqc_asym_algo_len);
188 4 : ptr += desired_pqc_asym_algo_len;
189 : }
190 :
191 : } else {
192 6 : desired_key_usage = 0;
193 6 : desired_asym_algo = 0;
194 6 : desired_pqc_asym_algo = 0;
195 6 : desired_assoc_cert_slot_mask = 0;
196 : }
197 :
198 19 : if (((capabilities & SPDM_KEY_PAIR_CAP_GEN_KEY_CAP) == 0) &&
199 : (operation == SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION)) {
200 0 : return libspdm_generate_error_response(spdm_context,
201 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
202 : response_size, response);
203 : }
204 19 : if (((capabilities & SPDM_KEY_PAIR_CAP_ERASABLE_CAP) == 0) &&
205 : (operation == SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION)) {
206 0 : return libspdm_generate_error_response(spdm_context,
207 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
208 : response_size, response);
209 : }
210 19 : if (((capabilities & SPDM_KEY_PAIR_CAP_CERT_ASSOC_CAP) == 0) &&
211 0 : (desired_assoc_cert_slot_mask != 0) &&
212 0 : (desired_assoc_cert_slot_mask != assoc_cert_slot_mask)) {
213 0 : return libspdm_generate_error_response(spdm_context,
214 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
215 : response_size, response);
216 : }
217 :
218 19 : if (((capabilities & SPDM_KEY_PAIR_CAP_KEY_USAGE_CAP) == 0) && (desired_key_usage != 0)) {
219 0 : return libspdm_generate_error_response(spdm_context,
220 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
221 : response_size, response);
222 : }
223 19 : if ((desired_key_usage != 0) &&
224 6 : ((key_usage_capabilities | desired_key_usage) != key_usage_capabilities)) {
225 0 : return libspdm_generate_error_response(spdm_context,
226 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
227 : response_size, response);
228 : }
229 :
230 19 : if (((capabilities & SPDM_KEY_PAIR_CAP_ASYM_ALGO_CAP) == 0) &&
231 0 : ((desired_asym_algo != 0) || (desired_pqc_asym_algo != 0))) {
232 0 : return libspdm_generate_error_response(spdm_context,
233 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
234 : response_size, response);
235 : }
236 19 : if (!libspdm_onehot0(desired_asym_algo) || !libspdm_onehot0(desired_pqc_asym_algo)) {
237 1 : return libspdm_generate_error_response(spdm_context,
238 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
239 : response_size, response);
240 : }
241 18 : if ((desired_asym_algo != 0) && (desired_pqc_asym_algo != 0)) {
242 0 : return libspdm_generate_error_response(spdm_context,
243 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
244 : response_size, response);
245 : }
246 18 : if ((desired_asym_algo != 0) &&
247 5 : ((asym_algo_capabilities | desired_asym_algo) != asym_algo_capabilities)) {
248 0 : return libspdm_generate_error_response(spdm_context,
249 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
250 : response_size, response);
251 : }
252 18 : if ((desired_pqc_asym_algo != 0) &&
253 0 : ((pqc_asym_algo_capabilities | desired_pqc_asym_algo) != pqc_asym_algo_capabilities)) {
254 0 : return libspdm_generate_error_response(
255 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
256 : SPDM_SET_KEY_PAIR_INFO, response_size, response);
257 : }
258 :
259 18 : if (((capabilities & SPDM_KEY_PAIR_CAP_SHAREABLE_CAP) == 0) &&
260 0 : (!libspdm_onehot0(desired_assoc_cert_slot_mask))) {
261 0 : return libspdm_generate_error_response(spdm_context,
262 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
263 : response_size, response);
264 : }
265 18 : if (operation > SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION) {
266 0 : return libspdm_generate_error_response(spdm_context,
267 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
268 : response_size, response);
269 : }
270 18 : if ((operation == SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION) ||
271 : (operation == SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION)) {
272 6 : if (assoc_cert_slot_mask != 0) {
273 1 : return libspdm_generate_error_response(spdm_context,
274 : SPDM_ERROR_CODE_OPERATION_FAILED, 0,
275 : response_size, response);
276 : }
277 : }
278 :
279 17 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
280 6 : need_reset = libspdm_is_capabilities_flag_supported(
281 : spdm_context, false, 0,
282 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_RESET_CAP);
283 : } else {
284 11 : need_reset = libspdm_is_capabilities_flag_supported(
285 : spdm_context, false, 0,
286 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP);
287 : }
288 17 : result = libspdm_write_key_pair_info(
289 : spdm_context,
290 : key_pair_id,
291 : operation,
292 : desired_key_usage,
293 : desired_asym_algo,
294 : desired_pqc_asym_algo,
295 : desired_assoc_cert_slot_mask,
296 : &need_reset);
297 17 : if (!result) {
298 0 : return libspdm_generate_error_response(spdm_context,
299 : SPDM_ERROR_CODE_OPERATION_FAILED, 0,
300 : response_size, response);
301 : }
302 :
303 17 : spdm_response = response;
304 17 : *response_size = sizeof(spdm_set_key_pair_info_ack_response_t);
305 :
306 17 : if (need_reset) {
307 8 : return libspdm_generate_error_response(spdm_context,
308 : SPDM_ERROR_CODE_RESET_REQUIRED, 0,
309 : response_size, response);
310 : } else {
311 9 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
312 9 : spdm_response->header.request_response_code = SPDM_SET_KEY_PAIR_INFO_ACK;
313 9 : spdm_response->header.param1 = 0;
314 9 : spdm_response->header.param2 = 0;
315 : }
316 :
317 9 : return LIBSPDM_STATUS_SUCCESS;
318 : }
319 :
320 : #endif /*LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP*/
|