1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * libspdm_x509_verify_cert_chain, libspdm_x509_get_cert_from_cert_chain, check
24 * and prototypes taken from DMTF: Copyright 2021-2022 DMTF. All rights reserved.
25 * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
26 */
27 
28 #include "internal_crypt_lib.h"
29 
30 #ifdef USE_LKCA
31 #include <crypto/public_key.h>
32 #include <keys/asymmetric-type.h>
33 #endif
34 
libspdm_x509_construct_certificate(const uint8_t * cert,size_t cert_size,uint8_t ** single_x509_cert)35 bool libspdm_x509_construct_certificate(const uint8_t *cert, size_t cert_size,
36                                         uint8_t **single_x509_cert)
37 {
38     LIBSPDM_ASSERT(false);
39     return false;
40 }
41 
libspdm_x509_construct_certificate_stack(uint8_t ** x509_stack,...)42 bool libspdm_x509_construct_certificate_stack(uint8_t **x509_stack, ...)
43 {
44     LIBSPDM_ASSERT(false);
45     return false;
46 }
47 
libspdm_x509_free(void * x509_cert)48 void libspdm_x509_free(void *x509_cert)
49 {
50     LIBSPDM_ASSERT(false);
51 }
52 
libspdm_x509_stack_free(void * x509_stack)53 void libspdm_x509_stack_free(void *x509_stack)
54 {
55     LIBSPDM_ASSERT(false);
56 }
57 
lkca_asn1_get_tag(uint8_t const * ptr,uint8_t const * end,size_t * length,uint32_t tag)58 static bool lkca_asn1_get_tag(uint8_t const *ptr, uint8_t const *end,
59                               size_t *length, uint32_t tag)
60 {
61     uint64_t max_len = end - ptr;
62 
63     // Chain must be less than 1 GB
64     if ((max_len < 2) || (max_len > (1024 * 1024 * 1024))) {
65         return false;
66     }
67 
68     // We only deal with universal and application tags
69     if (ptr[0] != tag) {
70         return false;
71     }
72 
73     if (ptr[1] < 0x80) {
74         *length = ptr[1] + 2;
75     } else if (ptr[1] == 0x81) {
76         if (max_len < 3) {
77             return false;
78         }
79         *length = ptr[2] + 3;
80     } else if (ptr[1] == 0x82) {
81         if (max_len < 4) {
82             return false;
83         }
84         *length = (ptr[2] << 8) + ptr[3] + 4;
85     } else {
86         // In theory it could be bigger than 64KB
87         return false;
88     }
89 
90     if (*length > max_len) {
91         return false;
92     }
93 
94     return true;
95 }
96 
libspdm_asn1_get_tag(uint8_t ** ptr,const uint8_t * end,size_t * length,uint32_t tag)97 bool libspdm_asn1_get_tag(uint8_t **ptr, const uint8_t *end, size_t *length,
98                           uint32_t tag)
99 {
100     return lkca_asn1_get_tag(*ptr, end, length, tag);
101 }
102 
libspdm_x509_get_subject_name(const uint8_t * cert,size_t cert_size,uint8_t * cert_subject,size_t * subject_size)103 bool libspdm_x509_get_subject_name(const uint8_t *cert, size_t cert_size,
104                                    uint8_t *cert_subject,
105                                    size_t *subject_size)
106 {
107     LIBSPDM_ASSERT(false);
108     return false;
109 }
110 
libspdm_x509_get_common_name(const uint8_t * cert,size_t cert_size,char * common_name,size_t * common_name_size)111 bool libspdm_x509_get_common_name(const uint8_t *cert, size_t cert_size,
112                                   char *common_name,
113                                   size_t *common_name_size)
114 {
115     LIBSPDM_ASSERT(false);
116     return false;
117 }
118 
119 bool
libspdm_x509_get_organization_name(const uint8_t * cert,size_t cert_size,char * name_buffer,size_t * name_buffer_size)120 libspdm_x509_get_organization_name(const uint8_t *cert, size_t cert_size,
121                                    char *name_buffer,
122                                    size_t *name_buffer_size)
123 {
124     LIBSPDM_ASSERT(false);
125     return false;
126 }
127 
128 #if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
libspdm_rsa_get_public_key_from_x509(const uint8_t * cert,size_t cert_size,void ** rsa_context)129 bool libspdm_rsa_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
130                                           void **rsa_context)
131 {
132     LIBSPDM_ASSERT(false);
133     return false;
134 }
135 #endif /* (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT) */
136 
libspdm_ec_get_public_key_from_x509(const uint8_t * cert,size_t cert_size,void ** ec_context)137 bool libspdm_ec_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
138                                          void **ec_context)
139 {
140 #ifdef USE_LKCA
141     bool ret = false;
142     uint32_t key_size = 0;
143     struct key_preparsed_payload lkca_cert;
144     struct public_key *pub;
145 
146     lkca_cert.data = cert;
147     lkca_cert.datalen = cert_size;
148 
149     if (cert == NULL) {
150         return false;
151     }
152 
153     if(key_type_asymmetric.preparse(&lkca_cert)) {
154         return false;
155     }
156 
157     pub = lkca_cert.payload.data[asym_crypto];
158     // -1 is since lkca prepends '4' to public keys...
159     key_size = pub->keylen - 1;
160 
161     if (key_size == (2 * 256 / 8)) {
162         *ec_context = libspdm_ec_new_by_nid(LIBSPDM_CRYPTO_NID_SECP256R1);
163     } else if (key_size == (2 * 384 / 8)) {
164         *ec_context = libspdm_ec_new_by_nid(LIBSPDM_CRYPTO_NID_SECP384R1);
165     } else {
166         goto err;
167     }
168 
169     if (*ec_context == NULL) {
170         goto err;
171     }
172 
173     // Again skip '4' in key to be in line with spdm protocol. We will add it
174     // back in ecda_verify
175     if (!lkca_ec_set_pub_key(*ec_context, (char *) pub->key + 1, key_size)) {
176         libspdm_ec_free(*ec_context);
177         goto err;
178     }
179 
180     ret = true;
181 err:
182     key_type_asymmetric.free_preparse(&lkca_cert);
183     return ret;
184 #else
185     return false;
186 #endif
187 }
188 
libspdm_ecd_get_public_key_from_x509(const uint8_t * cert,size_t cert_size,void ** ecd_context)189 bool libspdm_ecd_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
190                                           void **ecd_context)
191 {
192     LIBSPDM_ASSERT(false);
193     return false;
194 }
195 
libspdm_sm2_get_public_key_from_x509(const uint8_t * cert,size_t cert_size,void ** sm2_context)196 bool libspdm_sm2_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
197                                           void **sm2_context)
198 {
199     LIBSPDM_ASSERT(false);
200     return false;
201 }
202 
lkca_x509_verify_cert(const uint8_t * cert,size_t cert_size,const uint8_t * ca_cert,size_t ca_cert_size)203 static int lkca_x509_verify_cert(const uint8_t *cert, size_t cert_size,
204                                  const uint8_t *ca_cert, size_t ca_cert_size)
205 {
206 #ifdef USE_LKCA
207     int ret;
208     struct key_preparsed_payload lkca_cert;
209     struct key_preparsed_payload lkca_ca_cert;
210 
211     lkca_cert.data = cert;
212     lkca_cert.datalen = cert_size;
213     lkca_ca_cert.data = ca_cert;
214     lkca_ca_cert.datalen = ca_cert_size;
215 
216     ret = key_type_asymmetric.preparse(&lkca_cert);
217     if (ret) {
218         return ret;
219     }
220 
221     ret = key_type_asymmetric.preparse(&lkca_ca_cert);
222     if (ret) {
223         key_type_asymmetric.free_preparse(&lkca_cert);
224         return ret;
225     }
226 
227     ret = public_key_verify_signature(lkca_ca_cert.payload.data[asym_crypto],
228                                       lkca_cert.payload.data[asym_auth]);
229 
230     key_type_asymmetric.free_preparse(&lkca_cert);
231     key_type_asymmetric.free_preparse(&lkca_ca_cert);
232 
233     return ret;
234 #else
235     return false;
236 #endif
237 }
238 
libspdm_x509_verify_cert(const uint8_t * cert,size_t cert_size,const uint8_t * ca_cert,size_t ca_cert_size)239 bool libspdm_x509_verify_cert(const uint8_t *cert, size_t cert_size,
240                               const uint8_t *ca_cert, size_t ca_cert_size)
241 {
242     return lkca_x509_verify_cert(cert, cert_size, ca_cert, ca_cert_size) == 0;
243 }
244 
libspdm_x509_verify_cert_chain(const uint8_t * root_cert,size_t root_cert_length,const uint8_t * cert_chain,size_t cert_chain_length)245 bool libspdm_x509_verify_cert_chain(const uint8_t *root_cert, size_t root_cert_length,
246                                     const uint8_t *cert_chain, size_t cert_chain_length)
247 {
248     size_t preceding_cert_len;
249     const uint8_t *preceding_cert;
250     size_t current_cert_len;
251     const uint8_t *current_cert;
252     bool verify_flag;
253     int ret;
254 
255     verify_flag = false;
256     preceding_cert = root_cert;
257     preceding_cert_len = root_cert_length;
258 
259     current_cert = cert_chain;
260 
261 
262     /* Get Current certificate from certificates buffer and Verify with preceding cert*/
263     do {
264         if (!lkca_asn1_get_tag(
265             current_cert, cert_chain + cert_chain_length, &current_cert_len,
266             LIBSPDM_CRYPTO_ASN1_CONSTRUCTED | LIBSPDM_CRYPTO_ASN1_SEQUENCE)) {
267             break;
268         }
269 
270         ret = lkca_x509_verify_cert(current_cert, current_cert_len,
271                                     preceding_cert, preceding_cert_len);
272         if (ret != 0) {
273             verify_flag = false;
274             break;
275         } else {
276             verify_flag = true;
277         }
278 
279         preceding_cert = current_cert;
280         preceding_cert_len = current_cert_len;
281 
282         current_cert = current_cert + current_cert_len;
283     } while (true);
284 
285     return verify_flag;
286 }
287 
libspdm_x509_get_cert_from_cert_chain(const uint8_t * cert_chain,size_t cert_chain_length,const int32_t cert_index,const uint8_t ** cert,size_t * cert_length)288 bool libspdm_x509_get_cert_from_cert_chain(const uint8_t *cert_chain,
289                                            size_t cert_chain_length,
290                                            const int32_t cert_index, const uint8_t **cert,
291                                            size_t *cert_length)
292 {
293     size_t asn1_len;
294     int32_t current_index;
295     size_t current_cert_len;
296     const uint8_t *current_cert;
297 
298     current_cert_len = 0;
299 
300     /* Check input parameters.*/
301     if ((cert_chain == NULL) || (cert == NULL) || (cert_index < -1) ||
302         (cert_length == NULL)) {
303         return false;
304     }
305 
306     current_cert = cert_chain;
307     current_index = -1;
308 
309     /* Traverse the certificate chain*/
310     while (true) {
311         /* Get asn1 tag len*/
312         if (!lkca_asn1_get_tag(
313             current_cert, cert_chain + cert_chain_length, &asn1_len,
314             LIBSPDM_CRYPTO_ASN1_CONSTRUCTED | LIBSPDM_CRYPTO_ASN1_SEQUENCE)) {
315             break;
316         }
317 
318         current_cert_len = asn1_len;
319         current_index++;
320 
321         if (current_index == cert_index) {
322             *cert = current_cert;
323             *cert_length = current_cert_len;
324             return true;
325         }
326 
327         current_cert = current_cert + current_cert_len;
328     }
329 
330     /* If cert_index is -1, Return the last certificate*/
331     if (cert_index == -1 && current_index >= 0) {
332         *cert = current_cert - current_cert_len;
333         *cert_length = current_cert_len;
334         return true;
335     }
336 
337     return false;
338 }
339 
libspdm_x509_get_tbs_cert(const uint8_t * cert,size_t cert_size,uint8_t ** tbs_cert,size_t * tbs_cert_size)340 bool libspdm_x509_get_tbs_cert(const uint8_t *cert, size_t cert_size,
341                                uint8_t **tbs_cert, size_t *tbs_cert_size)
342 {
343     LIBSPDM_ASSERT(false);
344     return false;
345 }
346 
libspdm_x509_get_version(const uint8_t * cert,size_t cert_size,size_t * version)347 bool libspdm_x509_get_version(const uint8_t *cert, size_t cert_size,
348                               size_t *version)
349 {
350     LIBSPDM_ASSERT(false);
351     return false;
352 }
353 
libspdm_x509_get_serial_number(const uint8_t * cert,size_t cert_size,uint8_t * serial_number,size_t * serial_number_size)354 bool libspdm_x509_get_serial_number(const uint8_t *cert, size_t cert_size,
355                                     uint8_t *serial_number,
356                                     size_t *serial_number_size)
357 {
358     LIBSPDM_ASSERT(false);
359     return false;
360 }
361 
libspdm_x509_get_issuer_name(const uint8_t * cert,size_t cert_size,uint8_t * cert_issuer,size_t * issuer_size)362 bool libspdm_x509_get_issuer_name(const uint8_t *cert, size_t cert_size,
363                                   uint8_t *cert_issuer,
364                                   size_t *issuer_size)
365 {
366     LIBSPDM_ASSERT(false);
367     return false;
368 }
369 
370 bool
libspdm_x509_get_issuer_common_name(const uint8_t * cert,size_t cert_size,char * common_name,size_t * common_name_size)371 libspdm_x509_get_issuer_common_name(const uint8_t *cert, size_t cert_size,
372                                     char *common_name,
373                                     size_t *common_name_size)
374 {
375     LIBSPDM_ASSERT(false);
376     return false;
377 }
378 
379 bool
libspdm_x509_get_issuer_orgnization_name(const uint8_t * cert,size_t cert_size,char * name_buffer,size_t * name_buffer_size)380 libspdm_x509_get_issuer_orgnization_name(const uint8_t *cert, size_t cert_size,
381                                          char *name_buffer,
382                                          size_t *name_buffer_size)
383 {
384     LIBSPDM_ASSERT(false);
385     return false;
386 }
387 
libspdm_x509_get_signature_algorithm(const uint8_t * cert,size_t cert_size,uint8_t * oid,size_t * oid_size)388 bool libspdm_x509_get_signature_algorithm(const uint8_t *cert,
389                                           size_t cert_size, uint8_t *oid,
390                                           size_t *oid_size)
391 {
392     LIBSPDM_ASSERT(false);
393     return false;
394 }
395 
libspdm_x509_get_extension_data(const uint8_t * cert,size_t cert_size,const uint8_t * oid,size_t oid_size,uint8_t * extension_data,size_t * extension_data_size)396 bool libspdm_x509_get_extension_data(const uint8_t *cert, size_t cert_size,
397                                      const uint8_t *oid, size_t oid_size,
398                                      uint8_t *extension_data,
399                                      size_t *extension_data_size)
400 {
401     LIBSPDM_ASSERT(false);
402     return false;
403 }
404 
libspdm_x509_get_validity(const uint8_t * cert,size_t cert_size,uint8_t * from,size_t * from_size,uint8_t * to,size_t * to_size)405 bool libspdm_x509_get_validity(const uint8_t *cert, size_t cert_size,
406                                uint8_t *from, size_t *from_size, uint8_t *to,
407                                size_t *to_size)
408 {
409     LIBSPDM_ASSERT(false);
410     return false;
411 }
412 
libspdm_x509_get_key_usage(const uint8_t * cert,size_t cert_size,size_t * usage)413 bool libspdm_x509_get_key_usage(const uint8_t *cert, size_t cert_size,
414                                 size_t *usage)
415 {
416     LIBSPDM_ASSERT(false);
417     return false;
418 }
419 
libspdm_x509_get_extended_key_usage(const uint8_t * cert,size_t cert_size,uint8_t * usage,size_t * usage_size)420 bool libspdm_x509_get_extended_key_usage(const uint8_t *cert,
421                                          size_t cert_size, uint8_t *usage,
422                                          size_t *usage_size)
423 {
424     LIBSPDM_ASSERT(false);
425     return false;
426 }
427 
libspdm_x509_get_extended_basic_constraints(const uint8_t * cert,size_t cert_size,uint8_t * basic_constraints,size_t * basic_constraints_size)428 bool libspdm_x509_get_extended_basic_constraints(const uint8_t *cert,
429                                                  size_t cert_size,
430                                                  uint8_t *basic_constraints,
431                                                  size_t *basic_constraints_size)
432 {
433     LIBSPDM_ASSERT(false);
434     return false;
435 }
436 
libspdm_x509_set_date_time(char const * date_time_str,void * date_time,size_t * date_time_size)437 bool libspdm_x509_set_date_time(char const *date_time_str, void *date_time, size_t *date_time_size)
438 {
439     LIBSPDM_ASSERT(false);
440     return false;
441 }
442 
libspdm_x509_compare_date_time(const void * date_time1,const void * date_time2)443 int32_t libspdm_x509_compare_date_time(const void *date_time1, const void *date_time2)
444 {
445     LIBSPDM_ASSERT(false);
446     return -3;
447 }
448 
libspdm_gen_x509_csr(size_t hash_nid,size_t asym_nid,uint8_t * requester_info,size_t requester_info_length,void * context,char * subject_name,size_t * csr_len,uint8_t ** csr_pointer)449 bool libspdm_gen_x509_csr(size_t hash_nid, size_t asym_nid,
450                           uint8_t *requester_info, size_t requester_info_length,
451                           void *context, char *subject_name,
452                           size_t *csr_len, uint8_t **csr_pointer)
453 {
454     LIBSPDM_ASSERT(false);
455     return false;
456 }
457