Skip to content

Commit f9703b2

Browse files
Enable all-zero shared secret check for curve448/25519 by default. Change macro to opt-out macro WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK. Add unit test.
Thanks to Xiangdong Li for the report.
1 parent 7a56e62 commit f9703b2

7 files changed

Lines changed: 100 additions & 8 deletions

File tree

.wolfssl_known_macro_extras

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,6 @@ WOLFSSL_ECC_BLIND_K
756756
WOLFSSL_ECC_GEN_REJECT_SAMPLING
757757
WOLFSSL_ECC_NO_SMALL_STACK
758758
WOLFSSL_ECC_SIGALG_PARAMS_NULL_ALLOWED
759-
WOLFSSL_ECDHX_SHARED_NOT_ZERO
760759
WOLFSSL_ECDSA_MATCH_HASH
761760
WOLFSSL_ECDSA_SET_K_ONE_LOOP
762761
WOLFSSL_EC_POINT_CMP_JACOBIAN
@@ -833,6 +832,7 @@ WOLFSSL_NO_DECODE_EXTRA
833832
WOLFSSL_NO_DER_TO_PEM
834833
WOLFSSL_NO_DH186
835834
WOLFSSL_NO_DTLS_SIZE_CHECK
835+
WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
836836
WOLFSSL_NO_ETM_ALERT
837837
WOLFSSL_NO_FENCE
838838
WOLFSSL_NO_ISSUERHASH_TDPEER

tests/api/test_curve25519.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,51 @@ int test_wc_curve25519_shared_secret_ex(void)
353353
return EXPECT_RESULT();
354354
} /* END test_wc_curve25519_shared_secret_ex */
355355

356+
/*
357+
* Testing that wc_curve25519_shared_secret_ex rejects an all-zero shared
358+
* secret (RFC 7748 section 6.1). This is the default behavior; users that
359+
* need the legacy behavior can opt out with WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK.
360+
*/
361+
int test_wc_curve25519_shared_secret_zero_check(void)
362+
{
363+
EXPECT_DECLS;
364+
#if defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT) && \
365+
!defined(WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK)
366+
curve25519_key private_key;
367+
curve25519_key public_key;
368+
WC_RNG rng;
369+
byte out[CURVE25519_KEYSIZE];
370+
word32 outLen = sizeof(out);
371+
/* All-zero public key is a low-order point that yields an all-zero
372+
* shared secret for any private key. */
373+
byte zero_pub[CURVE25519_KEYSIZE];
374+
375+
XMEMSET(&rng, 0, sizeof(WC_RNG));
376+
XMEMSET(zero_pub, 0, sizeof(zero_pub));
377+
378+
ExpectIntEQ(wc_curve25519_init(&private_key), 0);
379+
ExpectIntEQ(wc_curve25519_init(&public_key), 0);
380+
ExpectIntEQ(wc_InitRng(&rng), 0);
381+
#ifdef WOLFSSL_CURVE25519_BLINDING
382+
ExpectIntEQ(wc_curve25519_set_rng(&private_key, &rng), 0);
383+
#endif
384+
385+
ExpectIntEQ(wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, &private_key),
386+
0);
387+
ExpectIntEQ(wc_curve25519_import_public_ex(zero_pub, sizeof(zero_pub),
388+
&public_key, EC25519_LITTLE_ENDIAN), 0);
389+
390+
ExpectIntEQ(wc_curve25519_shared_secret_ex(&private_key, &public_key, out,
391+
&outLen, EC25519_BIG_ENDIAN),
392+
WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E));
393+
394+
DoExpectIntEQ(wc_FreeRng(&rng), 0);
395+
wc_curve25519_free(&private_key);
396+
wc_curve25519_free(&public_key);
397+
#endif
398+
return EXPECT_RESULT();
399+
} /* END test_wc_curve25519_shared_secret_zero_check */
400+
356401
/*
357402
* Testing wc_curve25519_make_pub
358403
*/

tests/api/test_curve25519.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ int test_wc_curve25519_export_key_raw(void);
3030
int test_wc_curve25519_export_key_raw_ex(void);
3131
int test_wc_curve25519_make_key(void);
3232
int test_wc_curve25519_shared_secret_ex(void);
33+
int test_wc_curve25519_shared_secret_zero_check(void);
3334
int test_wc_curve25519_make_pub(void);
3435
int test_wc_curve25519_export_public_ex(void);
3536
int test_wc_curve25519_export_private_raw_ex(void);
@@ -43,6 +44,7 @@ int test_wc_curve25519_import_private(void);
4344
TEST_DECL_GROUP("curve25519", test_wc_curve25519_export_key_raw_ex), \
4445
TEST_DECL_GROUP("curve25519", test_wc_curve25519_make_key), \
4546
TEST_DECL_GROUP("curve25519", test_wc_curve25519_shared_secret_ex), \
47+
TEST_DECL_GROUP("curve25519", test_wc_curve25519_shared_secret_zero_check),\
4648
TEST_DECL_GROUP("curve25519", test_wc_curve25519_make_pub), \
4749
TEST_DECL_GROUP("curve25519", test_wc_curve25519_export_public_ex), \
4850
TEST_DECL_GROUP("curve25519", test_wc_curve25519_export_private_raw_ex), \

tests/api/test_curve448.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,48 @@ int test_wc_curve448_shared_secret_ex(void)
116116
return EXPECT_RESULT();
117117
} /* END test_wc_curve448_shared_secret_ex */
118118

119+
/*
120+
* Testing that wc_curve448_shared_secret_ex rejects an all-zero shared
121+
* secret (RFC 7748 section 6.2). This is the default behavior; users that
122+
* need the legacy behavior can opt out with WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK.
123+
*/
124+
int test_wc_curve448_shared_secret_zero_check(void)
125+
{
126+
EXPECT_DECLS;
127+
#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT) && \
128+
defined(HAVE_CURVE448_SHARED_SECRET) && \
129+
!defined(WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK)
130+
curve448_key private_key;
131+
curve448_key public_key;
132+
WC_RNG rng;
133+
byte out[CURVE448_KEY_SIZE];
134+
word32 outLen = sizeof(out);
135+
/* All-zero public key is a low-order point that yields an all-zero
136+
* shared secret for any private key. */
137+
byte zero_pub[CURVE448_PUB_KEY_SIZE];
138+
139+
XMEMSET(&rng, 0, sizeof(WC_RNG));
140+
XMEMSET(zero_pub, 0, sizeof(zero_pub));
141+
142+
ExpectIntEQ(wc_curve448_init(&private_key), 0);
143+
ExpectIntEQ(wc_curve448_init(&public_key), 0);
144+
ExpectIntEQ(wc_InitRng(&rng), 0);
145+
146+
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &private_key), 0);
147+
ExpectIntEQ(wc_curve448_import_public_ex(zero_pub, sizeof(zero_pub),
148+
&public_key, EC448_LITTLE_ENDIAN), 0);
149+
150+
ExpectIntEQ(wc_curve448_shared_secret_ex(&private_key, &public_key, out,
151+
&outLen, EC448_BIG_ENDIAN),
152+
WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E));
153+
154+
DoExpectIntEQ(wc_FreeRng(&rng), 0);
155+
wc_curve448_free(&private_key);
156+
wc_curve448_free(&public_key);
157+
#endif
158+
return EXPECT_RESULT();
159+
} /* END test_wc_curve448_shared_secret_zero_check */
160+
119161
/*
120162
* Testing test_wc_curve448_export_public_ex
121163
*/

tests/api/test_curve448.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
int test_wc_curve448_make_key(void);
2828
int test_wc_curve448_shared_secret_ex(void);
29+
int test_wc_curve448_shared_secret_zero_check(void);
2930
int test_wc_curve448_export_public_ex(void);
3031
int test_wc_curve448_export_private_raw_ex(void);
3132
int test_wc_curve448_export_key_raw(void);
@@ -38,6 +39,7 @@ int test_wc_Curve448PrivateKeyToDer(void);
3839
#define TEST_CURVE448_DECLS \
3940
TEST_DECL_GROUP("curve448", test_wc_curve448_make_key), \
4041
TEST_DECL_GROUP("curve448", test_wc_curve448_shared_secret_ex), \
42+
TEST_DECL_GROUP("curve448", test_wc_curve448_shared_secret_zero_check), \
4143
TEST_DECL_GROUP("curve448", test_wc_curve448_export_public_ex), \
4244
TEST_DECL_GROUP("curve448", test_wc_curve448_export_private_raw_ex), \
4345
TEST_DECL_GROUP("curve448", test_wc_curve448_export_key_raw), \

wolfcrypt/src/curve25519.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ static int wc_curve25519_shared_secret_nb(curve25519_key* privKey,
627627
}
628628
break;
629629
case 2:
630-
#ifdef WOLFSSL_ECDHX_SHARED_NOT_ZERO
630+
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
631631
{
632632
int i;
633633
byte t = 0;
@@ -639,13 +639,13 @@ static int wc_curve25519_shared_secret_nb(curve25519_key* privKey,
639639
ret = ECC_OUT_OF_RANGE_E;
640640
}
641641
else
642-
#endif /* WOLFSSL_ECDHX_SHARED_NOT_ZERO */
642+
#endif /* !WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK */
643643
{
644644
curve25519_copy_point(out, privKey->nb_ctx->o.point, endian);
645645
*outlen = CURVE25519_KEYSIZE;
646646
ret = 0;
647647
}
648-
#ifdef WOLFSSL_ECDHX_SHARED_NOT_ZERO
648+
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
649649
}
650650
#endif
651651
break;
@@ -751,7 +751,7 @@ int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
751751
#endif
752752
}
753753
#endif /* FREESCALE_LTC_ECC */
754-
#ifdef WOLFSSL_ECDHX_SHARED_NOT_ZERO
754+
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
755755
if (ret == 0) {
756756
int i;
757757
byte t = 0;
@@ -762,7 +762,7 @@ int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
762762
ret = ECC_OUT_OF_RANGE_E;
763763
}
764764
}
765-
#endif /* WOLFSSL_ECDHX_SHARED_NOT_ZERO */
765+
#endif /* !WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK */
766766
if (ret == 0) {
767767
curve25519_copy_point(out, o.point, endian);
768768
*outlen = CURVE25519_KEYSIZE;

wolfcrypt/src/curve448.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
* (when HAVE_CURVE448 is enabled)
3434
* HAVE_CURVE448_KEY_EXPORT: Enable Curve448 key export default: on
3535
* HAVE_CURVE448_KEY_IMPORT: Enable Curve448 key import default: on
36-
* WOLFSSL_ECDHX_SHARED_NOT_ZERO: Check ECDH shared secret != 0 default: off
36+
* WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK: Skip ECDH shared secret != 0 check
37+
* default: off
3738
*/
3839

3940
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
@@ -176,7 +177,7 @@ int wc_curve448_shared_secret_ex(curve448_key* private_key,
176177
if (ret == 0) {
177178
ret = curve448(o, private_key->k, public_key->p);
178179
}
179-
#ifdef WOLFSSL_ECDHX_SHARED_NOT_ZERO
180+
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
180181
if (ret == 0) {
181182
byte t = 0;
182183
for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) {

0 commit comments

Comments
 (0)