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 15 : 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 15 : spdm_request = request;
45 :
46 : /* -=[Check Parameters Phase]=- */
47 15 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_SET_KEY_PAIR_INFO);
48 :
49 15 : 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 15 : 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 15 : 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 15 : 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 15 : 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 15 : 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 15 : 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 15 : total_key_pairs = spdm_context->local_context.total_key_pairs;
111 15 : key_pair_id = spdm_request->key_pair_id;
112 15 : 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 14 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_set_key_pair_info_ack_response_t));
119 :
120 14 : libspdm_zero_mem(response, *response_size);
121 :
122 14 : 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 14 : if (!result) {
135 0 : return libspdm_generate_error_response(spdm_context,
136 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
137 : response_size, response);
138 : }
139 :
140 14 : operation = spdm_request->header.param1;
141 :
142 14 : if (operation != SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION) {
143 10 : 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 9 : ptr = (const uint8_t*)(spdm_request + 1);
151 9 : ptr += sizeof(uint8_t);
152 :
153 9 : desired_key_usage = libspdm_read_uint16((const uint8_t *)ptr);
154 9 : ptr += sizeof(uint16_t);
155 :
156 9 : desired_asym_algo = libspdm_read_uint32((const uint8_t *)ptr);
157 9 : ptr += sizeof(uint32_t);
158 :
159 9 : desired_assoc_cert_slot_mask = *ptr;
160 9 : ptr += sizeof(uint8_t);
161 :
162 9 : desired_pqc_asym_algo = 0;
163 9 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_14) {
164 0 : 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 0 : desired_pqc_asym_algo_len = *ptr;
173 0 : ptr += sizeof(uint8_t);
174 :
175 0 : 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 0 : 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 0 : if (desired_pqc_asym_algo_len > sizeof(uint32_t)) {
184 0 : desired_pqc_asym_algo_len = sizeof(uint32_t);
185 : }
186 0 : libspdm_copy_mem (&desired_pqc_asym_algo, sizeof(desired_pqc_asym_algo),
187 : ptr, desired_pqc_asym_algo_len);
188 0 : ptr += desired_pqc_asym_algo_len;
189 : }
190 :
191 : } else {
192 4 : desired_key_usage = 0;
193 4 : desired_asym_algo = 0;
194 4 : desired_pqc_asym_algo = 0;
195 4 : desired_assoc_cert_slot_mask = 0;
196 : }
197 :
198 13 : 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 13 : 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 13 : 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 13 : 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 13 : if ((desired_key_usage != 0) &&
224 4 : ((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 13 : 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 13 : 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 12 : 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 12 : if ((desired_asym_algo != 0) &&
247 3 : ((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 12 : 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 12 : 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 12 : 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 12 : if ((operation == SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION) ||
271 : (operation == SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION)) {
272 4 : 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 11 : need_reset = libspdm_is_capabilities_flag_supported(
280 : spdm_context, false, 0,
281 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP);
282 11 : result = libspdm_write_key_pair_info(
283 : spdm_context,
284 : key_pair_id,
285 : operation,
286 : desired_key_usage,
287 : desired_asym_algo,
288 : desired_pqc_asym_algo,
289 : desired_assoc_cert_slot_mask,
290 : &need_reset);
291 11 : if (!result) {
292 0 : return libspdm_generate_error_response(spdm_context,
293 : SPDM_ERROR_CODE_OPERATION_FAILED, 0,
294 : response_size, response);
295 : }
296 :
297 11 : spdm_response = response;
298 11 : *response_size = sizeof(spdm_set_key_pair_info_ack_response_t);
299 :
300 11 : if (need_reset) {
301 5 : return libspdm_generate_error_response(spdm_context,
302 : SPDM_ERROR_CODE_RESET_REQUIRED, 0,
303 : response_size, response);
304 : } else {
305 6 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
306 6 : spdm_response->header.request_response_code = SPDM_SET_KEY_PAIR_INFO_ACK;
307 6 : spdm_response->header.param1 = 0;
308 6 : spdm_response->header.param2 = 0;
309 : }
310 :
311 6 : return LIBSPDM_STATUS_SUCCESS;
312 : }
313 :
314 : #endif /*LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP*/
|