da0092bc 10f9bd84 297ce820 f34b5cae 920a0e5f 9526874d aa1b889b 20d791ed 3e7b2ea1 21c188b3 8fa41201 515a5dbd c74a7b7e 74c34e72 7006f1b9 ea5e8a9c 793ad901 2e5e4b67 fecf436d 49f608de 49002274 6ad908aa 4f01840b 61ae37c6 486205aa 5d0dbef0 0559fc6e be6944ad a69df3ad b39d431a 0b83b203 09971a3f 9281c9f4 423b6d19 a310e79e 39a36db9 a1102b12 Deal with - secp256k1_test_rng removal in commit 77a19750b46916b93bb6a08837c26f585bd940fa - ecmult_gen context simplification after making table static in commit 3b0c2185eab0fe5cb910fffee4c88e134f6d3cad
707 lines
27 KiB
C
707 lines
27 KiB
C
/***********************************************************************
|
|
* Copyright (c) 2013, 2014 Pieter Wuille *
|
|
* Distributed under the MIT software license, see the accompanying *
|
|
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
|
***********************************************************************/
|
|
|
|
#ifndef SECP256K1_GROUP_IMPL_H
|
|
#define SECP256K1_GROUP_IMPL_H
|
|
|
|
#include "field.h"
|
|
#include "group.h"
|
|
|
|
#define SECP256K1_G_ORDER_13 SECP256K1_GE_CONST(\
|
|
0xc3459c3d, 0x35326167, 0xcd86cce8, 0x07a2417f,\
|
|
0x5b8bd567, 0xde8538ee, 0x0d507b0c, 0xd128f5bb,\
|
|
0x8e467fec, 0xcd30000a, 0x6cc1184e, 0x25d382c2,\
|
|
0xa2f4494e, 0x2fbe9abc, 0x8b64abac, 0xd005fb24\
|
|
)
|
|
#define SECP256K1_G_ORDER_199 SECP256K1_GE_CONST(\
|
|
0x226e653f, 0xc8df7744, 0x9bacbf12, 0x7d1dcbf9,\
|
|
0x87f05b2a, 0xe7edbd28, 0x1f564575, 0xc48dcf18,\
|
|
0xa13872c2, 0xe933bb17, 0x5d9ffd5b, 0xb5b6e10c,\
|
|
0x57fe3c00, 0xbaaaa15a, 0xe003ec3e, 0x9c269bae\
|
|
)
|
|
/** Generator for secp256k1, value 'g' defined in
|
|
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
|
|
*/
|
|
#define SECP256K1_G SECP256K1_GE_CONST(\
|
|
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL,\
|
|
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL,\
|
|
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL,\
|
|
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL\
|
|
)
|
|
/* These exhaustive group test orders and generators are chosen such that:
|
|
* - The field size is equal to that of secp256k1, so field code is the same.
|
|
* - The curve equation is of the form y^2=x^3+B for some constant B.
|
|
* - The subgroup has a generator 2*P, where P.x=1.
|
|
* - The subgroup has size less than 1000 to permit exhaustive testing.
|
|
* - The subgroup admits an endomorphism of the form lambda*(x,y) == (beta*x,y).
|
|
*
|
|
* These parameters are generated using sage/gen_exhaustive_groups.sage.
|
|
*/
|
|
#if defined(EXHAUSTIVE_TEST_ORDER)
|
|
# if EXHAUSTIVE_TEST_ORDER == 13
|
|
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_13;
|
|
|
|
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
|
|
0x3d3486b2, 0x159a9ca5, 0xc75638be, 0xb23a69bc,
|
|
0x946a45ab, 0x24801247, 0xb4ed2b8e, 0x26b6a417
|
|
);
|
|
# elif EXHAUSTIVE_TEST_ORDER == 199
|
|
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_199;
|
|
|
|
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
|
|
0x2cca28fa, 0xfc614b80, 0x2a3db42b, 0x00ba00b1,
|
|
0xbea8d943, 0xdace9ab2, 0x9536daea, 0x0074defb
|
|
);
|
|
# else
|
|
# error No known generator for the specified exhaustive test group order.
|
|
# endif
|
|
#else
|
|
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G;
|
|
|
|
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 7);
|
|
#endif
|
|
|
|
static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) {
|
|
secp256k1_fe zi2;
|
|
secp256k1_fe zi3;
|
|
VERIFY_CHECK(!a->infinity);
|
|
secp256k1_fe_sqr(&zi2, zi);
|
|
secp256k1_fe_mul(&zi3, &zi2, zi);
|
|
secp256k1_fe_mul(&r->x, &a->x, &zi2);
|
|
secp256k1_fe_mul(&r->y, &a->y, &zi3);
|
|
r->infinity = a->infinity;
|
|
}
|
|
|
|
static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) {
|
|
r->infinity = 0;
|
|
r->x = *x;
|
|
r->y = *y;
|
|
}
|
|
|
|
static int secp256k1_ge_is_infinity(const secp256k1_ge *a) {
|
|
return a->infinity;
|
|
}
|
|
|
|
static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) {
|
|
*r = *a;
|
|
secp256k1_fe_normalize_weak(&r->y);
|
|
secp256k1_fe_negate(&r->y, &r->y, 1);
|
|
}
|
|
|
|
static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) {
|
|
secp256k1_fe z2, z3;
|
|
r->infinity = a->infinity;
|
|
secp256k1_fe_inv(&a->z, &a->z);
|
|
secp256k1_fe_sqr(&z2, &a->z);
|
|
secp256k1_fe_mul(&z3, &a->z, &z2);
|
|
secp256k1_fe_mul(&a->x, &a->x, &z2);
|
|
secp256k1_fe_mul(&a->y, &a->y, &z3);
|
|
secp256k1_fe_set_int(&a->z, 1);
|
|
r->x = a->x;
|
|
r->y = a->y;
|
|
}
|
|
|
|
static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) {
|
|
secp256k1_fe z2, z3;
|
|
if (a->infinity) {
|
|
secp256k1_ge_set_infinity(r);
|
|
return;
|
|
}
|
|
secp256k1_fe_inv_var(&a->z, &a->z);
|
|
secp256k1_fe_sqr(&z2, &a->z);
|
|
secp256k1_fe_mul(&z3, &a->z, &z2);
|
|
secp256k1_fe_mul(&a->x, &a->x, &z2);
|
|
secp256k1_fe_mul(&a->y, &a->y, &z3);
|
|
secp256k1_fe_set_int(&a->z, 1);
|
|
secp256k1_ge_set_xy(r, &a->x, &a->y);
|
|
}
|
|
|
|
static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) {
|
|
secp256k1_fe u;
|
|
size_t i;
|
|
size_t last_i = SIZE_MAX;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (a[i].infinity) {
|
|
secp256k1_ge_set_infinity(&r[i]);
|
|
} else {
|
|
/* Use destination's x coordinates as scratch space */
|
|
if (last_i == SIZE_MAX) {
|
|
r[i].x = a[i].z;
|
|
} else {
|
|
secp256k1_fe_mul(&r[i].x, &r[last_i].x, &a[i].z);
|
|
}
|
|
last_i = i;
|
|
}
|
|
}
|
|
if (last_i == SIZE_MAX) {
|
|
return;
|
|
}
|
|
secp256k1_fe_inv_var(&u, &r[last_i].x);
|
|
|
|
i = last_i;
|
|
while (i > 0) {
|
|
i--;
|
|
if (!a[i].infinity) {
|
|
secp256k1_fe_mul(&r[last_i].x, &r[i].x, &u);
|
|
secp256k1_fe_mul(&u, &u, &a[last_i].z);
|
|
last_i = i;
|
|
}
|
|
}
|
|
VERIFY_CHECK(!a[last_i].infinity);
|
|
r[last_i].x = u;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (!a[i].infinity) {
|
|
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr) {
|
|
size_t i = len - 1;
|
|
secp256k1_fe zs;
|
|
|
|
if (len > 0) {
|
|
/* The z of the final point gives us the "global Z" for the table. */
|
|
r[i].x = a[i].x;
|
|
r[i].y = a[i].y;
|
|
/* Ensure all y values are in weak normal form for fast negation of points */
|
|
secp256k1_fe_normalize_weak(&r[i].y);
|
|
*globalz = a[i].z;
|
|
r[i].infinity = 0;
|
|
zs = zr[i];
|
|
|
|
/* Work our way backwards, using the z-ratios to scale the x/y values. */
|
|
while (i > 0) {
|
|
if (i != len - 1) {
|
|
secp256k1_fe_mul(&zs, &zs, &zr[i]);
|
|
}
|
|
i--;
|
|
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zs);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void secp256k1_gej_set_infinity(secp256k1_gej *r) {
|
|
r->infinity = 1;
|
|
secp256k1_fe_clear(&r->x);
|
|
secp256k1_fe_clear(&r->y);
|
|
secp256k1_fe_clear(&r->z);
|
|
}
|
|
|
|
static void secp256k1_ge_set_infinity(secp256k1_ge *r) {
|
|
r->infinity = 1;
|
|
secp256k1_fe_clear(&r->x);
|
|
secp256k1_fe_clear(&r->y);
|
|
}
|
|
|
|
static void secp256k1_gej_clear(secp256k1_gej *r) {
|
|
r->infinity = 0;
|
|
secp256k1_fe_clear(&r->x);
|
|
secp256k1_fe_clear(&r->y);
|
|
secp256k1_fe_clear(&r->z);
|
|
}
|
|
|
|
static void secp256k1_ge_clear(secp256k1_ge *r) {
|
|
r->infinity = 0;
|
|
secp256k1_fe_clear(&r->x);
|
|
secp256k1_fe_clear(&r->y);
|
|
}
|
|
|
|
static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) {
|
|
secp256k1_fe x2, x3;
|
|
r->x = *x;
|
|
secp256k1_fe_sqr(&x2, x);
|
|
secp256k1_fe_mul(&x3, x, &x2);
|
|
r->infinity = 0;
|
|
secp256k1_fe_add(&x3, &secp256k1_fe_const_b);
|
|
return secp256k1_fe_sqrt(&r->y, &x3);
|
|
}
|
|
|
|
static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) {
|
|
if (!secp256k1_ge_set_xquad(r, x)) {
|
|
return 0;
|
|
}
|
|
secp256k1_fe_normalize_var(&r->y);
|
|
if (secp256k1_fe_is_odd(&r->y) != odd) {
|
|
secp256k1_fe_negate(&r->y, &r->y, 1);
|
|
}
|
|
return 1;
|
|
|
|
}
|
|
|
|
static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) {
|
|
r->infinity = a->infinity;
|
|
r->x = a->x;
|
|
r->y = a->y;
|
|
secp256k1_fe_set_int(&r->z, 1);
|
|
}
|
|
|
|
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
|
|
secp256k1_fe r, r2;
|
|
VERIFY_CHECK(!a->infinity);
|
|
secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
|
|
r2 = a->x; secp256k1_fe_normalize_weak(&r2);
|
|
return secp256k1_fe_equal_var(&r, &r2);
|
|
}
|
|
|
|
static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) {
|
|
r->infinity = a->infinity;
|
|
r->x = a->x;
|
|
r->y = a->y;
|
|
r->z = a->z;
|
|
secp256k1_fe_normalize_weak(&r->y);
|
|
secp256k1_fe_negate(&r->y, &r->y, 1);
|
|
}
|
|
|
|
static int secp256k1_gej_is_infinity(const secp256k1_gej *a) {
|
|
return a->infinity;
|
|
}
|
|
|
|
static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
|
|
secp256k1_fe y2, x3;
|
|
if (a->infinity) {
|
|
return 0;
|
|
}
|
|
/* y^2 = x^3 + 7 */
|
|
secp256k1_fe_sqr(&y2, &a->y);
|
|
secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
|
|
secp256k1_fe_add(&x3, &secp256k1_fe_const_b);
|
|
secp256k1_fe_normalize_weak(&x3);
|
|
return secp256k1_fe_equal_var(&y2, &x3);
|
|
}
|
|
|
|
static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp256k1_gej *a) {
|
|
/* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate.
|
|
*
|
|
* Note that there is an implementation described at
|
|
* https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
|
* which trades a multiply for a square, but in practice this is actually slower,
|
|
* mainly because it requires more normalizations.
|
|
*/
|
|
secp256k1_fe t1,t2,t3,t4;
|
|
|
|
r->infinity = a->infinity;
|
|
|
|
secp256k1_fe_mul(&r->z, &a->z, &a->y);
|
|
secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */
|
|
secp256k1_fe_sqr(&t1, &a->x);
|
|
secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */
|
|
secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */
|
|
secp256k1_fe_sqr(&t3, &a->y);
|
|
secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */
|
|
secp256k1_fe_sqr(&t4, &t3);
|
|
secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */
|
|
secp256k1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */
|
|
r->x = t3;
|
|
secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */
|
|
secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */
|
|
secp256k1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */
|
|
secp256k1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */
|
|
secp256k1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */
|
|
secp256k1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */
|
|
secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */
|
|
secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */
|
|
secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */
|
|
}
|
|
|
|
static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) {
|
|
/** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity,
|
|
* Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have
|
|
* y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p.
|
|
*
|
|
* Having said this, if this function receives a point on a sextic twist, e.g. by
|
|
* a fault attack, it is possible for y to be 0. This happens for y^2 = x^3 + 6,
|
|
* since -6 does have a cube root mod p. For this point, this function will not set
|
|
* the infinity flag even though the point doubles to infinity, and the result
|
|
* point will be gibberish (z = 0 but infinity = 0).
|
|
*/
|
|
if (a->infinity) {
|
|
secp256k1_gej_set_infinity(r);
|
|
if (rzr != NULL) {
|
|
secp256k1_fe_set_int(rzr, 1);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (rzr != NULL) {
|
|
*rzr = a->y;
|
|
secp256k1_fe_normalize_weak(rzr);
|
|
secp256k1_fe_mul_int(rzr, 2);
|
|
}
|
|
|
|
secp256k1_gej_double(r, a);
|
|
}
|
|
|
|
static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) {
|
|
/* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */
|
|
secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t;
|
|
|
|
if (a->infinity) {
|
|
VERIFY_CHECK(rzr == NULL);
|
|
*r = *b;
|
|
return;
|
|
}
|
|
|
|
if (b->infinity) {
|
|
if (rzr != NULL) {
|
|
secp256k1_fe_set_int(rzr, 1);
|
|
}
|
|
*r = *a;
|
|
return;
|
|
}
|
|
|
|
r->infinity = 0;
|
|
secp256k1_fe_sqr(&z22, &b->z);
|
|
secp256k1_fe_sqr(&z12, &a->z);
|
|
secp256k1_fe_mul(&u1, &a->x, &z22);
|
|
secp256k1_fe_mul(&u2, &b->x, &z12);
|
|
secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z);
|
|
secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
|
|
secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
|
|
secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
|
|
if (secp256k1_fe_normalizes_to_zero_var(&h)) {
|
|
if (secp256k1_fe_normalizes_to_zero_var(&i)) {
|
|
secp256k1_gej_double_var(r, a, rzr);
|
|
} else {
|
|
if (rzr != NULL) {
|
|
secp256k1_fe_set_int(rzr, 0);
|
|
}
|
|
secp256k1_gej_set_infinity(r);
|
|
}
|
|
return;
|
|
}
|
|
secp256k1_fe_sqr(&i2, &i);
|
|
secp256k1_fe_sqr(&h2, &h);
|
|
secp256k1_fe_mul(&h3, &h, &h2);
|
|
secp256k1_fe_mul(&h, &h, &b->z);
|
|
if (rzr != NULL) {
|
|
*rzr = h;
|
|
}
|
|
secp256k1_fe_mul(&r->z, &a->z, &h);
|
|
secp256k1_fe_mul(&t, &u1, &h2);
|
|
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2);
|
|
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i);
|
|
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1);
|
|
secp256k1_fe_add(&r->y, &h3);
|
|
}
|
|
|
|
static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) {
|
|
/* 8 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */
|
|
secp256k1_fe z12, u1, u2, s1, s2, h, i, i2, h2, h3, t;
|
|
if (a->infinity) {
|
|
VERIFY_CHECK(rzr == NULL);
|
|
secp256k1_gej_set_ge(r, b);
|
|
return;
|
|
}
|
|
if (b->infinity) {
|
|
if (rzr != NULL) {
|
|
secp256k1_fe_set_int(rzr, 1);
|
|
}
|
|
*r = *a;
|
|
return;
|
|
}
|
|
r->infinity = 0;
|
|
|
|
secp256k1_fe_sqr(&z12, &a->z);
|
|
u1 = a->x; secp256k1_fe_normalize_weak(&u1);
|
|
secp256k1_fe_mul(&u2, &b->x, &z12);
|
|
s1 = a->y; secp256k1_fe_normalize_weak(&s1);
|
|
secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
|
|
secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
|
|
secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
|
|
if (secp256k1_fe_normalizes_to_zero_var(&h)) {
|
|
if (secp256k1_fe_normalizes_to_zero_var(&i)) {
|
|
secp256k1_gej_double_var(r, a, rzr);
|
|
} else {
|
|
if (rzr != NULL) {
|
|
secp256k1_fe_set_int(rzr, 0);
|
|
}
|
|
secp256k1_gej_set_infinity(r);
|
|
}
|
|
return;
|
|
}
|
|
secp256k1_fe_sqr(&i2, &i);
|
|
secp256k1_fe_sqr(&h2, &h);
|
|
secp256k1_fe_mul(&h3, &h, &h2);
|
|
if (rzr != NULL) {
|
|
*rzr = h;
|
|
}
|
|
secp256k1_fe_mul(&r->z, &a->z, &h);
|
|
secp256k1_fe_mul(&t, &u1, &h2);
|
|
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2);
|
|
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i);
|
|
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1);
|
|
secp256k1_fe_add(&r->y, &h3);
|
|
}
|
|
|
|
static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) {
|
|
/* 9 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */
|
|
secp256k1_fe az, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t;
|
|
|
|
if (b->infinity) {
|
|
*r = *a;
|
|
return;
|
|
}
|
|
if (a->infinity) {
|
|
secp256k1_fe bzinv2, bzinv3;
|
|
r->infinity = b->infinity;
|
|
secp256k1_fe_sqr(&bzinv2, bzinv);
|
|
secp256k1_fe_mul(&bzinv3, &bzinv2, bzinv);
|
|
secp256k1_fe_mul(&r->x, &b->x, &bzinv2);
|
|
secp256k1_fe_mul(&r->y, &b->y, &bzinv3);
|
|
secp256k1_fe_set_int(&r->z, 1);
|
|
return;
|
|
}
|
|
r->infinity = 0;
|
|
|
|
/** We need to calculate (rx,ry,rz) = (ax,ay,az) + (bx,by,1/bzinv). Due to
|
|
* secp256k1's isomorphism we can multiply the Z coordinates on both sides
|
|
* by bzinv, and get: (rx,ry,rz*bzinv) = (ax,ay,az*bzinv) + (bx,by,1).
|
|
* This means that (rx,ry,rz) can be calculated as
|
|
* (ax,ay,az*bzinv) + (bx,by,1), when not applying the bzinv factor to rz.
|
|
* The variable az below holds the modified Z coordinate for a, which is used
|
|
* for the computation of rx and ry, but not for rz.
|
|
*/
|
|
secp256k1_fe_mul(&az, &a->z, bzinv);
|
|
|
|
secp256k1_fe_sqr(&z12, &az);
|
|
u1 = a->x; secp256k1_fe_normalize_weak(&u1);
|
|
secp256k1_fe_mul(&u2, &b->x, &z12);
|
|
s1 = a->y; secp256k1_fe_normalize_weak(&s1);
|
|
secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &az);
|
|
secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
|
|
secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
|
|
if (secp256k1_fe_normalizes_to_zero_var(&h)) {
|
|
if (secp256k1_fe_normalizes_to_zero_var(&i)) {
|
|
secp256k1_gej_double_var(r, a, NULL);
|
|
} else {
|
|
secp256k1_gej_set_infinity(r);
|
|
}
|
|
return;
|
|
}
|
|
secp256k1_fe_sqr(&i2, &i);
|
|
secp256k1_fe_sqr(&h2, &h);
|
|
secp256k1_fe_mul(&h3, &h, &h2);
|
|
r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h);
|
|
secp256k1_fe_mul(&t, &u1, &h2);
|
|
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2);
|
|
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i);
|
|
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1);
|
|
secp256k1_fe_add(&r->y, &h3);
|
|
}
|
|
|
|
|
|
static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) {
|
|
/* Operations: 7 mul, 5 sqr, 4 normalize, 21 mul_int/add/negate/cmov */
|
|
static const secp256k1_fe fe_1 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
|
|
secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr;
|
|
secp256k1_fe m_alt, rr_alt;
|
|
int infinity, degenerate;
|
|
VERIFY_CHECK(!b->infinity);
|
|
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1);
|
|
|
|
/** In:
|
|
* Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks.
|
|
* In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002.
|
|
* we find as solution for a unified addition/doubling formula:
|
|
* lambda = ((x1 + x2)^2 - x1 * x2 + a) / (y1 + y2), with a = 0 for secp256k1's curve equation.
|
|
* x3 = lambda^2 - (x1 + x2)
|
|
* 2*y3 = lambda * (x1 + x2 - 2 * x3) - (y1 + y2).
|
|
*
|
|
* Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives:
|
|
* U1 = X1*Z2^2, U2 = X2*Z1^2
|
|
* S1 = Y1*Z2^3, S2 = Y2*Z1^3
|
|
* Z = Z1*Z2
|
|
* T = U1+U2
|
|
* M = S1+S2
|
|
* Q = T*M^2
|
|
* R = T^2-U1*U2
|
|
* X3 = 4*(R^2-Q)
|
|
* Y3 = 4*(R*(3*Q-2*R^2)-M^4)
|
|
* Z3 = 2*M*Z
|
|
* (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.)
|
|
*
|
|
* This formula has the benefit of being the same for both addition
|
|
* of distinct points and doubling. However, it breaks down in the
|
|
* case that either point is infinity, or that y1 = -y2. We handle
|
|
* these cases in the following ways:
|
|
*
|
|
* - If b is infinity we simply bail by means of a VERIFY_CHECK.
|
|
*
|
|
* - If a is infinity, we detect this, and at the end of the
|
|
* computation replace the result (which will be meaningless,
|
|
* but we compute to be constant-time) with b.x : b.y : 1.
|
|
*
|
|
* - If a = -b, we have y1 = -y2, which is a degenerate case.
|
|
* But here the answer is infinity, so we simply set the
|
|
* infinity flag of the result, overriding the computed values
|
|
* without even needing to cmov.
|
|
*
|
|
* - If y1 = -y2 but x1 != x2, which does occur thanks to certain
|
|
* properties of our curve (specifically, 1 has nontrivial cube
|
|
* roots in our field, and the curve equation has no x coefficient)
|
|
* then the answer is not infinity but also not given by the above
|
|
* equation. In this case, we cmov in place an alternate expression
|
|
* for lambda. Specifically (y1 - y2)/(x1 - x2). Where both these
|
|
* expressions for lambda are defined, they are equal, and can be
|
|
* obtained from each other by multiplication by (y1 + y2)/(y1 + y2)
|
|
* then substitution of x^3 + 7 for y^2 (using the curve equation).
|
|
* For all pairs of nonzero points (a, b) at least one is defined,
|
|
* so this covers everything.
|
|
*/
|
|
|
|
secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */
|
|
u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */
|
|
secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */
|
|
s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */
|
|
secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */
|
|
secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */
|
|
t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */
|
|
m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */
|
|
secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */
|
|
secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */
|
|
secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */
|
|
secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */
|
|
/** If lambda = R/M = 0/0 we have a problem (except in the "trivial"
|
|
* case that Z = z1z2 = 0, and this is special-cased later on). */
|
|
degenerate = secp256k1_fe_normalizes_to_zero(&m) &
|
|
secp256k1_fe_normalizes_to_zero(&rr);
|
|
/* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2.
|
|
* This means either x1 == beta*x2 or beta*x1 == x2, where beta is
|
|
* a nontrivial cube root of one. In either case, an alternate
|
|
* non-indeterminate expression for lambda is (y1 - y2)/(x1 - x2),
|
|
* so we set R/M equal to this. */
|
|
rr_alt = s1;
|
|
secp256k1_fe_mul_int(&rr_alt, 2); /* rr = Y1*Z2^3 - Y2*Z1^3 (2) */
|
|
secp256k1_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 */
|
|
|
|
secp256k1_fe_cmov(&rr_alt, &rr, !degenerate);
|
|
secp256k1_fe_cmov(&m_alt, &m, !degenerate);
|
|
/* Now Ralt / Malt = lambda and is guaranteed not to be 0/0.
|
|
* From here on out Ralt and Malt represent the numerator
|
|
* and denominator of lambda; R and M represent the explicit
|
|
* expressions x1^2 + x2^2 + x1x2 and y1 + y2. */
|
|
secp256k1_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */
|
|
secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*Malt^2 (1) */
|
|
/* These two lines use the observation that either M == Malt or M == 0,
|
|
* so M^3 * Malt is either Malt^4 (which is computed by squaring), or
|
|
* zero (which is "computed" by cmov). So the cost is one squaring
|
|
* versus two multiplications. */
|
|
secp256k1_fe_sqr(&n, &n);
|
|
secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */
|
|
secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */
|
|
secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Malt*Z (1) */
|
|
infinity = secp256k1_fe_normalizes_to_zero(&r->z) & ~a->infinity;
|
|
secp256k1_fe_mul_int(&r->z, 2); /* r->z = Z3 = 2*Malt*Z (2) */
|
|
secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */
|
|
secp256k1_fe_add(&t, &q); /* t = Ralt^2-Q (3) */
|
|
secp256k1_fe_normalize_weak(&t);
|
|
r->x = t; /* r->x = Ralt^2-Q (1) */
|
|
secp256k1_fe_mul_int(&t, 2); /* t = 2*x3 (2) */
|
|
secp256k1_fe_add(&t, &q); /* t = 2*x3 - Q: (4) */
|
|
secp256k1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*x3 - Q) (1) */
|
|
secp256k1_fe_add(&t, &n); /* t = Ralt*(2*x3 - Q) + M^3*Malt (3) */
|
|
secp256k1_fe_negate(&r->y, &t, 3); /* r->y = Ralt*(Q - 2x3) - M^3*Malt (4) */
|
|
secp256k1_fe_normalize_weak(&r->y);
|
|
secp256k1_fe_mul_int(&r->x, 4); /* r->x = X3 = 4*(Ralt^2-Q) */
|
|
secp256k1_fe_mul_int(&r->y, 4); /* r->y = Y3 = 4*Ralt*(Q - 2x3) - 4*M^3*Malt (4) */
|
|
|
|
/** In case a->infinity == 1, replace r with (b->x, b->y, 1). */
|
|
secp256k1_fe_cmov(&r->x, &b->x, a->infinity);
|
|
secp256k1_fe_cmov(&r->y, &b->y, a->infinity);
|
|
secp256k1_fe_cmov(&r->z, &fe_1, a->infinity);
|
|
r->infinity = infinity;
|
|
}
|
|
|
|
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) {
|
|
/* Operations: 4 mul, 1 sqr */
|
|
secp256k1_fe zz;
|
|
VERIFY_CHECK(!secp256k1_fe_is_zero(s));
|
|
secp256k1_fe_sqr(&zz, s);
|
|
secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */
|
|
secp256k1_fe_mul(&r->y, &r->y, &zz);
|
|
secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */
|
|
secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */
|
|
}
|
|
|
|
static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) {
|
|
secp256k1_fe x, y;
|
|
VERIFY_CHECK(!a->infinity);
|
|
x = a->x;
|
|
secp256k1_fe_normalize(&x);
|
|
y = a->y;
|
|
secp256k1_fe_normalize(&y);
|
|
secp256k1_fe_to_storage(&r->x, &x);
|
|
secp256k1_fe_to_storage(&r->y, &y);
|
|
}
|
|
|
|
static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a) {
|
|
secp256k1_fe_from_storage(&r->x, &a->x);
|
|
secp256k1_fe_from_storage(&r->y, &a->y);
|
|
r->infinity = 0;
|
|
}
|
|
|
|
static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) {
|
|
secp256k1_fe_cmov(&r->x, &a->x, flag);
|
|
secp256k1_fe_cmov(&r->y, &a->y, flag);
|
|
secp256k1_fe_cmov(&r->z, &a->z, flag);
|
|
|
|
r->infinity ^= (r->infinity ^ a->infinity) & flag;
|
|
}
|
|
|
|
static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) {
|
|
secp256k1_fe_storage_cmov(&r->x, &a->x, flag);
|
|
secp256k1_fe_storage_cmov(&r->y, &a->y, flag);
|
|
}
|
|
|
|
static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
|
|
static const secp256k1_fe beta = SECP256K1_FE_CONST(
|
|
0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul,
|
|
0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul
|
|
);
|
|
*r = *a;
|
|
secp256k1_fe_mul(&r->x, &r->x, &beta);
|
|
}
|
|
|
|
static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) {
|
|
secp256k1_fe yz;
|
|
|
|
if (a->infinity) {
|
|
return 0;
|
|
}
|
|
|
|
/* We rely on the fact that the Jacobi symbol of 1 / a->z^3 is the same as
|
|
* that of a->z. Thus a->y / a->z^3 is a quadratic residue iff a->y * a->z
|
|
is */
|
|
secp256k1_fe_mul(&yz, &a->y, &a->z);
|
|
return secp256k1_fe_is_quad_var(&yz);
|
|
}
|
|
|
|
static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
|
|
#ifdef EXHAUSTIVE_TEST_ORDER
|
|
secp256k1_gej out;
|
|
int i;
|
|
|
|
/* A very simple EC multiplication ladder that avoids a dependency on ecmult. */
|
|
secp256k1_gej_set_infinity(&out);
|
|
for (i = 0; i < 32; ++i) {
|
|
secp256k1_gej_double_var(&out, &out, NULL);
|
|
if ((((uint32_t)EXHAUSTIVE_TEST_ORDER) >> (31 - i)) & 1) {
|
|
secp256k1_gej_add_ge_var(&out, &out, ge, NULL);
|
|
}
|
|
}
|
|
return secp256k1_gej_is_infinity(&out);
|
|
#else
|
|
(void)ge;
|
|
/* The real secp256k1 group has cofactor 1, so the subgroup is the entire curve. */
|
|
return 1;
|
|
#endif
|
|
}
|
|
|
|
#endif /* SECP256K1_GROUP_IMPL_H */
|