|
55 | 55 | * Key data is assigned into Dilithium key rather than copied. |
56 | 56 | * Life of key data passed in is tightly coupled to life of Dilithium key. |
57 | 57 | * Cannot be used when make key is enabled. |
| 58 | + * WOLFSSL_DILITHIUM_DYNAMIC_KEYS Default: OFF |
| 59 | + * Key buffers (public and private) are dynamically allocated on the heap |
| 60 | + * instead of being static arrays in the key struct. Buffers are right-sized |
| 61 | + * for the key's ML-DSA level and only allocated when needed (e.g. no private |
| 62 | + * key buffer for verify-only keys). Reduces memory footprint significantly. |
| 63 | + * Cannot be used with WOLFSSL_DILITHIUM_ASSIGN_KEY. |
58 | 64 | * WOLFSSL_DILITHIUM_SIGN_SMALL_MEM Default: OFF |
59 | 65 | * Compiles signature implementation that uses smaller amounts of memory but |
60 | 66 | * is considerably slower. |
@@ -218,6 +224,11 @@ void print_data(const char* name, const byte* d, int len) |
218 | 224 | #error "Cannot use assign key when making keys" |
219 | 225 | #endif |
220 | 226 |
|
| 227 | +#if defined(WOLFSSL_DILITHIUM_DYNAMIC_KEYS) && \ |
| 228 | + defined(WOLFSSL_DILITHIUM_ASSIGN_KEY) |
| 229 | + #error "Cannot use both WOLFSSL_DILITHIUM_DYNAMIC_KEYS and WOLFSSL_DILITHIUM_ASSIGN_KEY" |
| 230 | +#endif |
| 231 | + |
221 | 232 |
|
222 | 233 | /* Number of bytes from first block to use for sign. */ |
223 | 234 | #define DILITHIUM_SIGN_BYTES 8 |
@@ -358,6 +369,76 @@ static int dilithium_get_params(int level, const wc_dilithium_params** params) |
358 | 369 | return ret; |
359 | 370 | } |
360 | 371 |
|
| 372 | +#if defined(WOLFSSL_DILITHIUM_DYNAMIC_KEYS) && \ |
| 373 | + defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) |
| 374 | +/* Allocate the private key buffer for the current level if not already |
| 375 | + * allocated. Buffer is sized via wc_dilithium_size(key) and the allocated size |
| 376 | + * is stored in key->kSz for later use (ForceZero, free). On failure key->k may |
| 377 | + * remain NULL; callers must not inspect it. */ |
| 378 | +static int dilithium_alloc_priv_buf(dilithium_key* key) |
| 379 | +{ |
| 380 | + int ret = 0; |
| 381 | + |
| 382 | + if (key->k == NULL) { |
| 383 | + int secSz = wc_dilithium_size(key); |
| 384 | + if (secSz < 0) { |
| 385 | + /* Should not happen, as the level checks have already been |
| 386 | + * performed, but defense-in-depth. */ |
| 387 | + ret = BAD_STATE_E; |
| 388 | + } |
| 389 | + else { |
| 390 | + #ifdef USE_INTEL_SPEEDUP |
| 391 | + secSz += 8; |
| 392 | + #endif |
| 393 | + key->k = (byte*)XMALLOC((word32)secSz, key->heap, |
| 394 | + DYNAMIC_TYPE_DILITHIUM); |
| 395 | + if (key->k == NULL) { |
| 396 | + ret = MEMORY_E; |
| 397 | + } |
| 398 | + else { |
| 399 | + key->kSz = (word32)secSz; |
| 400 | + } |
| 401 | + } |
| 402 | + } |
| 403 | + return ret; |
| 404 | +} |
| 405 | +#endif |
| 406 | + |
| 407 | +#if defined(WOLFSSL_DILITHIUM_DYNAMIC_KEYS) && \ |
| 408 | + defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) |
| 409 | +/* Allocate the public key buffer for the current level if not already |
| 410 | + * allocated. Buffer is sized via wc_dilithium_pub_size(key) and the allocated |
| 411 | + * size is stored in key->pSz for later use. On failure key->p may remain NULL; |
| 412 | + * callers must not inspect it. */ |
| 413 | +static int dilithium_alloc_pub_buf(dilithium_key* key) |
| 414 | +{ |
| 415 | + int ret = 0; |
| 416 | + |
| 417 | + if (key->p == NULL) { |
| 418 | + int pubSz = wc_dilithium_pub_size(key); |
| 419 | + if (pubSz < 0) { |
| 420 | + /* Should not happen, as the level checks have already been |
| 421 | + * performed, but defense-in-depth. */ |
| 422 | + ret = BAD_STATE_E; |
| 423 | + } |
| 424 | + else { |
| 425 | + #ifdef USE_INTEL_SPEEDUP |
| 426 | + pubSz += 8; |
| 427 | + #endif |
| 428 | + key->p = (byte*)XMALLOC((word32)pubSz, key->heap, |
| 429 | + DYNAMIC_TYPE_DILITHIUM); |
| 430 | + if (key->p == NULL) { |
| 431 | + ret = MEMORY_E; |
| 432 | + } |
| 433 | + else { |
| 434 | + key->pSz = (word32)pubSz; |
| 435 | + } |
| 436 | + } |
| 437 | + } |
| 438 | + return ret; |
| 439 | +} |
| 440 | +#endif |
| 441 | + |
361 | 442 | /****************************************************************************** |
362 | 443 | * Hash operations |
363 | 444 | ******************************************************************************/ |
@@ -7654,9 +7735,20 @@ static int dilithium_make_key_from_seed(dilithium_key* key, const byte* seed) |
7654 | 7735 | sword32* s1 = NULL; |
7655 | 7736 | sword32* s2 = NULL; |
7656 | 7737 | sword32* t = NULL; |
7657 | | - byte* pub_seed = key->k; |
| 7738 | + byte* pub_seed = NULL; |
7658 | 7739 | byte kl[2]; |
7659 | 7740 |
|
| 7741 | +#ifdef WOLFSSL_DILITHIUM_DYNAMIC_KEYS |
| 7742 | + ret = dilithium_alloc_priv_buf(key); |
| 7743 | + if (ret == 0) { |
| 7744 | + ret = dilithium_alloc_pub_buf(key); |
| 7745 | + } |
| 7746 | +#endif |
| 7747 | + |
| 7748 | + if (ret == 0) { |
| 7749 | + pub_seed = key->k; |
| 7750 | + } |
| 7751 | + |
7660 | 7752 | /* Allocate memory for large intermediates. */ |
7661 | 7753 | #ifdef WC_DILITHIUM_CACHE_MATRIX_A |
7662 | 7754 | #ifndef WC_DILITHIUM_FIXED_ARRAY |
@@ -7818,11 +7910,22 @@ static int dilithium_make_key_from_seed(dilithium_key* key, const byte* seed) |
7818 | 7910 | sword64* t64 = NULL; |
7819 | 7911 | #endif |
7820 | 7912 | byte* h = NULL; |
7821 | | - byte* pub_seed = key->k; |
| 7913 | + byte* pub_seed = NULL; |
7822 | 7914 | unsigned int r; |
7823 | 7915 | unsigned int s; |
7824 | 7916 | byte kl[2]; |
7825 | 7917 |
|
| 7918 | +#ifdef WOLFSSL_DILITHIUM_DYNAMIC_KEYS |
| 7919 | + ret = dilithium_alloc_priv_buf(key); |
| 7920 | + if (ret == 0) { |
| 7921 | + ret = dilithium_alloc_pub_buf(key); |
| 7922 | + } |
| 7923 | +#endif |
| 7924 | + |
| 7925 | + if (ret == 0) { |
| 7926 | + pub_seed = key->k; |
| 7927 | + } |
| 7928 | + |
7826 | 7929 | /* Allocate memory for large intermediates. */ |
7827 | 7930 | if (ret == 0) { |
7828 | 7931 | unsigned int allocSz; |
@@ -10000,6 +10103,16 @@ static int oqs_dilithium_make_key(dilithium_key* key, WC_RNG* rng) |
10000 | 10103 | ret = SIG_TYPE_E; |
10001 | 10104 | } |
10002 | 10105 |
|
| 10106 | + |
| 10107 | +#ifdef WOLFSSL_DILITHIUM_DYNAMIC_KEYS |
| 10108 | + if (ret == 0) { |
| 10109 | + ret = dilithium_alloc_priv_buf(key); |
| 10110 | + } |
| 10111 | + if (ret == 0) { |
| 10112 | + ret = dilithium_alloc_pub_buf(key); |
| 10113 | + } |
| 10114 | +#endif |
| 10115 | + |
10003 | 10116 | if (ret == 0) { |
10004 | 10117 | ret = wolfSSL_liboqsRngMutexLock(rng); |
10005 | 10118 | if (ret == 0) { |
@@ -10921,6 +11034,20 @@ int wc_dilithium_set_level(dilithium_key* key, byte level) |
10921 | 11034 | #endif |
10922 | 11035 | #endif /* WOLFSSL_WC_DILITHIUM */ |
10923 | 11036 |
|
| 11037 | +#ifdef WOLFSSL_DILITHIUM_DYNAMIC_KEYS |
| 11038 | + if (key->k != NULL) { |
| 11039 | + ForceZero(key->k, key->kSz); |
| 11040 | + XFREE(key->k, key->heap, DYNAMIC_TYPE_DILITHIUM); |
| 11041 | + key->k = NULL; |
| 11042 | + key->kSz = 0; |
| 11043 | + } |
| 11044 | + if (key->p != NULL) { |
| 11045 | + XFREE(key->p, key->heap, DYNAMIC_TYPE_DILITHIUM); |
| 11046 | + key->p = NULL; |
| 11047 | + key->pSz = 0; |
| 11048 | + } |
| 11049 | +#endif |
| 11050 | + |
10924 | 11051 | /* Store level and indicate public and private key are not set. */ |
10925 | 11052 | key->level = level % WC_ML_DSA_DRAFT; |
10926 | 11053 | key->pubKeySet = 0; |
@@ -10991,6 +11118,15 @@ void wc_dilithium_free(dilithium_key* key) |
10991 | 11118 | /* Free the SHAKE-128/256 object. */ |
10992 | 11119 | wc_Shake256_Free(&key->shake); |
10993 | 11120 | #endif |
| 11121 | +#endif |
| 11122 | +#ifdef WOLFSSL_DILITHIUM_DYNAMIC_KEYS |
| 11123 | + if (key->k != NULL) { |
| 11124 | + ForceZero(key->k, key->kSz); |
| 11125 | + XFREE(key->k, key->heap, DYNAMIC_TYPE_DILITHIUM); |
| 11126 | + } |
| 11127 | + if (key->p != NULL) { |
| 11128 | + XFREE(key->p, key->heap, DYNAMIC_TYPE_DILITHIUM); |
| 11129 | + } |
10994 | 11130 | #endif |
10995 | 11131 | /* Ensure all private data is zeroized. */ |
10996 | 11132 | ForceZero(key, sizeof(*key)); |
@@ -11553,12 +11689,19 @@ int wc_dilithium_import_public(const byte* in, word32 inLen, dilithium_key* key) |
11553 | 11689 | } |
11554 | 11690 | } |
11555 | 11691 |
|
| 11692 | + |
| 11693 | +#ifdef WOLFSSL_DILITHIUM_DYNAMIC_KEYS |
| 11694 | + if (ret == 0) { |
| 11695 | + ret = dilithium_alloc_pub_buf(key); |
| 11696 | + } |
| 11697 | +#endif |
| 11698 | + |
11556 | 11699 | if (ret == 0) { |
11557 | 11700 | /* Copy the private key data in or copy pointer. */ |
11558 | | - #ifndef WOLFSSL_DILITHIUM_ASSIGN_KEY |
11559 | | - XMEMCPY(key->p, in, inLen); |
11560 | | - #else |
| 11701 | + #ifdef WOLFSSL_DILITHIUM_ASSIGN_KEY |
11561 | 11702 | key->p = in; |
| 11703 | + #else |
| 11704 | + XMEMCPY(key->p, in, inLen); |
11562 | 11705 | #endif |
11563 | 11706 |
|
11564 | 11707 | #ifdef WC_DILITHIUM_CACHE_PUB_VECTORS |
@@ -11630,23 +11773,35 @@ static int dilithium_set_priv_key(const byte* priv, word32 privSz, |
11630 | 11773 | dilithium_key* key) |
11631 | 11774 | { |
11632 | 11775 | int ret = 0; |
| 11776 | + int expPrivSz; |
11633 | 11777 | #ifdef WC_DILITHIUM_CACHE_MATRIX_A |
11634 | 11778 | const wc_dilithium_params* params = key->params; |
11635 | 11779 | #endif |
11636 | 11780 |
|
11637 | | - /* Validate parameters. */ |
11638 | | - if ((privSz != ML_DSA_LEVEL2_KEY_SIZE) && |
11639 | | - (privSz != ML_DSA_LEVEL3_KEY_SIZE) && |
11640 | | - (privSz != ML_DSA_LEVEL5_KEY_SIZE)) { |
| 11781 | + /* Validate parameters. privSz must match the expected size for the |
| 11782 | + * level set on the key. This is required so that subsequent code |
| 11783 | + * which reads via key->params stays within the (possibly dynamically |
| 11784 | + * sized) buffer. */ |
| 11785 | + expPrivSz = wc_dilithium_size(key); |
| 11786 | + if (expPrivSz < 0) { |
11641 | 11787 | ret = BAD_FUNC_ARG; |
11642 | 11788 | } |
| 11789 | + else if (privSz != (word32)expPrivSz) { |
| 11790 | + ret = BAD_FUNC_ARG; |
| 11791 | + } |
| 11792 | + |
| 11793 | +#ifdef WOLFSSL_DILITHIUM_DYNAMIC_KEYS |
| 11794 | + if (ret == 0) { |
| 11795 | + ret = dilithium_alloc_priv_buf(key); |
| 11796 | + } |
| 11797 | +#endif |
11643 | 11798 |
|
11644 | 11799 | if (ret == 0) { |
11645 | 11800 | /* Copy the private key data in or copy pointer. */ |
11646 | | - #ifndef WOLFSSL_DILITHIUM_ASSIGN_KEY |
11647 | | - XMEMCPY(key->k, priv, privSz); |
11648 | | - #else |
| 11801 | + #ifdef WOLFSSL_DILITHIUM_ASSIGN_KEY |
11649 | 11802 | key->k = priv; |
| 11803 | + #else |
| 11804 | + XMEMCPY(key->k, priv, privSz); |
11650 | 11805 | #endif |
11651 | 11806 | } |
11652 | 11807 |
|
|
0 commit comments