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