Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions doc/dox_comments/header_files/asn_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -2830,10 +2830,48 @@ int wc_Curve25519KeyToDer(curve25519_key* key, byte* output, word32 outLen,
\endcode

\sa wc_Ed25519PrivateKeyToDer
\sa wc_Ed25519PrivateKeyDecode_ex
*/
int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
ed25519_key* key, word32 inSz);

/*!
\ingroup Ed25519
\brief Decodes Ed25519 private key from DER format with control over
validation of a bundled public key. When the DER contains a public key
and trusted is 0, the public key is validated with
wc_ed25519_check_key(), including a check that it matches the private
key. When trusted is 1 all validation of the bundled public key is
skipped, so trusted should only be set with known-good key material.
wc_Ed25519PrivateKeyDecode() behaves as trusted set to 0.

\return 0 on success
\return negative on error

\param input DER encoded Ed25519 private key buffer
\param inOutIdx Pointer to index in buffer
\param key Ed25519 key structure to store key
\param inSz Size of input buffer
\param trusted Indicates whether the bundled public key data is trusted.
When 0, the public key is validated with wc_ed25519_check_key().
When 1, the public key is imported without any validation.

_Example_
\code
ed25519_key key;
word32 idx = 0;
// key material comes from this application's own storage
int ret = wc_Ed25519PrivateKeyDecode_ex(derBuf, &idx, &key,
derSz, 1);
\endcode

\sa wc_Ed25519PrivateKeyDecode
\sa wc_Ed25519PrivateKeyToDer
\sa wc_ed25519_import_private_key_ex
*/
int wc_Ed25519PrivateKeyDecode_ex(const byte* input, word32* inOutIdx,
ed25519_key* key, word32 inSz, int trusted);

/*!
\ingroup Ed25519
\brief Decodes Ed25519 public key from DER format.
Expand Down Expand Up @@ -2952,10 +2990,48 @@ int wc_Ed25519PublicKeyToDer(const ed25519_key* key, byte* output,
\endcode

\sa wc_Ed448PrivateKeyToDer
\sa wc_Ed448PrivateKeyDecode_ex
*/
int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx,
ed448_key* key, word32 inSz);

/*!
\ingroup Ed448
\brief Decodes Ed448 private key from DER format with control over
validation of a bundled public key. When the DER contains a public key
and trusted is 0, the public key is validated with wc_ed448_check_key(),
including a check that it matches the private key. When trusted is 1
all validation of the bundled public key is skipped, so trusted should
only be set with known-good key material. wc_Ed448PrivateKeyDecode()
behaves as trusted set to 0.

\return 0 on success
\return negative on error

\param input DER encoded Ed448 private key buffer
\param inOutIdx Pointer to index in buffer
\param key Ed448 key structure to store key
\param inSz Size of input buffer
\param trusted Indicates whether the bundled public key data is trusted.
When 0, the public key is validated with wc_ed448_check_key().
When 1, the public key is imported without any validation.

_Example_
\code
ed448_key key;
word32 idx = 0;
// key material comes from this application's own storage
int ret = wc_Ed448PrivateKeyDecode_ex(derBuf, &idx, &key,
derSz, 1);
\endcode

\sa wc_Ed448PrivateKeyDecode
\sa wc_Ed448PrivateKeyToDer
\sa wc_ed448_import_private_key_ex
*/
int wc_Ed448PrivateKeyDecode_ex(const byte* input, word32* inOutIdx,
ed448_key* key, word32 inSz, int trusted);

/*!
\ingroup Ed448
\brief Decodes Ed448 public key from DER format.
Expand Down
62 changes: 62 additions & 0 deletions tests/api/test_ed25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,68 @@ int test_wc_Ed25519KeyToDer_oneasymkey_version(void)
return EXPECT_RESULT();
}

/* The trusted flag controls whether a public key bundled in the DER is
* checked against the private key during decode. */
int test_wc_Ed25519PrivateKeyDecode_ex(void)
{
EXPECT_DECLS;
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) && \
defined(HAVE_ED25519_KEY_IMPORT) && defined(HAVE_ED25519_MAKE_KEY)
ed25519_key key;
ed25519_key key2;
WC_RNG rng;
byte der[256];
int derSz = 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 private+public DER; public key is the trailing
* ED25519_PUB_KEY_SIZE bytes. */
ExpectIntGT(derSz = wc_Ed25519KeyToDer(&key, der, (word32)sizeof(der)),
0);

/* Intact DER decodes with either trust setting. */
idx = 0;
ExpectIntEQ(wc_Ed25519PrivateKeyDecode_ex(der, &idx, &key2,
(word32)derSz, 0), 0);
idx = 0;
ExpectIntEQ(wc_Ed25519PrivateKeyDecode_ex(der, &idx, &key2,
(word32)derSz, 1), 0);

/* Corrupt the bundled public key. */
if (derSz > 0) {
der[derSz - 1] ^= 0x01;
}

/* Untrusted decode checks the public key and must reject it, as must
* the non-ex decode. */
idx = 0;
ExpectIntEQ(wc_Ed25519PrivateKeyDecode_ex(der, &idx, &key2,
(word32)derSz, 0), WC_NO_ERR_TRACE(PUBLIC_KEY_E));
idx = 0;
ExpectIntEQ(wc_Ed25519PrivateKeyDecode(der, &idx, &key2, (word32)derSz),
WC_NO_ERR_TRACE(PUBLIC_KEY_E));

/* Trusted decode skips the check. */
idx = 0;
ExpectIntEQ(wc_Ed25519PrivateKeyDecode_ex(der, &idx, &key2,
(word32)derSz, 1), 0);

wc_ed25519_free(&key);
wc_ed25519_free(&key2);
wc_FreeRng(&rng);
#endif
return EXPECT_RESULT();
}

/* Ed25519 identity and small-order public keys must be rejected. When
* the public key is the identity point (or any small-order point), any
* signature of the form (R = [S]B, S) verifies for arbitrary messages
Expand Down
4 changes: 3 additions & 1 deletion tests/api/test_ed25519.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ int test_wc_Ed25519PublicKeyToDer(void);
int test_wc_Ed25519KeyToDer(void);
int test_wc_Ed25519PrivateKeyToDer(void);
int test_wc_Ed25519KeyToDer_oneasymkey_version(void);
int test_wc_Ed25519PrivateKeyDecode_ex(void);
int test_wc_ed25519_reject_small_order_keys(void);
int test_wc_ed25519_sign_verify_ctx_ph(void);
int test_wc_ed25519_verify_streaming(void);
Expand All @@ -63,6 +64,7 @@ int test_wc_ed25519_make_public_argchecks(void);
TEST_DECL_GROUP("ed25519", test_wc_ed25519_verify_streaming), \
TEST_DECL_GROUP("ed25519", test_wc_ed25519_check_key_edgecases), \
TEST_DECL_GROUP("ed25519", test_wc_ed25519_import_variants), \
TEST_DECL_GROUP("ed25519", test_wc_ed25519_make_public_argchecks)
TEST_DECL_GROUP("ed25519", test_wc_ed25519_make_public_argchecks), \
TEST_DECL_GROUP("ed25519", test_wc_Ed25519PrivateKeyDecode_ex)

#endif /* WOLFCRYPT_TEST_ED25519_H */
61 changes: 61 additions & 0 deletions tests/api/test_ed448.c
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,67 @@ int test_wc_Ed448KeyToDer_oneasymkey_version(void)
return EXPECT_RESULT();
}

/* The trusted flag controls whether a public key bundled in the DER is
* checked against the private key during decode. */
int test_wc_Ed448PrivateKeyDecode_ex(void)
{
EXPECT_DECLS;
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) && \
defined(HAVE_ED448_KEY_IMPORT)
ed448_key key;
ed448_key key2;
WC_RNG rng;
byte der[512];
int derSz = 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 private+public DER; public key is the trailing
* ED448_PUB_KEY_SIZE bytes. */
ExpectIntGT(derSz = wc_Ed448KeyToDer(&key, der, (word32)sizeof(der)), 0);

/* Intact DER decodes with either trust setting. */
idx = 0;
ExpectIntEQ(wc_Ed448PrivateKeyDecode_ex(der, &idx, &key2,
(word32)derSz, 0), 0);
idx = 0;
ExpectIntEQ(wc_Ed448PrivateKeyDecode_ex(der, &idx, &key2,
(word32)derSz, 1), 0);

/* Corrupt the bundled public key. */
if (derSz > 0) {
der[derSz - 1] ^= 0x01;
}

/* Untrusted decode checks the public key and must reject it, as must
* the non-ex decode. */
idx = 0;
ExpectIntEQ(wc_Ed448PrivateKeyDecode_ex(der, &idx, &key2,
(word32)derSz, 0), WC_NO_ERR_TRACE(PUBLIC_KEY_E));
idx = 0;
ExpectIntEQ(wc_Ed448PrivateKeyDecode(der, &idx, &key2, (word32)derSz),
WC_NO_ERR_TRACE(PUBLIC_KEY_E));

/* Trusted decode skips the check. */
idx = 0;
ExpectIntEQ(wc_Ed448PrivateKeyDecode_ex(der, &idx, &key2,
(word32)derSz, 1), 0);

wc_ed448_free(&key);
wc_ed448_free(&key2);
wc_FreeRng(&rng);
#endif
return EXPECT_RESULT();
}

/* Ed448 identity and small-order public keys must be rejected.
* Edwards448 has cofactor 4, so the small-order subgroup contains the
* identity, an order-2 point, and two order-4 points. With any of these
Expand Down
2 changes: 2 additions & 0 deletions tests/api/test_ed448.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ int test_wc_Ed448PublicKeyToDer(void);
int test_wc_Ed448KeyToDer(void);
int test_wc_Ed448PrivateKeyToDer(void);
int test_wc_Ed448KeyToDer_oneasymkey_version(void);
int test_wc_Ed448PrivateKeyDecode_ex(void);
int test_wc_ed448_reject_small_order_keys(void);

#define TEST_ED448_DECLS \
Expand All @@ -53,6 +54,7 @@ int test_wc_ed448_reject_small_order_keys(void);
TEST_DECL_GROUP("ed448", test_wc_Ed448KeyToDer), \
TEST_DECL_GROUP("ed448", test_wc_Ed448PrivateKeyToDer), \
TEST_DECL_GROUP("ed448", test_wc_Ed448KeyToDer_oneasymkey_version), \
TEST_DECL_GROUP("ed448", test_wc_Ed448PrivateKeyDecode_ex), \
TEST_DECL_GROUP("ed448", test_wc_ed448_reject_small_order_keys)

#endif /* WOLFCRYPT_TEST_ED448_H */
28 changes: 20 additions & 8 deletions wolfcrypt/src/asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -33691,8 +33691,8 @@ int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz,
#endif /* WC_ENABLE_ASYM_KEY_IMPORT */

#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT)
int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
ed25519_key* key, word32 inSz)
int wc_Ed25519PrivateKeyDecode_ex(const byte* input, word32* inOutIdx,
ed25519_key* key, word32 inSz, int trusted)
{
int ret;
byte privKey[ED25519_KEY_SIZE], pubKey[2*ED25519_PUB_KEY_SIZE+1];
Expand All @@ -33710,13 +33710,19 @@ int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
ret = wc_ed25519_import_private_only(privKey, privKeyLen, key);
}
else {
ret = wc_ed25519_import_private_key(privKey, privKeyLen,
pubKey, pubKeyLen, key);
ret = wc_ed25519_import_private_key_ex(privKey, privKeyLen,
pubKey, pubKeyLen, key, trusted);
}
}
return ret;
}

int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
ed25519_key* key, word32 inSz)
{
return wc_Ed25519PrivateKeyDecode_ex(input, inOutIdx, key, inSz, 0);
}

int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx,
ed25519_key* key, word32 inSz)
{
Expand Down Expand Up @@ -34114,8 +34120,8 @@ int wc_Curve25519KeyToDer(curve25519_key* key, byte* output, word32 outLen,
#endif /* HAVE_CURVE25519 && HAVE_CURVE25519_KEY_EXPORT */

#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)
int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx,
ed448_key* key, word32 inSz)
int wc_Ed448PrivateKeyDecode_ex(const byte* input, word32* inOutIdx,
ed448_key* key, word32 inSz, int trusted)
{
int ret;
byte privKey[ED448_KEY_SIZE], pubKey[ED448_PUB_KEY_SIZE];
Expand All @@ -34133,13 +34139,19 @@ int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx,
ret = wc_ed448_import_private_only(privKey, privKeyLen, key);
}
else {
ret = wc_ed448_import_private_key(privKey, privKeyLen,
pubKey, pubKeyLen, key);
ret = wc_ed448_import_private_key_ex(privKey, privKeyLen,
pubKey, pubKeyLen, key, trusted);
}
}
return ret;
}

int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx,
ed448_key* key, word32 inSz)
{
return wc_Ed448PrivateKeyDecode_ex(input, inOutIdx, key, inSz, 0);
}

int wc_Ed448PublicKeyDecode(const byte* input, word32* inOutIdx,
ed448_key* key, word32 inSz)
{
Expand Down
6 changes: 6 additions & 0 deletions wolfssl/wolfcrypt/asn_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,9 @@ WOLFSSL_API int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz);
#ifdef HAVE_ED25519_KEY_IMPORT
WOLFSSL_API int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
ed25519_key* key, word32 inSz);
WOLFSSL_API int wc_Ed25519PrivateKeyDecode_ex(const byte* input,
word32* inOutIdx, ed25519_key* key, word32 inSz,
int trusted);
WOLFSSL_API int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx,
ed25519_key* key, word32 inSz);
#endif
Expand Down Expand Up @@ -886,6 +889,9 @@ WOLFSSL_API int wc_Curve25519KeyToDer(curve25519_key* key, byte* output,
#ifdef HAVE_ED448_KEY_IMPORT
WOLFSSL_API int wc_Ed448PrivateKeyDecode(
const byte* input, word32* inOutIdx, ed448_key* key, word32 inSz);
WOLFSSL_API int wc_Ed448PrivateKeyDecode_ex(
const byte* input, word32* inOutIdx, ed448_key* key, word32 inSz,
int trusted);
WOLFSSL_API int wc_Ed448PublicKeyDecode(
const byte* input, word32* inOutIdx, ed448_key* key, word32 inSz);
#endif
Expand Down
Loading