Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-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 : /** @file
8 : * RSA Asymmetric Cipher Wrapper Implementation.
9 : *
10 : * This file implements following APIs which provide more capabilities for RSA:
11 : * 1) libspdm_rsa_get_key
12 : * 2) libspdm_rsa_generate_key
13 : * 3) libspdm_rsa_check_key
14 : * 4) rsa_pkcs1_sign
15 : *
16 : * RFC 8017 - PKCS #1: RSA Cryptography Specifications version 2.2
17 : **/
18 :
19 : #include "internal_crypt_lib.h"
20 : #include <mbedtls/rsa.h>
21 :
22 : #if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
23 : /**
24 : * Gets the tag-designated RSA key component from the established RSA context.
25 : *
26 : * This function retrieves the tag-designated RSA key component from the
27 : * established RSA context as a non-negative integer (octet string format
28 : * represented in RSA PKCS#1).
29 : * If specified key component has not been set or has been cleared, then returned
30 : * bn_size is set to 0.
31 : * If the big_number buffer is too small to hold the contents of the key, false
32 : * is returned and bn_size is set to the required buffer size to obtain the key.
33 : *
34 : * If rsa_context is NULL, then return false.
35 : * If bn_size is NULL, then return false.
36 : * If bn_size is large enough but big_number is NULL, then return false.
37 : *
38 : * @param[in, out] rsa_context Pointer to RSA context being set.
39 : * @param[in] key_tag tag of RSA key component being set.
40 : * @param[out] big_number Pointer to octet integer buffer.
41 : * @param[in, out] bn_size On input, the size of big number buffer in bytes.
42 : * On output, the size of data returned in big number buffer in bytes.
43 : *
44 : * @retval true RSA key component was retrieved successfully.
45 : * @retval false Invalid RSA key component tag.
46 : * @retval false bn_size is too small.
47 : *
48 : **/
49 0 : bool libspdm_rsa_get_key(void *rsa_context, const libspdm_rsa_key_tag_t key_tag,
50 : uint8_t *big_number, size_t *bn_size)
51 : {
52 : mbedtls_rsa_context *rsa_key;
53 : int ret;
54 : mbedtls_mpi value;
55 : size_t size;
56 :
57 :
58 : /* Check input parameters.*/
59 :
60 0 : if (rsa_context == NULL || *bn_size > INT_MAX) {
61 0 : return false;
62 : }
63 :
64 : /* Init mbedtls_mpi*/
65 :
66 0 : mbedtls_mpi_init(&value);
67 0 : size = *bn_size;
68 0 : *bn_size = 0;
69 :
70 0 : rsa_key = (mbedtls_rsa_context *)rsa_context;
71 :
72 0 : switch (key_tag) {
73 0 : case LIBSPDM_RSA_KEY_N:
74 0 : ret = mbedtls_rsa_export(rsa_key, &value, NULL, NULL, NULL,
75 : NULL);
76 0 : break;
77 0 : case LIBSPDM_RSA_KEY_E:
78 0 : ret = mbedtls_rsa_export(rsa_key, NULL, NULL, NULL, NULL,
79 : &value);
80 0 : break;
81 0 : case LIBSPDM_RSA_KEY_D:
82 0 : ret = mbedtls_rsa_export(rsa_key, NULL, NULL, NULL, &value,
83 : NULL);
84 0 : break;
85 0 : case LIBSPDM_RSA_KEY_Q:
86 0 : ret = mbedtls_rsa_export(rsa_key, NULL, NULL, &value, NULL,
87 : NULL);
88 0 : break;
89 0 : case LIBSPDM_RSA_KEY_P:
90 0 : ret = mbedtls_rsa_export(rsa_key, NULL, &value, NULL, NULL,
91 : NULL);
92 0 : break;
93 0 : case LIBSPDM_RSA_KEY_DP:
94 : case LIBSPDM_RSA_KEY_DQ:
95 : case LIBSPDM_RSA_KEY_Q_INV:
96 : default:
97 0 : ret = -1;
98 0 : break;
99 : }
100 :
101 0 : if (ret != 0) {
102 0 : return false;
103 : }
104 :
105 0 : if (!mbedtls_mpi_size(&value)) {
106 0 : ret = 0;
107 0 : goto end;
108 : }
109 :
110 0 : *bn_size = size;
111 :
112 0 : if (ret == 0) {
113 0 : size = mbedtls_mpi_size(&value);
114 : }
115 0 : if (size == 0) {
116 0 : ret = 1;
117 0 : goto end;
118 : }
119 :
120 0 : if (*bn_size < size) {
121 0 : ret = 1;
122 0 : *bn_size = size;
123 0 : goto end;
124 : }
125 :
126 0 : if (big_number == NULL) {
127 0 : ret = 0;
128 0 : *bn_size = size;
129 0 : goto end;
130 : }
131 :
132 0 : if (big_number != NULL && ret == 0) {
133 0 : ret = mbedtls_mpi_write_binary(&value, big_number, size);
134 0 : *bn_size = size;
135 : }
136 0 : end:
137 0 : mbedtls_mpi_free(&value);
138 0 : return ret == 0;
139 : }
140 :
141 : /**
142 : * Generates RSA key components.
143 : *
144 : * This function generates RSA key components. It takes RSA public exponent E and
145 : * length in bits of RSA modulus N as input, and generates all key components.
146 : * If public_exponent is NULL, the default RSA public exponent (0x10001) will be used.
147 : *
148 : * If rsa_context is NULL, then return false.
149 : *
150 : * @param[in, out] rsa_context Pointer to RSA context being set.
151 : * @param[in] modulus_length length of RSA modulus N in bits.
152 : * @param[in] public_exponent Pointer to RSA public exponent.
153 : * @param[in] public_exponent_size size of RSA public exponent buffer in bytes.
154 : *
155 : * @retval true RSA key component was generated successfully.
156 : * @retval false Invalid RSA key component tag.
157 : *
158 : **/
159 0 : bool libspdm_rsa_generate_key(void *rsa_context, size_t modulus_length,
160 : const uint8_t *public_exponent,
161 : size_t public_exponent_size)
162 : {
163 0 : int32_t ret = 0;
164 : mbedtls_rsa_context *rsa;
165 : uint32_t e;
166 :
167 :
168 : /* Check input parameters.*/
169 0 : if (rsa_context == NULL || modulus_length > INT_MAX ||
170 : public_exponent_size > INT_MAX) {
171 0 : return false;
172 : }
173 :
174 0 : rsa = (mbedtls_rsa_context *)rsa_context;
175 :
176 0 : if (public_exponent == NULL) {
177 0 : e = 0x10001;
178 : } else {
179 0 : if (public_exponent_size == 0) {
180 0 : return false;
181 : }
182 :
183 0 : switch (public_exponent_size) {
184 0 : case 1:
185 0 : e = public_exponent[0];
186 0 : break;
187 0 : case 2:
188 0 : e = public_exponent[0] << 8 | public_exponent[1];
189 0 : break;
190 0 : case 3:
191 0 : e = public_exponent[0] << 16 | public_exponent[1] << 8 |
192 0 : public_exponent[2];
193 0 : break;
194 0 : case 4:
195 0 : e = public_exponent[0] << 24 | public_exponent[1] << 16 |
196 0 : public_exponent[2] << 8 | public_exponent[3];
197 0 : break;
198 0 : default:
199 0 : return false;
200 : }
201 : }
202 :
203 0 : if (ret == 0) {
204 0 : ret = mbedtls_rsa_gen_key(rsa, libspdm_myrand, NULL,
205 : (uint32_t)modulus_length, e);
206 : }
207 :
208 0 : return ret == 0;
209 : }
210 :
211 : /**
212 : * Validates key components of RSA context.
213 : * NOTE: This function performs integrity checks on all the RSA key material, so
214 : * the RSA key structure must contain all the private key data.
215 : *
216 : * This function validates key components of RSA context in following aspects:
217 : * - Whether p is a prime
218 : * - Whether q is a prime
219 : * - Whether n = p * q
220 : * - Whether d*e = 1 mod lcm(p-1,q-1)
221 : *
222 : * If rsa_context is NULL, then return false.
223 : *
224 : * @param[in] rsa_context Pointer to RSA context to check.
225 : *
226 : * @retval true RSA key components are valid.
227 : * @retval false RSA key components are not valid.
228 : *
229 : **/
230 0 : bool libspdm_rsa_check_key(void *rsa_context)
231 : {
232 : int ret;
233 :
234 0 : if (rsa_context == NULL) {
235 0 : return false;
236 : }
237 :
238 0 : ret = mbedtls_rsa_complete(rsa_context);
239 0 : if (ret == 0) {
240 0 : ret = mbedtls_rsa_check_privkey(rsa_context);
241 : }
242 0 : return ret == 0;
243 : }
244 : #endif /* (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT) */
245 :
246 : #if LIBSPDM_RSA_SSA_SUPPORT
247 : /**
248 : * Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.
249 : *
250 : * This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in
251 : * RSA PKCS#1.
252 : * If the signature buffer is too small to hold the contents of signature, false
253 : * is returned and sig_size is set to the required buffer size to obtain the signature.
254 : *
255 : * If rsa_context is NULL, then return false.
256 : * If message_hash is NULL, then return false.
257 : * If hash_size need match the hash_nid. hash_nid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
258 : * If sig_size is large enough but signature is NULL, then return false.
259 : * If this interface is not supported, then return false.
260 : *
261 : * @param[in] rsa_context Pointer to RSA context for signature generation.
262 : * @param[in] hash_nid hash NID
263 : * @param[in] message_hash Pointer to octet message hash to be signed.
264 : * @param[in] hash_size size of the message hash in bytes.
265 : * @param[out] signature Pointer to buffer to receive RSA PKCS1-v1_5 signature.
266 : * @param[in, out] sig_size On input, the size of signature buffer in bytes.
267 : * On output, the size of data returned in signature buffer in bytes.
268 : *
269 : * @retval true signature successfully generated in PKCS1-v1_5.
270 : * @retval false signature generation failed.
271 : * @retval false sig_size is too small.
272 : * @retval false This interface is not supported.
273 : *
274 : **/
275 37 : bool libspdm_rsa_pkcs1_sign_with_nid(void *rsa_context, size_t hash_nid,
276 : const uint8_t *message_hash,
277 : size_t hash_size, uint8_t *signature,
278 : size_t *sig_size)
279 : {
280 : int ret;
281 : mbedtls_md_type_t md_alg;
282 : mbedtls_rsa_context *rsa_key;
283 :
284 37 : if (rsa_context == NULL || message_hash == NULL) {
285 0 : return false;
286 : }
287 :
288 37 : rsa_key = (mbedtls_rsa_context *)rsa_context;
289 37 : if (mbedtls_rsa_complete(rsa_key) != 0) {
290 0 : return false;
291 : }
292 :
293 37 : switch (hash_nid) {
294 37 : case LIBSPDM_CRYPTO_NID_SHA256:
295 37 : md_alg = MBEDTLS_MD_SHA256;
296 37 : if (hash_size != LIBSPDM_SHA256_DIGEST_SIZE) {
297 0 : return false;
298 : }
299 37 : break;
300 :
301 0 : case LIBSPDM_CRYPTO_NID_SHA384:
302 0 : md_alg = MBEDTLS_MD_SHA384;
303 0 : if (hash_size != LIBSPDM_SHA384_DIGEST_SIZE) {
304 0 : return false;
305 : }
306 0 : break;
307 :
308 0 : case LIBSPDM_CRYPTO_NID_SHA512:
309 0 : md_alg = MBEDTLS_MD_SHA512;
310 0 : if (hash_size != LIBSPDM_SHA512_DIGEST_SIZE) {
311 0 : return false;
312 : }
313 0 : break;
314 :
315 0 : case LIBSPDM_CRYPTO_NID_SHA3_256:
316 0 : md_alg = MBEDTLS_MD_SHA3_256;
317 0 : if (hash_size != LIBSPDM_SHA3_256_DIGEST_SIZE) {
318 0 : return false;
319 : }
320 0 : break;
321 :
322 0 : case LIBSPDM_CRYPTO_NID_SHA3_384:
323 0 : md_alg = MBEDTLS_MD_SHA3_384;
324 0 : if (hash_size != LIBSPDM_SHA3_384_DIGEST_SIZE) {
325 0 : return false;
326 : }
327 0 : break;
328 :
329 0 : case LIBSPDM_CRYPTO_NID_SHA3_512:
330 0 : md_alg = MBEDTLS_MD_SHA3_512;
331 0 : if (hash_size != LIBSPDM_SHA3_512_DIGEST_SIZE) {
332 0 : return false;
333 : }
334 0 : break;
335 :
336 0 : default:
337 0 : return false;
338 : }
339 :
340 37 : if (mbedtls_rsa_get_len(rsa_context) > *sig_size) {
341 0 : *sig_size = mbedtls_rsa_get_len(rsa_context);
342 0 : return false;
343 : }
344 :
345 37 : mbedtls_rsa_set_padding(rsa_context, MBEDTLS_RSA_PKCS_V15, md_alg);
346 :
347 37 : ret = mbedtls_rsa_pkcs1_sign(rsa_context, libspdm_myrand, NULL,
348 : md_alg,
349 : (uint32_t)hash_size, message_hash,
350 : signature);
351 37 : if (ret != 0) {
352 0 : return false;
353 : }
354 37 : *sig_size = mbedtls_rsa_get_len(rsa_context);
355 37 : return true;
356 : }
357 : #endif /* LIBSPDM_RSA_SSA_SUPPORT */
358 :
359 : #if LIBSPDM_RSA_PSS_SUPPORT
360 : /**
361 : * Carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme.
362 : *
363 : * This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined in
364 : * RSA PKCS#1 v2.2.
365 : *
366 : * The salt length is same as digest length.
367 : *
368 : * If the signature buffer is too small to hold the contents of signature, false
369 : * is returned and sig_size is set to the required buffer size to obtain the signature.
370 : *
371 : * If rsa_context is NULL, then return false.
372 : * If message_hash is NULL, then return false.
373 : * If hash_size need match the hash_nid. nid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
374 : * If sig_size is large enough but signature is NULL, then return false.
375 : *
376 : * @param[in] rsa_context Pointer to RSA context for signature generation.
377 : * @param[in] hash_nid hash NID
378 : * @param[in] message_hash Pointer to octet message hash to be signed.
379 : * @param[in] hash_size size of the message hash in bytes.
380 : * @param[out] signature Pointer to buffer to receive RSA-SSA PSS signature.
381 : * @param[in, out] sig_size On input, the size of signature buffer in bytes.
382 : * On output, the size of data returned in signature buffer in bytes.
383 : *
384 : * @retval true signature successfully generated in RSA-SSA PSS.
385 : * @retval false signature generation failed.
386 : * @retval false sig_size is too small.
387 : *
388 : **/
389 0 : bool libspdm_rsa_pss_sign(void *rsa_context, size_t hash_nid,
390 : const uint8_t *message_hash, size_t hash_size,
391 : uint8_t *signature, size_t *sig_size)
392 : {
393 : int ret;
394 : mbedtls_md_type_t md_alg;
395 : mbedtls_rsa_context *rsa_key;
396 :
397 0 : if (rsa_context == NULL || message_hash == NULL) {
398 0 : return false;
399 : }
400 :
401 0 : rsa_key = (mbedtls_rsa_context *)rsa_context;
402 0 : if (mbedtls_rsa_complete(rsa_key) != 0) {
403 0 : return false;
404 : }
405 :
406 0 : switch (hash_nid) {
407 0 : case LIBSPDM_CRYPTO_NID_SHA256:
408 0 : md_alg = MBEDTLS_MD_SHA256;
409 0 : if (hash_size != LIBSPDM_SHA256_DIGEST_SIZE) {
410 0 : return false;
411 : }
412 0 : break;
413 :
414 0 : case LIBSPDM_CRYPTO_NID_SHA384:
415 0 : md_alg = MBEDTLS_MD_SHA384;
416 0 : if (hash_size != LIBSPDM_SHA384_DIGEST_SIZE) {
417 0 : return false;
418 : }
419 0 : break;
420 :
421 0 : case LIBSPDM_CRYPTO_NID_SHA512:
422 0 : md_alg = MBEDTLS_MD_SHA512;
423 0 : if (hash_size != LIBSPDM_SHA512_DIGEST_SIZE) {
424 0 : return false;
425 : }
426 0 : break;
427 :
428 0 : case LIBSPDM_CRYPTO_NID_SHA3_256:
429 0 : md_alg = MBEDTLS_MD_SHA3_256;
430 0 : if (hash_size != LIBSPDM_SHA3_256_DIGEST_SIZE) {
431 0 : return false;
432 : }
433 0 : break;
434 :
435 0 : case LIBSPDM_CRYPTO_NID_SHA3_384:
436 0 : md_alg = MBEDTLS_MD_SHA3_384;
437 0 : if (hash_size != LIBSPDM_SHA3_384_DIGEST_SIZE) {
438 0 : return false;
439 : }
440 0 : break;
441 :
442 0 : case LIBSPDM_CRYPTO_NID_SHA3_512:
443 0 : md_alg = MBEDTLS_MD_SHA3_512;
444 0 : if (hash_size != LIBSPDM_SHA3_512_DIGEST_SIZE) {
445 0 : return false;
446 : }
447 0 : break;
448 :
449 0 : default:
450 0 : return false;
451 : }
452 :
453 0 : if (signature == NULL) {
454 :
455 : /* If signature is NULL, return safe signature_size*/
456 :
457 0 : *sig_size = MBEDTLS_MPI_MAX_SIZE;
458 0 : return false;
459 : }
460 :
461 0 : mbedtls_rsa_set_padding(rsa_context, MBEDTLS_RSA_PKCS_V21, md_alg);
462 :
463 0 : ret = mbedtls_rsa_rsassa_pss_sign(rsa_context, libspdm_myrand, NULL,
464 : md_alg,
465 : (uint32_t)hash_size, message_hash,
466 : signature);
467 :
468 0 : if (ret != 0) {
469 0 : return false;
470 : }
471 0 : *sig_size = mbedtls_rsa_get_len(rsa_context);
472 0 : return true;
473 : }
474 :
475 : #if LIBSPDM_FIPS_MODE
476 :
477 : /*random function() for RSA_PSS*/
478 5 : int libspdm_myrand_rsapss_fips(void *rng_state, unsigned char *output, size_t len)
479 : {
480 :
481 : bool result;
482 :
483 5 : if (len == 0) {
484 1 : return 0;
485 : } else {
486 4 : result = libspdm_random_bytes(output, len);
487 : /* The MbedTLS function f_rng, which myrand implements, is not
488 : * documented well. From looking at code: zero is considered success,
489 : * while non-zero return value is considered failure.*/
490 :
491 4 : return result ? 0 : -1;
492 : }
493 : }
494 :
495 : /**
496 : * Carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme for FIPS test.
497 : *
498 : * This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined in
499 : * RSA PKCS#1 v2.2 for FIPS test.
500 : *
501 : * The salt length is zero.
502 : *
503 : * If the signature buffer is too small to hold the contents of signature, false
504 : * is returned and sig_size is set to the required buffer size to obtain the signature.
505 : *
506 : * If rsa_context is NULL, then return false.
507 : * If message_hash is NULL, then return false.
508 : * If hash_size need match the hash_nid. nid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
509 : * If sig_size is large enough but signature is NULL, then return false.
510 : *
511 : * @param[in] rsa_context Pointer to RSA context for signature generation.
512 : * @param[in] hash_nid hash NID
513 : * @param[in] message_hash Pointer to octet message hash to be signed.
514 : * @param[in] hash_size size of the message hash in bytes.
515 : * @param[out] signature Pointer to buffer to receive RSA-SSA PSS signature.
516 : * @param[in, out] sig_size On input, the size of signature buffer in bytes.
517 : * On output, the size of data returned in signature buffer in bytes.
518 : *
519 : * @retval true signature successfully generated in RSA-SSA PSS.
520 : * @retval false signature generation failed.
521 : * @retval false sig_size is too small.
522 : *
523 : **/
524 1 : bool libspdm_rsa_pss_sign_fips(void *rsa_context, size_t hash_nid,
525 : const uint8_t *message_hash, size_t hash_size,
526 : uint8_t *signature, size_t *sig_size)
527 : {
528 : int ret;
529 : mbedtls_md_type_t md_alg;
530 : mbedtls_rsa_context *rsa_key;
531 :
532 1 : if (rsa_context == NULL || message_hash == NULL) {
533 0 : return false;
534 : }
535 :
536 1 : rsa_key = (mbedtls_rsa_context *)rsa_context;
537 1 : if (mbedtls_rsa_complete(rsa_key) != 0) {
538 0 : return false;
539 : }
540 :
541 1 : switch (hash_nid) {
542 1 : case LIBSPDM_CRYPTO_NID_SHA256:
543 1 : md_alg = MBEDTLS_MD_SHA256;
544 1 : if (hash_size != LIBSPDM_SHA256_DIGEST_SIZE) {
545 0 : return false;
546 : }
547 1 : break;
548 :
549 0 : case LIBSPDM_CRYPTO_NID_SHA384:
550 0 : md_alg = MBEDTLS_MD_SHA384;
551 0 : if (hash_size != LIBSPDM_SHA384_DIGEST_SIZE) {
552 0 : return false;
553 : }
554 0 : break;
555 :
556 0 : case LIBSPDM_CRYPTO_NID_SHA512:
557 0 : md_alg = MBEDTLS_MD_SHA512;
558 0 : if (hash_size != LIBSPDM_SHA512_DIGEST_SIZE) {
559 0 : return false;
560 : }
561 0 : break;
562 :
563 0 : case LIBSPDM_CRYPTO_NID_SHA3_256:
564 0 : md_alg = MBEDTLS_MD_SHA3_256;
565 0 : if (hash_size != LIBSPDM_SHA3_256_DIGEST_SIZE) {
566 0 : return false;
567 : }
568 0 : break;
569 :
570 0 : case LIBSPDM_CRYPTO_NID_SHA3_384:
571 0 : md_alg = MBEDTLS_MD_SHA3_384;
572 0 : if (hash_size != LIBSPDM_SHA3_384_DIGEST_SIZE) {
573 0 : return false;
574 : }
575 0 : break;
576 :
577 0 : case LIBSPDM_CRYPTO_NID_SHA3_512:
578 0 : md_alg = MBEDTLS_MD_SHA3_512;
579 0 : if (hash_size != LIBSPDM_SHA3_512_DIGEST_SIZE) {
580 0 : return false;
581 : }
582 0 : break;
583 :
584 0 : default:
585 0 : return false;
586 : }
587 :
588 1 : if (signature == NULL) {
589 :
590 : /* If signature is NULL, return safe signature_size*/
591 :
592 0 : *sig_size = MBEDTLS_MPI_MAX_SIZE;
593 0 : return false;
594 : }
595 :
596 1 : mbedtls_rsa_set_padding(rsa_context, MBEDTLS_RSA_PKCS_V21, md_alg);
597 :
598 : /*salt len is 0*/
599 1 : ret = mbedtls_rsa_rsassa_pss_sign_ext(rsa_context, libspdm_myrand_rsapss_fips, NULL,
600 : md_alg, (uint32_t)hash_size, message_hash,
601 : 0, signature);
602 1 : if (ret != 0) {
603 0 : return false;
604 : }
605 1 : *sig_size = mbedtls_rsa_get_len(rsa_context);
606 1 : return true;
607 : }
608 : #endif /*LIBSPDM_FIPS_MODE*/
609 :
610 : #endif /* LIBSPDM_RSA_PSS_SUPPORT */
|