Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2024 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 <stdarg.h>
8 : #include <stddef.h>
9 : #include <setjmp.h>
10 : #include <stdint.h>
11 : #include <stdlib.h>
12 : #include <stdio.h>
13 : #include <assert.h>
14 : #include <string.h>
15 :
16 : #include <base.h>
17 : #include "library/memlib.h"
18 : #include "spdm_device_secret_lib_internal.h"
19 : #include "internal/libspdm_common_lib.h"
20 :
21 : #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP
22 19 : bool libspdm_read_cached_last_csr_request(uint8_t **last_csr_request,
23 : size_t *last_csr_request_len,
24 : uint8_t req_csr_tracking_tag,
25 : uint8_t *available_rsp_csr_tracking_tag)
26 : {
27 : bool res;
28 : uint8_t index;
29 : size_t file_size;
30 : uint8_t *file_data;
31 :
32 19 : file_data = NULL;
33 19 : *available_rsp_csr_tracking_tag = 0;
34 19 : char file[] = "cached_last_csr_x_request";
35 : /*change the file name, for example: cached_last_csr_1_request*/
36 19 : file[16] = (char)(req_csr_tracking_tag + '0');
37 19 : res = libspdm_read_input_file(file, (void **)last_csr_request, last_csr_request_len);
38 :
39 152 : for (index = 1; index <= SPDM_MAX_CSR_TRACKING_TAG; index++) {
40 133 : file[16] = (char)(index + '0');
41 133 : libspdm_read_input_file(file, (void **)(&file_data), &file_size);
42 133 : if (file_size == 0) {
43 85 : *available_rsp_csr_tracking_tag |= (1 << index);
44 : } else {
45 48 : if (file_data != NULL) {
46 35 : free(file_data);
47 : }
48 : }
49 : }
50 :
51 19 : return res;
52 : }
53 :
54 13 : bool libspdm_cache_last_csr_request(const uint8_t *last_csr_request,
55 : size_t last_csr_request_len,
56 : uint8_t req_csr_tracking_tag)
57 : {
58 : bool res;
59 :
60 13 : char file[] = "cached_last_csr_x_request";
61 : /*change the file name, for example: cached_last_csr_1_request*/
62 13 : file[16] = (char)(req_csr_tracking_tag + '0');
63 13 : res = libspdm_write_output_file(file, last_csr_request, last_csr_request_len);
64 :
65 13 : return res;
66 : }
67 :
68 : /*clean the cached last SPDM csr request*/
69 1 : bool libspdm_discard_all_cached_last_request()
70 : {
71 : uint8_t index;
72 :
73 1 : char file[] = "cached_last_csr_x_request";
74 :
75 8 : for (index = 1; index <= SPDM_MAX_CSR_TRACKING_TAG; index++) {
76 7 : file[16] = (char)(index + '0');
77 7 : if (!libspdm_write_output_file(file, NULL, 0)) {
78 0 : return false;
79 : }
80 : }
81 :
82 1 : return true;
83 : }
84 :
85 : /*
86 : * return true represent that: the device complete the csr by reset successfully
87 : * return false represent that: the device complete the csr need reset
88 : **/
89 4 : bool libspdm_read_cached_csr(uint8_t **csr_pointer, size_t *csr_len)
90 : {
91 : bool res;
92 : char *file;
93 :
94 4 : file = "test_csr/cached.csr";
95 :
96 4 : res = libspdm_read_input_file(file, (void **)csr_pointer, csr_len);
97 4 : return res;
98 : }
99 :
100 6 : bool libspdm_gen_csr_without_reset(uint32_t base_hash_algo, uint32_t base_asym_algo,
101 : uint32_t pqc_asym_algo,
102 : uint8_t *requester_info, size_t requester_info_length,
103 : uint8_t *opaque_data, uint16_t opaque_data_length,
104 : size_t *csr_len, uint8_t *csr_pointer,
105 : bool is_device_cert_model)
106 : {
107 : bool result;
108 : size_t hash_nid;
109 : size_t asym_nid;
110 : size_t pqc_asym_nid;
111 : void *context;
112 : size_t csr_buffer_size;
113 :
114 6 : csr_buffer_size = *csr_len;
115 :
116 : #if !LIBSPDM_PRIVATE_KEY_MODE_RAW_KEY_ONLY
117 6 : if (g_private_key_mode) {
118 : void *x509_ca_cert;
119 : void *prikey, *cert;
120 : size_t prikey_size, cert_size;
121 :
122 6 : if (pqc_asym_algo != 0) {
123 0 : result = libspdm_read_responder_pqc_private_key(
124 : pqc_asym_algo, &prikey, &prikey_size);
125 : } else {
126 6 : result = libspdm_read_responder_private_key(
127 : base_asym_algo, &prikey, &prikey_size);
128 : }
129 6 : if (!result) {
130 0 : return false;
131 : }
132 :
133 6 : if (pqc_asym_algo != 0) {
134 0 : result = libspdm_read_responder_pqc_certificate(
135 : pqc_asym_algo, &cert, &cert_size);
136 : } else {
137 6 : result = libspdm_read_responder_certificate(
138 : base_asym_algo, &cert, &cert_size);
139 : }
140 6 : if (!result) {
141 0 : return false;
142 : }
143 :
144 6 : result = libspdm_x509_construct_certificate(cert, cert_size,
145 : (uint8_t **)&x509_ca_cert);
146 6 : if ((x509_ca_cert == NULL) || (!result)) {
147 0 : return false;
148 : }
149 :
150 6 : if (pqc_asym_algo != 0) {
151 0 : result = libspdm_pqc_asym_get_private_key_from_pem(
152 : pqc_asym_algo, prikey, prikey_size, NULL, &context);
153 : } else {
154 6 : result = libspdm_asym_get_private_key_from_pem(
155 : base_asym_algo, prikey, prikey_size, NULL, &context);
156 : }
157 6 : if (!result) {
158 0 : libspdm_zero_mem(prikey, prikey_size);
159 0 : free(prikey);
160 0 : return false;
161 : }
162 6 : hash_nid = libspdm_get_hash_nid(base_hash_algo);
163 6 : asym_nid = libspdm_get_aysm_nid(base_asym_algo);
164 6 : pqc_asym_nid = libspdm_get_pqc_aysm_nid(pqc_asym_algo);
165 :
166 6 : char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1";
167 :
168 6 : if (pqc_asym_algo != 0) {
169 0 : result = libspdm_gen_x509_csr_with_pqc(hash_nid, 0, pqc_asym_nid,
170 : requester_info, requester_info_length,
171 0 : !is_device_cert_model,
172 : context, subject_name,
173 : csr_len, csr_pointer,
174 0 : x509_ca_cert);
175 0 : libspdm_pqc_asym_free(pqc_asym_algo, context);
176 : } else {
177 6 : result = libspdm_gen_x509_csr(hash_nid, asym_nid,
178 : requester_info, requester_info_length,
179 6 : !is_device_cert_model,
180 : context, subject_name,
181 : csr_len, csr_pointer,
182 6 : x509_ca_cert);
183 6 : libspdm_asym_free(base_asym_algo, context);
184 : }
185 6 : libspdm_zero_mem(prikey, prikey_size);
186 6 : free(prikey);
187 6 : free(cert);
188 : } else {
189 : #endif
190 : void *x509_ca_cert;
191 : void *cert;
192 : size_t cert_size;
193 :
194 0 : if (pqc_asym_algo != 0) {
195 0 : result = libspdm_get_responder_pqc_private_key_from_raw_data(pqc_asym_algo, &context);
196 : } else {
197 0 : result = libspdm_get_responder_private_key_from_raw_data(base_asym_algo, &context);
198 : }
199 0 : if (!result) {
200 0 : return false;
201 : }
202 :
203 0 : if (pqc_asym_algo != 0) {
204 0 : result = libspdm_read_responder_pqc_certificate(
205 : pqc_asym_algo, &cert, &cert_size);
206 : } else {
207 0 : result = libspdm_read_responder_certificate(
208 : base_asym_algo, &cert, &cert_size);
209 : }
210 0 : if (!result) {
211 0 : return false;
212 : }
213 :
214 0 : result = libspdm_x509_construct_certificate(cert, cert_size,
215 : (uint8_t **)&x509_ca_cert);
216 0 : if ((x509_ca_cert == NULL) || (!result)) {
217 0 : return false;
218 : }
219 :
220 0 : hash_nid = libspdm_get_hash_nid(base_hash_algo);
221 0 : asym_nid = libspdm_get_aysm_nid(base_asym_algo);
222 0 : pqc_asym_nid = libspdm_get_pqc_aysm_nid(pqc_asym_algo);
223 :
224 0 : char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1";
225 :
226 0 : if (pqc_asym_algo != 0) {
227 0 : result = libspdm_gen_x509_csr_with_pqc(hash_nid, 0, pqc_asym_nid,
228 : requester_info, requester_info_length,
229 0 : !is_device_cert_model,
230 : context, subject_name,
231 : csr_len, csr_pointer,
232 0 : x509_ca_cert);
233 0 : libspdm_pqc_asym_free(pqc_asym_algo, context);
234 : } else {
235 0 : result = libspdm_gen_x509_csr(hash_nid, asym_nid,
236 : requester_info, requester_info_length,
237 0 : !is_device_cert_model,
238 : context, subject_name,
239 : csr_len, csr_pointer,
240 0 : x509_ca_cert);
241 0 : libspdm_asym_free(base_asym_algo, context);
242 : }
243 0 : free(cert);
244 : #if !LIBSPDM_PRIVATE_KEY_MODE_RAW_KEY_ONLY
245 : }
246 : #endif
247 :
248 6 : if (csr_buffer_size < *csr_len) {
249 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"csr buffer is too small to store generated csr! \n"));
250 0 : result = false;
251 : }
252 6 : return result;
253 : }
254 :
255 10 : bool libspdm_gen_csr(
256 : #if LIBSPDM_HAL_PASS_SPDM_CONTEXT
257 : void *spdm_context,
258 : #endif
259 : uint32_t base_hash_algo, uint32_t base_asym_algo, bool *need_reset,
260 : const void *request, size_t request_size,
261 : uint8_t *requester_info, size_t requester_info_length,
262 : uint8_t *opaque_data, uint16_t opaque_data_length,
263 : size_t *csr_len, uint8_t *csr_pointer,
264 : bool is_device_cert_model
265 : #if LIBSPDM_SET_CERT_CSR_PARAMS
266 : , bool *is_busy, bool *unexpected_request
267 : #endif
268 : )
269 : {
270 : bool result;
271 : uint8_t *cached_last_csr_request;
272 : size_t cached_last_request_len;
273 : uint8_t *cached_csr;
274 : size_t csr_buffer_size;
275 : uint8_t rsp_csr_tracking_tag;
276 :
277 10 : csr_buffer_size = *csr_len;
278 :
279 : /*device gen csr need reset*/
280 10 : if (*need_reset) {
281 4 : result = libspdm_read_cached_last_csr_request(&cached_last_csr_request,
282 : &cached_last_request_len,
283 : 1, &rsp_csr_tracking_tag);
284 :
285 : /*get the cached last csr request and csr*/
286 4 : if ((result) &&
287 5 : (cached_last_request_len == request_size) &&
288 2 : (libspdm_consttime_is_mem_equal(cached_last_csr_request, request,
289 2 : request_size)) &&
290 2 : (libspdm_read_cached_csr(&cached_csr, csr_len)) &&
291 1 : (*csr_len != 0)) {
292 :
293 : /*get and save cached csr*/
294 1 : if (csr_buffer_size < *csr_len) {
295 0 : free(cached_csr);
296 0 : free(cached_last_csr_request);
297 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
298 : "csr buffer is too small to store cached csr! \n"));
299 0 : return false;
300 : } else {
301 1 : libspdm_copy_mem(csr_pointer, csr_buffer_size, cached_csr, *csr_len);
302 : }
303 :
304 : /*device don't need reset this time*/
305 1 : *need_reset = false;
306 :
307 1 : free(cached_csr);
308 1 : free(cached_last_csr_request);
309 1 : return true;
310 : } else {
311 3 : if (cached_last_csr_request != NULL) {
312 2 : free(cached_last_csr_request);
313 : }
314 :
315 : /*device need reset this time: cache the last_csr_request */
316 3 : result = libspdm_cache_last_csr_request(request, request_size, 1);
317 3 : if (!result) {
318 0 : return result;
319 : }
320 :
321 : /*device need reset this time*/
322 3 : *need_reset = true;
323 3 : return true;
324 : }
325 : } else {
326 6 : result = libspdm_gen_csr_without_reset(base_hash_algo, base_asym_algo, 0,
327 : requester_info, requester_info_length,
328 : opaque_data, opaque_data_length,
329 : csr_len, csr_pointer, is_device_cert_model);
330 6 : return result;
331 : }
332 :
333 : }
334 :
335 : #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX
336 15 : bool libspdm_gen_csr_ex(
337 : #if LIBSPDM_HAL_PASS_SPDM_CONTEXT
338 : void *spdm_context,
339 : #endif
340 : uint32_t base_hash_algo, uint32_t base_asym_algo, uint32_t pqc_asym_algo,
341 : bool *need_reset,
342 : const void *request, size_t request_size,
343 : uint8_t *requester_info, size_t requester_info_length,
344 : uint8_t *opaque_data, uint16_t opaque_data_length,
345 : size_t *csr_len, uint8_t *csr_pointer,
346 : uint8_t req_cert_model,
347 : uint8_t *req_csr_tracking_tag,
348 : uint8_t req_key_pair_id,
349 : bool overwrite
350 : #if LIBSPDM_SET_CERT_CSR_PARAMS
351 : , bool *is_busy, bool *unexpected_request
352 : #endif
353 : )
354 : {
355 : bool result;
356 : uint8_t *cached_last_csr_request;
357 : size_t cached_last_request_len;
358 : uint8_t *cached_csr;
359 : size_t csr_buffer_size;
360 : uint8_t rsp_csr_tracking_tag;
361 : uint8_t available_csr_tracking_tag;
362 : uint8_t *request_change;
363 : uint8_t index;
364 : bool flag;
365 : bool is_device_cert_model;
366 :
367 15 : available_csr_tracking_tag = 0;
368 15 : csr_buffer_size = *csr_len;
369 :
370 : /*device gen csr need reset*/
371 15 : if (*need_reset) {
372 15 : result = libspdm_read_cached_last_csr_request(&cached_last_csr_request,
373 : &cached_last_request_len,
374 15 : *req_csr_tracking_tag,
375 : &rsp_csr_tracking_tag);
376 :
377 48 : for (index = 1; index <= SPDM_MAX_CSR_TRACKING_TAG; index++) {
378 47 : if (((rsp_csr_tracking_tag >> index) & 0x01) == 0x01) {
379 14 : available_csr_tracking_tag = index;
380 14 : break;
381 : }
382 : }
383 :
384 15 : if (*req_csr_tracking_tag == 0) {
385 11 : if (available_csr_tracking_tag == 0) {
386 : /*no available tracking tag*/
387 : #if LIBSPDM_SET_CERT_CSR_PARAMS
388 : *is_busy = true;
389 : #endif
390 1 : return false;
391 : } else {
392 10 : flag = false;
393 : }
394 : } else {
395 : /*matched csr_tracking_tag*/
396 4 : if (((rsp_csr_tracking_tag >> *req_csr_tracking_tag) & 0x01) == 0) {
397 2 : flag = true;
398 : } else {
399 : /*unexpected*/
400 2 : return false;
401 : }
402 : }
403 :
404 : /*get the cached last csr request and csr*/
405 12 : if ((result) &&
406 4 : (cached_last_request_len == request_size) &&
407 2 : (libspdm_consttime_is_mem_equal(cached_last_csr_request, request,
408 2 : request_size)) &&
409 2 : (libspdm_read_cached_csr(&cached_csr, csr_len)) &&
410 1 : (*csr_len != 0) &&
411 : (flag)) {
412 :
413 : /*get and save cached csr*/
414 1 : if (csr_buffer_size < *csr_len) {
415 0 : free(cached_csr);
416 0 : free(cached_last_csr_request);
417 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
418 : "csr buffer is too small to store cached csr! \n"));
419 0 : return false;
420 : } else {
421 1 : libspdm_copy_mem(csr_pointer, csr_buffer_size, cached_csr, *csr_len);
422 : }
423 :
424 : /*device don't need reset this time*/
425 1 : *need_reset = false;
426 :
427 1 : free(cached_csr);
428 1 : free(cached_last_csr_request);
429 1 : return true;
430 : } else {
431 11 : if (cached_last_csr_request != NULL) {
432 1 : free(cached_last_csr_request);
433 : }
434 :
435 11 : if ((*req_csr_tracking_tag == 0) && (available_csr_tracking_tag != 0)) {
436 10 : request_change = malloc(request_size);
437 10 : libspdm_copy_mem(request_change, request_size, request,request_size);
438 :
439 10 : if (overwrite) {
440 1 : available_csr_tracking_tag = 1;
441 : /*discard all previously generated CSRTrackingTags. */
442 1 : result = libspdm_discard_all_cached_last_request();
443 1 : if (!result) {
444 0 : free(request_change);
445 0 : return result;
446 : }
447 : }
448 :
449 10 : request_change[3] |=
450 : (available_csr_tracking_tag <<
451 : SPDM_GET_CSR_REQUEST_ATTRIBUTES_CSR_TRACKING_TAG_OFFSET);
452 :
453 : /*device need reset this time: cache the last_csr_request */
454 10 : result = libspdm_cache_last_csr_request(request_change,
455 : request_size, available_csr_tracking_tag);
456 10 : if (!result) {
457 0 : free(request_change);
458 0 : return result;
459 : }
460 :
461 : /*device need reset this time*/
462 10 : *need_reset = true;
463 10 : *req_csr_tracking_tag = available_csr_tracking_tag;
464 10 : free(request_change);
465 10 : return true;
466 : } else {
467 : /*the device is busy*/
468 : #if LIBSPDM_SET_CERT_CSR_PARAMS
469 : *is_busy = true;
470 : #endif
471 1 : return false;
472 : }
473 : }
474 : } else {
475 0 : if (req_cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT) {
476 0 : is_device_cert_model = true;
477 : } else {
478 0 : is_device_cert_model = false;
479 : }
480 0 : result = libspdm_gen_csr_without_reset(base_hash_algo, base_asym_algo, pqc_asym_algo,
481 : requester_info, requester_info_length,
482 : opaque_data, opaque_data_length,
483 : csr_len, csr_pointer, is_device_cert_model);
484 0 : return result;
485 : }
486 : }
487 : #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX*/
488 :
489 : #endif /* LIBSPDM_ENABLE_CAPABILITY_CSR_CAP */
|