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 : libspdm_x509_free(x509_ca_cert);
161 0 : return false;
162 : }
163 6 : hash_nid = libspdm_get_hash_nid(base_hash_algo);
164 6 : asym_nid = libspdm_get_aysm_nid(base_asym_algo);
165 6 : pqc_asym_nid = libspdm_get_pqc_aysm_nid(pqc_asym_algo);
166 :
167 6 : char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1";
168 :
169 6 : if (pqc_asym_algo != 0) {
170 0 : result = libspdm_gen_x509_csr_with_pqc(hash_nid, 0, pqc_asym_nid,
171 : requester_info, requester_info_length,
172 0 : !is_device_cert_model,
173 : context, subject_name,
174 : csr_len, csr_pointer,
175 0 : x509_ca_cert);
176 0 : libspdm_pqc_asym_free(pqc_asym_algo, context);
177 : } else {
178 6 : result = libspdm_gen_x509_csr(hash_nid, asym_nid,
179 : requester_info, requester_info_length,
180 6 : !is_device_cert_model,
181 : context, subject_name,
182 : csr_len, csr_pointer,
183 6 : x509_ca_cert);
184 6 : libspdm_asym_free(base_asym_algo, context);
185 : }
186 6 : libspdm_zero_mem(prikey, prikey_size);
187 6 : free(prikey);
188 6 : free(cert);
189 6 : libspdm_x509_free(x509_ca_cert);
190 : } else {
191 : #endif
192 : void *x509_ca_cert;
193 : void *cert;
194 : size_t cert_size;
195 :
196 0 : if (pqc_asym_algo != 0) {
197 0 : result = libspdm_get_responder_pqc_private_key_from_raw_data(pqc_asym_algo, &context);
198 : } else {
199 0 : result = libspdm_get_responder_private_key_from_raw_data(base_asym_algo, &context);
200 : }
201 0 : if (!result) {
202 0 : return false;
203 : }
204 :
205 0 : if (pqc_asym_algo != 0) {
206 0 : result = libspdm_read_responder_pqc_certificate(
207 : pqc_asym_algo, &cert, &cert_size);
208 : } else {
209 0 : result = libspdm_read_responder_certificate(
210 : base_asym_algo, &cert, &cert_size);
211 : }
212 0 : if (!result) {
213 0 : return false;
214 : }
215 :
216 0 : result = libspdm_x509_construct_certificate(cert, cert_size,
217 : (uint8_t **)&x509_ca_cert);
218 0 : if ((x509_ca_cert == NULL) || (!result)) {
219 0 : return false;
220 : }
221 :
222 0 : hash_nid = libspdm_get_hash_nid(base_hash_algo);
223 0 : asym_nid = libspdm_get_aysm_nid(base_asym_algo);
224 0 : pqc_asym_nid = libspdm_get_pqc_aysm_nid(pqc_asym_algo);
225 :
226 0 : char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1";
227 :
228 0 : if (pqc_asym_algo != 0) {
229 0 : result = libspdm_gen_x509_csr_with_pqc(hash_nid, 0, pqc_asym_nid,
230 : requester_info, requester_info_length,
231 0 : !is_device_cert_model,
232 : context, subject_name,
233 : csr_len, csr_pointer,
234 0 : x509_ca_cert);
235 0 : libspdm_pqc_asym_free(pqc_asym_algo, context);
236 : } else {
237 0 : result = libspdm_gen_x509_csr(hash_nid, asym_nid,
238 : requester_info, requester_info_length,
239 0 : !is_device_cert_model,
240 : context, subject_name,
241 : csr_len, csr_pointer,
242 0 : x509_ca_cert);
243 0 : libspdm_asym_free(base_asym_algo, context);
244 : }
245 0 : libspdm_x509_free(x509_ca_cert);
246 0 : free(cert);
247 : #if !LIBSPDM_PRIVATE_KEY_MODE_RAW_KEY_ONLY
248 : }
249 : #endif
250 :
251 6 : if (csr_buffer_size < *csr_len) {
252 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"csr buffer is too small to store generated csr! \n"));
253 0 : result = false;
254 : }
255 6 : return result;
256 : }
257 :
258 10 : bool libspdm_gen_csr(
259 : void *spdm_context,
260 : uint32_t base_hash_algo, uint32_t base_asym_algo, bool *need_reset,
261 : const void *request, size_t request_size,
262 : uint8_t *requester_info, size_t requester_info_length,
263 : uint8_t *opaque_data, uint16_t opaque_data_length,
264 : size_t *csr_len, uint8_t *csr_pointer,
265 : bool is_device_cert_model,
266 : bool *is_busy, bool *unexpected_request)
267 : {
268 : bool result;
269 : uint8_t *cached_last_csr_request;
270 : size_t cached_last_request_len;
271 : uint8_t *cached_csr;
272 : size_t csr_buffer_size;
273 : uint8_t rsp_csr_tracking_tag;
274 :
275 10 : csr_buffer_size = *csr_len;
276 :
277 : /*device gen csr need reset*/
278 10 : if (*need_reset) {
279 4 : result = libspdm_read_cached_last_csr_request(&cached_last_csr_request,
280 : &cached_last_request_len,
281 : 1, &rsp_csr_tracking_tag);
282 :
283 : /*get the cached last csr request and csr*/
284 4 : if ((result) &&
285 5 : (cached_last_request_len == request_size) &&
286 2 : (libspdm_consttime_is_mem_equal(cached_last_csr_request, request,
287 2 : request_size)) &&
288 2 : (libspdm_read_cached_csr(&cached_csr, csr_len)) &&
289 1 : (*csr_len != 0)) {
290 :
291 : /*get and save cached csr*/
292 1 : if (csr_buffer_size < *csr_len) {
293 0 : free(cached_csr);
294 0 : free(cached_last_csr_request);
295 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
296 : "csr buffer is too small to store cached csr! \n"));
297 0 : return false;
298 : } else {
299 1 : libspdm_copy_mem(csr_pointer, csr_buffer_size, cached_csr, *csr_len);
300 : }
301 :
302 : /*device don't need reset this time*/
303 1 : *need_reset = false;
304 :
305 1 : free(cached_csr);
306 1 : free(cached_last_csr_request);
307 1 : return true;
308 : } else {
309 3 : if (cached_last_csr_request != NULL) {
310 2 : free(cached_last_csr_request);
311 : }
312 :
313 : /*device need reset this time: cache the last_csr_request */
314 3 : result = libspdm_cache_last_csr_request(request, request_size, 1);
315 3 : if (!result) {
316 0 : return result;
317 : }
318 :
319 : /*device need reset this time*/
320 3 : *need_reset = true;
321 3 : return true;
322 : }
323 : } else {
324 6 : result = libspdm_gen_csr_without_reset(base_hash_algo, base_asym_algo, 0,
325 : requester_info, requester_info_length,
326 : opaque_data, opaque_data_length,
327 : csr_len, csr_pointer, is_device_cert_model);
328 6 : return result;
329 : }
330 :
331 : }
332 :
333 : #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX
334 15 : bool libspdm_gen_csr_ex(
335 : void *spdm_context,
336 : uint32_t base_hash_algo, uint32_t base_asym_algo, uint32_t pqc_asym_algo,
337 : bool *need_reset,
338 : const void *request, size_t request_size,
339 : uint8_t *requester_info, size_t requester_info_length,
340 : uint8_t *opaque_data, uint16_t opaque_data_length,
341 : size_t *csr_len, uint8_t *csr_pointer,
342 : uint8_t req_cert_model,
343 : uint8_t *req_csr_tracking_tag,
344 : uint8_t req_key_pair_id,
345 : bool overwrite,
346 : bool *is_busy, bool *unexpected_request)
347 : {
348 : bool result;
349 : uint8_t *cached_last_csr_request;
350 : size_t cached_last_request_len;
351 : uint8_t *cached_csr;
352 : size_t csr_buffer_size;
353 : uint8_t rsp_csr_tracking_tag;
354 : uint8_t available_csr_tracking_tag;
355 : uint8_t *request_change;
356 : uint8_t index;
357 : bool flag;
358 : bool is_device_cert_model;
359 :
360 15 : available_csr_tracking_tag = 0;
361 15 : csr_buffer_size = *csr_len;
362 :
363 : /*device gen csr need reset*/
364 15 : if (*need_reset) {
365 15 : result = libspdm_read_cached_last_csr_request(&cached_last_csr_request,
366 : &cached_last_request_len,
367 15 : *req_csr_tracking_tag,
368 : &rsp_csr_tracking_tag);
369 :
370 48 : for (index = 1; index <= SPDM_MAX_CSR_TRACKING_TAG; index++) {
371 47 : if (((rsp_csr_tracking_tag >> index) & 0x01) == 0x01) {
372 14 : available_csr_tracking_tag = index;
373 14 : break;
374 : }
375 : }
376 :
377 15 : if (*req_csr_tracking_tag == 0) {
378 11 : if (available_csr_tracking_tag == 0) {
379 : /*no available tracking tag*/
380 1 : *is_busy = true;
381 1 : return false;
382 : } else {
383 10 : flag = false;
384 : }
385 : } else {
386 : /*matched csr_tracking_tag*/
387 4 : if (((rsp_csr_tracking_tag >> *req_csr_tracking_tag) & 0x01) == 0) {
388 2 : flag = true;
389 : } else {
390 : /*unexpected*/
391 2 : return false;
392 : }
393 : }
394 :
395 : /*get the cached last csr request and csr*/
396 12 : if ((result) &&
397 4 : (cached_last_request_len == request_size) &&
398 2 : (libspdm_consttime_is_mem_equal(cached_last_csr_request, request,
399 2 : request_size)) &&
400 2 : (libspdm_read_cached_csr(&cached_csr, csr_len)) &&
401 1 : (*csr_len != 0) &&
402 : (flag)) {
403 :
404 : /*get and save cached csr*/
405 1 : if (csr_buffer_size < *csr_len) {
406 0 : free(cached_csr);
407 0 : free(cached_last_csr_request);
408 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
409 : "csr buffer is too small to store cached csr! \n"));
410 0 : return false;
411 : } else {
412 1 : libspdm_copy_mem(csr_pointer, csr_buffer_size, cached_csr, *csr_len);
413 : }
414 :
415 : /*device don't need reset this time*/
416 1 : *need_reset = false;
417 :
418 1 : free(cached_csr);
419 1 : free(cached_last_csr_request);
420 1 : return true;
421 : } else {
422 11 : if (cached_last_csr_request != NULL) {
423 1 : free(cached_last_csr_request);
424 : }
425 :
426 11 : if ((*req_csr_tracking_tag == 0) && (available_csr_tracking_tag != 0)) {
427 10 : request_change = malloc(request_size);
428 10 : libspdm_copy_mem(request_change, request_size, request,request_size);
429 :
430 10 : if (overwrite) {
431 1 : available_csr_tracking_tag = 1;
432 : /*discard all previously generated CSRTrackingTags. */
433 1 : result = libspdm_discard_all_cached_last_request();
434 1 : if (!result) {
435 0 : free(request_change);
436 0 : return result;
437 : }
438 : }
439 :
440 10 : request_change[3] |=
441 : (available_csr_tracking_tag <<
442 : SPDM_GET_CSR_REQUEST_ATTRIBUTES_CSR_TRACKING_TAG_OFFSET);
443 :
444 : /*device need reset this time: cache the last_csr_request */
445 10 : result = libspdm_cache_last_csr_request(request_change,
446 : request_size, available_csr_tracking_tag);
447 10 : if (!result) {
448 0 : free(request_change);
449 0 : return result;
450 : }
451 :
452 : /*device need reset this time*/
453 10 : *need_reset = true;
454 10 : *req_csr_tracking_tag = available_csr_tracking_tag;
455 10 : free(request_change);
456 10 : return true;
457 : } else {
458 : /*the device is busy*/
459 1 : *is_busy = true;
460 1 : return false;
461 : }
462 : }
463 : } else {
464 0 : if (req_cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT) {
465 0 : is_device_cert_model = true;
466 : } else {
467 0 : is_device_cert_model = false;
468 : }
469 0 : result = libspdm_gen_csr_without_reset(base_hash_algo, base_asym_algo, pqc_asym_algo,
470 : requester_info, requester_info_length,
471 : opaque_data, opaque_data_length,
472 : csr_len, csr_pointer, is_device_cert_model);
473 0 : return result;
474 : }
475 : }
476 : #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX*/
477 :
478 : #endif /* LIBSPDM_ENABLE_CAPABILITY_CSR_CAP */
|