mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-02 12:14:38 +02:00
Support importing seed of ML-DSA key
This commit is contained in:
@@ -16658,7 +16658,219 @@ int test_wc_dilithium_verify_kats(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_mldsa_pkcs8(void)
|
||||
#if !defined(NO_ASN) && defined(HAVE_PKCS8) && \
|
||||
defined(HAVE_DILITHIUM) && defined(WOLFSSL_WC_DILITHIUM) && \
|
||||
!defined(WOLFSSL_DILITHIUM_NO_ASN1) && defined(WOLFSSL_ASN_TEMPLATE)
|
||||
static struct {
|
||||
const char* fileName;
|
||||
byte level;
|
||||
/* 0: Unsupported, 1: Supported*/
|
||||
int p8_lv; /* Support PKCS8 format with specifying level */
|
||||
int p8_nolv; /* Support PKCS8 format without specifying level */
|
||||
int trad_lv; /* Support traditional format with specifying level */
|
||||
int trad_nolv; /* Support traditional format without specifying level */
|
||||
} ossl_form[] = {
|
||||
/*
|
||||
* Generated test files with the following commands:
|
||||
* openssl genpkey -outform DER -algorithm ${ALGO} \
|
||||
* -provparam ml-dsa.output_formats=${OUT_FORM} -out ${OUT_FILE}
|
||||
*/
|
||||
|
||||
/* ALGO=ML-DSA-44, OUT_FORM=seed-only, OUT_FILE=mldsa44_seed-only.der */
|
||||
{"certs/mldsa/mldsa44_seed-only.der", WC_ML_DSA_44, 1, 1, 1, 0},
|
||||
/* ALGO=ML-DSA-44, OUT_FORM=priv-only, OUT_FILE=mldsa44_priv-only.der */
|
||||
{"certs/mldsa/mldsa44_priv-only.der", WC_ML_DSA_44, 1, 1, 1, 0},
|
||||
/* ALGO=ML-DSA-44, OUT_FORM=seed-priv, OUT_FILE=mldsa44_seed-priv.der */
|
||||
{"certs/mldsa/mldsa44_seed-priv.der", WC_ML_DSA_44, 1, 1, 1, 0},
|
||||
/* ALGO=ML-DSA-44, OUT_FORM=oqskeypair, OUT_FILE=mldsa44_oqskeypair.der */
|
||||
{"certs/mldsa/mldsa44_oqskeypair.der", WC_ML_DSA_44, 1, 1, 1, 0},
|
||||
/* ALGO=ML-DSA-44, OUT_FORM=bare-seed, OUT_FILE=mldsa44_bare-seed.der */
|
||||
{"certs/mldsa/mldsa44_bare-seed.der", WC_ML_DSA_44, 0, 0, 0, 0},
|
||||
/* ALGO=ML-DSA-44, OUT_FORM=bare-priv, OUT_FILE=mldsa44_bare-priv.der */
|
||||
{"certs/mldsa/mldsa44_bare-priv.der", WC_ML_DSA_44, 0, 0, 0, 0},
|
||||
/* ALGO=ML-DSA-65, OUT_FORM=seed-only, OUT_FILE=mldsa65_seed-only.der */
|
||||
{"certs/mldsa/mldsa65_seed-only.der", WC_ML_DSA_65, 1, 1, 1, 0},
|
||||
/* ALGO=ML-DSA-65, OUT_FORM=priv-only, OUT_FILE=mldsa65_priv-only.der */
|
||||
{"certs/mldsa/mldsa65_priv-only.der", WC_ML_DSA_65, 1, 1, 1, 0},
|
||||
/* ALGO=ML-DSA-65, OUT_FORM=seed-priv, OUT_FILE=mldsa65_seed-priv.der */
|
||||
{"certs/mldsa/mldsa65_seed-priv.der", WC_ML_DSA_65, 1, 1, 1, 0},
|
||||
/* ALGO=ML-DSA-65, OUT_FORM=oqskeypair, OUT_FILE=mldsa65_oqskeypair.der */
|
||||
{"certs/mldsa/mldsa65_oqskeypair.der", WC_ML_DSA_65, 1, 1, 1, 0},
|
||||
/* ALGO=ML-DSA-65, OUT_FORM=bare-seed, OUT_FILE=mldsa65_bare-seed.der */
|
||||
{"certs/mldsa/mldsa65_bare-seed.der", WC_ML_DSA_65, 0, 0, 0, 0},
|
||||
/* ALGO=ML-DSA-65, OUT_FORM=bare-priv, OUT_FILE=mldsa65_bare-priv.der */
|
||||
{"certs/mldsa/mldsa65_bare-priv.der", WC_ML_DSA_65, 0, 0, 0, 0},
|
||||
/* ALGO=ML-DSA-87, OUT_FORM=seed-only, OUT_FILE=mldsa87_seed-only.der */
|
||||
{"certs/mldsa/mldsa87_seed-only.der", WC_ML_DSA_87, 1, 1, 1, 0},
|
||||
/* ALGO=ML-DSA-87, OUT_FORM=priv-only, OUT_FILE=mldsa87_priv-only.der */
|
||||
{"certs/mldsa/mldsa87_priv-only.der", WC_ML_DSA_87, 1, 1, 1, 0},
|
||||
/* ALGO=ML-DSA-87, OUT_FORM=seed-priv, OUT_FILE=mldsa87_seed-priv.der */
|
||||
{"certs/mldsa/mldsa87_seed-priv.der", WC_ML_DSA_87, 1, 1, 1, 0},
|
||||
/* ALGO=ML-DSA-87, OUT_FORM=oqskeypair, OUT_FILE=mldsa87_oqskeypair.der */
|
||||
{"certs/mldsa/mldsa87_oqskeypair.der", WC_ML_DSA_87, 1, 1, 1, 0},
|
||||
/* ALGO=ML-DSA-87, OUT_FORM=bare-seed, OUT_FILE=mldsa87_bare-seed.der */
|
||||
{"certs/mldsa/mldsa87_bare-seed.der", WC_ML_DSA_87, 0, 0, 0, 0},
|
||||
/* ALGO=ML-DSA-87, OUT_FORM=bare-priv, OUT_FILE=mldsa87_bare-priv.der */
|
||||
{"certs/mldsa/mldsa87_bare-priv.der", WC_ML_DSA_87, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
int test_wc_Dilithium_PrivateKeyDecode_OpenSSL_form(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
|
||||
#if !defined(NO_ASN) && defined(HAVE_PKCS8) && \
|
||||
defined(HAVE_DILITHIUM) && defined(WOLFSSL_WC_DILITHIUM) && \
|
||||
!defined(WOLFSSL_DILITHIUM_NO_ASN1) && defined(WOLFSSL_ASN_TEMPLATE)
|
||||
|
||||
byte* der = NULL;
|
||||
size_t derMaxSz = ML_DSA_LEVEL5_BOTH_KEY_DER_SIZE;
|
||||
size_t derSz = 0;
|
||||
FILE* fp = NULL;
|
||||
word32 inOutIdx = 0;
|
||||
word32 inOutIdx2 = 0;
|
||||
dilithium_key key;
|
||||
int expect = 0;
|
||||
int pkeySz = 0;
|
||||
byte level = 0;
|
||||
|
||||
ExpectNotNull(der = (byte*) XMALLOC(derMaxSz, NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER));
|
||||
|
||||
for (size_t i = 0; i < sizeof(ossl_form) / sizeof(ossl_form[0]); ++i) {
|
||||
ExpectNotNull(fp = XFOPEN(ossl_form[i].fileName, "rb"));
|
||||
ExpectIntGT(derSz = XFREAD(der, 1, derMaxSz, fp), 0);
|
||||
ExpectIntEQ(XFCLOSE(fp), 0);
|
||||
|
||||
/* Specify a level with PKCS8 format */
|
||||
XMEMSET(&key, 0, sizeof(key));
|
||||
ExpectIntEQ(wc_dilithium_init(&key), 0);
|
||||
ExpectIntEQ(wc_dilithium_set_level(&key, ossl_form[i].level), 0);
|
||||
inOutIdx = 0;
|
||||
expect = ossl_form[i].p8_lv ? 0 : ASN_PARSE_E;
|
||||
ExpectIntEQ(wc_Dilithium_PrivateKeyDecode(der, &inOutIdx, &key,
|
||||
(word32)derSz), expect);
|
||||
if (expect == 0) {
|
||||
ExpectIntEQ(wc_dilithium_get_level(&key, &level), 0);
|
||||
ExpectIntEQ(level, ossl_form[i].level);
|
||||
}
|
||||
wc_dilithium_free(&key);
|
||||
|
||||
/* Not specify a level with PKCS8 format */
|
||||
XMEMSET(&key, 0, sizeof(key));
|
||||
ExpectIntEQ(wc_dilithium_init(&key), 0);
|
||||
inOutIdx = 0;
|
||||
expect = ossl_form[i].p8_nolv ? 0 : ASN_PARSE_E;
|
||||
ExpectIntEQ(wc_Dilithium_PrivateKeyDecode(der, &inOutIdx, &key,
|
||||
(word32)derSz), expect);
|
||||
if (expect == 0) {
|
||||
ExpectIntEQ(wc_dilithium_get_level(&key, &level), 0);
|
||||
ExpectIntEQ(level, ossl_form[i].level);
|
||||
}
|
||||
wc_dilithium_free(&key);
|
||||
|
||||
/* Specify a level with traditional format */
|
||||
XMEMSET(&key, 0, sizeof(key));
|
||||
ExpectIntEQ(wc_dilithium_init(&key), 0);
|
||||
ExpectIntEQ(wc_dilithium_set_level(&key, ossl_form[i].level), 0);
|
||||
inOutIdx = 0;
|
||||
expect = ossl_form[i].trad_lv ? 0 : ASN_PARSE_E;
|
||||
ExpectIntGT(pkeySz = wc_GetPkcs8TraditionalOffset(der, &inOutIdx,
|
||||
(word32)derSz), 0);
|
||||
inOutIdx2 = 0;
|
||||
ExpectIntEQ(wc_Dilithium_PrivateKeyDecode(der + inOutIdx, &inOutIdx2,
|
||||
&key, (word32)pkeySz), expect);
|
||||
if (expect == 0) {
|
||||
ExpectIntEQ(wc_dilithium_get_level(&key, &level), 0);
|
||||
ExpectIntEQ(level, ossl_form[i].level);
|
||||
}
|
||||
wc_dilithium_free(&key);
|
||||
|
||||
/* Not specify a level with traditional format */
|
||||
XMEMSET(&key, 0, sizeof(key));
|
||||
ExpectIntEQ(wc_dilithium_init(&key), 0);
|
||||
inOutIdx = 0;
|
||||
expect = ossl_form[i].trad_nolv ? 0 : ASN_PARSE_E;
|
||||
ExpectIntGT(pkeySz = wc_GetPkcs8TraditionalOffset(der, &inOutIdx,
|
||||
(word32)derSz), 0);
|
||||
inOutIdx2 = 0;
|
||||
ExpectIntEQ(wc_Dilithium_PrivateKeyDecode(der + inOutIdx, &inOutIdx2,
|
||||
&key, (word32)pkeySz), expect);
|
||||
if (expect == 0) {
|
||||
ExpectIntEQ(wc_dilithium_get_level(&key, &level), 0);
|
||||
ExpectIntEQ(level, ossl_form[i].level);
|
||||
}
|
||||
wc_dilithium_free(&key);
|
||||
}
|
||||
|
||||
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_mldsa_pkcs8_import_OpenSSL_form(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if !defined(NO_ASN) && defined(HAVE_PKCS8) && \
|
||||
defined(HAVE_DILITHIUM) && defined(WOLFSSL_WC_DILITHIUM) && \
|
||||
!defined(WOLFSSL_DILITHIUM_NO_ASN1) && defined(WOLFSSL_ASN_TEMPLATE) && \
|
||||
!defined(NO_TLS) && \
|
||||
(!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER))
|
||||
|
||||
byte* der = NULL;
|
||||
size_t derMaxSz = ML_DSA_LEVEL5_BOTH_KEY_DER_SIZE;
|
||||
size_t derSz = 0;
|
||||
WOLFSSL_CTX* ctx = NULL;
|
||||
FILE* fp = NULL;
|
||||
#ifdef WOLFSSL_DER_TO_PEM
|
||||
byte* pem = NULL;
|
||||
size_t pemMaxSz = ML_DSA_LEVEL5_BOTH_KEY_PEM_SIZE;
|
||||
size_t pemSz = 0;
|
||||
#endif /* WOLFSSL_DER_TO_PEM */
|
||||
int expect = 0;
|
||||
|
||||
ExpectNotNull(der = (byte*) XMALLOC(derMaxSz, NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER));
|
||||
#ifdef WOLFSSL_DER_TO_PEM
|
||||
ExpectNotNull(pem = (byte*) XMALLOC(pemMaxSz, NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER));
|
||||
#endif /* WOLFSSL_DER_TO_PEM */
|
||||
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
||||
#else
|
||||
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
||||
#endif /* NO_WOLFSSL_SERVER */
|
||||
|
||||
for (size_t i = 0; i < sizeof(ossl_form) / sizeof(ossl_form[0]); ++i) {
|
||||
ExpectNotNull(fp = XFOPEN(ossl_form[i].fileName, "rb"));
|
||||
ExpectIntGT(derSz = XFREAD(der, 1, derMaxSz, fp), 0);
|
||||
ExpectIntEQ(XFCLOSE(fp), 0);
|
||||
|
||||
/* DER */
|
||||
expect = ossl_form[i].p8_nolv ? WOLFSSL_SUCCESS : WOLFSSL_BAD_FILE;
|
||||
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz,
|
||||
WOLFSSL_FILETYPE_ASN1), expect);
|
||||
|
||||
#ifdef WOLFSSL_DER_TO_PEM
|
||||
/* PEM */
|
||||
ExpectIntGT(pemSz = wc_DerToPem(der, (word32)derSz, pem,
|
||||
(word32)pemMaxSz, PKCS8_PRIVATEKEY_TYPE), 0);
|
||||
expect = ossl_form[i].p8_nolv ? WOLFSSL_SUCCESS : ASN_PARSE_E;
|
||||
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, pem, pemSz,
|
||||
WOLFSSL_FILETYPE_PEM), expect);
|
||||
#endif /* WOLFSSL_DER_TO_PEM */
|
||||
}
|
||||
|
||||
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#ifdef WOLFSSL_DER_TO_PEM
|
||||
XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif /* WOLFSSL_DER_TO_PEM */
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_mldsa_pkcs8_export_import_wolfSSL_form(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if !defined(NO_ASN) && defined(HAVE_PKCS8) && \
|
||||
@@ -16676,10 +16888,8 @@ int test_mldsa_pkcs8(void)
|
||||
byte* temp = NULL; /* Store PEM or intermediate key */
|
||||
word32 derSz = 0;
|
||||
word32 pemSz = 0;
|
||||
word32 keySz = 0;
|
||||
dilithium_key mldsa_key;
|
||||
WC_RNG rng;
|
||||
word32 size;
|
||||
int ret;
|
||||
|
||||
struct {
|
||||
@@ -16746,43 +16956,6 @@ int test_mldsa_pkcs8(void)
|
||||
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz,
|
||||
WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
|
||||
|
||||
#ifdef WOLFSSL_DER_TO_PEM
|
||||
ExpectIntGT(pemSz = wc_DerToPem(der, derSz, temp, tempMaxSz,
|
||||
PKCS8_PRIVATEKEY_TYPE), 0);
|
||||
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, temp, pemSz,
|
||||
WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
|
||||
#endif /* WOLFSSL_DER_TO_PEM */
|
||||
}
|
||||
|
||||
/* Test private + public key (integrated format) */
|
||||
for (i = 0; i < sizeof(test_variant) / sizeof(test_variant[0]); ++i) {
|
||||
ExpectIntEQ(wc_dilithium_set_level(&mldsa_key, test_variant[i].wcId),
|
||||
0);
|
||||
ExpectIntEQ(wc_dilithium_make_key(&mldsa_key, &rng), 0);
|
||||
|
||||
if (EXPECT_FAIL())
|
||||
break;
|
||||
|
||||
keySz = 0;
|
||||
temp[0] = 0x04; /* ASN.1 OCTET STRING */
|
||||
temp[1] = 0x82; /* 2 bytes length field */
|
||||
temp[2] = (test_variant[i].keySz >> 8) & 0xff; /* MSB of the length */
|
||||
temp[3] = test_variant[i].keySz & 0xff; /* LSB of the length */
|
||||
keySz += 4;
|
||||
size = tempMaxSz - keySz;
|
||||
ExpectIntEQ(wc_dilithium_export_private(&mldsa_key, temp + keySz,
|
||||
&size), 0);
|
||||
keySz += size;
|
||||
size = tempMaxSz - keySz;
|
||||
ExpectIntEQ(wc_dilithium_export_public(&mldsa_key, temp + keySz, &size),
|
||||
0);
|
||||
keySz += size;
|
||||
derSz = derMaxSz;
|
||||
ExpectIntGT(wc_CreatePKCS8Key(der, &derSz, temp, keySz,
|
||||
test_variant[i].oidSum, NULL, 0), 0);
|
||||
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz,
|
||||
WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
|
||||
|
||||
#ifdef WOLFSSL_DER_TO_PEM
|
||||
ExpectIntGT(pemSz = wc_DerToPem(der, derSz, temp, tempMaxSz,
|
||||
PKCS8_PRIVATEKEY_TYPE), 0);
|
||||
|
@@ -35,22 +35,26 @@ int test_wc_dilithium_der(void);
|
||||
int test_wc_dilithium_make_key_from_seed(void);
|
||||
int test_wc_dilithium_sig_kats(void);
|
||||
int test_wc_dilithium_verify_kats(void);
|
||||
int test_mldsa_pkcs8(void);
|
||||
int test_wc_Dilithium_PrivateKeyDecode_OpenSSL_form(void);
|
||||
int test_mldsa_pkcs8_import_OpenSSL_form(void);
|
||||
int test_mldsa_pkcs8_export_import_wolfSSL_form(void);
|
||||
int test_mldsa_pkcs12(void);
|
||||
|
||||
#define TEST_MLDSA_DECLS \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_make_key), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_sign), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_verify), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_sign_vfy), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_check_key), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_public_der_decode), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_der), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_make_key_from_seed), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_sig_kats), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_verify_kats), \
|
||||
TEST_DECL_GROUP("mldsa", test_mldsa_pkcs8), \
|
||||
#define TEST_MLDSA_DECLS \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_make_key), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_sign), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_verify), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_sign_vfy), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_check_key), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_public_der_decode), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_der), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_make_key_from_seed), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_sig_kats), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_dilithium_verify_kats), \
|
||||
TEST_DECL_GROUP("mldsa", test_wc_Dilithium_PrivateKeyDecode_OpenSSL_form), \
|
||||
TEST_DECL_GROUP("mldsa", test_mldsa_pkcs8_import_OpenSSL_form), \
|
||||
TEST_DECL_GROUP("mldsa", test_mldsa_pkcs8_export_import_wolfSSL_form), \
|
||||
TEST_DECL_GROUP("mldsa", test_mldsa_pkcs12)
|
||||
|
||||
#endif /* WOLFCRYPT_TEST_MLDSA_H */
|
||||
|
@@ -36991,6 +36991,7 @@ int wc_EccKeyToPKCS8(ecc_key* key, byte* output,
|
||||
/* ASN.1 template for a general asymmetric private key: Ed25519, Ed448,
|
||||
* falcon, dilithium, etc.
|
||||
* RFC 8410, 7 - Private Key Format (but public value is EXPLICIT OCTET_STRING)
|
||||
* Check draft-ietf-lamps-dilithium-certificates of draft RFC also.
|
||||
*/
|
||||
static const ASNItem privateKeyASN[] = {
|
||||
/* SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
|
||||
@@ -37001,9 +37002,13 @@ static const ASNItem privateKeyASN[] = {
|
||||
/* PKEYALGO_OID */ { 2, ASN_OBJECT_ID, 0, 0, 1 },
|
||||
/* privateKey */
|
||||
/* PKEY */ { 1, ASN_OCTET_STRING, 0, 1, 0 },
|
||||
/* CurvePrivateKey */
|
||||
/* CurvePrivateKey */
|
||||
/* PKEY_CURVEPKEY */ { 2, ASN_OCTET_STRING, 0, 0, 2 },
|
||||
/* PKEY_MLDSASEQ */ { 2, ASN_SEQUENCE, 1, 0, 2 },
|
||||
/* PKEY_SEED_ONLY */ { 2, ASN_CONTEXT_SPECIFIC | ASN_PKEY_SEED,
|
||||
0, 0, 2 },
|
||||
/* PKEY_BOTH_SEQ */ { 2, ASN_SEQUENCE, 1, 1, 2 },
|
||||
/* PKEY_BOTH_SEED */ { 3, ASN_OCTET_STRING, 0, 0, 0 },
|
||||
/* PKEY_BOTH_KEY */ { 3, ASN_OCTET_STRING, 0, 0, 0 },
|
||||
/* attributes */
|
||||
/* ATTRS */ { 1, ASN_CONTEXT_SPECIFIC | ASN_ASYMKEY_ATTRS, 1, 1, 1 },
|
||||
/* publicKey */
|
||||
@@ -37016,7 +37021,10 @@ enum {
|
||||
PRIVKEYASN_IDX_PKEYALGO_OID,
|
||||
PRIVKEYASN_IDX_PKEY,
|
||||
PRIVKEYASN_IDX_PKEY_CURVEPKEY,
|
||||
PRIVKEYASN_IDX_PKEY_MLDSASEQ,
|
||||
PRIVKEYASN_IDX_PKEY_SEED_ONLY,
|
||||
PRIVKEYASN_IDX_PKEY_BOTH_SEQ,
|
||||
PRIVKEYASN_IDX_PKEY_BOTH_SEED,
|
||||
PRIVKEYASN_IDX_PKEY_BOTH_KEY,
|
||||
PRIVKEYASN_IDX_ATTRS,
|
||||
PRIVKEYASN_IDX_PUBKEY
|
||||
};
|
||||
@@ -37033,9 +37041,11 @@ enum {
|
||||
|
||||
|
||||
int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz,
|
||||
const byte** seed, word32* seedLen,
|
||||
const byte** privKey, word32* privKeyLen,
|
||||
const byte** pubKey, word32* pubKeyLen, int* inOutKeyType)
|
||||
{
|
||||
int allowSeed = 0;
|
||||
#ifndef WOLFSSL_ASN_TEMPLATE
|
||||
word32 oid;
|
||||
int version, length, endKeyIdx, privSz, pubSz;
|
||||
@@ -37048,14 +37058,27 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz,
|
||||
#endif
|
||||
|
||||
if (input == NULL || inOutIdx == NULL || inSz == 0 ||
|
||||
privKey == NULL || privKeyLen == NULL || inOutKeyType == NULL) {
|
||||
privKey == NULL || privKeyLen == NULL ||
|
||||
pubKey == NULL || pubKeyLen == NULL ||
|
||||
inOutKeyType == NULL) {
|
||||
#ifdef WOLFSSL_ASN_TEMPLATE
|
||||
FREE_ASNGETDATA(dataASN, NULL);
|
||||
#endif
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if ((seed == NULL && seedLen != NULL) ||
|
||||
(seed != NULL && seedLen == NULL)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
allowSeed = (seed != NULL && seedLen != NULL);
|
||||
|
||||
#ifndef WOLFSSL_ASN_TEMPLATE
|
||||
/* The seed can't be parsed without WOLF_ASN_TEMPLATE */
|
||||
if (allowSeed) {
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if (GetSequence(input, inOutIdx, &length, inSz) >= 0) {
|
||||
endKeyIdx = (int)*inOutIdx + length;
|
||||
|
||||
@@ -37083,13 +37106,7 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz,
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0) {
|
||||
if (oid != ML_DSA_LEVEL2k && oid != ML_DSA_LEVEL3k &&
|
||||
oid != ML_DSA_LEVEL5k) {
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
if (GetSequence(input, inOutIdx, &privSz, inSz) < 0) {
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
priv = input + *inOutIdx;
|
||||
@@ -37150,53 +37167,69 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz,
|
||||
}
|
||||
|
||||
/* Parse full private key. */
|
||||
ret = GetASN_Items(privateKeyASN, dataASN, privateKeyASN_Length, 1, input,
|
||||
inOutIdx, inSz);
|
||||
if (ret != 0) {
|
||||
/* Parse just the OCTET_STRING. */
|
||||
ret = GetASN_Items(privateKeyASN, dataASN, privateKeyASN_Length, 1,
|
||||
input, inOutIdx, inSz);
|
||||
if (ret == 0) {
|
||||
/* Store detected OID if requested */
|
||||
if (ret == 0 && *inOutKeyType == ANONk) {
|
||||
*inOutKeyType =
|
||||
(int)dataASN[PRIVKEYASN_IDX_PKEYALGO_OID].data.oid.sum;
|
||||
}
|
||||
}
|
||||
/* Parse traditional format (a part of full private key). */
|
||||
else if (ret != 0) {
|
||||
ret = GetASN_Items(&privateKeyASN[PRIVKEYASN_IDX_PKEY_CURVEPKEY],
|
||||
&dataASN[PRIVKEYASN_IDX_PKEY_CURVEPKEY], 1, 0, input,
|
||||
inOutIdx, inSz);
|
||||
&dataASN[PRIVKEYASN_IDX_PKEY_CURVEPKEY],
|
||||
PRIVKEYASN_IDX_ATTRS - PRIVKEYASN_IDX_PKEY_CURVEPKEY, 0,
|
||||
input, inOutIdx, inSz);
|
||||
if (ret != 0) {
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
}
|
||||
|
||||
/* Store detected OID if requested */
|
||||
if (ret == 0 && *inOutKeyType == ANONk) {
|
||||
*inOutKeyType =
|
||||
(int)dataASN[PRIVKEYASN_IDX_PKEYALGO_OID].data.oid.sum;
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* priv-only */
|
||||
if (dataASN[PRIVKEYASN_IDX_PKEY_CURVEPKEY].data.ref.length != 0) {
|
||||
if (allowSeed) {
|
||||
*seedLen = 0;
|
||||
*seed = NULL;
|
||||
}
|
||||
*privKeyLen
|
||||
= dataASN[PRIVKEYASN_IDX_PKEY_CURVEPKEY].data.ref.length;
|
||||
*privKey = dataASN[PRIVKEYASN_IDX_PKEY_CURVEPKEY].data.ref.data;
|
||||
}
|
||||
}
|
||||
if (ret == 0 && dataASN[PRIVKEYASN_IDX_PKEY_CURVEPKEY].data.ref.length != 0) {
|
||||
/* Import private value. */
|
||||
*privKeyLen = dataASN[PRIVKEYASN_IDX_PKEY_CURVEPKEY].data.ref.length;
|
||||
*privKey = dataASN[PRIVKEYASN_IDX_PKEY_CURVEPKEY].data.ref.data;
|
||||
}
|
||||
else if (ret == 0 &&
|
||||
dataASN[PRIVKEYASN_IDX_PKEY_MLDSASEQ].data.ref.length != 0) {
|
||||
if (*inOutKeyType != ML_DSA_LEVEL2k &&
|
||||
*inOutKeyType != ML_DSA_LEVEL3k &&
|
||||
*inOutKeyType != ML_DSA_LEVEL5k) {
|
||||
ret = ASN_PARSE_E;
|
||||
/* seed-only */
|
||||
else if (allowSeed &&
|
||||
dataASN[PRIVKEYASN_IDX_PKEY_SEED_ONLY].data.ref.length != 0) {
|
||||
*seedLen = dataASN[PRIVKEYASN_IDX_PKEY_SEED_ONLY].data.ref.length;
|
||||
*seed = dataASN[PRIVKEYASN_IDX_PKEY_SEED_ONLY].data.ref.data;
|
||||
*privKeyLen = 0;
|
||||
*privKey = NULL;
|
||||
}
|
||||
/* seed-priv */
|
||||
else if (allowSeed &&
|
||||
dataASN[PRIVKEYASN_IDX_PKEY_BOTH_SEQ].data.ref.length != 0) {
|
||||
*seedLen = dataASN[PRIVKEYASN_IDX_PKEY_BOTH_SEED].data.ref.length;
|
||||
*seed = dataASN[PRIVKEYASN_IDX_PKEY_BOTH_SEED].data.ref.data;
|
||||
*privKeyLen = dataASN[PRIVKEYASN_IDX_PKEY_BOTH_KEY].data.ref.length;
|
||||
*privKey = dataASN[PRIVKEYASN_IDX_PKEY_BOTH_KEY].data.ref.data;
|
||||
}
|
||||
else {
|
||||
/* Import private value. */
|
||||
*privKeyLen = dataASN[PRIVKEYASN_IDX_PKEY_MLDSASEQ].data.ref.length;
|
||||
*privKey = dataASN[PRIVKEYASN_IDX_PKEY_MLDSASEQ].data.ref.data;
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
}
|
||||
if ((ret == 0) && dataASN[PRIVKEYASN_IDX_PUBKEY].tag == 0) {
|
||||
/* Set public length to 0 as not seen. */
|
||||
if (pubKeyLen != NULL)
|
||||
*pubKeyLen = 0;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
/* Import public value. */
|
||||
if (pubKeyLen != NULL)
|
||||
|
||||
if (ret == 0) {
|
||||
if (dataASN[PRIVKEYASN_IDX_PUBKEY].data.ref.length != 0) {
|
||||
/* Import public value. */
|
||||
*pubKeyLen = dataASN[PRIVKEYASN_IDX_PUBKEY].data.ref.length;
|
||||
if (pubKey != NULL && pubKeyLen != NULL)
|
||||
*pubKey = dataASN[PRIVKEYASN_IDX_PUBKEY].data.ref.data;
|
||||
}
|
||||
else {
|
||||
/* Set public length to 0 as not seen. */
|
||||
*pubKeyLen = 0;
|
||||
*pubKey = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
FREE_ASNGETDATA(dataASN, NULL);
|
||||
@@ -37219,8 +37252,8 @@ int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz,
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ret = DecodeAsymKey_Assign(input, inOutIdx, inSz, &privKeyPtr,
|
||||
&privKeyPtrLen, &pubKeyPtr, &pubKeyPtrLen, &keyType);
|
||||
ret = DecodeAsymKey_Assign(input, inOutIdx, inSz, NULL, NULL,
|
||||
&privKeyPtr, &privKeyPtrLen, &pubKeyPtr, &pubKeyPtrLen, &keyType);
|
||||
}
|
||||
if ((ret == 0) && (privKeyPtrLen > *privKeyLen)) {
|
||||
ret = BUFFER_E;
|
||||
@@ -37606,10 +37639,11 @@ int SetAsymKeyDer(const byte* privKey, word32 privKeyLen,
|
||||
oidKeyType);
|
||||
/* Leave space for private key. */
|
||||
SetASN_Buffer(&dataASN[PRIVKEYASN_IDX_PKEY_CURVEPKEY], NULL, privKeyLen);
|
||||
/* Don't write ML-DSA specific things. */
|
||||
SetASNItem_NoOut(dataASN, PRIVKEYASN_IDX_PKEY_SEED_ONLY,
|
||||
PRIVKEYASN_IDX_ATTRS);
|
||||
/* Don't write out attributes. */
|
||||
dataASN[PRIVKEYASN_IDX_ATTRS].noOut = 1;
|
||||
/* Don't write sequence. */
|
||||
dataASN[PRIVKEYASN_IDX_PKEY_MLDSASEQ].noOut = 1;
|
||||
if (pubKey) {
|
||||
/* Leave space for public key. */
|
||||
SetASN_Buffer(&dataASN[PRIVKEYASN_IDX_PUBKEY], NULL, pubKeyLen);
|
||||
|
@@ -9659,31 +9659,6 @@ int dilithium_get_oid_sum(dilithium_key* key, int* keyFormat) {
|
||||
|
||||
#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY)
|
||||
|
||||
/* OCT <seed of 32 bytes> OCT <private key data of more than 256 bytes> */
|
||||
#define ALT_PRIV_DER_PREFIX (2 + 32 + 4)
|
||||
/* SEQ [ OCT <seed of 32 bytes> OCT <private key data> ] */
|
||||
#define ALT_PRIV_DER_PREFIX_SEQ (4 + 2 + 32 + 4)
|
||||
|
||||
/* Get the private only key size for the ML-DSA level/parameter id.
|
||||
*
|
||||
* @param [in] level Level of the ML-DSA key.
|
||||
* @return Private key only encoding size for key level on success.
|
||||
* @return 0 on failure.
|
||||
*/
|
||||
static word32 dilithium_get_priv_size(int level)
|
||||
{
|
||||
switch (level) {
|
||||
case WC_ML_DSA_44:
|
||||
return ML_DSA_LEVEL2_KEY_SIZE;
|
||||
case WC_ML_DSA_65:
|
||||
return ML_DSA_LEVEL3_KEY_SIZE;
|
||||
case WC_ML_DSA_87:
|
||||
return ML_DSA_LEVEL5_KEY_SIZE;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode the DER encoded Dilithium key.
|
||||
*
|
||||
* @param [in] input Array holding DER encoded data.
|
||||
@@ -9708,11 +9683,14 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx,
|
||||
dilithium_key* key, word32 inSz)
|
||||
{
|
||||
int ret = 0;
|
||||
const byte* seed = NULL;
|
||||
const byte* privKey = NULL;
|
||||
const byte* pubKey = NULL;
|
||||
word32 seedLen = 0;
|
||||
word32 privKeyLen = 0;
|
||||
word32 pubKeyLen = 0;
|
||||
int keyType = 0;
|
||||
int autoKeyType = ANONk;
|
||||
|
||||
/* Validate parameters. */
|
||||
if ((input == NULL) || (inOutIdx == NULL) || (key == NULL) || (inSz == 0)) {
|
||||
@@ -9756,34 +9734,45 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx,
|
||||
|
||||
if (ret == 0) {
|
||||
/* Decode the asymmetric key and get out private and public key data. */
|
||||
#ifndef WOLFSSL_ASN_TEMPLATE
|
||||
ret = DecodeAsymKey_Assign(input, inOutIdx, inSz,
|
||||
NULL, NULL,
|
||||
&privKey, &privKeyLen,
|
||||
&pubKey, &pubKeyLen, &keyType);
|
||||
if (ret == 0
|
||||
#ifdef WOLFSSL_WC_DILITHIUM
|
||||
&& key->params == NULL
|
||||
#endif
|
||||
) {
|
||||
&pubKey, &pubKeyLen, &autoKeyType);
|
||||
#else
|
||||
ret = DecodeAsymKey_Assign(input, inOutIdx, inSz,
|
||||
&seed, &seedLen,
|
||||
&privKey, &privKeyLen,
|
||||
&pubKey, &pubKeyLen, &autoKeyType);
|
||||
#endif /* WOLFSSL_ASN_TEMPLATE */
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
if (keyType == ANONk && autoKeyType != ANONk) {
|
||||
/* Set the security level based on the decoded key. */
|
||||
ret = mapOidToSecLevel(keyType);
|
||||
ret = mapOidToSecLevel(autoKeyType);
|
||||
if (ret > 0) {
|
||||
ret = wc_dilithium_set_level(key, (byte)ret);
|
||||
}
|
||||
}
|
||||
/* If it failed to decode try alternative DER encoding. */
|
||||
else if (ret != 0) {
|
||||
word32 levelSize = dilithium_get_priv_size(key->level);
|
||||
privKey = input + *inOutIdx;
|
||||
privKeyLen = inSz - *inOutIdx;
|
||||
|
||||
/* Check for an alternative DER encoding. */
|
||||
if (privKeyLen == ALT_PRIV_DER_PREFIX_SEQ + levelSize) {
|
||||
privKey += ALT_PRIV_DER_PREFIX_SEQ;
|
||||
privKeyLen -= ALT_PRIV_DER_PREFIX_SEQ;
|
||||
else if (keyType != ANONk && autoKeyType != ANONk) {
|
||||
if (keyType == autoKeyType)
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
else if (keyType != ANONk && autoKeyType == ANONk) {
|
||||
ret = 0;
|
||||
}
|
||||
else { /* keyType == ANONk && autoKeyType == ANONk */
|
||||
/*
|
||||
* When decoding traditional format with not specifying a level will
|
||||
* cause this error.
|
||||
*/
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret == 0) && (pubKey == NULL) && (pubKeyLen == 0)) {
|
||||
/* Check if the public key is included in the private key. */
|
||||
#if defined(WOLFSSL_DILITHIUM_FIPS204_DRAFT)
|
||||
@@ -9828,32 +9817,39 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx,
|
||||
pubKeyLen = ML_DSA_LEVEL5_PUB_KEY_SIZE;
|
||||
privKeyLen -= ML_DSA_LEVEL5_PUB_KEY_SIZE;
|
||||
}
|
||||
else {
|
||||
word32 levelSize = dilithium_get_priv_size(key->level);
|
||||
|
||||
if (privKeyLen == ALT_PRIV_DER_PREFIX + levelSize) {
|
||||
privKey += ALT_PRIV_DER_PREFIX;
|
||||
privKeyLen -= ALT_PRIV_DER_PREFIX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/* Check whether public key data was found. */
|
||||
#if defined(WOLFSSL_DILITHIUM_PUBLIC_KEY)
|
||||
if (pubKeyLen == 0)
|
||||
/* Generate a key pair if seed exists and decoded key pair is ignored */
|
||||
if (seedLen != 0) {
|
||||
#if defined(WOLFSSL_WC_DILITHIUM)
|
||||
if (seedLen == DILITHIUM_SEED_SZ) {
|
||||
ret = wc_dilithium_make_key_from_seed(key, seed);
|
||||
}
|
||||
else {
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
#else
|
||||
ret = NOT_COMPILED_IN;
|
||||
#endif
|
||||
{
|
||||
/* No public key data, only import private key data. */
|
||||
ret = wc_dilithium_import_private(privKey, privKeyLen, key);
|
||||
}
|
||||
#if defined(WOLFSSL_DILITHIUM_PUBLIC_KEY)
|
||||
else {
|
||||
/* Check whether public key data was found. */
|
||||
else if (pubKeyLen != 0 && privKeyLen != 0) {
|
||||
/* Import private and public key data. */
|
||||
ret = wc_dilithium_import_key(privKey, privKeyLen, pubKey,
|
||||
pubKeyLen, key);
|
||||
}
|
||||
#endif
|
||||
else if (pubKeyLen == 0 && privKeyLen != 0)
|
||||
{
|
||||
/* No public key data, only import private key data. */
|
||||
ret = wc_dilithium_import_private(privKey, privKeyLen, key);
|
||||
}
|
||||
else {
|
||||
/* Not a problem of ASN.1 structure, but the contents is invalid */
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
}
|
||||
|
||||
(void)pubKey;
|
||||
|
@@ -204,7 +204,10 @@ enum ASN_Tags {
|
||||
|
||||
/* OneAsymmetricKey Fields */
|
||||
ASN_ASYMKEY_ATTRS = 0x00,
|
||||
ASN_ASYMKEY_PUBKEY = 0x01
|
||||
ASN_ASYMKEY_PUBKEY = 0x01,
|
||||
|
||||
/* PKEY Fields */
|
||||
ASN_PKEY_SEED = 0x00
|
||||
};
|
||||
|
||||
/* NOTE: If ASN_UTC_TIME_SIZE or ASN_GENERALIZED_TIME_SIZE are ever modified
|
||||
@@ -2727,8 +2730,9 @@ 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* inOutKeyType);
|
||||
word32 inSz, const byte** seed, word32* seedLen, 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,
|
||||
|
Reference in New Issue
Block a user