Add ML-DSA SPKI/PKCS#8 DER support to d2i_PUBKEY and d2i_PrivateKey.

This commit is contained in:
Chris Conlon
2026-04-24 16:12:07 -06:00
parent 5151a695bc
commit fe4473fbea
9 changed files with 3513 additions and 85 deletions
+20
View File
@@ -0,0 +1,20 @@
ML-DSA (FIPS 204) test key material for wolfSSL tests.
File variants, per level N in {44, 65, 87}:
mldsa<N>_bare-seed.der raw 32-byte seed
mldsa<N>_seed-only.der PKCS#8 with seed-only private key
mldsa<N>_bare-priv.der raw expanded private key
mldsa<N>_priv-only.der PKCS#8 with expanded-only private key
mldsa<N>_seed-priv.der PKCS#8 with seed-and-expanded private key
mldsa<N>_oqskeypair.der liboqs concatenated (priv || pub) format
mldsa<N>_pub-spki.der SubjectPublicKeyInfo wrapping the public key
The *_pub-spki.der files were derived from the matching *_priv-only.der files
using OpenSSL 3.5+:
openssl pkey -inform DER -in mldsa<N>_priv-only.der \
-pubout -outform DER -out mldsa<N>_pub-spki.der
Regenerating the private-key variants requires producing each of the
PKCS#8 shape options explicitly; OpenSSL's default output is the
seed-and-expanded form.
+4
View File
@@ -3,20 +3,24 @@
#
EXTRA_DIST += \
certs/mldsa/README.txt \
certs/mldsa/mldsa44_seed-only.der \
certs/mldsa/mldsa44_priv-only.der \
certs/mldsa/mldsa44_pub-spki.der \
certs/mldsa/mldsa44_seed-priv.der \
certs/mldsa/mldsa44_oqskeypair.der \
certs/mldsa/mldsa44_bare-seed.der \
certs/mldsa/mldsa44_bare-priv.der \
certs/mldsa/mldsa65_seed-only.der \
certs/mldsa/mldsa65_priv-only.der \
certs/mldsa/mldsa65_pub-spki.der \
certs/mldsa/mldsa65_seed-priv.der \
certs/mldsa/mldsa65_oqskeypair.der \
certs/mldsa/mldsa65_bare-seed.der \
certs/mldsa/mldsa65_bare-priv.der \
certs/mldsa/mldsa87_seed-only.der \
certs/mldsa/mldsa87_priv-only.der \
certs/mldsa/mldsa87_pub-spki.der \
certs/mldsa/mldsa87_seed-priv.der \
certs/mldsa/mldsa87_oqskeypair.der \
certs/mldsa/mldsa87_bare-seed.der \
Binary file not shown.
Binary file not shown.
Binary file not shown.
+45
View File
@@ -2094,6 +2094,51 @@ static const unsigned char bench_dilithium_level5_pubkey[] = {
";
# ML-DSA test key material encoded per the IETF LAMPS WG profile:
# SubjectPublicKeyInfo for public keys, PKCS#8 PrivateKeyInfo for
# private keys, using the NIST id-ml-dsa-N OIDs.
print OUT_FILE "#if defined(HAVE_DILITHIUM)\n\n";
for my $L ( [44,"WOLFSSL_NO_ML_DSA_44"],
[65,"WOLFSSL_NO_ML_DSA_65"],
[87,"WOLFSSL_NO_ML_DSA_87"] ) {
my ($n, $noLevel) = @$L;
print OUT_FILE "#if !defined($noLevel)\n\n";
print OUT_FILE "#ifndef WOLFSSL_DILITHIUM_NO_VERIFY\n";
print OUT_FILE "/* ./certs/mldsa/mldsa${n}_pub-spki.der */\n";
print OUT_FILE "static const unsigned char mldsa${n}_pub_spki[] =\n{\n";
file_to_hex("./certs/mldsa/mldsa${n}_pub-spki.der");
print OUT_FILE "};\n";
print OUT_FILE "#define sizeof_mldsa${n}_pub_spki (sizeof(mldsa${n}_pub_spki))\n";
print OUT_FILE "#endif /* !WOLFSSL_DILITHIUM_NO_VERIFY */\n\n";
print OUT_FILE "#ifndef WOLFSSL_DILITHIUM_NO_SIGN\n";
print OUT_FILE "/* ./certs/mldsa/mldsa${n}_priv-only.der */\n";
print OUT_FILE "static const unsigned char mldsa${n}_priv_only[] =\n{\n";
file_to_hex("./certs/mldsa/mldsa${n}_priv-only.der");
print OUT_FILE "};\n";
print OUT_FILE "#define sizeof_mldsa${n}_priv_only (sizeof(mldsa${n}_priv_only))\n";
print OUT_FILE "/* ./certs/mldsa/mldsa${n}_seed-priv.der */\n";
print OUT_FILE "static const unsigned char mldsa${n}_seed_priv[] =\n{\n";
file_to_hex("./certs/mldsa/mldsa${n}_seed-priv.der");
print OUT_FILE "};\n";
print OUT_FILE "#define sizeof_mldsa${n}_seed_priv (sizeof(mldsa${n}_seed_priv))\n";
print OUT_FILE "/* ./certs/mldsa/mldsa${n}_seed-only.der */\n";
print OUT_FILE "static const unsigned char mldsa${n}_seed_only[] =\n{\n";
file_to_hex("./certs/mldsa/mldsa${n}_seed-only.der");
print OUT_FILE "};\n";
print OUT_FILE "#define sizeof_mldsa${n}_seed_only (sizeof(mldsa${n}_seed_only))\n";
print OUT_FILE "#endif /* !WOLFSSL_DILITHIUM_NO_SIGN */\n\n";
print OUT_FILE "#endif /* !$noLevel */\n\n";
}
print OUT_FILE "#endif /* HAVE_DILITHIUM */\n\n";
# convert and print 256-bit cert/keys
print OUT_FILE "#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256)\n\n";
for (my $i = 0; $i < $num_ecc; $i++) {
+312
View File
@@ -18853,6 +18853,48 @@ static int test_wolfSSL_ticket_keys(void)
#ifndef NO_BIO
#if defined(OPENSSL_EXTRA) && defined(HAVE_DILITHIUM)
/* Verify wc_dilithium auto detects the expected ML-DSA level from the OID
* in a SPKI / PKCS#8 DER buffer. Returns 0 on match. */
static int check_dilithium_der_level(const byte* der, word32 derSz,
byte expectedLevel, int isPrivate)
{
dilithium_key key;
word32 idx = 0;
byte level = 0;
int rc;
#ifndef WOLFSSL_DILITHIUM_PRIVATE_KEY
(void)isPrivate;
#endif
if ((rc = wc_dilithium_init(&key)) != 0) {
return rc;
}
#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY)
if (isPrivate) {
rc = wc_Dilithium_PrivateKeyDecode(der, &idx, &key, derSz);
}
else
#endif
{
rc = wc_Dilithium_PublicKeyDecode(der, &idx, &key, derSz);
}
if (rc == 0) {
rc = wc_dilithium_get_level(&key, &level);
}
if (rc == 0 && level != expectedLevel) {
rc = -1;
}
wc_dilithium_free(&key);
return rc;
}
#endif /* OPENSSL_EXTRA && HAVE_DILITHIUM */
static int test_wolfSSL_d2i_PUBKEY(void)
{
EXPECT_DECLS;
@@ -18903,6 +18945,93 @@ defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA)
#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
#endif /* USE_CERT_BUFFERS_2048 && !NO_DH && && OPENSSL_EXTRA */
#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_VERIFY)
#if !defined(WOLFSSL_NO_ML_DSA_44)
/* ML-DSA-44 PUBKEY test (raw key bytes) */
ExpectIntGT(BIO_write(bio, bench_dilithium_level2_pubkey,
sizeof_bench_dilithium_level2_pubkey), 0);
ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
EVP_PKEY_free(pkey);
pkey = NULL;
/* ML-DSA-44 PUBKEY test (LAMPS SubjectPublicKeyInfo DER) */
ExpectIntGT(BIO_write(bio, mldsa44_pub_spki, sizeof_mldsa44_pub_spki), 0);
ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
ExpectIntEQ(check_dilithium_der_level(mldsa44_pub_spki,
sizeof_mldsa44_pub_spki, WC_ML_DSA_44, 0), 0);
EVP_PKEY_free(pkey);
pkey = NULL;
#endif
#if !defined(WOLFSSL_NO_ML_DSA_65)
/* ML-DSA-65 PUBKEY test (raw key bytes) */
ExpectIntGT(BIO_write(bio, bench_dilithium_level3_pubkey,
sizeof_bench_dilithium_level3_pubkey), 0);
ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
EVP_PKEY_free(pkey);
pkey = NULL;
/* ML-DSA-65 PUBKEY test (LAMPS SubjectPublicKeyInfo DER) */
ExpectIntGT(BIO_write(bio, mldsa65_pub_spki, sizeof_mldsa65_pub_spki), 0);
ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
ExpectIntEQ(check_dilithium_der_level(mldsa65_pub_spki,
sizeof_mldsa65_pub_spki, WC_ML_DSA_65, 0), 0);
EVP_PKEY_free(pkey);
pkey = NULL;
#endif
#if !defined(WOLFSSL_NO_ML_DSA_87)
/* ML-DSA-87 PUBKEY test (raw key bytes) */
ExpectIntGT(BIO_write(bio, bench_dilithium_level5_pubkey,
sizeof_bench_dilithium_level5_pubkey), 0);
ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
EVP_PKEY_free(pkey);
pkey = NULL;
/* ML-DSA-87 PUBKEY test (LAMPS SubjectPublicKeyInfo DER) */
ExpectIntGT(BIO_write(bio, mldsa87_pub_spki, sizeof_mldsa87_pub_spki), 0);
ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
ExpectIntEQ(check_dilithium_der_level(mldsa87_pub_spki,
sizeof_mldsa87_pub_spki, WC_ML_DSA_87, 0), 0);
EVP_PKEY_free(pkey);
pkey = NULL;
#endif
#endif /* HAVE_DILITHIUM && !NO_VERIFY */
/* Negative test, invalid input must return NULL */
{
BIO* nbio = NULL;
unsigned char garbage[64];
XMEMSET(garbage, 0xA5, sizeof(garbage));
ExpectNotNull(nbio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(nbio, garbage, (int)sizeof(garbage)), 0);
ExpectNull(d2i_PUBKEY_bio(nbio, NULL));
BIO_free(nbio);
}
/* Negative test: unrecognized input with a pre-allocated *out must
* return NULL, not the caller pre-existing key. */
{
unsigned char garbage[64];
const unsigned char* p = garbage;
EVP_PKEY* preAlloc = NULL;
EVP_PKEY* result;
XMEMSET(garbage, 0xA5, sizeof(garbage));
ExpectNotNull(preAlloc = EVP_PKEY_new());
result = preAlloc;
ExpectNull(d2i_PUBKEY(&result, &p, (long)sizeof(garbage)));
EVP_PKEY_free(preAlloc);
}
BIO_free(bio);
(void)pkey;
@@ -18989,6 +19118,161 @@ static int test_wolfSSL_d2i_PrivateKeys_bio(void)
}
#endif
#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN)
#if !defined(WOLFSSL_NO_ML_DSA_44)
/* ML-DSA-44 PrivateKey test (raw bytes) */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(bio, bench_dilithium_level2_key,
sizeof_bench_dilithium_level2_key), 0);
ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
/* ML-DSA-44 PrivateKey test (LAMPS PKCS#8 priv-only DER) */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(bio, mldsa44_priv_only,
sizeof_mldsa44_priv_only), 0);
ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
ExpectIntEQ(check_dilithium_der_level(mldsa44_priv_only,
sizeof_mldsa44_priv_only, WC_ML_DSA_44, 1), 0);
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
/* ML-DSA-44 PrivateKey test (LAMPS PKCS#8 seed-priv DER) */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(bio, mldsa44_seed_priv,
sizeof_mldsa44_seed_priv), 0);
ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
#ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY
/* ML-DSA-44 PrivateKey test (LAMPS PKCS#8 seed-only DER) --
* requires wc_dilithium_make_key_from_seed to expand the seed. */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(bio, mldsa44_seed_only,
sizeof_mldsa44_seed_only), 0);
ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
#endif
#endif
#if !defined(WOLFSSL_NO_ML_DSA_65)
/* ML-DSA-65 PrivateKey test (raw bytes) */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(bio, bench_dilithium_level3_key,
sizeof_bench_dilithium_level3_key), 0);
ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
/* ML-DSA-65 PrivateKey test (LAMPS PKCS#8 priv-only DER) */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(bio, mldsa65_priv_only,
sizeof_mldsa65_priv_only), 0);
ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
ExpectIntEQ(check_dilithium_der_level(mldsa65_priv_only,
sizeof_mldsa65_priv_only, WC_ML_DSA_65, 1), 0);
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
/* ML-DSA-65 PrivateKey test (LAMPS PKCS#8 seed-priv DER) */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(bio, mldsa65_seed_priv,
sizeof_mldsa65_seed_priv), 0);
ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
#ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY
/* ML-DSA-65 PrivateKey test (LAMPS PKCS#8 seed-only DER) --
* requires wc_dilithium_make_key_from_seed to expand the seed. */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(bio, mldsa65_seed_only,
sizeof_mldsa65_seed_only), 0);
ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
#endif
#endif
#if !defined(WOLFSSL_NO_ML_DSA_87)
/* ML-DSA-87 PrivateKey test (raw bytes) */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(bio, bench_dilithium_level5_key,
sizeof_bench_dilithium_level5_key), 0);
ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
/* ML-DSA-87 PrivateKey test (LAMPS PKCS#8 priv-only DER) */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(bio, mldsa87_priv_only,
sizeof_mldsa87_priv_only), 0);
ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
ExpectIntEQ(check_dilithium_der_level(mldsa87_priv_only,
sizeof_mldsa87_priv_only, WC_ML_DSA_87, 1), 0);
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
/* ML-DSA-87 PrivateKey test (LAMPS PKCS#8 seed-priv DER) */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(bio, mldsa87_seed_priv,
sizeof_mldsa87_seed_priv), 0);
ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
#ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY
/* ML-DSA-87 PrivateKey test (LAMPS PKCS#8 seed-only DER) --
* requires wc_dilithium_make_key_from_seed to expand the seed. */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(bio, mldsa87_seed_only,
sizeof_mldsa87_seed_only), 0);
ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL));
ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM);
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
#endif
#endif
#endif /* HAVE_DILITHIUM && !NO_SIGN */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
#ifndef NO_WOLFSSL_SERVER
ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method()));
@@ -19058,6 +19342,34 @@ static int test_wolfSSL_d2i_PrivateKeys_bio(void)
RSA_free(rsa);
}
#endif /* WOLFSSL_KEY_GEN && !NO_RSA */
/* Negative test, invalid input must return NULL */
{
BIO* nbio = NULL;
unsigned char garbage[64];
XMEMSET(garbage, 0xA5, sizeof(garbage));
ExpectNotNull(nbio = BIO_new(BIO_s_mem()));
ExpectIntGT(BIO_write(nbio, garbage, (int)sizeof(garbage)), 0);
ExpectNull(d2i_PrivateKey_bio(nbio, NULL));
BIO_free(nbio);
}
/* Negative test: unrecognized input with a pre-allocated *out must
* return NULL, not the caller pre-existing key. */
{
unsigned char garbage[64];
unsigned char* p = garbage;
EVP_PKEY* preAlloc = NULL;
EVP_PKEY* result;
XMEMSET(garbage, 0xA5, sizeof(garbage));
ExpectNotNull(preAlloc = EVP_PKEY_new());
result = preAlloc;
ExpectNull(wolfSSL_d2i_PrivateKey_EVP(&result, &p,
(long)sizeof(garbage)));
EVP_PKEY_free(preAlloc);
}
SSL_CTX_free(ctx);
ctx = NULL;
BIO_free(bio);
+97 -85
View File
@@ -101,7 +101,9 @@ static int d2i_make_pkey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
* @param [in] memSz Size of key data in bytes.
* @param [in] priv 1 means private key, 0 means public key.
* @return 1 on success.
* @return 0 otherwise.
* @return 0 when input was recognized as this key type but
* object creation/import failed.
* @return WOLFSSL_FATAL_ERROR when input is not this key type.
*/
static int d2iTryRsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
long memSz, int priv)
@@ -169,7 +171,9 @@ static int d2iTryRsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
* @param [in] memSz Size of key data in bytes.
* @param [in] priv 1 means private key, 0 means public key.
* @return 1 on success.
* @return 0 otherwise.
* @return 0 when input was recognized as this key type but
* object creation/import failed.
* @return WOLFSSL_FATAL_ERROR when input is not this key type.
*/
static int d2iTryEccKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
long memSz, int priv)
@@ -241,8 +245,9 @@ static int d2iTryEccKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
* @param [in] memSz Size of key data in bytes.
* @param [in] priv 1 means private key, 0 means public key.
* @return 1 on success.
* @return 0 on allocation/initialization failure
* @return WOLFSSL_FATAL_ERROR if the input is not an Ed25519 key.
* @return 0 when input was recognized as this key type but object
* creation/import failed.
* @return WOLFSSL_FATAL_ERROR when input is not this key type.
*/
static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
long memSz, int priv)
@@ -306,8 +311,9 @@ static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
* @param [in] memSz Size of key data in bytes.
* @param [in] priv 1 means private key, 0 means public key.
* @return 1 on success.
* @return 0 on allocation/initialization failure.
* @return WOLFSSL_FATAL_ERROR if the input is not an Ed448 key.
* @return 0 when input was recognized as this key type but object
* creation/import failed.
* @return WOLFSSL_FATAL_ERROR when input is not this key type.
*/
static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
long memSz, int priv)
@@ -551,7 +557,9 @@ WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_raw_private_key(int type,
* @param [in] memSz Size of key data in bytes.
* @param [in] priv 1 means private key, 0 means public key.
* @return 1 on success.
* @return 0 otherwise.
* @return 0 when input was recognized as this key type but
* object creation/import failed.
* @return WOLFSSL_FATAL_ERROR when input is not this key type.
*/
static int d2iTryDsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
long memSz, int priv)
@@ -626,7 +634,9 @@ static int d2iTryDsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
* @param [in] memSz Size of key data in bytes.
* @param [in] priv 1 means private key, 0 means public key.
* @return 1 on success.
* @return 0 otherwise.
* @return 0 when input was recognized as this key type but
* object creation/import failed.
* @return WOLFSSL_FATAL_ERROR when input is not this key type.
*/
static int d2iTryDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
long memSz, int priv)
@@ -694,7 +704,9 @@ static int d2iTryDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
* @param [in] memSz Size of key data in bytes.
* @param [in] priv 1 means private key, 0 means public key.
* @return 1 on success.
* @return 0 otherwise.
* @return 0 when input was recognized as this key type but
* object creation/import failed.
* @return WOLFSSL_FATAL_ERROR when input is not this key type.
*/
static int d2iTryAltDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
long memSz, int priv)
@@ -792,7 +804,9 @@ static int d2i_falcon_pub_key_level(falcon_key* falcon, byte level,
* @param [in] memSz Size of key data in bytes.
* @param [in] priv 1 means private key, 0 means public key.
* @return 1 on success.
* @return 0 otherwise.
* @return 0 when input was recognized as this key type but
* object creation/import failed.
* @return WOLFSSL_FATAL_ERROR when input is not this key type.
*/
static int d2iTryFalconKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
long memSz, int priv)
@@ -839,60 +853,39 @@ static int d2iTryFalconKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
#endif /* HAVE_FALCON */
#ifdef HAVE_DILITHIUM
#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY)
/**
* Attempt to import a private Dilithium key at a specified level.
*
* @param [in] dilithium Dilithium key object.
* @param [in] level Level of Dilithium key.
* @param [in] mem Memory containing key data.
* @param [in] memSz Size of key data in bytes.
* @return 1 on success.
* @return 0 otherwise.
*/
static int d2i_dilithium_priv_key_level(dilithium_key* dilithium, byte level,
const unsigned char* mem, long memSz)
{
return (wc_dilithium_set_level(dilithium, level) == 0) &&
(wc_dilithium_import_private(mem, (word32)memSz, dilithium) == 0);
}
#endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY */
/**
* Attempt to import a public Dilithium key at a specified level.
*
* @param [in] dilithium Dilithium key object.
* @param [in] level Level of Dilithium key.
* @param [in] mem Memory containing key data.
* @param [in] memSz Size of key data in bytes.
* @return 1 on success.
* @return 0 otherwise.
*/
static int d2i_dilithium_pub_key_level(dilithium_key* dilithium, byte level,
const unsigned char* mem, long memSz)
{
return (wc_dilithium_set_level(dilithium, level) == 0) &&
(wc_dilithium_import_public(mem, (word32)memSz, dilithium) == 0);
}
/**
* Try to make a Dilithium EVP PKEY from data.
*
* Accepts either raw key bytes or DER (PKCS#8 / SPKI). Raw bytes are
* size-keyed, so each level is tried in turn. DER input is decoded once,
* letting the decoder auto-detect the level from the OID.
*
* @param [in, out] out On in, an EVP PKEY or NULL.
* On out, an EVP PKEY or NULL.
* @param [in] mem Memory containing key data.
* @param [in] memSz Size of key data in bytes.
* @param [in] priv 1 means private key, 0 means public key.
* @return 1 on success.
* @return 0 otherwise.
* @return 0 when input was recognized as this key type but
* object creation/import failed.
* @return WOLFSSL_FATAL_ERROR when input is not this key type.
*/
static int d2iTryDilithiumKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
long memSz, int priv)
{
static const byte levels[] = { WC_ML_DSA_44, WC_ML_DSA_65, WC_ML_DSA_87 };
word32 inSz = (word32)memSz;
word32 keyIdx = 0;
int isDilithium = 0;
int i, numLevels, rc;
WC_DECLARE_VAR(dilithium, dilithium_key, 1, NULL);
#if !defined(WOLFSSL_DILITHIUM_PRIVATE_KEY)
if (priv) {
return WOLFSSL_FATAL_ERROR;
}
#endif
WC_ALLOC_VAR_EX(dilithium, dilithium_key, 1, NULL, DYNAMIC_TYPE_DILITHIUM,
return 0);
@@ -901,34 +894,47 @@ static int d2iTryDilithiumKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
return 0;
}
/* Try decoding data as a Dilithium private/public key. */
if (priv) {
#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY)
isDilithium = d2i_dilithium_priv_key_level(dilithium, WC_ML_DSA_44,
mem, memSz);
if (!isDilithium) {
isDilithium = d2i_dilithium_priv_key_level(dilithium, WC_ML_DSA_65,
mem, memSz);
/* Raw key bytes are size-keyed, try each level */
numLevels = (int)(sizeof(levels) / sizeof(levels[0]));
for (i = 0; i < numLevels && !isDilithium; i++) {
if (wc_dilithium_set_level(dilithium, levels[i]) != 0) {
continue;
}
if (!isDilithium) {
isDilithium = d2i_dilithium_priv_key_level(dilithium, WC_ML_DSA_87,
mem, memSz);
#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY)
if (priv) {
rc = wc_dilithium_import_private(mem, inSz, dilithium);
}
#endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY */
}
else {
isDilithium = d2i_dilithium_pub_key_level(dilithium, WC_ML_DSA_44,
mem, memSz);
if (!isDilithium) {
isDilithium = d2i_dilithium_pub_key_level(dilithium, WC_ML_DSA_65,
mem, memSz);
else
#endif
{
rc = wc_dilithium_import_public(mem, inSz, dilithium);
}
if (!isDilithium) {
isDilithium = d2i_dilithium_pub_key_level(dilithium, WC_ML_DSA_87,
mem, memSz);
if (rc == 0) {
isDilithium = 1;
}
}
/* Dispose of any Dilithium key created. */
/* DER input includes auto level detection */
if (!isDilithium) {
wc_dilithium_free(dilithium);
if (wc_dilithium_init(dilithium) != 0) {
WC_FREE_VAR_EX(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
return 0;
}
#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY)
if (priv) {
rc = wc_Dilithium_PrivateKeyDecode(mem, &keyIdx, dilithium, inSz);
}
else
#endif
{
rc = wc_Dilithium_PublicKeyDecode(mem, &keyIdx, dilithium, inSz);
}
if (rc == 0) {
isDilithium = 1;
}
}
wc_dilithium_free(dilithium);
WC_FREE_VAR_EX(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
@@ -936,7 +942,6 @@ static int d2iTryDilithiumKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
return WOLFSSL_FATAL_ERROR;
}
/* Create an EVP PKEY object. */
return d2i_make_pkey(out, NULL, 0, priv, WC_EVP_PKEY_DILITHIUM);
}
#endif /* HAVE_DILITHIUM */
@@ -949,13 +954,14 @@ static int d2iTryDilithiumKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
* @param [in] mem Memory containing key data.
* @param [in] memSz Size of key data in bytes.
* @param [in] priv 1 means private key, 0 means public key.
* @return 1 on success.
* @return 0 otherwise.
* @return Non-NULL WOLFSSL_EVP_PKEY* on success.
* @return NULL on bad arguments or unrecognized input type.
*/
static WOLFSSL_EVP_PKEY* d2i_evp_pkey_try(WOLFSSL_EVP_PKEY** out,
const unsigned char** in, long inSz, int priv)
{
WOLFSSL_EVP_PKEY* pkey = NULL;
int found = 0;
WOLFSSL_ENTER("d2i_evp_pkey_try");
@@ -970,19 +976,19 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey_try(WOLFSSL_EVP_PKEY** out,
#if !defined(NO_RSA)
if (d2iTryRsaKey(&pkey, *in, inSz, priv) >= 0) {
;
found = 1;
}
else
#endif /* NO_RSA */
#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
if (d2iTryEccKey(&pkey, *in, inSz, priv) >= 0) {
;
found = 1;
}
else
#endif /* HAVE_ECC && OPENSSL_EXTRA */
#if !defined(NO_DSA)
if (d2iTryDsaKey(&pkey, *in, inSz, priv) >= 0) {
;
found = 1;
}
else
#endif /* NO_DSA */
@@ -990,7 +996,7 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey_try(WOLFSSL_EVP_PKEY** out,
#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
(HAVE_FIPS_VERSION > 2))
if (d2iTryDhKey(&pkey, *in, inSz, priv) >= 0) {
;
found = 1;
}
else
#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
@@ -1000,7 +1006,7 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey_try(WOLFSSL_EVP_PKEY** out,
#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
(HAVE_FIPS_VERSION > 2))
if (d2iTryAltDhKey(&pkey, *in, inSz, priv) >= 0) {
;
found = 1;
}
else
#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
@@ -1008,25 +1014,25 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey_try(WOLFSSL_EVP_PKEY** out,
#ifdef HAVE_ED25519
if (d2iTryEd25519Key(&pkey, *in, inSz, priv) >= 0) {
;
found = 1;
}
else
#endif /* HAVE_ED25519 */
#ifdef HAVE_ED448
if (d2iTryEd448Key(&pkey, *in, inSz, priv) >= 0) {
;
found = 1;
}
else
#endif /* HAVE_ED448 */
#ifdef HAVE_FALCON
if (d2iTryFalconKey(&pkey, *in, inSz, priv) >= 0) {
;
found = 1;
}
else
#endif /* HAVE_FALCON */
#ifdef HAVE_DILITHIUM
if (d2iTryDilithiumKey(&pkey, *in, inSz, priv) >= 0) {
;
found = 1;
}
else
#endif /* HAVE_DILITHIUM */
@@ -1034,6 +1040,10 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey_try(WOLFSSL_EVP_PKEY** out,
WOLFSSL_MSG("d2i_evp_pkey_try couldn't determine key type");
}
if (!found) {
return NULL;
}
if ((pkey != NULL) && (out != NULL)) {
*out = pkey;
}
@@ -1049,7 +1059,8 @@ static WOLFSSL_EVP_PKEY* d2i_evp_pkey_try(WOLFSSL_EVP_PKEY** out,
* @param [in, out] in DER buffer to convert.
* @param [in] inSz Size of in buffer.
* @return Pointer to a new WOLFSSL_EVP_PKEY structure on success.
* @return NULL on failure.
* @return NULL on failure. *out is left unchanged on failure; caller
* retains ownership of any pre-existing key passed via *out.
*/
WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out,
const unsigned char** in, long inSz)
@@ -1118,7 +1129,8 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
* @param [in, out] in DER buffer to convert.
* @param [in] inSz Size of in buffer.
* @return Pointer to a new WOLFSSL_EVP_PKEY structure on success.
* @return NULL on failure.
* @return NULL on failure. *out is left unchanged on failure; caller
* retains ownership of any pre-existing key passed via *out.
*/
WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out,
unsigned char** in, long inSz)
+3035
View File
File diff suppressed because it is too large Load Diff