mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 09:30:51 +02:00
Add ML-DSA SPKI/PKCS#8 DER support to d2i_PUBKEY and d2i_PrivateKey.
This commit is contained in:
@@ -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.
|
||||
@@ -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.
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user