From 0e6ac11d15156eacde72355fe3189ff4ccea98db Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Mon, 11 Nov 2024 12:46:42 -0700 Subject: [PATCH 01/10] - Add ability to obtain Dilithium security level (parameters) from a DER encoded key based on the algorithm type OID - Add test coverage for decoding DER keys without level specified --- wolfcrypt/src/dilithium.c | 135 ++++++++++++++++++++++++++++++++++++-- wolfcrypt/test/test.c | 111 +++++++++++++++++++++++++++++++ 2 files changed, 242 insertions(+), 4 deletions(-) diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c index ce01042c86..44f9e7972a 100644 --- a/wolfcrypt/src/dilithium.c +++ b/wolfcrypt/src/dilithium.c @@ -9501,6 +9501,82 @@ int wc_dilithium_export_key(dilithium_key* key, byte* priv, word32 *privSz, #ifndef WOLFSSL_DILITHIUM_NO_ASN1 +/* Maps ASN.1 OID to wolfCrypt security level macros */ +static int mapOidToSecLevel(word32 oid) +{ + switch (oid) { + case ML_DSA_LEVEL2k: + return WC_ML_DSA_44; + case ML_DSA_LEVEL3k: + return WC_ML_DSA_65; + case ML_DSA_LEVEL5k: + return WC_ML_DSA_87; +#ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT + case DILITHIUM_LEVEL2k: + return WC_ML_DSA_44_DRAFT; + case DILITHIUM_LEVEL3k: + return WC_ML_DSA_65_DRAFT; + case DILITHIUM_LEVEL5k: + return WC_ML_DSA_87_DRAFT; +#endif + default: + return ASN_UNKNOWN_OID_E; + } +} + +/* Get security level from DER encoded key. Returns a positive security level + * (e.g. WC_ML_DSA_44, etc.) on success, or a negative value on error. + * + * Expected ASN.1 Structure: + * + * SEQUENCE { -- Outer wrapper + * version INTEGER, -- Version number (usually 0) + * algorithm SEQUENCE { -- AlgorithmIdentifier + * algorithm OBJECT IDENTIFIER -- OID identifying Dilithium variant + * } + * -- Note: Remaining key data after algorithm is ignored for this function + * } + */ +static int getSecLevelFromDer(const byte* der, word32 derSz) +{ + word32 idx = 0; + int seqSz, algSeqSz; + int ret; + word32 oid = 0; + int version; + + if (der == NULL || derSz == 0) { + return BAD_FUNC_ARG; + } + + /* Parse outer SEQUENCE wrapper and get its size + * Advances idx past the SEQUENCE header */ + if ((ret = GetSequence(der, &idx, &seqSz, derSz)) < 0) { + return ret; + } + + /* Parse and skip over version INTEGER + * Advances idx past the version field */ + if ((ret = GetMyVersion(der, &idx, &version, derSz)) < 0) { + return ret; + } + + /* Parse AlgorithmIdentifier SEQUENCE and get its size + * Advances idx past the SEQUENCE header */ + if ((ret = GetSequence(der, &idx, &algSeqSz, derSz)) < 0) { + return ret; + } + + /* Parse OID value from AlgorithmIdentifier + * Advances idx past the OID, stores numeric OID value + * oidSigType indicates this is a signature algorithm OID */ + if ((ret = GetObjectId(der, &idx, &oid, oidSigType, derSz - idx)) < 0) { + return ret; + } + + return mapOidToSecLevel(oid); +} + #if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) /* Decode the DER encoded Dilithium key. @@ -9508,11 +9584,18 @@ int wc_dilithium_export_key(dilithium_key* key, byte* priv, word32 *privSz, * @param [in] input Array holding DER encoded data. * @param [in, out] inOutIdx On in, index into array of start of DER encoding. * On out, index into array after DER encoding. - * @param [in, out] key Dilithium key to store key. - * @param [in] inSz Total size of data in array. + * @param [in, out] key Dilithium key structure to hold the decoded key. + * If the security level is set in the key structure on + * input, the DER key will be decoded as such and will + * fail if there is a mismatch. If the level and + * parameters are not set in the key structure on + * input, the level will be detected from the DER + * file based on the algorithm OID, appropriately + * decoded, then updated in the key structure on + * output. + * @param [in] inSz Total size of the input DER buffer array. * @return 0 on success. * @return BAD_FUNC_ARG when input, inOutIdx or key is NULL or inSz is 0. - * @return BAD_FUNC_ARG when level not set. * @return Other negative on parse error. */ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, @@ -9530,6 +9613,23 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, ret = BAD_FUNC_ARG; } + /* If expected security level not set in key, detect it from DER */ + if (key->level == 0 || key->params == NULL +#ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT + || key->params->level == 0) +#endif + ) { + int level; + level = getSecLevelFromDer(input + *inOutIdx, inSz - *inOutIdx); + if (level < 0) { + ret = level; + } + else { + /* Set params based on level parsed from DER*/ + ret = wc_dilithium_set_level(key, level); + } + } + if (ret == 0) { /* Get OID sum for level. */ #if defined(WOLFSSL_DILITHIUM_FIPS204_DRAFT) @@ -9756,7 +9856,15 @@ static int dilithium_check_type(const byte* input, word32* inOutIdx, byte type, * @param [in] input Array holding DER encoded data. * @param [in, out] inOutIdx On in, index into array of start of DER encoding. * On out, index into array after DER encoding. - * @param [in, out] key Dilithium key to store key. + * @param [in, out] key Dilithium key structure to hold the decoded key. + * If the security level is set in the key structure + * on input, the DER key will be decoded as such + * and will fail if there is a mismatch. If the level + * and parameters are not set in the key structure on + * input, the level will be detected from the DER file + * based on the algorithm OID, appropriately decoded, + * then updated in the key structure on output. + * updated in the key structure on output. * @param [in] inSz Total size of data in array. * @return 0 on success. * @return BAD_FUNC_ARG when input, inOutIdx or key is NULL or inSz is 0. @@ -9775,6 +9883,25 @@ int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx, ret = BAD_FUNC_ARG; } +#if !defined(WOLFSSL_DILITHIUM_NO_ASN1) + /* If expected security level not set in key, detect it from DER */ + if (key->level == 0 || key->params == NULL +#ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT + || key->params->level == 0) +#endif + ) { + int level; + level = getSecLevelFromDer(input + *inOutIdx, inSz - *inOutIdx); + if (level < 0) { + ret = level; + } + else { + /* Set params based on level parsed from DER*/ + ret = wc_dilithium_set_level(key, level); + } + } +#endif /* !WOLFSSL_DILITHIUM_NO_ASN1 */ + if (ret == 0) { /* Try to import the key directly. */ ret = wc_dilithium_import_public(input, inSz, key); diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 10dabe7960..f105641ea3 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -45669,6 +45669,112 @@ static wc_test_ret_t dilithium_param_test(int param, WC_RNG* rng) } #endif +/* Tests decoding a key from DER without the security level specified */ +static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, + word32 rawKeySz, + int expectedLevel) +{ + int ret; + dilithium_key key; + word32 idx; + byte* der; + word32 derSz; + + /* DER encoding adds ~256 bytes of overhead to raw key */ + const word32 estimatedDerSz = rawKeySz + 256; + + /* Allocate DER buffer */ + der = (byte*)XMALLOC(estimatedDerSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + return MEMORY_E; + } + + /* Initialize key */ + ret = wc_dilithium_init(&key); + + /* Import raw key, setting the security level */ + if (ret == 0) { + ret = wc_dilithium_set_level(&key, expectedLevel); + } + if (ret == 0) { + ret = wc_dilithium_import_private(rawKey, rawKeySz, &key); + } + + /* Export raw key as DER */ + if (ret == 0) { + ret = wc_Dilithium_PrivateKeyToDer(&key, der, estimatedDerSz); + if (ret >= 0) { + derSz = ret; + ret = 0; + } + } + + /* Free and reinit key to test fresh decode */ + if (ret == 0) { + wc_dilithium_free(&key); + ret = wc_dilithium_init(&key); + } + + /* Test decoding without setting security level - should auto-detect */ + if (ret == 0) { + idx = 0; + ret = wc_Dilithium_PrivateKeyDecode(der, &idx, &key, derSz); + } + + /* Verify detected security level */ + if (ret == 0 && key.level != expectedLevel) { + printf("Dilithium key decode failed to detect level.\n" + "\tExpected level=%d\n\tGot level=%d\n", + expectedLevel, key.level); + ret = WC_TEST_RET_ENC_NC; + } + + /* Cleanup */ + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_dilithium_free(&key); + return ret; +} + +/* Test Dilithium private key decoding and security level detection */ +static wc_test_ret_t dilithium_decode_test(void) +{ + wc_test_ret_t ret; + const byte* privKey; + word32 privKeySz; + +#ifndef WOLFSSL_NO_ML_DSA_44 + /* Test ML-DSA-44 */ + privKey = bench_dilithium_level2_key; + privKeySz = sizeof_bench_dilithium_level2_key; + ret = test_dilithium_decode_level(privKey, privKeySz, WC_ML_DSA_44); + if (ret != 0) { + return ret; + } +#endif /* WOLFSSL_NO_ML_DSA_44 */ + +#ifndef WOLFSSL_NO_ML_DSA_65 + /* Test ML-DSA-65 */ + privKey = bench_dilithium_level3_key; + privKeySz = sizeof_bench_dilithium_level3_key; + ret = test_dilithium_decode_level(privKey, privKeySz, WC_ML_DSA_65); + if (ret != 0) { + return ret; + } +#endif /* WOLFSSL_NO_ML_DSA_65 */ + +#ifndef WOLFSSL_NO_ML_DSA_87 + /* Test ML-DSA-87 */ + privKey = bench_dilithium_level5_key; + privKeySz = sizeof_bench_dilithium_level5_key; + ret = test_dilithium_decode_level(privKey, privKeySz, WC_ML_DSA_87); + if (ret != 0) { + return ret; + } +#endif /* WOLFSSL_NO_ML_DSA_87 */ + + return ret; +} + WOLFSSL_TEST_SUBROUTINE wc_test_ret_t dilithium_test(void) { wc_test_ret_t ret; @@ -45727,6 +45833,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t dilithium_test(void) #endif #endif + ret = dilithium_decode_test(); + if (ret != 0) { + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + } + #if !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) || \ !defined(WOLFSSL_DILITHIUM_NO_VERIFY) out: From 6b1b6ece00e27e3c04906787626307812af3364d Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Tue, 12 Nov 2024 16:06:07 -0700 Subject: [PATCH 02/10] guard use of dilithium_key->params on WC implementation --- wolfcrypt/src/dilithium.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c index 44f9e7972a..c74ca493ad 100644 --- a/wolfcrypt/src/dilithium.c +++ b/wolfcrypt/src/dilithium.c @@ -9614,9 +9614,9 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, } /* If expected security level not set in key, detect it from DER */ - if (key->level == 0 || key->params == NULL -#ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT - || key->params->level == 0) + if (key->level == 0 +#ifdef WOLFSSL_WC_DILITHIUM + || key->params == NULL #endif ) { int level; @@ -9885,9 +9885,9 @@ int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx, #if !defined(WOLFSSL_DILITHIUM_NO_ASN1) /* If expected security level not set in key, detect it from DER */ - if (key->level == 0 || key->params == NULL -#ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT - || key->params->level == 0) + if (key->level == 0 +#ifdef WOLFSSL_WC_DILITHIUM + || key->params == NULL #endif ) { int level; From f672105d557261eb376073faf06f12f347500ae3 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Wed, 13 Nov 2024 13:07:31 -0700 Subject: [PATCH 03/10] - Move automatic OID detection from Dilithium code into ASN code --- wolfcrypt/src/asn.c | 108 +++++++++++++++++++++++++------ wolfcrypt/src/dilithium.c | 129 ++++++++++---------------------------- wolfcrypt/test/test.c | 95 ++++++++++++++++++++++------ wolfssl/wolfcrypt/asn.h | 8 +++ 4 files changed, 206 insertions(+), 134 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index bf9d5886b7..efdb541031 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -35307,9 +35307,10 @@ enum { || (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT)) \ || defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || defined(HAVE_SPHINCS)) -int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, + +int DecodeAsymKey_Assign_ex(const byte* input, word32* inOutIdx, word32 inSz, const byte** privKey, word32* privKeyLen, - const byte** pubKey, word32* pubKeyLen, int keyType) + const byte** pubKey, word32* pubKeyLen, int* inOutKeyType) { #ifndef WOLFSSL_ASN_TEMPLATE word32 oid; @@ -35337,14 +35338,24 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) return ASN_PARSE_E; if (version != 0) { - WOLFSSL_MSG("Unrecognized version of ED25519 private key"); + WOLFSSL_MSG("Unrecognized version of private key"); return ASN_PARSE_E; } if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0) return ASN_PARSE_E; - if (oid != (word32)keyType) - return ASN_PARSE_E; + + if (inOutKeyType != NULL) { + /* If user supplies ANONk (0) key type, we want to auto-detect from + * DER and copy it back to user */ + if (*inOutKeyType == ANONk) { + *inOutKeyType = oid; + } + /* Otherwise strictly validate against the expected type */ + else if (oid != (word32)*inOutKeyType) { + return ASN_PARSE_E; + } + } if (GetOctetString(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -35394,10 +35405,21 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, return 0; #else if (ret == 0) { - /* Require OID. */ - word32 oidSz; - const byte* oid = OidFromId((word32)keyType, oidKeyType, &oidSz); - GetASN_ExpBuffer(&dataASN[EDKEYASN_IDX_PKEYALGO_OID], oid, oidSz); + /* If user supplies an expected keyType (algorithm OID sum), attempt to + * process DER accordingly */ + if (inOutKeyType != NULL && *inOutKeyType != 0) { + word32 oidSz; + /* Explicit OID check - use expected type */ + const byte* oidDerBytes = OidFromId((word32)*inOutKeyType, + oidKeyType, &oidSz); + GetASN_ExpBuffer(&dataASN[EDKEYASN_IDX_PKEYALGO_OID], oidDerBytes, + oidSz); + } + else { + /* Auto-detect OID using template */ + GetASN_OID(&dataASN[EDKEYASN_IDX_PKEYALGO_OID], oidKeyType); + } + /* Parse full private key. */ ret = GetASN_Items(edKeyASN, dataASN, edKeyASN_Length, 1, input, inOutIdx, inSz); @@ -35410,6 +35432,12 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, ret = ASN_PARSE_E; } } + + /* Store detected OID if requested */ + if (ret == 0 && inOutKeyType != NULL && *inOutKeyType == ANONk) { + *inOutKeyType = + (int)dataASN[EDKEYASN_IDX_PKEYALGO_OID].data.oid.sum; + } } if (ret == 0) { /* Import private value. */ @@ -35434,6 +35462,15 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, #endif /* WOLFSSL_ASN_TEMPLATE */ } + +int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, + const byte** privKey, word32* privKeyLen, + const byte** pubKey, word32* pubKeyLen, int keyType) +{ + return DecodeAsymKey_Assign_ex(input, inOutIdx, inSz, privKey, privKeyLen, + pubKey, pubKeyLen, &keyType); +} + int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, byte* privKey, word32* privKeyLen, byte* pubKey, word32* pubKeyLen, int keyType) @@ -35472,8 +35509,8 @@ int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, return ret; } -int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, - const byte** pubKey, word32* pubKeyLen, int keyType) +int DecodeAsymKeyPublic_Assign_ex(const byte* input, word32* inOutIdx, word32 inSz, + const byte** pubKey, word32* pubKeyLen, int *inOutKeyType) { int ret = 0; #ifndef WOLFSSL_ASN_TEMPLATE @@ -35498,8 +35535,18 @@ int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, if (GetObjectId(input, inOutIdx, &oid, oidKeyType, inSz) < 0) return ASN_PARSE_E; - if (oid != (word32)keyType) - return ASN_PARSE_E; + + if (inOutKeyType != NULL) { + /* If user supplies ANONk (0) key type, we want to auto-detect from + * DER and copy it back to user */ + if (*inOutKeyType == ANONk) { + *inOutKeyType = oid; + } + /* Otherwise strictly validate against the expected type */ + else if (oid != (word32)*inOutKeyType) { + return ASN_PARSE_E; + } + } /* key header */ ret = CheckBitString(input, inOutIdx, &length, inSz, 1, NULL); @@ -35519,12 +35566,21 @@ int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, CALLOC_ASNGETDATA(dataASN, publicKeyASN_Length, ret, NULL); if (ret == 0) { - /* Require OID. */ - word32 oidSz; - const byte* oid = OidFromId((word32)keyType, oidKeyType, &oidSz); - - GetASN_ExpBuffer(&dataASN[PUBKEYASN_IDX_ALGOID_OID], oid, oidSz); - /* Decode Ed25519 private key. */ + /* If user supplies an expected keyType (algorithm OID sum), attempt to + * process DER accordingly */ + if (inOutKeyType != NULL && *inOutKeyType != ANONk) { + word32 oidSz; + /* Explicit OID check - use expected type */ + const byte* oidDerBytes = OidFromId((word32)*inOutKeyType, + oidKeyType, &oidSz); + GetASN_ExpBuffer(&dataASN[PUBKEYASN_IDX_ALGOID_OID], oidDerBytes, + oidSz); + } + else { + /* Auto-detect OID using template */ + GetASN_OID(&dataASN[PUBKEYASN_IDX_ALGOID_OID], oidKeyType); + } + /* Decode public key. */ ret = GetASN_Items(publicKeyASN, dataASN, publicKeyASN_Length, 1, input, inOutIdx, inSz); if (ret != 0) @@ -35532,6 +35588,12 @@ int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, /* check that input buffer is exhausted */ if (*inOutIdx != inSz) ret = ASN_PARSE_E; + + /* Store detected OID if requested */ + if (ret == 0 && inOutKeyType != NULL && *inOutKeyType == ANONk) { + *inOutKeyType = + (int)dataASN[PUBKEYASN_IDX_ALGOID_OID].data.oid.sum; + } } /* Check that the all the buffer was used. */ if ((ret == 0) && @@ -35546,6 +35608,14 @@ int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, FREE_ASNGETDATA(dataASN, NULL); #endif /* WOLFSSL_ASN_TEMPLATE */ return ret; + +} + +int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, + const byte** pubKey, word32* pubKeyLen, int keyType) +{ + return DecodeAsymKeyPublic_Assign_ex(input, inOutIdx, inSz, pubKey, + pubKeyLen, &keyType); } int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz, diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c index c74ca493ad..b5bd40f43a 100644 --- a/wolfcrypt/src/dilithium.c +++ b/wolfcrypt/src/dilithium.c @@ -9524,59 +9524,6 @@ static int mapOidToSecLevel(word32 oid) } } -/* Get security level from DER encoded key. Returns a positive security level - * (e.g. WC_ML_DSA_44, etc.) on success, or a negative value on error. - * - * Expected ASN.1 Structure: - * - * SEQUENCE { -- Outer wrapper - * version INTEGER, -- Version number (usually 0) - * algorithm SEQUENCE { -- AlgorithmIdentifier - * algorithm OBJECT IDENTIFIER -- OID identifying Dilithium variant - * } - * -- Note: Remaining key data after algorithm is ignored for this function - * } - */ -static int getSecLevelFromDer(const byte* der, word32 derSz) -{ - word32 idx = 0; - int seqSz, algSeqSz; - int ret; - word32 oid = 0; - int version; - - if (der == NULL || derSz == 0) { - return BAD_FUNC_ARG; - } - - /* Parse outer SEQUENCE wrapper and get its size - * Advances idx past the SEQUENCE header */ - if ((ret = GetSequence(der, &idx, &seqSz, derSz)) < 0) { - return ret; - } - - /* Parse and skip over version INTEGER - * Advances idx past the version field */ - if ((ret = GetMyVersion(der, &idx, &version, derSz)) < 0) { - return ret; - } - - /* Parse AlgorithmIdentifier SEQUENCE and get its size - * Advances idx past the SEQUENCE header */ - if ((ret = GetSequence(der, &idx, &algSeqSz, derSz)) < 0) { - return ret; - } - - /* Parse OID value from AlgorithmIdentifier - * Advances idx past the OID, stores numeric OID value - * oidSigType indicates this is a signature algorithm OID */ - if ((ret = GetObjectId(der, &idx, &oid, oidSigType, derSz - idx)) < 0) { - return ret; - } - - return mapOidToSecLevel(oid); -} - #if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) /* Decode the DER encoded Dilithium key. @@ -9613,23 +9560,6 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, ret = BAD_FUNC_ARG; } - /* If expected security level not set in key, detect it from DER */ - if (key->level == 0 -#ifdef WOLFSSL_WC_DILITHIUM - || key->params == NULL -#endif - ) { - int level; - level = getSecLevelFromDer(input + *inOutIdx, inSz - *inOutIdx); - if (level < 0) { - ret = level; - } - else { - /* Set params based on level parsed from DER*/ - ret = wc_dilithium_set_level(key, level); - } - } - if (ret == 0) { /* Get OID sum for level. */ #if defined(WOLFSSL_DILITHIUM_FIPS204_DRAFT) @@ -9657,15 +9587,27 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, keytype = ML_DSA_LEVEL5k; } else { - /* Level not set. */ - ret = BAD_FUNC_ARG; + /* Level not set by caller, decode from DER */ + keytype = ANONk; /* 0, not a valid key type in this situation*/ } } if (ret == 0) { /* Decode the asymmetric key and get out private and public key data. */ - ret = DecodeAsymKey_Assign(input, inOutIdx, inSz, &privKey, &privKeyLen, - &pubKey, &pubKeyLen, keytype); + ret = DecodeAsymKey_Assign_ex(input, inOutIdx, inSz, + &privKey, &privKeyLen, + &pubKey, &pubKeyLen, &keytype); + if (ret == 0 +#ifdef WOLFSSL_WC_DILITHIUM + && key->params == NULL +#endif + ) { + /* Set the security level based on the decoded key. */ + ret = mapOidToSecLevel(keytype); + if (ret > 0) { + ret = wc_dilithium_set_level(key, ret); + } + } } if ((ret == 0) && (pubKey == NULL) && (pubKeyLen == 0)) { /* Check if the public key is included in the private key. */ @@ -9883,25 +9825,6 @@ int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx, ret = BAD_FUNC_ARG; } -#if !defined(WOLFSSL_DILITHIUM_NO_ASN1) - /* If expected security level not set in key, detect it from DER */ - if (key->level == 0 -#ifdef WOLFSSL_WC_DILITHIUM - || key->params == NULL -#endif - ) { - int level; - level = getSecLevelFromDer(input + *inOutIdx, inSz - *inOutIdx); - if (level < 0) { - ret = level; - } - else { - /* Set params based on level parsed from DER*/ - ret = wc_dilithium_set_level(key, level); - } - } -#endif /* !WOLFSSL_DILITHIUM_NO_ASN1 */ - if (ret == 0) { /* Try to import the key directly. */ ret = wc_dilithium_import_public(input, inSz, key); @@ -9945,13 +9868,25 @@ int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx, keytype = ML_DSA_LEVEL5k; } else { - /* Level not set. */ - ret = BAD_FUNC_ARG; + /* Level not set by caller, decode from DER */ + keytype = ANONk; /* 0, not a valid key type in this situation*/ } if (ret == 0) { /* Decode the asymmetric key and get out public key data. */ - ret = DecodeAsymKeyPublic_Assign(input, inOutIdx, inSz, &pubKey, - &pubKeyLen, keytype); + ret = DecodeAsymKeyPublic_Assign_ex(input, inOutIdx, inSz, + &pubKey, &pubKeyLen, + &keytype); + if (ret == 0 +#ifdef WOLFSSL_WC_DILITHIUM + && key->params == NULL +#endif + ) { + /* Set the security level based on the decoded key. */ + ret = mapOidToSecLevel(keytype); + if (ret > 0) { + ret = wc_dilithium_set_level(key, ret); + } + } } #else /* Get OID sum for level. */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index f105641ea3..65dd93d10b 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -45672,14 +45672,14 @@ static wc_test_ret_t dilithium_param_test(int param, WC_RNG* rng) /* Tests decoding a key from DER without the security level specified */ static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, word32 rawKeySz, - int expectedLevel) + int expectedLevel, + int isPublicOnlyKey) { int ret; dilithium_key key; word32 idx; byte* der; word32 derSz; - /* DER encoding adds ~256 bytes of overhead to raw key */ const word32 estimatedDerSz = rawKeySz + 256; @@ -45697,12 +45697,22 @@ static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, ret = wc_dilithium_set_level(&key, expectedLevel); } if (ret == 0) { - ret = wc_dilithium_import_private(rawKey, rawKeySz, &key); + if (isPublicOnlyKey) { + ret = wc_dilithium_import_public(rawKey, rawKeySz, &key); + } + else { + ret = wc_dilithium_import_private(rawKey, rawKeySz, &key); + } } /* Export raw key as DER */ if (ret == 0) { - ret = wc_Dilithium_PrivateKeyToDer(&key, der, estimatedDerSz); + if (isPublicOnlyKey) { + ret = wc_Dilithium_PublicKeyToDer(&key, der, estimatedDerSz, 1); + } + else { + ret = wc_Dilithium_PrivateKeyToDer(&key, der, estimatedDerSz); + } if (ret >= 0) { derSz = ret; ret = 0; @@ -45715,13 +45725,38 @@ static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, ret = wc_dilithium_init(&key); } + /* First test decoding when security level is set externally */ + if (ret == 0) { + ret = wc_dilithium_set_level(&key, expectedLevel); + } + if (ret == 0) { + idx = 0; + if (isPublicOnlyKey) { + ret = wc_Dilithium_PublicKeyDecode(der, &idx, &key, derSz); + } + else { + ret = wc_Dilithium_PrivateKeyDecode(der, &idx, &key, derSz); + } + } + + /* Free and reinit key to test fresh decode */ + if (ret == 0) { + wc_dilithium_free(&key); + ret = wc_dilithium_init(&key); + } + /* Test decoding without setting security level - should auto-detect */ if (ret == 0) { idx = 0; - ret = wc_Dilithium_PrivateKeyDecode(der, &idx, &key, derSz); + if (isPublicOnlyKey) { + ret = wc_Dilithium_PublicKeyDecode(der, &idx, &key, derSz); + } + else { + ret = wc_Dilithium_PrivateKeyDecode(der, &idx, &key, derSz); + } } - /* Verify detected security level */ + /* Verify auto-detected security level */ if (ret == 0 && key.level != expectedLevel) { printf("Dilithium key decode failed to detect level.\n" "\tExpected level=%d\n\tGot level=%d\n", @@ -45735,18 +45770,28 @@ static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, return ret; } -/* Test Dilithium private key decoding and security level detection */ +/* Test Dilithium key decoding and security level detection */ static wc_test_ret_t dilithium_decode_test(void) { wc_test_ret_t ret; - const byte* privKey; - word32 privKeySz; + const byte* key; + word32 keySz; + + const int isPrvKey = 0; + const int isPubKey = 1; #ifndef WOLFSSL_NO_ML_DSA_44 /* Test ML-DSA-44 */ - privKey = bench_dilithium_level2_key; - privKeySz = sizeof_bench_dilithium_level2_key; - ret = test_dilithium_decode_level(privKey, privKeySz, WC_ML_DSA_44); + key = bench_dilithium_level2_key; + keySz = sizeof_bench_dilithium_level2_key; + ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_44, isPrvKey); + if (ret != 0) { + return ret; + } + + key = bench_dilithium_level2_pubkey; + keySz = sizeof_bench_dilithium_level2_pubkey; + ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_44, isPubKey); if (ret != 0) { return ret; } @@ -45754,9 +45799,16 @@ static wc_test_ret_t dilithium_decode_test(void) #ifndef WOLFSSL_NO_ML_DSA_65 /* Test ML-DSA-65 */ - privKey = bench_dilithium_level3_key; - privKeySz = sizeof_bench_dilithium_level3_key; - ret = test_dilithium_decode_level(privKey, privKeySz, WC_ML_DSA_65); + key = bench_dilithium_level3_key; + keySz = sizeof_bench_dilithium_level3_key; + ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_65, isPrvKey); + if (ret != 0) { + return ret; + } + + key = bench_dilithium_level3_pubkey; + keySz = sizeof_bench_dilithium_level3_pubkey; + ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_65, isPubKey); if (ret != 0) { return ret; } @@ -45764,9 +45816,16 @@ static wc_test_ret_t dilithium_decode_test(void) #ifndef WOLFSSL_NO_ML_DSA_87 /* Test ML-DSA-87 */ - privKey = bench_dilithium_level5_key; - privKeySz = sizeof_bench_dilithium_level5_key; - ret = test_dilithium_decode_level(privKey, privKeySz, WC_ML_DSA_87); + key = bench_dilithium_level5_key; + keySz = sizeof_bench_dilithium_level5_key; + ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_87, isPrvKey); + if (ret != 0) { + return ret; + } + + key = bench_dilithium_level5_pubkey; + keySz = sizeof_bench_dilithium_level5_pubkey; + ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_87, isPubKey); if (ret != 0) { return ret; } diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index f9d1eb79cf..e37f3af4e3 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -2542,6 +2542,10 @@ WOLFSSL_LOCAL int SetAsymKeyDerPublic(const byte* pubKey, word32 pubKeyLen, WOLFSSL_LOCAL int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, const byte** pubKey, word32* pubKeyLen, int keyType); +WOLFSSL_LOCAL int DecodeAsymKeyPublic_Assign_ex(const byte* input, + word32* inOutIdx, word32 inSz, const byte** pubKey, word32* pubKeyLen, + int* keyType); + WOLFSSL_LOCAL int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz, byte* pubKey, word32* pubKeyLen, int keyType); @@ -2897,6 +2901,10 @@ WOLFSSL_LOCAL int VerifyX509Acert(const byte* cert, word32 certSz, WOLFSSL_LOCAL int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, const byte** privKey, word32* privKeyLen, const byte** pubKey, word32* pubKeyLen, int keyType); +WOLFSSL_LOCAL int DecodeAsymKey_Assign_ex(const byte* input, word32* inOutIdx, + word32 inSz, const byte** privKey, word32* privKeyLen, const byte** pubKey, + word32* pubKeyLen, int* inOutKeyType); + WOLFSSL_LOCAL int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, byte* privKey, word32* privKeyLen, byte* pubKey, word32* pubKeyLen, int keyType); From 2207791aab0a153ae13e250118c549817a33de7f Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Fri, 15 Nov 2024 10:25:10 -0700 Subject: [PATCH 04/10] removed DecodeAsymKeyXXX_Assign_ex function, functionality now included in original _Assign function --- wolfcrypt/src/asn.c | 24 ++++-------------------- wolfcrypt/src/dilithium.c | 12 ++++++------ wolfssl/wolfcrypt/asn.h | 6 ------ 3 files changed, 10 insertions(+), 32 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index efdb541031..9494efc46a 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -35308,7 +35308,7 @@ enum { || defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || defined(HAVE_SPHINCS)) -int DecodeAsymKey_Assign_ex(const byte* input, word32* inOutIdx, word32 inSz, +int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, const byte** privKey, word32* privKeyLen, const byte** pubKey, word32* pubKeyLen, int* inOutKeyType) { @@ -35462,15 +35462,6 @@ int DecodeAsymKey_Assign_ex(const byte* input, word32* inOutIdx, word32 inSz, #endif /* WOLFSSL_ASN_TEMPLATE */ } - -int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, - const byte** privKey, word32* privKeyLen, - const byte** pubKey, word32* pubKeyLen, int keyType) -{ - return DecodeAsymKey_Assign_ex(input, inOutIdx, inSz, privKey, privKeyLen, - pubKey, pubKeyLen, &keyType); -} - int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, byte* privKey, word32* privKeyLen, byte* pubKey, word32* pubKeyLen, int keyType) @@ -35487,7 +35478,7 @@ int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, if (ret == 0) { ret = DecodeAsymKey_Assign(input, inOutIdx, inSz, &privKeyPtr, - &privKeyPtrLen, &pubKeyPtr, &pubKeyPtrLen, keyType); + &privKeyPtrLen, &pubKeyPtr, &pubKeyPtrLen, &keyType); } if ((ret == 0) && (privKeyPtrLen > *privKeyLen)) { ret = BUFFER_E; @@ -35509,7 +35500,7 @@ int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, return ret; } -int DecodeAsymKeyPublic_Assign_ex(const byte* input, word32* inOutIdx, word32 inSz, +int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, const byte** pubKey, word32* pubKeyLen, int *inOutKeyType) { int ret = 0; @@ -35611,13 +35602,6 @@ int DecodeAsymKeyPublic_Assign_ex(const byte* input, word32* inOutIdx, word32 in } -int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, - const byte** pubKey, word32* pubKeyLen, int keyType) -{ - return DecodeAsymKeyPublic_Assign_ex(input, inOutIdx, inSz, pubKey, - pubKeyLen, &keyType); -} - int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz, byte* pubKey, word32* pubKeyLen, int keyType) { @@ -35631,7 +35615,7 @@ int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz, if (ret == 0) { ret = DecodeAsymKeyPublic_Assign(input, inOutIdx, inSz, &pubKeyPtr, - &pubKeyPtrLen, keyType); + &pubKeyPtrLen, &keyType); } if ((ret == 0) && (pubKeyPtrLen > *pubKeyLen)) { ret = BUFFER_E; diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c index b5bd40f43a..d07a4e4c4f 100644 --- a/wolfcrypt/src/dilithium.c +++ b/wolfcrypt/src/dilithium.c @@ -9594,9 +9594,9 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, if (ret == 0) { /* Decode the asymmetric key and get out private and public key data. */ - ret = DecodeAsymKey_Assign_ex(input, inOutIdx, inSz, - &privKey, &privKeyLen, - &pubKey, &pubKeyLen, &keytype); + ret = DecodeAsymKey_Assign(input, inOutIdx, inSz, + &privKey, &privKeyLen, + &pubKey, &pubKeyLen, &keytype); if (ret == 0 #ifdef WOLFSSL_WC_DILITHIUM && key->params == NULL @@ -9873,9 +9873,9 @@ int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx, } if (ret == 0) { /* Decode the asymmetric key and get out public key data. */ - ret = DecodeAsymKeyPublic_Assign_ex(input, inOutIdx, inSz, - &pubKey, &pubKeyLen, - &keytype); + ret = DecodeAsymKeyPublic_Assign(input, inOutIdx, inSz, + &pubKey, &pubKeyLen, + &keytype); if (ret == 0 #ifdef WOLFSSL_WC_DILITHIUM && key->params == NULL diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index e37f3af4e3..b8d1d16c38 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -2540,9 +2540,6 @@ WOLFSSL_LOCAL void FreeSignatureCtx(SignatureCtx* sigCtx); WOLFSSL_LOCAL int SetAsymKeyDerPublic(const byte* pubKey, word32 pubKeyLen, byte* output, word32 outLen, int keyType, int withHeader); WOLFSSL_LOCAL int DecodeAsymKeyPublic_Assign(const byte* input, - word32* inOutIdx, word32 inSz, const byte** pubKey, word32* pubKeyLen, - int keyType); -WOLFSSL_LOCAL int DecodeAsymKeyPublic_Assign_ex(const byte* input, word32* inOutIdx, word32 inSz, const byte** pubKey, word32* pubKeyLen, int* keyType); @@ -2899,9 +2896,6 @@ WOLFSSL_LOCAL int VerifyX509Acert(const byte* cert, word32 certSz, || (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT)) \ || defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || defined(HAVE_SPHINCS)) WOLFSSL_LOCAL int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, - word32 inSz, const byte** privKey, word32* privKeyLen, const byte** pubKey, - word32* pubKeyLen, int keyType); -WOLFSSL_LOCAL int DecodeAsymKey_Assign_ex(const byte* input, word32* inOutIdx, word32 inSz, const byte** privKey, word32* privKeyLen, const byte** pubKey, word32* pubKeyLen, int* inOutKeyType); From 07e2715f0c339524c98c8d35508d15fe1d89c608 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:59:17 -0700 Subject: [PATCH 05/10] update test in api.c to handle new dilithium security level DER parsing --- tests/api.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/api.c b/tests/api.c index a2a8f3441a..49dcf4fc9f 100644 --- a/tests/api.c +++ b/tests/api.c @@ -34843,10 +34843,12 @@ static int test_wc_dilithium_der(void) 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_Dilithium_PrivateKeyToDer(key, der, DILITHIUM_MAX_DER_SIZE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* When security level is not set, we attempt to parse it from DER. Since + * the supplied DER is invalid, this should fail with ASN parsing error */ ExpectIntEQ(wc_Dilithium_PublicKeyDecode(der, &idx, key, pubDerLen), - WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + WC_NO_ERR_TRACE(ASN_PARSE_E)); ExpectIntEQ(wc_Dilithium_PrivateKeyDecode(der, &idx, key, privDerLen), - WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + WC_NO_ERR_TRACE(ASN_PARSE_E)); #ifndef WOLFSSL_NO_ML_DSA_44 ExpectIntEQ(wc_dilithium_set_level(key, WC_ML_DSA_44), 0); From 63deea57e06b8768dcd2ca609ae99bed2f9d1eb9 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:19:41 -0700 Subject: [PATCH 06/10] properly protect test.c calls to dilithium public/private API --- wolfcrypt/test/test.c | 98 +++++++++++++++++++++++++++++++------------ 1 file changed, 71 insertions(+), 27 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 65dd93d10b..65295a07a5 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -45669,17 +45669,20 @@ static wc_test_ret_t dilithium_param_test(int param, WC_RNG* rng) } #endif + +#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) || \ + defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) /* Tests decoding a key from DER without the security level specified */ static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, - word32 rawKeySz, - int expectedLevel, - int isPublicOnlyKey) + word32 rawKeySz, + int expectedLevel, + int isPublicOnlyKey) { - int ret; + int ret; dilithium_key key; - word32 idx; - byte* der; - word32 derSz; + word32 idx; + byte* der; + word32 derSz; /* DER encoding adds ~256 bytes of overhead to raw key */ const word32 estimatedDerSz = rawKeySz + 256; @@ -45696,26 +45699,35 @@ static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, if (ret == 0) { ret = wc_dilithium_set_level(&key, expectedLevel); } + if (ret == 0) { +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY if (isPublicOnlyKey) { ret = wc_dilithium_import_public(rawKey, rawKeySz, &key); } - else { +#endif +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY + if (!isPublicOnlyKey) { ret = wc_dilithium_import_private(rawKey, rawKeySz, &key); } +#endif } /* Export raw key as DER */ if (ret == 0) { +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY if (isPublicOnlyKey) { ret = wc_Dilithium_PublicKeyToDer(&key, der, estimatedDerSz, 1); } - else { +#endif +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY + if (!isPublicOnlyKey) { ret = wc_Dilithium_PrivateKeyToDer(&key, der, estimatedDerSz); } +#endif if (ret >= 0) { derSz = ret; - ret = 0; + ret = 0; } } @@ -45729,14 +45741,19 @@ static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, if (ret == 0) { ret = wc_dilithium_set_level(&key, expectedLevel); } + if (ret == 0) { idx = 0; +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY if (isPublicOnlyKey) { ret = wc_Dilithium_PublicKeyDecode(der, &idx, &key, derSz); } - else { +#endif +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY + if (!isPublicOnlyKey) { ret = wc_Dilithium_PrivateKeyDecode(der, &idx, &key, derSz); } +#endif } /* Free and reinit key to test fresh decode */ @@ -45748,12 +45765,16 @@ static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, /* Test decoding without setting security level - should auto-detect */ if (ret == 0) { idx = 0; +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY if (isPublicOnlyKey) { ret = wc_Dilithium_PublicKeyDecode(der, &idx, &key, derSz); } - else { +#endif +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY + if (!isPublicOnlyKey) { ret = wc_Dilithium_PrivateKeyDecode(der, &idx, &key, derSz); } +#endif } /* Verify auto-detected security level */ @@ -45774,65 +45795,83 @@ static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, static wc_test_ret_t dilithium_decode_test(void) { wc_test_ret_t ret; - const byte* key; - word32 keySz; + const byte* key; + word32 keySz; +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY const int isPrvKey = 0; +#endif +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY const int isPubKey = 1; +#endif #ifndef WOLFSSL_NO_ML_DSA_44 +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY /* Test ML-DSA-44 */ - key = bench_dilithium_level2_key; + key = bench_dilithium_level2_key; keySz = sizeof_bench_dilithium_level2_key; - ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_44, isPrvKey); + ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_44, isPrvKey); if (ret != 0) { return ret; } +#endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY */ - key = bench_dilithium_level2_pubkey; +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY + key = bench_dilithium_level2_pubkey; keySz = sizeof_bench_dilithium_level2_pubkey; - ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_44, isPubKey); + ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_44, isPubKey); if (ret != 0) { return ret; } +#endif /* WOLFSSL_DILITHIUM_PUBLIC_KEY */ #endif /* WOLFSSL_NO_ML_DSA_44 */ #ifndef WOLFSSL_NO_ML_DSA_65 +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY /* Test ML-DSA-65 */ - key = bench_dilithium_level3_key; + key = bench_dilithium_level3_key; keySz = sizeof_bench_dilithium_level3_key; - ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_65, isPrvKey); + ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_65, isPrvKey); if (ret != 0) { return ret; } +#endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY */ - key = bench_dilithium_level3_pubkey; +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY + key = bench_dilithium_level3_pubkey; keySz = sizeof_bench_dilithium_level3_pubkey; - ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_65, isPubKey); + ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_65, isPubKey); if (ret != 0) { return ret; } +#endif /* WOLFSSL_DILITHIUM_PUBLIC_KEY */ #endif /* WOLFSSL_NO_ML_DSA_65 */ #ifndef WOLFSSL_NO_ML_DSA_87 +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY /* Test ML-DSA-87 */ - key = bench_dilithium_level5_key; + key = bench_dilithium_level5_key; keySz = sizeof_bench_dilithium_level5_key; - ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_87, isPrvKey); + ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_87, isPrvKey); if (ret != 0) { return ret; } +#endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY */ - key = bench_dilithium_level5_pubkey; +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY + key = bench_dilithium_level5_pubkey; keySz = sizeof_bench_dilithium_level5_pubkey; - ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_87, isPubKey); + ret = test_dilithium_decode_level(key, keySz, WC_ML_DSA_87, isPubKey); if (ret != 0) { return ret; } +#endif /* WOLFSSL_DILITHIUM_PUBLIC_KEY */ #endif /* WOLFSSL_NO_ML_DSA_87 */ return ret; } +#endif /* WOLFSSL_DILITHIUM_PUBLIC_KEY || WOLFSSL_DILITHIUM_PRIVATE_KEY */ + WOLFSSL_TEST_SUBROUTINE wc_test_ret_t dilithium_test(void) { @@ -45892,13 +45931,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t dilithium_test(void) #endif #endif +#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) || \ + defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) ret = dilithium_decode_test(); if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); } +#endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY || WOLFSSL_DILITHIUM_PUBLIC_KEY */ #if !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) || \ - !defined(WOLFSSL_DILITHIUM_NO_VERIFY) + !defined(WOLFSSL_DILITHIUM_NO_VERIFY) || \ + defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) || \ + defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) out: #endif wc_FreeRng(&rng); From d50fb630712e50a033ebe4f6c8cd75c1cfe4b0c1 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:14:26 -0700 Subject: [PATCH 07/10] add macros for dilithium DER export buffer sizes --- wolfcrypt/test/test.c | 11 ++++++----- wolfssl/wolfcrypt/dilithium.h | 24 +++++++++++++++++++++++- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 65295a07a5..042ac01ef1 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -45683,11 +45683,12 @@ static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, word32 idx; byte* der; word32 derSz; - /* DER encoding adds ~256 bytes of overhead to raw key */ - const word32 estimatedDerSz = rawKeySz + 256; + + /* Size the buffer to accomodate the largest encoded key size */ + const word32 maxDerSz = DILITHIUM_MAX_PRV_KEY_DER_SIZE; /* Allocate DER buffer */ - der = (byte*)XMALLOC(estimatedDerSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = (byte*)XMALLOC(maxDerSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { return MEMORY_E; } @@ -45717,12 +45718,12 @@ static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, if (ret == 0) { #ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY if (isPublicOnlyKey) { - ret = wc_Dilithium_PublicKeyToDer(&key, der, estimatedDerSz, 1); + ret = wc_Dilithium_PublicKeyToDer(&key, der, maxDerSz, 1); } #endif #ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY if (!isPublicOnlyKey) { - ret = wc_Dilithium_PrivateKeyToDer(&key, der, estimatedDerSz); + ret = wc_Dilithium_PrivateKeyToDer(&key, der, maxDerSz); } #endif if (ret >= 0) { diff --git a/wolfssl/wolfcrypt/dilithium.h b/wolfssl/wolfcrypt/dilithium.h index 804e51d58e..7f81ecbc4c 100644 --- a/wolfssl/wolfcrypt/dilithium.h +++ b/wolfssl/wolfcrypt/dilithium.h @@ -114,37 +114,55 @@ #define DILITHIUM_LEVEL2_PUB_KEY_SIZE 1312 #define DILITHIUM_LEVEL2_PRV_KEY_SIZE \ (DILITHIUM_LEVEL2_PUB_KEY_SIZE + DILITHIUM_LEVEL2_KEY_SIZE) +/* Buffer sizes large enough to store exported DER encoded keys */ +#define DILITHIUM_LEVEL2_PUB_KEY_DER_SIZE 1334 +#define DILITHIUM_LEVEL2_PRV_KEY_DER_SIZE 2588 #define DILITHIUM_LEVEL3_KEY_SIZE 4032 #define DILITHIUM_LEVEL3_SIG_SIZE 3309 #define DILITHIUM_LEVEL3_PUB_KEY_SIZE 1952 #define DILITHIUM_LEVEL3_PRV_KEY_SIZE \ (DILITHIUM_LEVEL3_PUB_KEY_SIZE + DILITHIUM_LEVEL3_KEY_SIZE) +/* Buffer sizes large enough to store exported DER encoded keys */ +#define DILITHIUM_LEVEL3_PUB_KEY_DER_SIZE 1974 +#define DILITHIUM_LEVEL3_PRV_KEY_DER_SIZE 4060 + #define DILITHIUM_LEVEL5_KEY_SIZE 4896 #define DILITHIUM_LEVEL5_SIG_SIZE 4627 #define DILITHIUM_LEVEL5_PUB_KEY_SIZE 2592 #define DILITHIUM_LEVEL5_PRV_KEY_SIZE \ (DILITHIUM_LEVEL5_PUB_KEY_SIZE + DILITHIUM_LEVEL5_KEY_SIZE) - +/* Buffer sizes large enough to store exported DER encoded keys */ +#define DILITHIUM_LEVEL5_PUB_KEY_DER_SIZE 2614 +#define DILITHIUM_LEVEL5_PRV_KEY_DER_SIZE 4924 #define ML_DSA_LEVEL2_KEY_SIZE 2560 #define ML_DSA_LEVEL2_SIG_SIZE 2420 #define ML_DSA_LEVEL2_PUB_KEY_SIZE 1312 #define ML_DSA_LEVEL2_PRV_KEY_SIZE \ (ML_DSA_LEVEL2_PUB_KEY_SIZE + ML_DSA_LEVEL2_KEY_SIZE) +/* Buffer sizes large enough to store exported DER encoded keys */ +#define ML_DSA_LEVEL2_PUB_KEY_DER_SIZE DILITHIUM_LEVEL2_PUB_KEY_DER_SIZE +#define ML_DSA_LEVEL2_PRV_KEY_DER_SIZE DILITHIUM_LEVEL2_PRV_KEY_DER_SIZE #define ML_DSA_LEVEL3_KEY_SIZE 4032 #define ML_DSA_LEVEL3_SIG_SIZE 3309 #define ML_DSA_LEVEL3_PUB_KEY_SIZE 1952 #define ML_DSA_LEVEL3_PRV_KEY_SIZE \ (ML_DSA_LEVEL3_PUB_KEY_SIZE + ML_DSA_LEVEL3_KEY_SIZE) +/* Buffer sizes large enough to store exported DER encoded keys */ +#define ML_DSA_LEVEL3_PUB_KEY_DER_SIZE DILITHIUM_LEVEL3_PUB_KEY_DER_SIZE +#define ML_DSA_LEVEL3_PRV_KEY_DER_SIZE DILITHIUM_LEVEL3_PRV_KEY_DER_SIZE #define ML_DSA_LEVEL5_KEY_SIZE 4896 #define ML_DSA_LEVEL5_SIG_SIZE 4627 #define ML_DSA_LEVEL5_PUB_KEY_SIZE 2592 #define ML_DSA_LEVEL5_PRV_KEY_SIZE \ (ML_DSA_LEVEL5_PUB_KEY_SIZE + ML_DSA_LEVEL5_KEY_SIZE) +/* Buffer sizes large enough to store exported DER encoded keys */ +#define ML_DSA_LEVEL5_PUB_KEY_DER_SIZE DILITHIUM_LEVEL5_PUB_KEY_DER_SIZE +#define ML_DSA_LEVEL5_PRV_KEY_DER_SIZE DILITHIUM_LEVEL5_PRV_KEY_DER_SIZE @@ -541,6 +559,10 @@ #define DILITHIUM_MAX_SIG_SIZE DILITHIUM_LEVEL5_SIG_SIZE #define DILITHIUM_MAX_PUB_KEY_SIZE DILITHIUM_LEVEL5_PUB_KEY_SIZE #define DILITHIUM_MAX_PRV_KEY_SIZE DILITHIUM_LEVEL5_PRV_KEY_SIZE +/* Buffer sizes large enough to store exported DER encoded keys */ +#define DILITHIUM_MAX_PUB_KEY_DER_SIZE DILITHIUM_LEVEL5_PUB_KEY_DER_SIZE +#define DILITHIUM_MAX_PRV_KEY_DER_SIZE DILITHIUM_LEVEL5_PRV_KEY_DER_SIZE + #ifdef WOLF_PRIVATE_KEY_ID #define DILITHIUM_MAX_ID_LEN 32 From 9815fcd3ea748b05d382a413f4d485165bb01f61 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:46:10 -0700 Subject: [PATCH 08/10] make inOutKeyType parameter mandatory for DecodeAsymKey_Assign --- wolfcrypt/src/asn.c | 48 +++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 9494efc46a..d9e618031a 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -35324,7 +35324,7 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, #endif if (input == NULL || inOutIdx == NULL || inSz == 0 || - privKey == NULL || privKeyLen == NULL) { + privKey == NULL || privKeyLen == NULL || inOutKeyType == NULL) { #ifdef WOLFSSL_ASN_TEMPLATE FREE_ASNGETDATA(dataASN, NULL); #endif @@ -35345,16 +35345,14 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0) return ASN_PARSE_E; - if (inOutKeyType != NULL) { - /* If user supplies ANONk (0) key type, we want to auto-detect from - * DER and copy it back to user */ - if (*inOutKeyType == ANONk) { - *inOutKeyType = oid; - } - /* Otherwise strictly validate against the expected type */ - else if (oid != (word32)*inOutKeyType) { - return ASN_PARSE_E; - } + /* If user supplies ANONk (0) key type, we want to auto-detect from + * DER and copy it back to user */ + if (*inOutKeyType == ANONk) { + *inOutKeyType = oid; + } + /* Otherwise strictly validate against the expected type */ + else if (oid != (word32)*inOutKeyType) { + return ASN_PARSE_E; } if (GetOctetString(input, inOutIdx, &length, inSz) < 0) @@ -35407,7 +35405,7 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, if (ret == 0) { /* If user supplies an expected keyType (algorithm OID sum), attempt to * process DER accordingly */ - if (inOutKeyType != NULL && *inOutKeyType != 0) { + if (*inOutKeyType != ANONk) { word32 oidSz; /* Explicit OID check - use expected type */ const byte* oidDerBytes = OidFromId((word32)*inOutKeyType, @@ -35434,7 +35432,7 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, } /* Store detected OID if requested */ - if (ret == 0 && inOutKeyType != NULL && *inOutKeyType == ANONk) { + if (ret == 0 && *inOutKeyType == ANONk) { *inOutKeyType = (int)dataASN[EDKEYASN_IDX_PKEYALGO_OID].data.oid.sum; } @@ -35513,7 +35511,7 @@ int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, #endif if (input == NULL || inSz == 0 || inOutIdx == NULL || - pubKey == NULL || pubKeyLen == NULL) { + pubKey == NULL || pubKeyLen == NULL || inOutKeyType == NULL) { return BAD_FUNC_ARG; } @@ -35527,16 +35525,14 @@ int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, if (GetObjectId(input, inOutIdx, &oid, oidKeyType, inSz) < 0) return ASN_PARSE_E; - if (inOutKeyType != NULL) { - /* If user supplies ANONk (0) key type, we want to auto-detect from - * DER and copy it back to user */ - if (*inOutKeyType == ANONk) { - *inOutKeyType = oid; - } - /* Otherwise strictly validate against the expected type */ - else if (oid != (word32)*inOutKeyType) { - return ASN_PARSE_E; - } + /* If user supplies ANONk (0) key type, we want to auto-detect from + * DER and copy it back to user */ + if (*inOutKeyType == ANONk) { + *inOutKeyType = oid; + } + /* Otherwise strictly validate against the expected type */ + else if (oid != (word32)*inOutKeyType) { + return ASN_PARSE_E; } /* key header */ @@ -35559,7 +35555,7 @@ int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, if (ret == 0) { /* If user supplies an expected keyType (algorithm OID sum), attempt to * process DER accordingly */ - if (inOutKeyType != NULL && *inOutKeyType != ANONk) { + if (*inOutKeyType != ANONk) { word32 oidSz; /* Explicit OID check - use expected type */ const byte* oidDerBytes = OidFromId((word32)*inOutKeyType, @@ -35581,7 +35577,7 @@ int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, ret = ASN_PARSE_E; /* Store detected OID if requested */ - if (ret == 0 && inOutKeyType != NULL && *inOutKeyType == ANONk) { + if (ret == 0 && *inOutKeyType == ANONk) { *inOutKeyType = (int)dataASN[PUBKEYASN_IDX_ALGOID_OID].data.oid.sum; } From 48dcbe9cafbbfe8ae296ebdb911e199c781f3a54 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:50:35 -0700 Subject: [PATCH 09/10] fix typo in comment --- wolfcrypt/test/test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 042ac01ef1..5efc443b98 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -45684,7 +45684,7 @@ static wc_test_ret_t test_dilithium_decode_level(const byte* rawKey, byte* der; word32 derSz; - /* Size the buffer to accomodate the largest encoded key size */ + /* Size the buffer to accommodate the largest encoded key size */ const word32 maxDerSz = DILITHIUM_MAX_PRV_KEY_DER_SIZE; /* Allocate DER buffer */ From 26d3b00a9c9db609039a73e12b7b2a5d9123daa5 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:53:12 -0700 Subject: [PATCH 10/10] added DER size macros to libOQS build --- wolfssl/wolfcrypt/dilithium.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/wolfssl/wolfcrypt/dilithium.h b/wolfssl/wolfcrypt/dilithium.h index 7f81ecbc4c..c43bc7e7a4 100644 --- a/wolfssl/wolfcrypt/dilithium.h +++ b/wolfssl/wolfcrypt/dilithium.h @@ -521,18 +521,27 @@ #define DILITHIUM_LEVEL2_PUB_KEY_SIZE OQS_SIG_ml_dsa_44_ipd_length_public_key #define DILITHIUM_LEVEL2_PRV_KEY_SIZE \ (DILITHIUM_LEVEL2_PUB_KEY_SIZE+DILITHIUM_LEVEL2_KEY_SIZE) +/* Buffer sizes large enough to store exported DER encoded keys */ +#define DILITHIUM_LEVEL2_PUB_KEY_DER_SIZE 1334 +#define DILITHIUM_LEVEL2_PRV_KEY_DER_SIZE 2588 #define DILITHIUM_LEVEL3_KEY_SIZE OQS_SIG_ml_dsa_65_ipd_length_secret_key #define DILITHIUM_LEVEL3_SIG_SIZE OQS_SIG_ml_dsa_65_ipd_length_signature #define DILITHIUM_LEVEL3_PUB_KEY_SIZE OQS_SIG_ml_dsa_65_ipd_length_public_key #define DILITHIUM_LEVEL3_PRV_KEY_SIZE \ (DILITHIUM_LEVEL3_PUB_KEY_SIZE+DILITHIUM_LEVEL3_KEY_SIZE) +/* Buffer sizes large enough to store exported DER encoded keys */ +#define DILITHIUM_LEVEL3_PUB_KEY_DER_SIZE 1974 +#define DILITHIUM_LEVEL3_PRV_KEY_DER_SIZE 4060 #define DILITHIUM_LEVEL5_KEY_SIZE OQS_SIG_ml_dsa_87_ipd_length_secret_key #define DILITHIUM_LEVEL5_SIG_SIZE OQS_SIG_ml_dsa_87_ipd_length_signature #define DILITHIUM_LEVEL5_PUB_KEY_SIZE OQS_SIG_ml_dsa_87_ipd_length_public_key #define DILITHIUM_LEVEL5_PRV_KEY_SIZE \ (DILITHIUM_LEVEL5_PUB_KEY_SIZE+DILITHIUM_LEVEL5_KEY_SIZE) +/* Buffer sizes large enough to store exported DER encoded keys */ +#define DILITHIUM_LEVEL5_PUB_KEY_DER_SIZE 2614 +#define DILITHIUM_LEVEL5_PRV_KEY_DER_SIZE 4924 #define ML_DSA_LEVEL2_KEY_SIZE OQS_SIG_ml_dsa_44_ipd_length_secret_key @@ -540,18 +549,27 @@ #define ML_DSA_LEVEL2_PUB_KEY_SIZE OQS_SIG_ml_dsa_44_ipd_length_public_key #define ML_DSA_LEVEL2_PRV_KEY_SIZE \ (ML_DSA_LEVEL2_PUB_KEY_SIZE+ML_DSA_LEVEL2_KEY_SIZE) +/* Buffer sizes large enough to store exported DER encoded keys */ +#define ML_DSA_LEVEL2_PUB_KEY_DER_SIZE DILITHIUM_LEVEL2_PUB_KEY_DER_SIZE +#define ML_DSA_LEVEL2_PRV_KEY_DER_SIZE DILITHIUM_LEVEL2_PRV_KEY_DER_SIZE #define ML_DSA_LEVEL3_KEY_SIZE OQS_SIG_ml_dsa_65_ipd_length_secret_key #define ML_DSA_LEVEL3_SIG_SIZE OQS_SIG_ml_dsa_65_ipd_length_signature #define ML_DSA_LEVEL3_PUB_KEY_SIZE OQS_SIG_ml_dsa_65_ipd_length_public_key #define ML_DSA_LEVEL3_PRV_KEY_SIZE \ (ML_DSA_LEVEL3_PUB_KEY_SIZE+ML_DSA_LEVEL3_KEY_SIZE) +/* Buffer sizes large enough to store exported DER encoded keys */ +#define ML_DSA_LEVEL3_PUB_KEY_DER_SIZE DILITHIUM_LEVEL3_PUB_KEY_DER_SIZE +#define ML_DSA_LEVEL3_PRV_KEY_DER_SIZE DILITHIUM_LEVEL3_PRV_KEY_DER_SIZE #define ML_DSA_LEVEL5_KEY_SIZE OQS_SIG_ml_dsa_87_ipd_length_secret_key #define ML_DSA_LEVEL5_SIG_SIZE OQS_SIG_ml_dsa_87_ipd_length_signature #define ML_DSA_LEVEL5_PUB_KEY_SIZE OQS_SIG_ml_dsa_87_ipd_length_public_key #define ML_DSA_LEVEL5_PRV_KEY_SIZE \ (ML_DSA_LEVEL5_PUB_KEY_SIZE+ML_DSA_LEVEL5_KEY_SIZE) +/* Buffer sizes large enough to store exported DER encoded keys */ +#define ML_DSA_LEVEL5_PUB_KEY_DER_SIZE DILITHIUM_LEVEL5_PUB_KEY_DER_SIZE +#define ML_DSA_LEVEL5_PRV_KEY_DER_SIZE DILITHIUM_LEVEL5_PRV_KEY_DER_SIZE #endif