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 : void *spdm_context,
257 : uint32_t base_hash_algo, uint32_t base_asym_algo, bool *need_reset,
258 : const void *request, size_t request_size,
259 : uint8_t *requester_info, size_t requester_info_length,
260 : uint8_t *opaque_data, uint16_t opaque_data_length,
261 : size_t *csr_len, uint8_t *csr_pointer,
262 : bool is_device_cert_model,
263 : bool *is_busy, bool *unexpected_request)
264 : {
265 : bool result;
266 : uint8_t *cached_last_csr_request;
267 : size_t cached_last_request_len;
268 : uint8_t *cached_csr;
269 : size_t csr_buffer_size;
270 : uint8_t rsp_csr_tracking_tag;
271 :
272 10 : csr_buffer_size = *csr_len;
273 :
274 : /*device gen csr need reset*/
275 10 : if (*need_reset) {
276 4 : result = libspdm_read_cached_last_csr_request(&cached_last_csr_request,
277 : &cached_last_request_len,
278 : 1, &rsp_csr_tracking_tag);
279 :
280 : /*get the cached last csr request and csr*/
281 4 : if ((result) &&
282 5 : (cached_last_request_len == request_size) &&
283 2 : (libspdm_consttime_is_mem_equal(cached_last_csr_request, request,
284 2 : request_size)) &&
285 2 : (libspdm_read_cached_csr(&cached_csr, csr_len)) &&
286 1 : (*csr_len != 0)) {
287 :
288 : /*get and save cached csr*/
289 1 : if (csr_buffer_size < *csr_len) {
290 0 : free(cached_csr);
291 0 : free(cached_last_csr_request);
292 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
293 : "csr buffer is too small to store cached csr! \n"));
294 0 : return false;
295 : } else {
296 1 : libspdm_copy_mem(csr_pointer, csr_buffer_size, cached_csr, *csr_len);
297 : }
298 :
299 : /*device don't need reset this time*/
300 1 : *need_reset = false;
301 :
302 1 : free(cached_csr);
303 1 : free(cached_last_csr_request);
304 1 : return true;
305 : } else {
306 3 : if (cached_last_csr_request != NULL) {
307 2 : free(cached_last_csr_request);
308 : }
309 :
310 : /*device need reset this time: cache the last_csr_request */
311 3 : result = libspdm_cache_last_csr_request(request, request_size, 1);
312 3 : if (!result) {
313 0 : return result;
314 : }
315 :
316 : /*device need reset this time*/
317 3 : *need_reset = true;
318 3 : return true;
319 : }
320 : } else {
321 6 : result = libspdm_gen_csr_without_reset(base_hash_algo, base_asym_algo, 0,
322 : requester_info, requester_info_length,
323 : opaque_data, opaque_data_length,
324 : csr_len, csr_pointer, is_device_cert_model);
325 6 : return result;
326 : }
327 :
328 : }
329 :
330 : #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX
331 15 : bool libspdm_gen_csr_ex(
332 : void *spdm_context,
333 : uint32_t base_hash_algo, uint32_t base_asym_algo, uint32_t pqc_asym_algo,
334 : bool *need_reset,
335 : const void *request, size_t request_size,
336 : uint8_t *requester_info, size_t requester_info_length,
337 : uint8_t *opaque_data, uint16_t opaque_data_length,
338 : size_t *csr_len, uint8_t *csr_pointer,
339 : uint8_t req_cert_model,
340 : uint8_t *req_csr_tracking_tag,
341 : uint8_t req_key_pair_id,
342 : bool overwrite,
343 : bool *is_busy, bool *unexpected_request)
344 : {
345 : bool result;
346 : uint8_t *cached_last_csr_request;
347 : size_t cached_last_request_len;
348 : uint8_t *cached_csr;
349 : size_t csr_buffer_size;
350 : uint8_t rsp_csr_tracking_tag;
351 : uint8_t available_csr_tracking_tag;
352 : uint8_t *request_change;
353 : uint8_t index;
354 : bool flag;
355 : bool is_device_cert_model;
356 :
357 15 : available_csr_tracking_tag = 0;
358 15 : csr_buffer_size = *csr_len;
359 :
360 : /*device gen csr need reset*/
361 15 : if (*need_reset) {
362 15 : result = libspdm_read_cached_last_csr_request(&cached_last_csr_request,
363 : &cached_last_request_len,
364 15 : *req_csr_tracking_tag,
365 : &rsp_csr_tracking_tag);
366 :
367 48 : for (index = 1; index <= SPDM_MAX_CSR_TRACKING_TAG; index++) {
368 47 : if (((rsp_csr_tracking_tag >> index) & 0x01) == 0x01) {
369 14 : available_csr_tracking_tag = index;
370 14 : break;
371 : }
372 : }
373 :
374 15 : if (*req_csr_tracking_tag == 0) {
375 11 : if (available_csr_tracking_tag == 0) {
376 : /*no available tracking tag*/
377 1 : *is_busy = true;
378 1 : return false;
379 : } else {
380 10 : flag = false;
381 : }
382 : } else {
383 : /*matched csr_tracking_tag*/
384 4 : if (((rsp_csr_tracking_tag >> *req_csr_tracking_tag) & 0x01) == 0) {
385 2 : flag = true;
386 : } else {
387 : /*unexpected*/
388 2 : return false;
389 : }
390 : }
391 :
392 : /*get the cached last csr request and csr*/
393 12 : if ((result) &&
394 4 : (cached_last_request_len == request_size) &&
395 2 : (libspdm_consttime_is_mem_equal(cached_last_csr_request, request,
396 2 : request_size)) &&
397 2 : (libspdm_read_cached_csr(&cached_csr, csr_len)) &&
398 1 : (*csr_len != 0) &&
399 : (flag)) {
400 :
401 : /*get and save cached csr*/
402 1 : if (csr_buffer_size < *csr_len) {
403 0 : free(cached_csr);
404 0 : free(cached_last_csr_request);
405 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
406 : "csr buffer is too small to store cached csr! \n"));
407 0 : return false;
408 : } else {
409 1 : libspdm_copy_mem(csr_pointer, csr_buffer_size, cached_csr, *csr_len);
410 : }
411 :
412 : /*device don't need reset this time*/
413 1 : *need_reset = false;
414 :
415 1 : free(cached_csr);
416 1 : free(cached_last_csr_request);
417 1 : return true;
418 : } else {
419 11 : if (cached_last_csr_request != NULL) {
420 1 : free(cached_last_csr_request);
421 : }
422 :
423 11 : if ((*req_csr_tracking_tag == 0) && (available_csr_tracking_tag != 0)) {
424 10 : request_change = malloc(request_size);
425 10 : libspdm_copy_mem(request_change, request_size, request,request_size);
426 :
427 10 : if (overwrite) {
428 1 : available_csr_tracking_tag = 1;
429 : /*discard all previously generated CSRTrackingTags. */
430 1 : result = libspdm_discard_all_cached_last_request();
431 1 : if (!result) {
432 0 : free(request_change);
433 0 : return result;
434 : }
435 : }
436 :
437 10 : request_change[3] |=
438 : (available_csr_tracking_tag <<
439 : SPDM_GET_CSR_REQUEST_ATTRIBUTES_CSR_TRACKING_TAG_OFFSET);
440 :
441 : /*device need reset this time: cache the last_csr_request */
442 10 : result = libspdm_cache_last_csr_request(request_change,
443 : request_size, available_csr_tracking_tag);
444 10 : if (!result) {
445 0 : free(request_change);
446 0 : return result;
447 : }
448 :
449 : /*device need reset this time*/
450 10 : *need_reset = true;
451 10 : *req_csr_tracking_tag = available_csr_tracking_tag;
452 10 : free(request_change);
453 10 : return true;
454 : } else {
455 : /*the device is busy*/
456 1 : *is_busy = true;
457 1 : return false;
458 : }
459 : }
460 : } else {
461 0 : if (req_cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT) {
462 0 : is_device_cert_model = true;
463 : } else {
464 0 : is_device_cert_model = false;
465 : }
466 0 : result = libspdm_gen_csr_without_reset(base_hash_algo, base_asym_algo, pqc_asym_algo,
467 : requester_info, requester_info_length,
468 : opaque_data, opaque_data_length,
469 : csr_len, csr_pointer, is_device_cert_model);
470 0 : return result;
471 : }
472 : }
473 : #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX*/
474 :
475 : #endif /* LIBSPDM_ENABLE_CAPABILITY_CSR_CAP */
|