Skip to content

Commit eb8b92c

Browse files
committed
wolfssl: expose trusted argument in ed25519/ed448 der export
1 parent 9d86960 commit eb8b92c

7 files changed

Lines changed: 226 additions & 9 deletions

File tree

doc/dox_comments/header_files/asn_public.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2830,10 +2830,46 @@ int wc_Curve25519KeyToDer(curve25519_key* key, byte* output, word32 outLen,
28302830
\endcode
28312831
28322832
\sa wc_Ed25519PrivateKeyToDer
2833+
\sa wc_Ed25519PrivateKeyDecode_ex
28332834
*/
28342835
int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
28352836
ed25519_key* key, word32 inSz);
28362837

2838+
/*!
2839+
\ingroup Ed25519
2840+
\brief Decodes Ed25519 private key from DER format with control over
2841+
validation of a bundled public key. When the DER contains a public key
2842+
and trusted is 0, the public key is checked to match the private key.
2843+
When trusted is 1 this check is skipped. wc_Ed25519PrivateKeyDecode()
2844+
behaves as trusted set to 0.
2845+
2846+
\return 0 on success
2847+
\return negative on error
2848+
2849+
\param input DER encoded Ed25519 private key buffer
2850+
\param inOutIdx Pointer to index in buffer
2851+
\param key Ed25519 key structure to store key
2852+
\param inSz Size of input buffer
2853+
\param trusted Indicates whether the public key data is trusted.
2854+
When 0, checks public key matches private key.
2855+
When 1, doesn't check public key matches private key.
2856+
2857+
_Example_
2858+
\code
2859+
ed25519_key key;
2860+
word32 idx = 0;
2861+
// key material comes from this application's own storage
2862+
int ret = wc_Ed25519PrivateKeyDecode_ex(derBuf, &idx, &key,
2863+
derSz, 1);
2864+
\endcode
2865+
2866+
\sa wc_Ed25519PrivateKeyDecode
2867+
\sa wc_Ed25519PrivateKeyToDer
2868+
\sa wc_ed25519_import_private_key_ex
2869+
*/
2870+
int wc_Ed25519PrivateKeyDecode_ex(const byte* input, word32* inOutIdx,
2871+
ed25519_key* key, word32 inSz, int trusted);
2872+
28372873
/*!
28382874
\ingroup Ed25519
28392875
\brief Decodes Ed25519 public key from DER format.
@@ -2952,10 +2988,46 @@ int wc_Ed25519PublicKeyToDer(const ed25519_key* key, byte* output,
29522988
\endcode
29532989
29542990
\sa wc_Ed448PrivateKeyToDer
2991+
\sa wc_Ed448PrivateKeyDecode_ex
29552992
*/
29562993
int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx,
29572994
ed448_key* key, word32 inSz);
29582995

2996+
/*!
2997+
\ingroup Ed448
2998+
\brief Decodes Ed448 private key from DER format with control over
2999+
validation of a bundled public key. When the DER contains a public key
3000+
and trusted is 0, the public key is checked to match the private key.
3001+
When trusted is 1 this check is skipped. wc_Ed448PrivateKeyDecode()
3002+
behaves as trusted set to 0.
3003+
3004+
\return 0 on success
3005+
\return negative on error
3006+
3007+
\param input DER encoded Ed448 private key buffer
3008+
\param inOutIdx Pointer to index in buffer
3009+
\param key Ed448 key structure to store key
3010+
\param inSz Size of input buffer
3011+
\param trusted Indicates whether the public key data is trusted.
3012+
When 0, checks public key matches private key.
3013+
When 1, doesn't check public key matches private key.
3014+
3015+
_Example_
3016+
\code
3017+
ed448_key key;
3018+
word32 idx = 0;
3019+
// key material comes from this application's own storage
3020+
int ret = wc_Ed448PrivateKeyDecode_ex(derBuf, &idx, &key,
3021+
derSz, 1);
3022+
\endcode
3023+
3024+
\sa wc_Ed448PrivateKeyDecode
3025+
\sa wc_Ed448PrivateKeyToDer
3026+
\sa wc_ed448_import_private_key_ex
3027+
*/
3028+
int wc_Ed448PrivateKeyDecode_ex(const byte* input, word32* inOutIdx,
3029+
ed448_key* key, word32 inSz, int trusted);
3030+
29593031
/*!
29603032
\ingroup Ed448
29613033
\brief Decodes Ed448 public key from DER format.

tests/api/test_ed25519.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,68 @@ int test_wc_Ed25519KeyToDer_oneasymkey_version(void)
731731
return EXPECT_RESULT();
732732
}
733733

734+
/* The trusted flag controls whether a public key bundled in the DER is
735+
* checked against the private key during decode. */
736+
int test_wc_Ed25519PrivateKeyDecode_ex(void)
737+
{
738+
EXPECT_DECLS;
739+
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) && \
740+
defined(HAVE_ED25519_KEY_IMPORT) && defined(HAVE_ED25519_MAKE_KEY)
741+
ed25519_key key;
742+
ed25519_key key2;
743+
WC_RNG rng;
744+
byte der[256];
745+
int derSz = 0;
746+
word32 idx;
747+
748+
XMEMSET(&key, 0, sizeof(key));
749+
XMEMSET(&key2, 0, sizeof(key2));
750+
XMEMSET(&rng, 0, sizeof(rng));
751+
752+
ExpectIntEQ(wc_InitRng(&rng), 0);
753+
ExpectIntEQ(wc_ed25519_init(&key), 0);
754+
ExpectIntEQ(wc_ed25519_init(&key2), 0);
755+
ExpectIntEQ(wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key), 0);
756+
757+
/* Bundled private+public DER; public key is the trailing
758+
* ED25519_PUB_KEY_SIZE bytes. */
759+
ExpectIntGT(derSz = wc_Ed25519KeyToDer(&key, der, (word32)sizeof(der)),
760+
0);
761+
762+
/* Intact DER decodes with either trust setting. */
763+
idx = 0;
764+
ExpectIntEQ(wc_Ed25519PrivateKeyDecode_ex(der, &idx, &key2,
765+
(word32)derSz, 0), 0);
766+
idx = 0;
767+
ExpectIntEQ(wc_Ed25519PrivateKeyDecode_ex(der, &idx, &key2,
768+
(word32)derSz, 1), 0);
769+
770+
/* Corrupt the bundled public key. */
771+
if (derSz > 0) {
772+
der[derSz - 1] ^= 0x01;
773+
}
774+
775+
/* Untrusted decode checks the public key and must reject it, as must
776+
* the non-ex decode. */
777+
idx = 0;
778+
ExpectIntEQ(wc_Ed25519PrivateKeyDecode_ex(der, &idx, &key2,
779+
(word32)derSz, 0), WC_NO_ERR_TRACE(PUBLIC_KEY_E));
780+
idx = 0;
781+
ExpectIntEQ(wc_Ed25519PrivateKeyDecode(der, &idx, &key2, (word32)derSz),
782+
WC_NO_ERR_TRACE(PUBLIC_KEY_E));
783+
784+
/* Trusted decode skips the check. */
785+
idx = 0;
786+
ExpectIntEQ(wc_Ed25519PrivateKeyDecode_ex(der, &idx, &key2,
787+
(word32)derSz, 1), 0);
788+
789+
wc_ed25519_free(&key);
790+
wc_ed25519_free(&key2);
791+
wc_FreeRng(&rng);
792+
#endif
793+
return EXPECT_RESULT();
794+
}
795+
734796
/* Ed25519 identity and small-order public keys must be rejected. When
735797
* the public key is the identity point (or any small-order point), any
736798
* signature of the form (R = [S]B, S) verifies for arbitrary messages

tests/api/test_ed25519.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ int test_wc_Ed25519PublicKeyToDer(void);
3737
int test_wc_Ed25519KeyToDer(void);
3838
int test_wc_Ed25519PrivateKeyToDer(void);
3939
int test_wc_Ed25519KeyToDer_oneasymkey_version(void);
40+
int test_wc_Ed25519PrivateKeyDecode_ex(void);
4041
int test_wc_ed25519_reject_small_order_keys(void);
4142
int test_wc_ed25519_sign_verify_ctx_ph(void);
4243
int test_wc_ed25519_verify_streaming(void);
@@ -63,6 +64,7 @@ int test_wc_ed25519_make_public_argchecks(void);
6364
TEST_DECL_GROUP("ed25519", test_wc_ed25519_verify_streaming), \
6465
TEST_DECL_GROUP("ed25519", test_wc_ed25519_check_key_edgecases), \
6566
TEST_DECL_GROUP("ed25519", test_wc_ed25519_import_variants), \
66-
TEST_DECL_GROUP("ed25519", test_wc_ed25519_make_public_argchecks)
67+
TEST_DECL_GROUP("ed25519", test_wc_ed25519_make_public_argchecks), \
68+
TEST_DECL_GROUP("ed25519", test_wc_Ed25519PrivateKeyDecode_ex)
6769

6870
#endif /* WOLFCRYPT_TEST_ED25519_H */

tests/api/test_ed448.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,67 @@ int test_wc_Ed448KeyToDer_oneasymkey_version(void)
663663
return EXPECT_RESULT();
664664
}
665665

666+
/* The trusted flag controls whether a public key bundled in the DER is
667+
* checked against the private key during decode. */
668+
int test_wc_Ed448PrivateKeyDecode_ex(void)
669+
{
670+
EXPECT_DECLS;
671+
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) && \
672+
defined(HAVE_ED448_KEY_IMPORT)
673+
ed448_key key;
674+
ed448_key key2;
675+
WC_RNG rng;
676+
byte der[512];
677+
int derSz = 0;
678+
word32 idx;
679+
680+
XMEMSET(&key, 0, sizeof(key));
681+
XMEMSET(&key2, 0, sizeof(key2));
682+
XMEMSET(&rng, 0, sizeof(rng));
683+
684+
ExpectIntEQ(wc_InitRng(&rng), 0);
685+
ExpectIntEQ(wc_ed448_init(&key), 0);
686+
ExpectIntEQ(wc_ed448_init(&key2), 0);
687+
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key), 0);
688+
689+
/* Bundled private+public DER; public key is the trailing
690+
* ED448_PUB_KEY_SIZE bytes. */
691+
ExpectIntGT(derSz = wc_Ed448KeyToDer(&key, der, (word32)sizeof(der)), 0);
692+
693+
/* Intact DER decodes with either trust setting. */
694+
idx = 0;
695+
ExpectIntEQ(wc_Ed448PrivateKeyDecode_ex(der, &idx, &key2,
696+
(word32)derSz, 0), 0);
697+
idx = 0;
698+
ExpectIntEQ(wc_Ed448PrivateKeyDecode_ex(der, &idx, &key2,
699+
(word32)derSz, 1), 0);
700+
701+
/* Corrupt the bundled public key. */
702+
if (derSz > 0) {
703+
der[derSz - 1] ^= 0x01;
704+
}
705+
706+
/* Untrusted decode checks the public key and must reject it, as must
707+
* the non-ex decode. */
708+
idx = 0;
709+
ExpectIntEQ(wc_Ed448PrivateKeyDecode_ex(der, &idx, &key2,
710+
(word32)derSz, 0), WC_NO_ERR_TRACE(PUBLIC_KEY_E));
711+
idx = 0;
712+
ExpectIntEQ(wc_Ed448PrivateKeyDecode(der, &idx, &key2, (word32)derSz),
713+
WC_NO_ERR_TRACE(PUBLIC_KEY_E));
714+
715+
/* Trusted decode skips the check. */
716+
idx = 0;
717+
ExpectIntEQ(wc_Ed448PrivateKeyDecode_ex(der, &idx, &key2,
718+
(word32)derSz, 1), 0);
719+
720+
wc_ed448_free(&key);
721+
wc_ed448_free(&key2);
722+
wc_FreeRng(&rng);
723+
#endif
724+
return EXPECT_RESULT();
725+
}
726+
666727
/* Ed448 identity and small-order public keys must be rejected.
667728
* Edwards448 has cofactor 4, so the small-order subgroup contains the
668729
* identity, an order-2 point, and two order-4 points. With any of these

tests/api/test_ed448.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ int test_wc_Ed448PublicKeyToDer(void);
3737
int test_wc_Ed448KeyToDer(void);
3838
int test_wc_Ed448PrivateKeyToDer(void);
3939
int test_wc_Ed448KeyToDer_oneasymkey_version(void);
40+
int test_wc_Ed448PrivateKeyDecode_ex(void);
4041
int test_wc_ed448_reject_small_order_keys(void);
4142

4243
#define TEST_ED448_DECLS \
@@ -53,6 +54,7 @@ int test_wc_ed448_reject_small_order_keys(void);
5354
TEST_DECL_GROUP("ed448", test_wc_Ed448KeyToDer), \
5455
TEST_DECL_GROUP("ed448", test_wc_Ed448PrivateKeyToDer), \
5556
TEST_DECL_GROUP("ed448", test_wc_Ed448KeyToDer_oneasymkey_version), \
57+
TEST_DECL_GROUP("ed448", test_wc_Ed448PrivateKeyDecode_ex), \
5658
TEST_DECL_GROUP("ed448", test_wc_ed448_reject_small_order_keys)
5759

5860
#endif /* WOLFCRYPT_TEST_ED448_H */

wolfcrypt/src/asn.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33691,8 +33691,8 @@ int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz,
3369133691
#endif /* WC_ENABLE_ASYM_KEY_IMPORT */
3369233692

3369333693
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT)
33694-
int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
33695-
ed25519_key* key, word32 inSz)
33694+
int wc_Ed25519PrivateKeyDecode_ex(const byte* input, word32* inOutIdx,
33695+
ed25519_key* key, word32 inSz, int trusted)
3369633696
{
3369733697
int ret;
3369833698
byte privKey[ED25519_KEY_SIZE], pubKey[2*ED25519_PUB_KEY_SIZE+1];
@@ -33710,13 +33710,19 @@ int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
3371033710
ret = wc_ed25519_import_private_only(privKey, privKeyLen, key);
3371133711
}
3371233712
else {
33713-
ret = wc_ed25519_import_private_key(privKey, privKeyLen,
33714-
pubKey, pubKeyLen, key);
33713+
ret = wc_ed25519_import_private_key_ex(privKey, privKeyLen,
33714+
pubKey, pubKeyLen, key, trusted);
3371533715
}
3371633716
}
3371733717
return ret;
3371833718
}
3371933719

33720+
int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
33721+
ed25519_key* key, word32 inSz)
33722+
{
33723+
return wc_Ed25519PrivateKeyDecode_ex(input, inOutIdx, key, inSz, 0);
33724+
}
33725+
3372033726
int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx,
3372133727
ed25519_key* key, word32 inSz)
3372233728
{
@@ -34114,8 +34120,8 @@ int wc_Curve25519KeyToDer(curve25519_key* key, byte* output, word32 outLen,
3411434120
#endif /* HAVE_CURVE25519 && HAVE_CURVE25519_KEY_EXPORT */
3411534121

3411634122
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)
34117-
int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx,
34118-
ed448_key* key, word32 inSz)
34123+
int wc_Ed448PrivateKeyDecode_ex(const byte* input, word32* inOutIdx,
34124+
ed448_key* key, word32 inSz, int trusted)
3411934125
{
3412034126
int ret;
3412134127
byte privKey[ED448_KEY_SIZE], pubKey[ED448_PUB_KEY_SIZE];
@@ -34133,13 +34139,19 @@ int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx,
3413334139
ret = wc_ed448_import_private_only(privKey, privKeyLen, key);
3413434140
}
3413534141
else {
34136-
ret = wc_ed448_import_private_key(privKey, privKeyLen,
34137-
pubKey, pubKeyLen, key);
34142+
ret = wc_ed448_import_private_key_ex(privKey, privKeyLen,
34143+
pubKey, pubKeyLen, key, trusted);
3413834144
}
3413934145
}
3414034146
return ret;
3414134147
}
3414234148

34149+
int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx,
34150+
ed448_key* key, word32 inSz)
34151+
{
34152+
return wc_Ed448PrivateKeyDecode_ex(input, inOutIdx, key, inSz, 0);
34153+
}
34154+
3414334155
int wc_Ed448PublicKeyDecode(const byte* input, word32* inOutIdx,
3414434156
ed448_key* key, word32 inSz)
3414534157
{

wolfssl/wolfcrypt/asn_public.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,9 @@ WOLFSSL_API int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz);
850850
#ifdef HAVE_ED25519_KEY_IMPORT
851851
WOLFSSL_API int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
852852
ed25519_key* key, word32 inSz);
853+
WOLFSSL_API int wc_Ed25519PrivateKeyDecode_ex(const byte* input,
854+
word32* inOutIdx, ed25519_key* key, word32 inSz,
855+
int trusted);
853856
WOLFSSL_API int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx,
854857
ed25519_key* key, word32 inSz);
855858
#endif
@@ -886,6 +889,9 @@ WOLFSSL_API int wc_Curve25519KeyToDer(curve25519_key* key, byte* output,
886889
#ifdef HAVE_ED448_KEY_IMPORT
887890
WOLFSSL_API int wc_Ed448PrivateKeyDecode(
888891
const byte* input, word32* inOutIdx, ed448_key* key, word32 inSz);
892+
WOLFSSL_API int wc_Ed448PrivateKeyDecode_ex(
893+
const byte* input, word32* inOutIdx, ed448_key* key, word32 inSz,
894+
int trusted);
889895
WOLFSSL_API int wc_Ed448PublicKeyDecode(
890896
const byte* input, word32* inOutIdx, ed448_key* key, word32 inSz);
891897
#endif

0 commit comments

Comments
 (0)