fix SetAsymKeyDer to set PKCS#8 version=1 when bundling publicKey (RFC 5958)

This commit is contained in:
Chris Conlon
2026-05-07 10:38:40 -06:00
parent 4b00525e90
commit 7cc84d38fb
14 changed files with 547 additions and 10 deletions
+72
View File
@@ -252,5 +252,77 @@ typedef struct testVector {
extern int testDevId;
/* Skip past outer SEQ header of a PKCS#8 / RFC 5958 OneAsymmetricKey DER blob,
* return version byte (0=v1, 1=v2) or -1 on malformed input. */
#ifdef WC_ENABLE_ASYM_KEY_EXPORT
static WC_INLINE int test_pkcs8_get_version_byte(const byte* der, word32 derSz)
{
word32 idx = 0;
word32 nBytes = 0;
/* SEQ tag + short len + INT tag + INT len + version = 5 */
if (der == NULL || derSz < 5) {
return -1;
}
/* SEQUENCE */
if (der[idx++] != 0x30) {
return -1;
}
if (idx >= derSz) {
return -1;
}
if ((der[idx] & 0x80) == 0) {
/* short-form length */
idx += 1;
}
else {
/* long-form length */
nBytes = (word32)(der[idx] & 0x7F);
if (nBytes == 0 || nBytes > 4) {
return -1;
}
idx += (1 + nBytes);
}
if (idx + 3 > derSz) {
return -1;
}
/* INTEGER, len 1 */
if (der[idx] != 0x02 || der[idx + 1] != 0x01) {
return -1;
}
return (int)der[idx + 2];
}
/* Overwrite OneAsymmetricKey version byte. Return the patched offset or
* -1 on malformed input. */
static WC_INLINE int test_pkcs8_patch_version_byte(byte* der, word32 derSz,
byte newVer)
{
word32 idx = 0;
word32 nBytes = 0;
if (der == NULL || derSz < 5 || der[idx++] != 0x30) {
return -1;
}
if ((der[idx] & 0x80) == 0) {
idx += 1;
}
else {
nBytes = (word32)(der[idx] & 0x7F);
if (nBytes == 0 || nBytes > 4) {
return -1;
}
idx += (1 + nBytes);
}
if (idx + 3 > derSz || der[idx] != 0x02 || der[idx + 1] != 0x01) {
return -1;
}
der[idx + 2] = newVer;
return (int)(idx + 2);
}
#endif /* WC_ENABLE_ASYM_KEY_EXPORT */
#endif /* WOLFCRYPT_TEST_API_H */
+161
View File
@@ -21,10 +21,16 @@
#include <tests/unit.h>
#include <tests/api/api.h>
#include <tests/api/test_asn.h>
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/rsa.h>
#ifdef HAVE_ED25519
#include <wolfssl/wolfcrypt/ed25519.h>
#endif
#if defined(WC_ENABLE_ASYM_KEY_EXPORT) && defined(HAVE_ED25519)
static int test_SetAsymKeyDer_once(byte* privKey, word32 privKeySz, byte* pubKey,
@@ -55,6 +61,9 @@ int test_SetAsymKeyDer(void)
#if defined(WC_ENABLE_ASYM_KEY_EXPORT) && defined(HAVE_ED25519)
/* We can't access the keyEd25519Oid variable, so declare it instead */
byte algId[] = {43, 101, 112};
/* RFC 5958: version is v1 (0) for private only, v2 (1) when public key
* bundled. Conditions 1-5 are private only, 6-8 include pub key and
* mutate version[0] = 0x1 before building trueDer. */
byte version[] = {0x0};
byte keyPat = 0xcc;
@@ -286,6 +295,7 @@ int test_SetAsymKeyDer(void)
privKeySz = 32;
pubKeySz = 32;
trueDerSz = 82;
version[0] = 0x1; /* publicKey present (v2) */
/* SEQ */
trueDer[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
@@ -328,6 +338,7 @@ int test_SetAsymKeyDer(void)
privKeySz = 32;
pubKeySz = 128;
trueDerSz = 180;
version[0] = 0x1; /* publicKey present (v2) */
/* SEQ */
trueDer[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
@@ -372,6 +383,7 @@ int test_SetAsymKeyDer(void)
privKeySz = 32;
pubKeySz = 256;
trueDerSz = 310;
version[0] = 0x1; /* publicKey present (v2) */
/* SEQ */
trueDer[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
@@ -413,6 +425,155 @@ int test_SetAsymKeyDer(void)
}
/* RFC 5958 leniency: parser must accept all four variants:
* {v=0,v=1} x {publicKey absent, present}. */
int test_DecodeAsymKey_lenient_versions(void)
{
EXPECT_DECLS;
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) && \
defined(HAVE_ED25519_KEY_IMPORT) && defined(WOLFSSL_KEY_GEN)
ed25519_key key;
ed25519_key parsed;
WC_RNG rng;
byte bundled[256]; /* v=1 + publicKey */
byte privOnly[256]; /* v=0, no publicKey */
byte tmp[256];
int bundledSz = 0;
int privOnlySz = 0;
word32 idx;
XMEMSET(&key, 0, sizeof(key));
XMEMSET(&parsed, 0, sizeof(parsed));
XMEMSET(&rng, 0, sizeof(rng));
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_ed25519_init(&key), 0);
ExpectIntEQ(wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key), 0);
ExpectIntGT(bundledSz = wc_Ed25519KeyToDer(&key, bundled,
(word32)sizeof(bundled)), 0);
ExpectIntGT(privOnlySz = wc_Ed25519PrivateKeyToDer(&key, privOnly,
(word32)sizeof(privOnly)), 0);
if (EXPECT_SUCCESS() &&
((bundledSz > 0) && ((size_t)bundledSz <= sizeof(bundled)) &&
(privOnlySz > 0) && ((size_t)privOnlySz <= sizeof(privOnly)))) {
/* v=1 + publicKey */
XMEMCPY(tmp, bundled, (size_t)bundledSz);
XMEMSET(&parsed, 0, sizeof(parsed));
ExpectIntEQ(wc_ed25519_init(&parsed), 0);
idx = 0;
ExpectIntEQ(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed,
(word32)bundledSz), 0);
wc_ed25519_free(&parsed);
/* v=0 + publicKey: patch version byte, [1] publicKey field present. */
XMEMCPY(tmp, bundled, (size_t)bundledSz);
ExpectIntGT(test_pkcs8_patch_version_byte(tmp, (word32)bundledSz, 0),
0);
XMEMSET(&parsed, 0, sizeof(parsed));
ExpectIntEQ(wc_ed25519_init(&parsed), 0);
idx = 0;
ExpectIntEQ(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed,
(word32)bundledSz), 0);
wc_ed25519_free(&parsed);
/* v=0, no publicKey */
XMEMCPY(tmp, privOnly, (size_t)privOnlySz);
XMEMSET(&parsed, 0, sizeof(parsed));
ExpectIntEQ(wc_ed25519_init(&parsed), 0);
idx = 0;
ExpectIntEQ(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed,
(word32)privOnlySz), 0);
wc_ed25519_free(&parsed);
/* v=1, no publicKey */
XMEMCPY(tmp, privOnly, (size_t)privOnlySz);
ExpectIntGT(test_pkcs8_patch_version_byte(tmp, (word32)privOnlySz, 1),
0);
XMEMSET(&parsed, 0, sizeof(parsed));
ExpectIntEQ(wc_ed25519_init(&parsed), 0);
idx = 0;
ExpectIntEQ(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed,
(word32)privOnlySz), 0);
wc_ed25519_free(&parsed);
}
wc_ed25519_free(&key);
wc_FreeRng(&rng);
#endif
return EXPECT_RESULT();
}
int test_DecodeAsymKey_negative(void)
{
EXPECT_DECLS;
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) && \
defined(HAVE_ED25519_KEY_IMPORT) && defined(WOLFSSL_KEY_GEN)
ed25519_key key;
ed25519_key parsed;
WC_RNG rng;
byte good[256];
byte tmp[256];
int goodSz = 0;
word32 idx;
XMEMSET(&key, 0, sizeof(key));
XMEMSET(&parsed, 0, sizeof(parsed));
XMEMSET(&rng, 0, sizeof(rng));
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_ed25519_init(&key), 0);
ExpectIntEQ(wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key), 0);
ExpectIntGT(goodSz = wc_Ed25519KeyToDer(&key, good,
(word32)sizeof(good)), 0);
if (EXPECT_SUCCESS() &&
(goodSz > 0 && (size_t)goodSz <= sizeof(good))) {
/* Truncated buffer */
XMEMCPY(tmp, good, (size_t)goodSz);
ExpectIntEQ(wc_ed25519_init(&parsed), 0);
idx = 0;
ExpectIntLT(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed,
(word32)(goodSz - 1)), 0);
wc_ed25519_free(&parsed);
/* Outer length too big. Patch low-order length byte (long form: bump
* the last byte of the multi-byte length encoding). */
XMEMCPY(tmp, good, (size_t)goodSz);
if ((good[1] & 0x80) == 0) {
tmp[1] = (byte)(good[1] + 1);
}
else {
word32 nBytes = (word32)(good[1] & 0x7F);
tmp[1 + nBytes] = (byte)(good[1 + nBytes] + 1);
}
XMEMSET(&parsed, 0, sizeof(parsed));
ExpectIntEQ(wc_ed25519_init(&parsed), 0);
idx = 0;
ExpectIntLT(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed,
(word32)goodSz), 0);
wc_ed25519_free(&parsed);
/* Outer tag not SEQUENCE */
XMEMCPY(tmp, good, (size_t)goodSz);
tmp[0] = 0x02;
XMEMSET(&parsed, 0, sizeof(parsed));
ExpectIntEQ(wc_ed25519_init(&parsed), 0);
idx = 0;
ExpectIntLT(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed,
(word32)goodSz), 0);
wc_ed25519_free(&parsed);
}
wc_ed25519_free(&key);
wc_FreeRng(&rng);
#endif
return EXPECT_RESULT();
}
#ifndef NO_ASN
static int test_GetSetShortInt_once(word32 val, byte* valDer, word32 valDerSz)
{
+4
View File
@@ -25,6 +25,8 @@
#include <tests/api/api_decl.h>
int test_SetAsymKeyDer(void);
int test_DecodeAsymKey_lenient_versions(void);
int test_DecodeAsymKey_negative(void);
int test_GetSetShortInt(void);
int test_wc_IndexSequenceOf(void);
int test_wolfssl_local_MatchBaseName(void);
@@ -34,6 +36,8 @@ int test_wc_DecodeObjectId(void);
#define TEST_ASN_DECLS \
TEST_DECL_GROUP("asn", test_SetAsymKeyDer), \
TEST_DECL_GROUP("asn", test_DecodeAsymKey_lenient_versions), \
TEST_DECL_GROUP("asn", test_DecodeAsymKey_negative), \
TEST_DECL_GROUP("asn", test_GetSetShortInt), \
TEST_DECL_GROUP("asn", test_wc_IndexSequenceOf), \
TEST_DECL_GROUP("asn", test_wolfssl_local_MatchBaseName), \
+58
View File
@@ -608,3 +608,61 @@ int test_wc_curve25519_priv_clamp_check(void)
return EXPECT_RESULT();
} /* END test_wc_curve25519_priv_clamp_check */
/*
* RFC 5958 OneAsymmetricKey: version=v2 (1) when publicKey is bundled,
* version=v1 (0) for private only.
*/
int test_wc_Curve25519KeyToDer_oneasymkey_version(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_EXPORT) && \
defined(HAVE_CURVE25519_KEY_IMPORT)
curve25519_key key;
curve25519_key key2;
WC_RNG rng;
byte ref[256]; /* reference DER (bundled, then private only) */
byte rt[256]; /* re-export target for memcmp */
int refSz = 0;
int rtSz = 0;
word32 idx;
XMEMSET(&key, 0, sizeof(key));
XMEMSET(&key2, 0, sizeof(key2));
XMEMSET(&rng, 0, sizeof(rng));
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve25519_init(&key), 0);
ExpectIntEQ(wc_curve25519_init(&key2), 0);
ExpectIntEQ(wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, &key), 0);
/* make_key sets both priv and pub: KeyToDer bundles both (v=1).
* Use wc_Curve25519KeyDecode so the publicKey field is preserved in key2 */
ExpectIntGT(refSz = wc_Curve25519KeyToDer(&key, ref,
(word32)sizeof(ref), 1), 0);
ExpectIntEQ(test_pkcs8_get_version_byte(ref, (word32)refSz), 1);
idx = 0;
ExpectIntEQ(wc_Curve25519KeyDecode(ref, &idx, &key2, (word32)refSz), 0);
ExpectIntEQ(rtSz = wc_Curve25519KeyToDer(&key2, rt, (word32)sizeof(rt), 1),
refSz);
ExpectIntEQ(XMEMCMP(ref, rt, (size_t)refSz), 0);
/* Private only creates v=0. Reuse ref/rt. */
XMEMSET(&key2, 0, sizeof(key2));
ExpectIntEQ(wc_curve25519_init(&key2), 0);
ExpectIntGT(refSz = wc_Curve25519PrivateKeyToDer(&key, ref,
(word32)sizeof(ref)), 0);
ExpectIntEQ(test_pkcs8_get_version_byte(ref, (word32)refSz), 0);
idx = 0;
ExpectIntEQ(wc_Curve25519PrivateKeyDecode(ref, &idx, &key2,
(word32)refSz), 0);
ExpectIntEQ(rtSz = wc_Curve25519PrivateKeyToDer(&key2, rt,
(word32)sizeof(rt)), refSz);
ExpectIntEQ(XMEMCMP(ref, rt, (size_t)refSz), 0);
wc_curve25519_free(&key);
wc_curve25519_free(&key2);
wc_FreeRng(&rng);
#endif
return EXPECT_RESULT();
}
+3 -1
View File
@@ -36,6 +36,7 @@ int test_wc_curve25519_export_private_raw_ex(void);
int test_wc_curve25519_import_private_raw_ex(void);
int test_wc_curve25519_import_private(void);
int test_wc_curve25519_priv_clamp_check(void);
int test_wc_Curve25519KeyToDer_oneasymkey_version(void);
#define TEST_CURVE25519_DECLS \
TEST_DECL_GROUP("curve25519", test_wc_curve25519_init), \
@@ -49,6 +50,7 @@ int test_wc_curve25519_priv_clamp_check(void);
TEST_DECL_GROUP("curve25519", test_wc_curve25519_export_private_raw_ex), \
TEST_DECL_GROUP("curve25519", test_wc_curve25519_import_private_raw_ex), \
TEST_DECL_GROUP("curve25519", test_wc_curve25519_import_private), \
TEST_DECL_GROUP("curve25519", test_wc_curve25519_priv_clamp_check)
TEST_DECL_GROUP("curve25519", test_wc_curve25519_priv_clamp_check), \
TEST_DECL_GROUP("curve25519", test_wc_Curve25519KeyToDer_oneasymkey_version)
#endif /* WOLFCRYPT_TEST_CURVE25519_H */
+45
View File
@@ -403,3 +403,48 @@ int test_wc_Curve448PrivateKeyToDer(void)
return EXPECT_RESULT();
} /* End wc_Curve448PrivateKeyToDer*/
/*
* RFC 5958: private only path must create version=v1 (0). Curve448 has no
* public API to create bundled key. Only test private key path. */
int test_wc_Curve448PrivateKeyToDer_oneasymkey_version(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_EXPORT) && \
defined(HAVE_CURVE448_KEY_IMPORT)
curve448_key key;
curve448_key key2;
WC_RNG rng;
byte ref[256]; /* reference DER (private only) */
byte rt[256]; /* re-export target for memcmp */
int refSz = 0;
int rtSz = 0;
word32 idx = 0;
XMEMSET(&key, 0, sizeof(key));
XMEMSET(&key2, 0, sizeof(key2));
XMEMSET(&rng, 0, sizeof(rng));
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_init(&key), 0);
ExpectIntEQ(wc_curve448_init(&key2), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &key), 0);
ExpectIntGT(refSz = wc_Curve448PrivateKeyToDer(&key, ref,
(word32)sizeof(ref)), 0);
ExpectIntEQ(test_pkcs8_get_version_byte(ref, (word32)refSz), 0);
idx = 0;
ExpectIntEQ(wc_Curve448PrivateKeyDecode(ref, &idx, &key2,
(word32)refSz), 0);
ExpectIntGT(rtSz = wc_Curve448PrivateKeyToDer(&key2, rt,
(word32)sizeof(rt)), 0);
ExpectIntEQ(rtSz, refSz);
ExpectIntEQ(XMEMCMP(ref, rt, (size_t)refSz), 0);
wc_curve448_free(&key);
wc_curve448_free(&key2);
wc_FreeRng(&rng);
#endif
return EXPECT_RESULT();
}
+3 -1
View File
@@ -34,6 +34,7 @@ int test_wc_curve448_import_private(void);
int test_wc_curve448_init(void);
int test_wc_curve448_size(void);
int test_wc_Curve448PrivateKeyToDer(void);
int test_wc_Curve448PrivateKeyToDer_oneasymkey_version(void);
#define TEST_CURVE448_DECLS \
TEST_DECL_GROUP("curve448", test_wc_curve448_make_key), \
@@ -45,6 +46,7 @@ int test_wc_Curve448PrivateKeyToDer(void);
TEST_DECL_GROUP("curve448", test_wc_curve448_import_private), \
TEST_DECL_GROUP("curve448", test_wc_curve448_init), \
TEST_DECL_GROUP("curve448", test_wc_curve448_size), \
TEST_DECL_GROUP("curve448", test_wc_Curve448PrivateKeyToDer)
TEST_DECL_GROUP("curve448", test_wc_Curve448PrivateKeyToDer), \
TEST_DECL_GROUP("curve448", test_wc_Curve448PrivateKeyToDer_oneasymkey_version)
#endif /* WOLFCRYPT_TEST_CURVE448_H */
+47
View File
@@ -678,3 +678,50 @@ int test_wc_Ed25519PrivateKeyToDer(void)
return EXPECT_RESULT();
} /* End test_wc_Ed25519PrivateKeyToDer*/
/*
* RFC 5958: version=v2 (1) when pub key is bundled, v1 (0) for private only. */
int test_wc_Ed25519KeyToDer_oneasymkey_version(void)
{
EXPECT_DECLS;
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) && \
defined(HAVE_ED25519_KEY_IMPORT) && defined(WOLFSSL_KEY_GEN)
ed25519_key key;
ed25519_key key2;
WC_RNG rng;
byte ref[256]; /* reference DER (bundled, then private only) */
byte rt[256]; /* re-export target for memcmp */
int refSz = 0;
int rtSz = 0;
word32 idx;
XMEMSET(&key, 0, sizeof(key));
XMEMSET(&key2, 0, sizeof(key2));
XMEMSET(&rng, 0, sizeof(rng));
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_ed25519_init(&key), 0);
ExpectIntEQ(wc_ed25519_init(&key2), 0);
ExpectIntEQ(wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key), 0);
/* Bundled (v=1) */
ExpectIntGT(refSz = wc_Ed25519KeyToDer(&key, ref, (word32)sizeof(ref)), 0);
ExpectIntEQ(test_pkcs8_get_version_byte(ref, (word32)refSz), 1);
idx = 0;
ExpectIntEQ(wc_Ed25519PrivateKeyDecode(ref, &idx, &key2, (word32)refSz),
0);
ExpectIntEQ(rtSz = wc_Ed25519KeyToDer(&key2, rt, (word32)sizeof(rt)),
refSz);
ExpectIntEQ(XMEMCMP(ref, rt, (size_t)refSz), 0);
/* Priv-only (v=0) */
ExpectIntGT(refSz = wc_Ed25519PrivateKeyToDer(&key, ref,
(word32)sizeof(ref)), 0);
ExpectIntEQ(test_pkcs8_get_version_byte(ref, (word32)refSz), 0);
wc_ed25519_free(&key);
wc_ed25519_free(&key2);
wc_FreeRng(&rng);
#endif
return EXPECT_RESULT();
}
+3 -1
View File
@@ -36,6 +36,7 @@ int test_wc_ed25519_exportKey(void);
int test_wc_Ed25519PublicKeyToDer(void);
int test_wc_Ed25519KeyToDer(void);
int test_wc_Ed25519PrivateKeyToDer(void);
int test_wc_Ed25519KeyToDer_oneasymkey_version(void);
#define TEST_ED25519_DECLS \
TEST_DECL_GROUP("ed25519", test_wc_ed25519_make_key), \
@@ -49,6 +50,7 @@ int test_wc_Ed25519PrivateKeyToDer(void);
TEST_DECL_GROUP("ed25519", test_wc_ed25519_exportKey), \
TEST_DECL_GROUP("ed25519", test_wc_Ed25519PublicKeyToDer), \
TEST_DECL_GROUP("ed25519", test_wc_Ed25519KeyToDer), \
TEST_DECL_GROUP("ed25519", test_wc_Ed25519PrivateKeyToDer)
TEST_DECL_GROUP("ed25519", test_wc_Ed25519PrivateKeyToDer), \
TEST_DECL_GROUP("ed25519", test_wc_Ed25519KeyToDer_oneasymkey_version)
#endif /* WOLFCRYPT_TEST_ED25519_H */
+45
View File
@@ -604,3 +604,48 @@ int test_wc_Ed448PrivateKeyToDer(void)
return EXPECT_RESULT();
} /* End test_wc_Ed448PrivateKeyToDer */
/*
* RFC 5958: version=v2 (1) when pub key is bundled, v1 (0) for private only. */
int test_wc_Ed448KeyToDer_oneasymkey_version(void)
{
EXPECT_DECLS;
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) && \
defined(HAVE_ED448_KEY_IMPORT) && defined(WOLFSSL_KEY_GEN)
ed448_key key;
ed448_key key2;
WC_RNG rng;
byte ref[512]; /* reference DER (bundled, then private only) */
byte rt[512]; /* re-export target for memcmp */
int refSz = 0;
int rtSz = 0;
word32 idx;
XMEMSET(&key, 0, sizeof(key));
XMEMSET(&key2, 0, sizeof(key2));
XMEMSET(&rng, 0, sizeof(rng));
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_ed448_init(&key), 0);
ExpectIntEQ(wc_ed448_init(&key2), 0);
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key), 0);
/* Bundled (v=1) */
ExpectIntGT(refSz = wc_Ed448KeyToDer(&key, ref, (word32)sizeof(ref)), 0);
ExpectIntEQ(test_pkcs8_get_version_byte(ref, (word32)refSz), 1);
idx = 0;
ExpectIntEQ(wc_Ed448PrivateKeyDecode(ref, &idx, &key2, (word32)refSz), 0);
ExpectIntEQ(rtSz = wc_Ed448KeyToDer(&key2, rt, (word32)sizeof(rt)), refSz);
ExpectIntEQ(XMEMCMP(ref, rt, (size_t)refSz), 0);
/* Private only (v=0) */
ExpectIntGT(refSz = wc_Ed448PrivateKeyToDer(&key, ref,
(word32)sizeof(ref)), 0);
ExpectIntEQ(test_pkcs8_get_version_byte(ref, (word32)refSz), 0);
wc_ed448_free(&key);
wc_ed448_free(&key2);
wc_FreeRng(&rng);
#endif
return EXPECT_RESULT();
}
+3 -1
View File
@@ -36,6 +36,7 @@ int test_wc_ed448_exportKey(void);
int test_wc_Ed448PublicKeyToDer(void);
int test_wc_Ed448KeyToDer(void);
int test_wc_Ed448PrivateKeyToDer(void);
int test_wc_Ed448KeyToDer_oneasymkey_version(void);
#define TEST_ED448_DECLS \
TEST_DECL_GROUP("ed448", test_wc_ed448_make_key), \
@@ -49,6 +50,7 @@ int test_wc_Ed448PrivateKeyToDer(void);
TEST_DECL_GROUP("ed448", test_wc_ed448_exportKey), \
TEST_DECL_GROUP("ed448", test_wc_Ed448PublicKeyToDer), \
TEST_DECL_GROUP("ed448", test_wc_Ed448KeyToDer), \
TEST_DECL_GROUP("ed448", test_wc_Ed448PrivateKeyToDer)
TEST_DECL_GROUP("ed448", test_wc_Ed448PrivateKeyToDer), \
TEST_DECL_GROUP("ed448", test_wc_Ed448KeyToDer_oneasymkey_version)
#endif /* WOLFCRYPT_TEST_ED448_H */
+93 -1
View File
@@ -2982,13 +2982,18 @@ int test_wc_dilithium_public_der_decode(void)
return EXPECT_RESULT();
}
#if defined(HAVE_DILITHIUM) && \
!defined(WOLFSSL_DILITHIUM_NO_ASN1) && \
!defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY)
#define DILITHIUM_MAX_DER_SIZE 8192
#endif
int test_wc_dilithium_der(void)
{
EXPECT_DECLS;
#if defined(HAVE_DILITHIUM) && \
!defined(WOLFSSL_DILITHIUM_NO_ASN1) && \
!defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY)
#define DILITHIUM_MAX_DER_SIZE 8192
dilithium_key* key;
WC_RNG rng;
byte* der = NULL;
@@ -3195,6 +3200,93 @@ int test_wc_dilithium_der(void)
return EXPECT_RESULT();
}
#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_ASN1) && \
!defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY)
/* Decode, re-export, byte-compare. Asserts version=1 on the bundled form and
* version=0 on the private only form. */
static int dilithium_oneasymkey_version_check(int level)
{
EXPECT_DECLS;
dilithium_key key;
dilithium_key key2;
WC_RNG rng;
byte* ref = NULL;
byte* rt = NULL;
int refSz = 0;
int rtSz = 0;
word32 idx;
XMEMSET(&key, 0, sizeof(key));
XMEMSET(&key2, 0, sizeof(key2));
XMEMSET(&rng, 0, sizeof(rng));
ExpectNotNull(ref = (byte*)XMALLOC(DILITHIUM_MAX_DER_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER));
ExpectNotNull(rt = (byte*)XMALLOC(DILITHIUM_MAX_DER_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER));
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_dilithium_init(&key), 0);
ExpectIntEQ(wc_dilithium_init(&key2), 0);
ExpectIntEQ(wc_dilithium_set_level(&key, level), 0);
ExpectIntEQ(wc_dilithium_set_level(&key2, level), 0);
ExpectIntEQ(wc_dilithium_make_key(&key, &rng), 0);
/* Bundled (v=1) */
PRIVATE_KEY_UNLOCK();
ExpectIntGT(refSz = wc_Dilithium_KeyToDer(&key, ref,
DILITHIUM_MAX_DER_SIZE), 0);
PRIVATE_KEY_LOCK();
ExpectIntEQ(test_pkcs8_get_version_byte(ref, (word32)refSz), 1);
idx = 0;
ExpectIntEQ(wc_Dilithium_PrivateKeyDecode(ref, &idx, &key2,
(word32)refSz), 0);
PRIVATE_KEY_UNLOCK();
ExpectIntEQ(rtSz = wc_Dilithium_KeyToDer(&key2, rt,
DILITHIUM_MAX_DER_SIZE), refSz);
PRIVATE_KEY_LOCK();
ExpectIntEQ(XMEMCMP(ref, rt, (size_t)refSz), 0);
/* Private only (v=0). Reuse ref. */
PRIVATE_KEY_UNLOCK();
ExpectIntGT(refSz = wc_Dilithium_PrivateKeyToDer(&key, ref,
DILITHIUM_MAX_DER_SIZE), 0);
PRIVATE_KEY_LOCK();
ExpectIntEQ(test_pkcs8_get_version_byte(ref, (word32)refSz), 0);
wc_dilithium_free(&key);
wc_dilithium_free(&key2);
wc_FreeRng(&rng);
XFREE(rt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(ref, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return EXPECT_RESULT();
}
#endif
int test_wc_dilithium_oneasymkey_version(void)
{
EXPECT_DECLS;
#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_ASN1) && \
!defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY)
#ifndef WOLFSSL_NO_ML_DSA_44
ExpectIntEQ(dilithium_oneasymkey_version_check(WC_ML_DSA_44),
TEST_SUCCESS);
#endif
#ifndef WOLFSSL_NO_ML_DSA_65
ExpectIntEQ(dilithium_oneasymkey_version_check(WC_ML_DSA_65),
TEST_SUCCESS);
#endif
#ifndef WOLFSSL_NO_ML_DSA_87
ExpectIntEQ(dilithium_oneasymkey_version_check(WC_ML_DSA_87),
TEST_SUCCESS);
#endif
#endif
return EXPECT_RESULT();
}
int test_wc_dilithium_make_key_from_seed(void)
{
EXPECT_DECLS;
+2
View File
@@ -33,6 +33,7 @@ int test_wc_dilithium_sign_vfy(void);
int test_wc_dilithium_check_key(void);
int test_wc_dilithium_public_der_decode(void);
int test_wc_dilithium_der(void);
int test_wc_dilithium_oneasymkey_version(void);
int test_wc_dilithium_make_key_from_seed(void);
int test_wc_dilithium_sig_kats(void);
int test_wc_dilithium_sign_ctx_kats(void);
@@ -57,6 +58,7 @@ int test_mldsa_x509_pubkey_sigtype(void);
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_oneasymkey_version), \
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_sign_ctx_kats), \
+8 -5
View File
@@ -31485,7 +31485,9 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz,
if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
return ASN_PARSE_E;
if (version != 0) {
/* RFC 5958: v1 (0) for privateKey only, v2 (1) when publicKey added. */
if (version != 0 && version != 1) {
WOLFSSL_MSG("Unrecognized version of private key");
return ASN_PARSE_E;
}
@@ -32008,8 +32010,8 @@ int SetAsymKeyDer(const byte* privKey, word32 privKeyLen,
/* seq */
seqSz = SetSequence(verSz + algoSz + privSz + pubSz, output);
idx = seqSz;
/* ver */
SetMyVersion(0, output + idx, FALSE);
/* ver: RFC 5958 requires v2 (1) iff publicKey present, else v1 (0). */
SetMyVersion((word32)(pubKey ? PKCS8v1 : PKCS8v0), output + idx, FALSE);
idx += verSz;
/* algo */
algoSz = SetAlgoID(keyType, output + idx, oidKeyType, 0);
@@ -32037,8 +32039,9 @@ int SetAsymKeyDer(const byte* privKey, word32 privKeyLen,
CALLOC_ASNSETDATA(dataASN, privateKeyASN_Length, ret, NULL);
if (ret == 0) {
/* Set version = 0 */
SetASN_Int8Bit(&dataASN[PRIVKEYASN_IDX_VER], 0);
/* RFC 5958: v2 (1) iff publicKey present, else v1 (0). */
SetASN_Int8Bit(&dataASN[PRIVKEYASN_IDX_VER],
(byte)(pubKey ? PKCS8v1 : PKCS8v0));
/* Set OID. */
SetASN_OID(&dataASN[PRIVKEYASN_IDX_PKEYALGO_OID], (word32)keyType,
oidKeyType);