Skip to content

Commit 08d7d89

Browse files
committed
Make pubkey parsing test whether points are in the correct subgroup
1 parent 87af00b commit 08d7d89

File tree

4 files changed

+38
-0
lines changed

4 files changed

+38
-0
lines changed

src/group.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,15 @@ static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_g
139139
/** Rescale a jacobian point by b which must be non-zero. Constant-time. */
140140
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b);
141141

142+
/** Determine if a point (which is assumed to be on the curve) is in the correct (sub)group of the curve.
143+
*
144+
* In normal mode, the used group is secp256k1, which has cofactor=1 meaning that every point on the curve is in the
145+
* group, and this function returns always true.
146+
*
147+
* When compiling in exhaustive test mode, a slightly different curve equation is used, leading to a group with a
148+
* (very) small subgroup, and that subgroup is what is used for all cryptographic operations. In that mode, this
149+
* function checks whether a point that is on the curve is in fact also in that subgroup.
150+
*/
151+
static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge);
152+
142153
#endif /* SECP256K1_GROUP_H */

src/group_impl.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,4 +671,25 @@ static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) {
671671
return secp256k1_fe_is_quad_var(&yz);
672672
}
673673

674+
static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
675+
#ifdef EXHAUSTIVE_TEST_ORDER
676+
secp256k1_gej out;
677+
int i;
678+
679+
/* A very simple EC multiplication ladder that avoids a dependecy on ecmult. */
680+
secp256k1_gej_set_infinity(&out);
681+
for (i = 0; i < 32; ++i) {
682+
secp256k1_gej_double_var(&out, &out, NULL);
683+
if ((((uint32_t)EXHAUSTIVE_TEST_ORDER) >> (31 - i)) & 1) {
684+
secp256k1_gej_add_ge_var(&out, &out, ge, NULL);
685+
}
686+
}
687+
return secp256k1_gej_is_infinity(&out);
688+
#else
689+
(void)ge;
690+
/* The real secp256k1 group has cofactor 1, so the subgroup is the entire curve. */
691+
return 1;
692+
#endif
693+
}
694+
674695
#endif /* SECP256K1_GROUP_IMPL_H */

src/modules/extrakeys/main_impl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ int secp256k1_xonly_pubkey_parse(const secp256k1_context* ctx, secp256k1_xonly_p
3333
if (!secp256k1_ge_set_xo_var(&pk, &x, 0)) {
3434
return 0;
3535
}
36+
if (!secp256k1_ge_is_in_correct_subgroup(&pk)) {
37+
return 0;
38+
}
3639
secp256k1_xonly_pubkey_save(pubkey, &pk);
3740
return 1;
3841
}

src/secp256k1.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@ int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pu
284284
if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) {
285285
return 0;
286286
}
287+
if (!secp256k1_ge_is_in_correct_subgroup(&Q)) {
288+
return 0;
289+
}
287290
secp256k1_pubkey_save(pubkey, &Q);
288291
secp256k1_ge_clear(&Q);
289292
return 1;

0 commit comments

Comments
 (0)