mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 12:20:52 +02:00
fix SetAsymKeyDer to set PKCS#8 version=1 when bundling publicKey (RFC 5958)
This commit is contained in:
@@ -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 */
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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), \
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user