diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index b7835f456..9d0db340e 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -84,9 +84,7 @@ static void bench_ecmult_teardown_helper(bench_data* data, size_t* seckey_offset } } secp256k1_ecmult_gen(&data->ctx->ecmult_gen_ctx, &tmp, &sum_scalars); - secp256k1_gej_neg(&tmp, &tmp); - secp256k1_gej_add_var(&tmp, &tmp, &sum_output, NULL); - CHECK(secp256k1_gej_is_infinity(&tmp)); + CHECK(secp256k1_gej_eq_var(&tmp, &sum_output)); } static void bench_ecmult_setup(void* arg) { diff --git a/src/group.h b/src/group.h index 585457d93..b79ba597d 100644 --- a/src/group.h +++ b/src/group.h @@ -97,6 +97,9 @@ static void secp256k1_gej_set_infinity(secp256k1_gej *r); /** Set a group element (jacobian) equal to another which is given in affine coordinates. */ static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a); +/** Check two group elements (jacobian) for equality in variable time. */ +static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b); + /** Compare the X coordinate of a group element (jacobian). */ static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a); diff --git a/src/group_impl.h b/src/group_impl.h index 63735ab68..dfe6e32c7 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -236,6 +236,13 @@ static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) { secp256k1_fe_set_int(&r->z, 1); } +static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) { + secp256k1_gej tmp; + secp256k1_gej_neg(&tmp, a); + secp256k1_gej_add_var(&tmp, &tmp, b, NULL); + return secp256k1_gej_is_infinity(&tmp); +} + static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { secp256k1_fe r, r2; VERIFY_CHECK(!a->infinity); diff --git a/src/tests.c b/src/tests.c index 9080a5f47..fd564a2ca 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3872,6 +3872,22 @@ void run_gej(void) { test_gej_cmov(&a, &b); test_gej_cmov(&b, &a); } + + /* Tests for secp256k1_gej_eq_var */ + for (i = 0; i < count; i++) { + secp256k1_fe fe; + random_gej_test(&a); + random_gej_test(&b); + CHECK(!secp256k1_gej_eq_var(&a, &b)); + + b = a; + random_field_element_test(&fe); + if (secp256k1_fe_is_zero(&fe)) { + continue; + } + secp256k1_gej_rescale(&a, &fe); + CHECK(secp256k1_gej_eq_var(&a, &b)); + } } void test_ec_combine(void) { @@ -4077,17 +4093,12 @@ void run_ecmult_chain(void) { 0xB95CBCA2, 0xC77DA786, 0x539BE8FD, 0x53354D2D, 0x3B4F566A, 0xE6580454, 0x07ED6015, 0xEE1B2A88 ); - - secp256k1_gej_neg(&rp, &rp); - secp256k1_gej_add_var(&rp, &rp, &x, NULL); - CHECK(secp256k1_gej_is_infinity(&rp)); + CHECK(secp256k1_gej_eq_var(&rp, &x)); } } /* redo the computation, but directly with the resulting ae and ge coefficients: */ secp256k1_ecmult(&x2, &a, &ae, &ge); - secp256k1_gej_neg(&x2, &x2); - secp256k1_gej_add_var(&x2, &x2, &x, NULL); - CHECK(secp256k1_gej_is_infinity(&x2)); + CHECK(secp256k1_gej_eq_var(&x, &x2)); } void test_point_times_order(const secp256k1_gej *point) { @@ -4380,16 +4391,12 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e /* only G scalar */ secp256k1_ecmult(&r2, &ptgj, &szero, &sc[0]); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0)); - secp256k1_gej_neg(&r2, &r2); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); + CHECK(secp256k1_gej_eq_var(&r, &r2)); /* 1-point */ secp256k1_ecmult(&r2, &ptgj, &sc[0], &szero); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 1)); - secp256k1_gej_neg(&r2, &r2); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); + CHECK(secp256k1_gej_eq_var(&r, &r2)); /* Try to multiply 1 point, but callback returns false */ CHECK(!ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1)); @@ -4397,16 +4404,12 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e /* 2-point */ secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 2)); - secp256k1_gej_neg(&r2, &r2); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); + CHECK(secp256k1_gej_eq_var(&r, &r2)); /* 2-point with G scalar */ secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1)); - secp256k1_gej_neg(&r2, &r2); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); + CHECK(secp256k1_gej_eq_var(&r, &r2)); } /* Check infinite outputs of various forms */ @@ -4491,9 +4494,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e secp256k1_ecmult(&r2, &r, &sc[0], &szero); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); - secp256k1_gej_neg(&r2, &r2); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); + CHECK(secp256k1_gej_eq_var(&r, &r2)); } /* Check random scalars, constant point */ @@ -4514,9 +4515,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e secp256k1_gej_set_ge(&p0j, &pt[0]); secp256k1_ecmult(&r2, &p0j, &rs, &szero); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); - secp256k1_gej_neg(&r2, &r2); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); + CHECK(secp256k1_gej_eq_var(&r, &r2)); } /* Sanity check that zero scalars don't cause problems */ @@ -4578,9 +4577,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e secp256k1_ecmult(&expected, &ptgj, &tmp1, &szero); CHECK(ecmult_multi(&ctx->error_callback, scratch, &actual, &szero, ecmult_multi_callback, &data, 2)); - secp256k1_gej_neg(&expected, &expected); - secp256k1_gej_add_var(&actual, &actual, &expected, NULL); - CHECK(secp256k1_gej_is_infinity(&actual)); + CHECK(secp256k1_gej_eq_var(&actual, &expected)); } } } @@ -4750,9 +4747,7 @@ int test_ecmult_multi_random(secp256k1_scratch *scratch) { CHECK(ecmult_multi(&ctx->error_callback, scratch, &computed, g_scalar_ptr, ecmult_multi_callback, &data, filled)); mults += num_nonzero + g_nonzero; /* Compare with expected result. */ - secp256k1_gej_neg(&computed, &computed); - secp256k1_gej_add_var(&computed, &computed, &expected, NULL); - CHECK(secp256k1_gej_is_infinity(&computed)); + CHECK(secp256k1_gej_eq_var(&computed, &expected)); return mults; }