diff --git a/configure.ac b/configure.ac index 13b4e56..88ca8df 100644 --- a/configure.ac +++ b/configure.ac @@ -223,7 +223,8 @@ case $set_bignum in gmp) AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed]) AC_DEFINE(USE_NUM_GMP, 1, [Define this symbol to use the gmp implementation]) - AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the USE_FIELD_INV_NUM implementation]) + AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the num-based field inverse implementation]) + AC_DEFINE(USE_SCALAR_INV_NUM, 1, [Define this symbol to use the num-based scalar inverse implementation]) ;; *) AC_MSG_ERROR([invalid bignum implementation]) diff --git a/src/ecdsa.h b/src/ecdsa.h index 3b1e048..5fc5230 100644 --- a/src/ecdsa.h +++ b/src/ecdsa.h @@ -7,17 +7,21 @@ #ifndef _SECP256K1_ECDSA_ #define _SECP256K1_ECDSA_ -#include "num.h" +#include "scalar.h" +#include "group.h" + +static void secp256k1_ecsda_start(void); +static void secp256k1_ecdsa_stop(void); typedef struct { - secp256k1_num_t r, s; + secp256k1_scalar_t r, s; } secp256k1_ecdsa_sig_t; static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size); static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a); -static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message); +static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message); static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid); -static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid); -static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s); +static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid); +static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s); #endif diff --git a/src/ecdsa_impl.h b/src/ecdsa_impl.h index dadf215..525516e 100644 --- a/src/ecdsa_impl.h +++ b/src/ecdsa_impl.h @@ -8,13 +8,47 @@ #ifndef _SECP256K1_ECDSA_IMPL_H_ #define _SECP256K1_ECDSA_IMPL_H_ -#include "num.h" +#include "scalar.h" #include "field.h" #include "group.h" #include "ecmult.h" #include "ecmult_gen.h" #include "ecdsa.h" +typedef struct { + secp256k1_fe_t order_as_fe; + secp256k1_fe_t p_minus_order; +} secp256k1_ecdsa_consts_t; + +static const secp256k1_ecdsa_consts_t *secp256k1_ecdsa_consts = NULL; + +static void secp256k1_ecdsa_start(void) { + if (secp256k1_ecdsa_consts != NULL) + return; + + /* Allocate. */ + secp256k1_ecdsa_consts_t *ret = (secp256k1_ecdsa_consts_t*)malloc(sizeof(secp256k1_ecdsa_consts_t)); + + unsigned char p[32]; + secp256k1_num_get_bin(p, 32, &secp256k1_ge_consts->order); + secp256k1_fe_set_b32(&ret->order_as_fe, p); + + secp256k1_fe_negate(&ret->p_minus_order, &ret->order_as_fe, 1); + secp256k1_fe_normalize(&ret->p_minus_order); + + /* Set the global pointer. */ + secp256k1_ecdsa_consts = ret; +} + +static void secp256k1_ecdsa_stop(void) { + if (secp256k1_ecdsa_consts == NULL) + return; + + secp256k1_ecdsa_consts_t *c = (secp256k1_ecdsa_consts_t*)secp256k1_ecmult_consts; + secp256k1_ecdsa_consts = NULL; + free(c); +} + static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) { if (sig[0] != 0x30) return 0; int lenr = sig[3]; @@ -26,18 +60,37 @@ static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned ch if (lenr == 0) return 0; if (sig[lenr+4] != 0x02) return 0; if (lens == 0) return 0; - secp256k1_num_set_bin(&r->r, sig+4, lenr); - secp256k1_num_set_bin(&r->s, sig+6+lenr, lens); + const unsigned char *sp = sig + 6 + lenr; + while (lens > 0 && sp[0] == 0) { + lens--; + sp++; + } + if (lens > 32) return 0; + const unsigned char *rp = sig + 4; + while (lenr > 0 && rp[0] == 0) { + lenr--; + rp++; + } + if (lenr > 32) return 0; + unsigned char ra[32] = {0}, sa[32] = {0}; + memcpy(ra + 32 - lenr, rp, lenr); + memcpy(sa + 32 - lens, sp, lens); + int overflow = 0; + secp256k1_scalar_set_b32(&r->r, ra, &overflow); + if (overflow) return 0; + secp256k1_scalar_set_b32(&r->s, sa, &overflow); + if (overflow) return 0; return 1; } static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) { - int lenR = (secp256k1_num_bits(&a->r) + 7)/8; - if (lenR == 0 || secp256k1_num_get_bit(&a->r, lenR*8-1)) - lenR++; - int lenS = (secp256k1_num_bits(&a->s) + 7)/8; - if (lenS == 0 || secp256k1_num_get_bit(&a->s, lenS*8-1)) - lenS++; + unsigned char r[33] = {0}, s[33] = {0}; + secp256k1_scalar_get_b32(&r[1], &a->r); + secp256k1_scalar_get_b32(&s[1], &a->s); + unsigned char *rp = r, *sp = s; + int lenR = 33, lenS = 33; + while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; } + while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; } if (*size < 6+lenS+lenR) return 0; *size = 6 + lenS + lenR; @@ -45,98 +98,67 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se sig[1] = 4 + lenS + lenR; sig[2] = 0x02; sig[3] = lenR; - secp256k1_num_get_bin(sig+4, lenR, &a->r); + memcpy(sig+4, rp, lenR); sig[4+lenR] = 0x02; sig[5+lenR] = lenS; - secp256k1_num_get_bin(sig+lenR+6, lenS, &a->s); + memcpy(sig+lenR+6, sp, lenS); return 1; } -static int secp256k1_ecdsa_sig_recompute(secp256k1_num_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) { - const secp256k1_ge_consts_t *c = secp256k1_ge_consts; - - if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s)) - return 0; - if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s)) - return 0; - if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0) +static int secp256k1_ecdsa_sig_recompute(secp256k1_scalar_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) { + if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s)) return 0; int ret = 0; - secp256k1_num_t sn, u1, u2; - secp256k1_num_init(&sn); - secp256k1_num_init(&u1); - secp256k1_num_init(&u2); - secp256k1_num_mod_inverse(&sn, &sig->s, &c->order); - secp256k1_num_mod_mul(&u1, &sn, message, &c->order); - secp256k1_num_mod_mul(&u2, &sn, &sig->r, &c->order); + secp256k1_scalar_t sn, u1, u2; + secp256k1_scalar_inverse_var(&sn, &sig->s); + secp256k1_scalar_mul(&u1, &sn, message); + secp256k1_scalar_mul(&u2, &sn, &sig->r); secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey); secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1); if (!secp256k1_gej_is_infinity(&pr)) { secp256k1_fe_t xr; secp256k1_gej_get_x_var(&xr, &pr); secp256k1_fe_normalize(&xr); unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr); - secp256k1_num_set_bin(r2, xrb, 32); - secp256k1_num_mod(r2, &c->order); + secp256k1_scalar_set_b32(r2, xrb, NULL); ret = 1; } - secp256k1_num_free(&sn); - secp256k1_num_free(&u1); - secp256k1_num_free(&u2); return ret; } -static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid) { - const secp256k1_ge_consts_t *c = secp256k1_ge_consts; - - if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s)) - return 0; - if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s)) - return 0; - if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0) +static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) { + if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s)) return 0; - secp256k1_num_t rx; - secp256k1_num_init(&rx); - secp256k1_num_copy(&rx, &sig->r); - if (recid & 2) { - secp256k1_num_add(&rx, &rx, &c->order); - if (secp256k1_num_cmp(&rx, &secp256k1_fe_consts->p) >= 0) - return 0; - } unsigned char brx[32]; - secp256k1_num_get_bin(brx, 32, &rx); - secp256k1_num_free(&rx); + secp256k1_scalar_get_b32(brx, &sig->r); secp256k1_fe_t fx; - VERIFY_CHECK(secp256k1_fe_set_b32(&fx, brx)); /* Either rx < n (and n < p), or rx + n < p (checked above). */ + VERIFY_CHECK(secp256k1_fe_set_b32(&fx, brx)); /* brx comes from a scalar, so is less than the order; certainly less than p */ + if (recid & 2) { + if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_consts->p_minus_order) >= 0) + return 0; + secp256k1_fe_add(&fx, &secp256k1_ecdsa_consts->order_as_fe); + } secp256k1_ge_t x; if (!secp256k1_ge_set_xo(&x, &fx, recid & 1)) return 0; secp256k1_gej_t xj; secp256k1_gej_set_ge(&xj, &x); - secp256k1_num_t rn, u1, u2; - secp256k1_num_init(&rn); - secp256k1_num_init(&u1); - secp256k1_num_init(&u2); - secp256k1_num_mod_inverse(&rn, &sig->r, &c->order); - secp256k1_num_mod_mul(&u1, &rn, message, &c->order); - secp256k1_num_sub(&u1, &c->order, &u1); - secp256k1_num_mod_mul(&u2, &rn, &sig->s, &c->order); + secp256k1_scalar_t rn, u1, u2; + secp256k1_scalar_inverse_var(&rn, &sig->r); + secp256k1_scalar_mul(&u1, &rn, message); + secp256k1_scalar_negate(&u1, &u1); + secp256k1_scalar_mul(&u2, &rn, &sig->s); secp256k1_gej_t qj; secp256k1_ecmult(&qj, &xj, &u2, &u1); secp256k1_ge_set_gej_var(pubkey, &qj); - secp256k1_num_free(&rn); - secp256k1_num_free(&u1); - secp256k1_num_free(&u2); return !secp256k1_gej_is_infinity(&qj); } -static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) { - secp256k1_num_t r2; - secp256k1_num_init(&r2); +static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) { + secp256k1_scalar_t r2; int ret = 0; - ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_num_cmp(&sig->r, &r2) == 0; - secp256k1_num_free(&r2); + ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_scalar_eq(&sig->r, &r2); return ret; } @@ -150,34 +172,30 @@ static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_ secp256k1_fe_normalize(&r.y); secp256k1_fe_get_b32(b, &r.x); int overflow = 0; - secp256k1_scalar_t sigr; - secp256k1_scalar_set_b32(&sigr, b, &overflow); + secp256k1_scalar_set_b32(&sig->r, b, &overflow); if (recid) *recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); secp256k1_scalar_t n; - secp256k1_scalar_mul(&n, &sigr, seckey); + secp256k1_scalar_mul(&n, &sig->r, seckey); secp256k1_scalar_add(&n, &n, message); - secp256k1_scalar_t sigs; - secp256k1_scalar_inverse(&sigs, nonce); - secp256k1_scalar_mul(&sigs, &sigs, &n); + secp256k1_scalar_inverse(&sig->s, nonce); + secp256k1_scalar_mul(&sig->s, &sig->s, &n); secp256k1_scalar_clear(&n); secp256k1_gej_clear(&rp); secp256k1_ge_clear(&r); - if (secp256k1_scalar_is_zero(&sigs)) + if (secp256k1_scalar_is_zero(&sig->s)) return 0; - if (secp256k1_scalar_is_high(&sigs)) { - secp256k1_scalar_negate(&sigs, &sigs); + if (secp256k1_scalar_is_high(&sig->s)) { + secp256k1_scalar_negate(&sig->s, &sig->s); if (recid) *recid ^= 1; } - secp256k1_scalar_get_num(&sig->s, &sigs); - secp256k1_scalar_get_num(&sig->r, &sigr); return 1; } -static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s) { - secp256k1_num_copy(&sig->r, r); - secp256k1_num_copy(&sig->s, s); +static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s) { + sig->r = *r; + sig->s = *s; } #endif diff --git a/src/eckey.h b/src/eckey.h index 024c8b8..6de5dc0 100644 --- a/src/eckey.h +++ b/src/eckey.h @@ -9,7 +9,6 @@ #include "group.h" #include "scalar.h" -#include "num.h" static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size); static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed); @@ -18,8 +17,8 @@ static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed); static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak); -static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak); +static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak); static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak); -static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak); +static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak); #endif diff --git a/src/eckey_impl.h b/src/eckey_impl.h index bddf51a..0f218ce 100644 --- a/src/eckey_impl.h +++ b/src/eckey_impl.h @@ -9,7 +9,7 @@ #include "eckey.h" -#include "num.h" +#include "scalar.h" #include "field.h" #include "group.h" #include "ecmult_gen.h" @@ -154,17 +154,12 @@ static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp return 1; } -static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak) { - if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0) - return 0; - +static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak) { secp256k1_gej_t pt; secp256k1_gej_set_ge(&pt, key); - secp256k1_num_t one; - secp256k1_num_init(&one); - secp256k1_num_set_int(&one, 1); + secp256k1_scalar_t one; + secp256k1_scalar_set_int(&one, 1); secp256k1_ecmult(&pt, &pt, &one, tweak); - secp256k1_num_free(&one); if (secp256k1_gej_is_infinity(&pt)) return 0; @@ -180,19 +175,15 @@ static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp return 1; } -static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak) { - if (secp256k1_num_is_zero(tweak)) - return 0; - if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0) +static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak) { + if (secp256k1_scalar_is_zero(tweak)) return 0; - secp256k1_num_t zero; - secp256k1_num_init(&zero); - secp256k1_num_set_int(&zero, 0); + secp256k1_scalar_t zero; + secp256k1_scalar_set_int(&zero, 0); secp256k1_gej_t pt; secp256k1_gej_set_ge(&pt, key); secp256k1_ecmult(&pt, &pt, tweak, &zero); - secp256k1_num_free(&zero); secp256k1_ge_set_gej(key, &pt); return 1; } diff --git a/src/ecmult.h b/src/ecmult.h index e3cf18b..15a7100 100644 --- a/src/ecmult.h +++ b/src/ecmult.h @@ -14,6 +14,6 @@ static void secp256k1_ecmult_start(void); static void secp256k1_ecmult_stop(void); /** Double multiply: R = na*A + ng*G */ -static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng); +static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng); #endif diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index 56cdd20..56e46cd 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -7,8 +7,8 @@ #ifndef _SECP256K1_ECMULT_IMPL_H_ #define _SECP256K1_ECMULT_IMPL_H_ -#include "num.h" #include "group.h" +#include "scalar.h" #include "ecmult.h" /* optimal for 128-bit and 256-bit exponents. */ @@ -121,47 +121,51 @@ static void secp256k1_ecmult_stop(void) { * with the following guarantees: * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) * - two non-zero entries in wnaf are separated by at least w-1 zeroes. - * - the index of the highest non-zero entry in wnaf (=return value-1) is at most bits, where - * bits is the number of bits necessary to represent the absolute value of the input. + * - the number of set values in wnaf is returned. This number is at most 256, and at most one more + * - than the number of bits in the (absolute value) of the input. */ -static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) { - int ret = 0; - int zeroes = 0; - secp256k1_num_t x; - secp256k1_num_copy(&x, a); +static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w) { + secp256k1_scalar_t s = *a; + int sign = 1; - if (secp256k1_num_is_neg(&x)) { + if (secp256k1_scalar_get_bits(&s, 255, 1)) { + secp256k1_scalar_negate(&s, &s); sign = -1; - secp256k1_num_negate(&x); } - while (!secp256k1_num_is_zero(&x)) { - while (!secp256k1_num_is_odd(&x)) { - zeroes++; - secp256k1_num_shift(&x, 1); + + int set_bits = 0; + int bit = 0; + while (bit < 256) { + if (secp256k1_scalar_get_bits(&s, bit, 1) == 0) { + bit++; + continue; } - int word = secp256k1_num_shift(&x, w); - while (zeroes) { - wnaf[ret++] = 0; - zeroes--; + while (set_bits < bit) { + wnaf[set_bits++] = 0; } + int now = w; + if (bit + now > 256) { + now = 256 - bit; + } + int word = secp256k1_scalar_get_bits_var(&s, bit, now); if (word & (1 << (w-1))) { - secp256k1_num_inc(&x); - wnaf[ret++] = sign * (word - (1 << w)); + secp256k1_scalar_add_bit(&s, bit + w); + wnaf[set_bits++] = sign * (word - (1 << w)); } else { - wnaf[ret++] = sign * word; + wnaf[set_bits++] = sign * word; } - zeroes = w-1; + bit += now; } - return ret; + return set_bits; } -static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng) { +static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng) { const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; #ifdef USE_ENDOMORPHISM - secp256k1_num_t na_1, na_lam; + secp256k1_scalar_t na_1, na_lam; /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ - secp256k1_gej_split_exp_var(&na_1, &na_lam, na); + secp256k1_scalar_split_lambda_var(&na_1, &na_lam, na); /* build wnaf representation for na_1 and na_lam. */ int wnaf_na_1[129]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A); @@ -170,7 +174,7 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const if (bits_na_lam > bits) bits = bits_na_lam; #else /* build wnaf representation for na. */ - int wnaf_na[257]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A); + int wnaf_na[256]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A); int bits = bits_na; #endif @@ -184,10 +188,10 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_mul_lambda(&pre_a_lam[i], &pre_a[i]); /* Splitted G factors. */ - secp256k1_num_t ng_1, ng_128; + secp256k1_scalar_t ng_1, ng_128; /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ - secp256k1_num_split(&ng_1, &ng_128, ng, 128); + secp256k1_scalar_split_128(&ng_1, &ng_128, ng); /* Build wnaf representation for ng_1 and ng_128 */ int wnaf_ng_1[129]; int bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G); diff --git a/src/field.h b/src/field.h index b56a0a9..cbd48c0 100644 --- a/src/field.h +++ b/src/field.h @@ -34,6 +34,7 @@ typedef struct { secp256k1_num_t p; + secp256k1_fe_t order; } secp256k1_fe_consts_t; static const secp256k1_fe_consts_t *secp256k1_fe_consts = NULL; @@ -59,6 +60,9 @@ static int secp256k1_fe_is_odd(const secp256k1_fe_t *a); /** Compare two field elements. Requires both inputs to be normalized */ static int secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b); +/** Compare two field elements. Requires both inputs to be normalized */ +static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b); + /** Set a field element equal to 32-byte big endian value. If succesful, the resulting field element is normalized. */ static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a); diff --git a/src/field_10x26_impl.h b/src/field_10x26_impl.h index de12d56..213b848 100644 --- a/src/field_10x26_impl.h +++ b/src/field_10x26_impl.h @@ -152,6 +152,20 @@ SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const se | (t[5]^u[5]) | (t[6]^u[6]) | (t[7]^u[7]) | (t[8]^u[8]) | (t[9]^u[9])) == 0; } +static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + VERIFY_CHECK(b->normalized); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); +#endif + for (int i = 9; i >= 0; i--) { + if (a->n[i] > b->n[i]) return 1; + if (a->n[i] < b->n[i]) return -1; + } + return 0; +} + static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h index e1e7ee1..cc9d0c1 100644 --- a/src/field_5x52_impl.h +++ b/src/field_5x52_impl.h @@ -150,6 +150,20 @@ SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const se return ((t[0]^u[0]) | (t[1]^u[1]) | (t[2]^u[2]) | (t[3]^u[3]) | (t[4]^u[4])) == 0; } +static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + VERIFY_CHECK(b->normalized); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); +#endif + for (int i = 4; i >= 0; i--) { + if (a->n[i] > b->n[i]) return 1; + if (a->n[i] < b->n[i]) return -1; + } + return 0; +} + static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; for (int i=0; i<32; i++) { diff --git a/src/field_gmp_impl.h b/src/field_gmp_impl.h index 3104522..4e59fe3 100644 --- a/src/field_gmp_impl.h +++ b/src/field_gmp_impl.h @@ -75,6 +75,14 @@ SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const se return ret; } +SECP256K1_INLINE static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { + for (int i=FIELD_LIMBS; i>=0; i--) { + if (a->n[i] > b->n[i]) return 1; + if (a->n[i] < b->n[i]) return -1; + } + return 0; +} + static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { for (int i=0; in[i] = 0; diff --git a/src/group.h b/src/group.h index ba02549..1600e96 100644 --- a/src/group.h +++ b/src/group.h @@ -34,7 +34,6 @@ typedef struct { #ifdef USE_ENDOMORPHISM /* constants related to secp256k1's efficiently computable endomorphism */ secp256k1_fe_t beta; - secp256k1_num_t lambda, a1b2, b1, a2; #endif } secp256k1_ge_consts_t; @@ -112,10 +111,6 @@ static void secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a); #ifdef USE_ENDOMORPHISM /** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a); - -/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (given that a is - not more than 256 bits). */ -static void secp256k1_gej_split_exp_var(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a); #endif /** Clear a secp256k1_gej_t to prevent leaking sensitive information. */ diff --git a/src/group_impl.h b/src/group_impl.h index 93d8583..84a87ab 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -414,30 +414,6 @@ static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t * *r = *a; secp256k1_fe_mul(&r->x, &r->x, beta); } - -static void secp256k1_gej_split_exp_var(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a) { - const secp256k1_ge_consts_t *c = secp256k1_ge_consts; - secp256k1_num_t bnc1, bnc2, bnt1, bnt2, bnn2; - - secp256k1_num_copy(&bnn2, &c->order); - secp256k1_num_shift(&bnn2, 1); - - secp256k1_num_mul(&bnc1, a, &c->a1b2); - secp256k1_num_add(&bnc1, &bnc1, &bnn2); - secp256k1_num_div(&bnc1, &bnc1, &c->order); - - secp256k1_num_mul(&bnc2, a, &c->b1); - secp256k1_num_add(&bnc2, &bnc2, &bnn2); - secp256k1_num_div(&bnc2, &bnc2, &c->order); - - secp256k1_num_mul(&bnt1, &bnc1, &c->a1b2); - secp256k1_num_mul(&bnt2, &bnc2, &c->a2); - secp256k1_num_add(&bnt1, &bnt1, &bnt2); - secp256k1_num_sub(r1, a, &bnt1); - secp256k1_num_mul(&bnt1, &bnc1, &c->b1); - secp256k1_num_mul(&bnt2, &bnc2, &c->a1b2); - secp256k1_num_sub(r2, &bnt1, &bnt2); -} #endif @@ -462,31 +438,12 @@ static void secp256k1_ge_start(void) { }; #ifdef USE_ENDOMORPHISM /* properties of secp256k1's efficiently computable endomorphism */ - static const unsigned char secp256k1_ge_consts_lambda[] = { - 0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0, - 0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, - 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78, - 0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72 - }; static const unsigned char secp256k1_ge_consts_beta[] = { 0x7a,0xe9,0x6a,0x2b,0x65,0x7c,0x07,0x10, 0x6e,0x64,0x47,0x9e,0xac,0x34,0x34,0xe9, 0x9c,0xf0,0x49,0x75,0x12,0xf5,0x89,0x95, 0xc1,0x39,0x6c,0x28,0x71,0x95,0x01,0xee }; - static const unsigned char secp256k1_ge_consts_a1b2[] = { - 0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd, - 0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15 - }; - static const unsigned char secp256k1_ge_consts_b1[] = { - 0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28, - 0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3 - }; - static const unsigned char secp256k1_ge_consts_a2[] = { - 0x01, - 0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6, - 0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8 - }; #endif if (secp256k1_ge_consts == NULL) { secp256k1_ge_consts_t *ret = (secp256k1_ge_consts_t*)malloc(sizeof(secp256k1_ge_consts_t)); @@ -494,10 +451,6 @@ static void secp256k1_ge_start(void) { secp256k1_num_copy(&ret->half_order, &ret->order); secp256k1_num_shift(&ret->half_order, 1); #ifdef USE_ENDOMORPHISM - secp256k1_num_set_bin(&ret->lambda, secp256k1_ge_consts_lambda, sizeof(secp256k1_ge_consts_lambda)); - secp256k1_num_set_bin(&ret->a1b2, secp256k1_ge_consts_a1b2, sizeof(secp256k1_ge_consts_a1b2)); - secp256k1_num_set_bin(&ret->a2, secp256k1_ge_consts_a2, sizeof(secp256k1_ge_consts_a2)); - secp256k1_num_set_bin(&ret->b1, secp256k1_ge_consts_b1, sizeof(secp256k1_ge_consts_b1)); VERIFY_CHECK(secp256k1_fe_set_b32(&ret->beta, secp256k1_ge_consts_beta)); #endif secp256k1_fe_t g_x, g_y; diff --git a/src/num.h b/src/num.h index c86f847..7beaf1d 100644 --- a/src/num.h +++ b/src/num.h @@ -17,9 +17,6 @@ #error "Please select num implementation" #endif -/** Clear a number to prevent the leak of sensitive data. */ -static void secp256k1_num_clear(secp256k1_num_t *r); - /** Copy a number. */ static void secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a); @@ -30,15 +27,9 @@ static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const sec /** Set a number to the value of a binary big-endian string. */ static void secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen); -/** Set a number equal to a (signed) integer. */ -static void secp256k1_num_set_int(secp256k1_num_t *r, int a); - /** Compute a modular inverse. The input must be less than the modulus. */ static void secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m); -/** Multiply two numbers modulo another. */ -static void secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m); - /** Compare the absolute value of two numbers. */ static int secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b); @@ -61,40 +52,16 @@ static void secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, cons even if r was negative. */ static void secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m); -/** Calculate the number of bits in (the absolute value of) a number. */ -static int secp256k1_num_bits(const secp256k1_num_t *a); - /** Right-shift the passed number by bits bits, and return those bits. */ static int secp256k1_num_shift(secp256k1_num_t *r, int bits); /** Check whether a number is zero. */ static int secp256k1_num_is_zero(const secp256k1_num_t *a); -/** Check whether a number is odd. */ -static int secp256k1_num_is_odd(const secp256k1_num_t *a); - /** Check whether a number is strictly negative. */ static int secp256k1_num_is_neg(const secp256k1_num_t *a); -/** Check whether a particular bit is set in a number. */ -static int secp256k1_num_get_bit(const secp256k1_num_t *a, int pos); - -/** Increase a number by 1. */ -static void secp256k1_num_inc(secp256k1_num_t *r); - -/** Set a number equal to the value of a hex string (unsigned). */ -static void secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen); - -/** Convert (the absolute value of) a number to a hexadecimal string. */ -static void secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a); - -/** Split a number into a low and high part. */ -static void secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits); - /** Change a number's sign. */ static void secp256k1_num_negate(secp256k1_num_t *r); -/** Get a bunch of bits from a number. */ -static int secp256k1_num_get_bits(const secp256k1_num_t *a, int offset, int count); - #endif diff --git a/src/num_gmp_impl.h b/src/num_gmp_impl.h index e7eae86..420a42d 100644 --- a/src/num_gmp_impl.h +++ b/src/num_gmp_impl.h @@ -22,35 +22,10 @@ static void secp256k1_num_sanity(const secp256k1_num_t *a) { #define secp256k1_num_sanity(a) do { } while(0) #endif -static void secp256k1_num_init(secp256k1_num_t *r) { - r->neg = 0; - r->limbs = 1; - r->data[0] = 0; -} - -static void secp256k1_num_clear(secp256k1_num_t *r) { - memset(r, 0, sizeof(*r)); -} - -static void secp256k1_num_free(secp256k1_num_t *r) { - (void)r; -} - static void secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) { *r = *a; } -static int secp256k1_num_bits(const secp256k1_num_t *a) { - int ret=(a->limbs-1)*GMP_NUMB_BITS; - mp_limb_t x=a->data[a->limbs-1]; - while (x) { - x >>= 1; - ret++; - } - return ret; -} - - static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) { unsigned char tmp[65]; int len = 0; @@ -81,12 +56,6 @@ static void secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, un while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; } -static void secp256k1_num_set_int(secp256k1_num_t *r, int a) { - r->limbs = 1; - r->neg = (a < 0); - r->data[0] = (a < 0) ? -a : a; -} - static void secp256k1_num_add_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs); r->limbs = a->limbs; @@ -165,10 +134,6 @@ static int secp256k1_num_is_zero(const secp256k1_num_t *a) { return (a->limbs == 1 && a->data[0] == 0); } -static int secp256k1_num_is_odd(const secp256k1_num_t *a) { - return a->data[0] & 1; -} - static int secp256k1_num_is_neg(const secp256k1_num_t *a) { return (a->limbs > 1 || a->data[0] != 0) && a->neg; } @@ -260,12 +225,6 @@ static void secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, cons r->neg = a->neg ^ b->neg; } -static void secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m) { - secp256k1_num_mul(r, a, b); - secp256k1_num_mod(r, m); -} - - static int secp256k1_num_shift(secp256k1_num_t *r, int bits) { VERIFY_CHECK(bits <= GMP_NUMB_BITS); mp_limb_t ret = mpn_rshift(r->data, r->data, r->limbs, bits); @@ -274,107 +233,8 @@ static int secp256k1_num_shift(secp256k1_num_t *r, int bits) { return ret; } -static int secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) { - return (a->limbs*GMP_NUMB_BITS > pos) && ((a->data[pos/GMP_NUMB_BITS] >> (pos % GMP_NUMB_BITS)) & 1); -} - -static void secp256k1_num_inc(secp256k1_num_t *r) { - mp_limb_t ret = mpn_add_1(r->data, r->data, r->limbs, (mp_limb_t)1); - if (ret) { - VERIFY_CHECK(r->limbs < 2*NUM_LIMBS); - r->data[r->limbs++] = ret; - } -} - -static void secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen) { - static const unsigned char cvt[256] = { - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, - 0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0, - 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, - 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, - 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0 - }; - unsigned char num[257] = {}; - for (int i=0; ilimbs = mpn_set_str(r->data, num, alen, 16); - r->neg = 0; - while (r->limbs > 1 && r->data[r->limbs-1] == 0) r->limbs--; -} - -static void secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a) { - static const unsigned char cvt[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - unsigned char *tmp = malloc(257); - mp_size_t len = mpn_get_str(tmp, 16, (mp_limb_t*)a->data, a->limbs); - VERIFY_CHECK(len <= rlen); - for (int i=0; i= 0); - VERIFY_CHECK(rlen-len+i < rlen); - VERIFY_CHECK(tmp[i] < 16); - r[rlen-len+i] = cvt[tmp[i]]; - } - for (int i=0; i= 0); - VERIFY_CHECK(i < rlen); - r[i] = cvt[0]; - } - free(tmp); -} - -static void secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) { - VERIFY_CHECK(bits > 0); - rh->neg = a->neg; - if (bits >= a->limbs * GMP_NUMB_BITS) { - *rl = *a; - rh->limbs = 1; - rh->data[0] = 0; - return; - } - rl->limbs = 0; - rl->neg = a->neg; - int left = bits; - while (left >= GMP_NUMB_BITS) { - rl->data[rl->limbs] = a->data[rl->limbs]; - rl->limbs++; - left -= GMP_NUMB_BITS; - } - if (left == 0) { - mpn_copyi(rh->data, a->data + rl->limbs, a->limbs - rl->limbs); - rh->limbs = a->limbs - rl->limbs; - } else { - mpn_rshift(rh->data, a->data + rl->limbs, a->limbs - rl->limbs, left); - rh->limbs = a->limbs - rl->limbs; - while (rh->limbs>1 && rh->data[rh->limbs-1]==0) rh->limbs--; - } - if (left > 0) { - rl->data[rl->limbs] = a->data[rl->limbs] & ((((mp_limb_t)1) << left) - 1); - rl->limbs++; - } - while (rl->limbs>1 && rl->data[rl->limbs-1]==0) rl->limbs--; -} - static void secp256k1_num_negate(secp256k1_num_t *r) { r->neg ^= 1; } -static int secp256k1_num_get_bits(const secp256k1_num_t *a, int offset, int count) { - int ret = 0; - for (int i = 0; i < count; i++) { - ret |= ((a->data[(offset + i) / GMP_NUMB_BITS] >> ((offset + i) % GMP_NUMB_BITS)) & 1) << i; - } - return ret; -} - #endif diff --git a/src/scalar.h b/src/scalar.h index 3baacb3..4b5d73f 100644 --- a/src/scalar.h +++ b/src/scalar.h @@ -21,21 +21,33 @@ #error "Please select scalar implementation" #endif +static void secp256k1_scalar_start(void); +static void secp256k1_scalar_stop(void); + /** Clear a scalar to prevent the leak of sensitive data. */ static void secp256k1_scalar_clear(secp256k1_scalar_t *r); -/** Access bits from a scalar. */ -static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count); +/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */ +static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count); + +/** Access bits from a scalar. Not constant time. */ +static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count); /** Set a scalar from a big endian byte array. */ static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *bin, int *overflow); +/** Set a scalar to an unsigned integer. */ +static void secp256k1_scalar_set_int(secp256k1_scalar_t *r, unsigned int v); + /** Convert a scalar to a byte array. */ static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar_t* a); /** Add two scalars together (modulo the group order). */ static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b); +/** Add a power of two to a scalar. The result is not allowed to overflow. */ +static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit); + /** Multiply two scalars (modulo the group order). */ static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b); @@ -45,6 +57,9 @@ static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t /** Compute the inverse of a scalar (modulo the group order). */ static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scalar_t *a); +/** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */ +static void secp256k1_scalar_inverse_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *a); + /** Compute the complement of a scalar (modulo the group order). */ static void secp256k1_scalar_negate(secp256k1_scalar_t *r, const secp256k1_scalar_t *a); @@ -60,4 +75,14 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a); /** Convert a scalar to a number. */ static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a); +/** Compare two scalars. */ +static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scalar_t *b); + +static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a); + +#ifdef USE_ENDOMORPHISM +/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */ +static void secp256k1_scalar_split_lambda_var(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a); +#endif + #endif diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index f787182..afa7a54 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -33,9 +33,27 @@ SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar_t *r) { r->d[3] = 0; } -SECP256K1_INLINE static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count) { - VERIFY_CHECK((offset + count - 1) / 64 == offset / 64); - return (a->d[offset / 64] >> (offset % 64)) & ((((uint64_t)1) << count) - 1); +SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar_t *r, unsigned int v) { + r->d[0] = v; + r->d[1] = 0; + r->d[2] = 0; + r->d[3] = 0; +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count) { + VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6); + return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1); +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count) { + VERIFY_CHECK(count < 32); + VERIFY_CHECK(offset + count <= 256); + if ((offset + count - 1) >> 6 == offset >> 6) { + return secp256k1_scalar_get_bits(a, offset, count); + } else { + VERIFY_CHECK((offset >> 6) + 1 < 4); + return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & ((((uint64_t)1) << count) - 1); + } } SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar_t *a) { @@ -75,6 +93,22 @@ static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t secp256k1_scalar_reduce(r, t + secp256k1_scalar_check_overflow(r)); } +static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit) { + VERIFY_CHECK(bit < 256); + uint128_t t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << bit); + r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F)); + r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[2] + (((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F)); + r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[3] + (((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F)); + r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; +#ifdef VERIFY + VERIFY_CHECK((t >> 64) == 0); + VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); +#endif +} + static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *b32, int *overflow) { r->d[0] = (uint64_t)b32[31] | (uint64_t)b32[30] << 8 | (uint64_t)b32[29] << 16 | (uint64_t)b32[28] << 24 | (uint64_t)b32[27] << 32 | (uint64_t)b32[26] << 40 | (uint64_t)b32[25] << 48 | (uint64_t)b32[24] << 56; r->d[1] = (uint64_t)b32[23] | (uint64_t)b32[22] << 8 | (uint64_t)b32[21] << 16 | (uint64_t)b32[20] << 24 | (uint64_t)b32[19] << 32 | (uint64_t)b32[18] << 40 | (uint64_t)b32[17] << 48 | (uint64_t)b32[16] << 56; @@ -356,4 +390,19 @@ static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t #undef extract #undef extract_fast +static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) { + r1->d[0] = a->d[0]; + r1->d[1] = a->d[1]; + r1->d[2] = 0; + r1->d[3] = 0; + r2->d[0] = a->d[2]; + r2->d[1] = a->d[3]; + r2->d[2] = 0; + r2->d[3] = 0; +} + +SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) { + return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3])) == 0; +} + #endif diff --git a/src/scalar_8x32_impl.h b/src/scalar_8x32_impl.h index e58be13..0f82bfb 100644 --- a/src/scalar_8x32_impl.h +++ b/src/scalar_8x32_impl.h @@ -45,9 +45,31 @@ SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar_t *r) { r->d[7] = 0; } -SECP256K1_INLINE static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count) { - VERIFY_CHECK((offset + count - 1) / 32 == offset / 32); - return (a->d[offset / 32] >> (offset % 32)) & ((1 << count) - 1); +SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar_t *r, unsigned int v) { + r->d[0] = v; + r->d[1] = 0; + r->d[2] = 0; + r->d[3] = 0; + r->d[4] = 0; + r->d[5] = 0; + r->d[6] = 0; + r->d[7] = 0; +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count) { + VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); + return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1); +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count) { + VERIFY_CHECK(count < 32); + VERIFY_CHECK(offset + count <= 256); + if ((offset + count - 1) >> 5 == offset >> 5) { + return secp256k1_scalar_get_bits(a, offset, count); + } else { + VERIFY_CHECK((offset >> 5) + 1 < 8); + return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & ((((uint32_t)1) << count) - 1); + } } SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar_t *a) { @@ -109,6 +131,30 @@ static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t secp256k1_scalar_reduce(r, t + secp256k1_scalar_check_overflow(r)); } +static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit) { + VERIFY_CHECK(bit < 256); + uint64_t t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << bit); + r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F)); + r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[2] + (((uint32_t)((bit >> 5) == 2)) << (bit & 0x1F)); + r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[3] + (((uint32_t)((bit >> 5) == 3)) << (bit & 0x1F)); + r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[4] + (((uint32_t)((bit >> 5) == 4)) << (bit & 0x1F)); + r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[5] + (((uint32_t)((bit >> 5) == 5)) << (bit & 0x1F)); + r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[6] + (((uint32_t)((bit >> 5) == 6)) << (bit & 0x1F)); + r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[7] + (((uint32_t)((bit >> 5) == 7)) << (bit & 0x1F)); + r->d[7] = t & 0xFFFFFFFFULL; +#ifdef VERIFY + VERIFY_CHECK((t >> 32) == 0); + VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); +#endif +} + static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *b32, int *overflow) { r->d[0] = (uint32_t)b32[31] | (uint32_t)b32[30] << 8 | (uint32_t)b32[29] << 16 | (uint32_t)b32[28] << 24; r->d[1] = (uint32_t)b32[27] | (uint32_t)b32[26] << 8 | (uint32_t)b32[25] << 16 | (uint32_t)b32[24] << 24; @@ -569,4 +615,27 @@ static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t #undef extract #undef extract_fast +static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) { + r1->d[0] = a->d[0]; + r1->d[1] = a->d[1]; + r1->d[2] = a->d[2]; + r1->d[3] = a->d[3]; + r1->d[4] = 0; + r1->d[5] = 0; + r1->d[6] = 0; + r1->d[7] = 0; + r2->d[0] = a->d[4]; + r2->d[1] = a->d[5]; + r2->d[2] = a->d[6]; + r2->d[3] = a->d[7]; + r2->d[4] = 0; + r2->d[5] = 0; + r2->d[6] = 0; + r2->d[7] = 0; +} + +SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) { + return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0; +} + #endif diff --git a/src/scalar_impl.h b/src/scalar_impl.h index ddc5061..dcddf3b 100644 --- a/src/scalar_impl.h +++ b/src/scalar_impl.h @@ -9,6 +9,7 @@ #include +#include "group.h" #include "scalar.h" #if defined HAVE_CONFIG_H @@ -23,6 +24,54 @@ #error "Please select scalar implementation" #endif +typedef struct { +#ifdef USE_ENDOMORPHISM + secp256k1_num_t a1b2, b1, a2; +#endif +} secp256k1_scalar_consts_t; + +static const secp256k1_scalar_consts_t *secp256k1_scalar_consts = NULL; + +static void secp256k1_scalar_start(void) { + if (secp256k1_scalar_consts != NULL) + return; + + /* Allocate. */ + secp256k1_scalar_consts_t *ret = (secp256k1_scalar_consts_t*)malloc(sizeof(secp256k1_scalar_consts_t)); + +#ifdef USE_ENDOMORPHISM + static const unsigned char secp256k1_scalar_consts_a1b2[] = { + 0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd, + 0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15 + }; + static const unsigned char secp256k1_scalar_consts_b1[] = { + 0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28, + 0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3 + }; + static const unsigned char secp256k1_scalar_consts_a2[] = { + 0x01, + 0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6, + 0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8 + }; + + secp256k1_num_set_bin(&ret->a1b2, secp256k1_scalar_consts_a1b2, sizeof(secp256k1_scalar_consts_a1b2)); + secp256k1_num_set_bin(&ret->a2, secp256k1_scalar_consts_a2, sizeof(secp256k1_scalar_consts_a2)); + secp256k1_num_set_bin(&ret->b1, secp256k1_scalar_consts_b1, sizeof(secp256k1_scalar_consts_b1)); +#endif + + /* Set the global pointer. */ + secp256k1_scalar_consts = ret; +} + +static void secp256k1_scalar_stop(void) { + if (secp256k1_scalar_consts == NULL) + return; + + secp256k1_scalar_consts_t *c = (secp256k1_scalar_consts_t*)secp256k1_scalar_consts; + secp256k1_scalar_consts = NULL; + free(c); +} + static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a) { unsigned char c[32]; secp256k1_scalar_get_b32(c, a); @@ -181,4 +230,65 @@ static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scal secp256k1_scalar_mul(r, t, &x6); /* 111111 */ } +static void secp256k1_scalar_inverse_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *x) { +#if defined(USE_SCALAR_INV_BUILTIN) + secp256k1_scalar_inverse(r, x); +#elif defined(USE_SCALAR_INV_NUM) + unsigned char b[32]; + secp256k1_scalar_get_b32(b, x); + secp256k1_num_t n; + secp256k1_num_set_bin(&n, b, 32); + secp256k1_num_mod_inverse(&n, &n, &secp256k1_ge_consts->order); + secp256k1_num_get_bin(b, 32, &n); + secp256k1_scalar_set_b32(r, b, NULL); +#else +#error "Please select scalar inverse implementation" +#endif +} + +#ifdef USE_ENDOMORPHISM +static void secp256k1_scalar_split_lambda_var(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) { + unsigned char b[32]; + secp256k1_scalar_get_b32(b, a); + secp256k1_num_t na; + secp256k1_num_set_bin(&na, b, 32); + + secp256k1_num_t rn1, rn2; + + const secp256k1_scalar_consts_t *c = secp256k1_scalar_consts; + const secp256k1_num_t *order = &secp256k1_ge_consts->order; + secp256k1_num_t bnc1, bnc2, bnt1, bnt2, bnn2; + + secp256k1_num_copy(&bnn2, order); + secp256k1_num_shift(&bnn2, 1); + + secp256k1_num_mul(&bnc1, &na, &c->a1b2); + secp256k1_num_add(&bnc1, &bnc1, &bnn2); + secp256k1_num_div(&bnc1, &bnc1, order); + + secp256k1_num_mul(&bnc2, &na, &c->b1); + secp256k1_num_add(&bnc2, &bnc2, &bnn2); + secp256k1_num_div(&bnc2, &bnc2, order); + + secp256k1_num_mul(&bnt1, &bnc1, &c->a1b2); + secp256k1_num_mul(&bnt2, &bnc2, &c->a2); + secp256k1_num_add(&bnt1, &bnt1, &bnt2); + secp256k1_num_sub(&rn1, &na, &bnt1); + secp256k1_num_mul(&bnt1, &bnc1, &c->b1); + secp256k1_num_mul(&bnt2, &bnc2, &c->a1b2); + secp256k1_num_sub(&rn2, &bnt1, &bnt2); + + secp256k1_num_get_bin(b, 32, &rn1); + secp256k1_scalar_set_b32(r1, b, NULL); + if (secp256k1_num_is_neg(&rn1)) { + secp256k1_scalar_negate(r1, r1); + } + secp256k1_num_get_bin(b, 32, &rn2); + secp256k1_scalar_set_b32(r2, b, NULL); + if (secp256k1_num_is_neg(&rn2)) { + secp256k1_scalar_negate(r2, r2); + } +} +#endif + #endif diff --git a/src/secp256k1.c b/src/secp256k1.c index 1ab5b37..20fc27d 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -21,6 +21,8 @@ void secp256k1_start(unsigned int flags) { secp256k1_fe_start(); secp256k1_ge_start(); + secp256k1_scalar_start(); + secp256k1_ecdsa_start(); if (flags & SECP256K1_START_SIGN) { secp256k1_ecmult_gen_start(); } @@ -32,6 +34,8 @@ void secp256k1_start(unsigned int flags) { void secp256k1_stop(void) { secp256k1_ecmult_stop(); secp256k1_ecmult_gen_stop(); + secp256k1_ecdsa_stop(); + secp256k1_scalar_stop(); secp256k1_ge_stop(); secp256k1_fe_stop(); } @@ -43,11 +47,13 @@ int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned DEBUG_CHECK(sig != NULL); DEBUG_CHECK(pubkey != NULL); + unsigned char msg32[32] = {0}; + memcpy(msg32 + 32 - msglen, msg, msglen); int ret = -3; - secp256k1_num_t m; + secp256k1_scalar_t m; secp256k1_ecdsa_sig_t s; secp256k1_ge_t q; - secp256k1_num_set_bin(&m, msg, msglen); + secp256k1_scalar_set_b32(&m, msg32, NULL); if (!secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen)) { ret = -1; @@ -123,8 +129,8 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, u ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid); } if (ret) { - secp256k1_num_get_bin(sig64, 32, &sig.r); - secp256k1_num_get_bin(sig64 + 32, 32, &sig.s); + secp256k1_scalar_get_b32(sig64, &sig.r); + secp256k1_scalar_get_b32(sig64 + 32, &sig.s); } secp256k1_scalar_clear(&msg); secp256k1_scalar_clear(&non); @@ -142,11 +148,20 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const DEBUG_CHECK(recid >= 0 && recid <= 3); int ret = 0; - secp256k1_num_t m; + unsigned char msg32[32] = {0}; + memcpy(msg32 + 32 - msglen, msg, msglen); + secp256k1_scalar_t m; secp256k1_ecdsa_sig_t sig; - secp256k1_num_set_bin(&sig.r, sig64, 32); - secp256k1_num_set_bin(&sig.s, sig64 + 32, 32); - secp256k1_num_set_bin(&m, msg, msglen); + int overflow = 0; + secp256k1_scalar_set_b32(&sig.r, sig64, &overflow); + if (overflow) { + return 0; + } + secp256k1_scalar_set_b32(&sig.s, sig64 + 32, &overflow); + if (overflow) { + return 0; + } + secp256k1_scalar_set_b32(&m, msg32, NULL); secp256k1_ge_t q; if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) { @@ -224,8 +239,12 @@ int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const un DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(tweak != NULL); - secp256k1_num_t term; - secp256k1_num_set_bin(&term, tweak, 32); + secp256k1_scalar_t term; + int overflow = 0; + secp256k1_scalar_set_b32(&term, tweak, &overflow); + if (overflow) { + return 0; + } secp256k1_ge_t p; int ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen); if (ret) { @@ -264,8 +283,12 @@ int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const un DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(tweak != NULL); - secp256k1_num_t factor; - secp256k1_num_set_bin(&factor, tweak, 32); + secp256k1_scalar_t factor; + int overflow = 0; + secp256k1_scalar_set_b32(&factor, tweak, &overflow); + if (overflow) { + return 0; + } secp256k1_ge_t p; int ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen); if (ret) { diff --git a/src/tests.c b/src/tests.c index 143f913..6830f74 100644 --- a/src/tests.c +++ b/src/tests.c @@ -100,6 +100,18 @@ void random_scalar_order_test(secp256k1_scalar_t *num) { } while(1); } +void random_scalar_order(secp256k1_scalar_t *num) { + do { + unsigned char b32[32]; + secp256k1_rand256(b32); + int overflow = 0; + secp256k1_scalar_set_b32(num, b32, &overflow); + if (overflow || secp256k1_scalar_is_zero(num)) + continue; + break; + } while(1); +} + void random_num_order(secp256k1_num_t *num) { do { unsigned char b32[32]; @@ -113,39 +125,6 @@ void random_num_order(secp256k1_num_t *num) { } while(1); } -void test_num_copy_inc_cmp(void) { - secp256k1_num_t n1,n2; - random_num_order(&n1); - secp256k1_num_copy(&n2, &n1); - CHECK(secp256k1_num_eq(&n1, &n2)); - CHECK(secp256k1_num_eq(&n2, &n1)); - secp256k1_num_inc(&n2); - CHECK(!secp256k1_num_eq(&n1, &n2)); - CHECK(!secp256k1_num_eq(&n2, &n1)); -} - - -void test_num_get_set_hex(void) { - secp256k1_num_t n1,n2; - random_num_order_test(&n1); - char c[64]; - secp256k1_num_get_hex(c, 64, &n1); - secp256k1_num_set_hex(&n2, c, 64); - CHECK(secp256k1_num_eq(&n1, &n2)); - for (int i=0; i<64; i++) { - /* check whether the lower 4 bits correspond to the last hex character */ - int low1 = secp256k1_num_shift(&n1, 4); - int lowh = c[63]; - int low2 = ((lowh>>6)*9+(lowh-'0'))&15; - CHECK(low1 == low2); - /* shift bits off the hex representation, and compare */ - memmove(c+1, c, 63); - c[0] = '0'; - secp256k1_num_set_hex(&n2, c, 64); - CHECK(secp256k1_num_eq(&n1, &n2)); - } -} - void test_num_get_set_bin(void) { secp256k1_num_t n1,n2; random_num_order_test(&n1); @@ -166,18 +145,6 @@ void test_num_get_set_bin(void) { } } -void run_num_int(void) { - secp256k1_num_t n1; - for (int i=-255; i<256; i++) { - unsigned char c1[3] = {}; - c1[2] = abs(i); - unsigned char c2[3] = {0x11,0x22,0x33}; - secp256k1_num_set_int(&n1, i); - secp256k1_num_get_bin(c2, 3, &n1); - CHECK(memcmp(c1, c2, 3) == 0); - } -} - void test_num_negate(void) { secp256k1_num_t n1; secp256k1_num_t n2; @@ -229,25 +196,14 @@ void test_num_add_sub(void) { void run_num_smalltests(void) { for (int i=0; i<100*count; i++) { - test_num_copy_inc_cmp(); - test_num_get_set_hex(); test_num_get_set_bin(); test_num_negate(); test_num_add_sub(); } - run_num_int(); } /***** SCALAR TESTS *****/ -int secp256k1_scalar_eq(const secp256k1_scalar_t *s1, const secp256k1_scalar_t *s2) { - secp256k1_scalar_t t; - secp256k1_scalar_negate(&t, s2); - secp256k1_scalar_add(&t, &t, s1); - int ret = secp256k1_scalar_is_zero(&t); - return ret; -} - void scalar_test(void) { unsigned char c[32]; @@ -278,15 +234,38 @@ void scalar_test(void) { { /* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */ - secp256k1_num_t n, t, m; - secp256k1_num_set_int(&n, 0); - secp256k1_num_set_int(&m, 16); + secp256k1_scalar_t n; + secp256k1_scalar_set_int(&n, 0); for (int i = 0; i < 256; i += 4) { - secp256k1_num_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); - secp256k1_num_mul(&n, &n, &m); - secp256k1_num_add(&n, &n, &t); + secp256k1_scalar_t t; + secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); + for (int j = 0; j < 4; j++) { + secp256k1_scalar_add(&n, &n, &n); + } + secp256k1_scalar_add(&n, &n, &t); } - CHECK(secp256k1_num_eq(&n, &snum)); + CHECK(secp256k1_scalar_eq(&n, &s)); + } + + { + /* Test that fetching groups of randomly-sized bits from a scalar and recursing n(i)=b*n(i-1)+p(i) reconstructs it. */ + secp256k1_scalar_t n; + secp256k1_scalar_set_int(&n, 0); + int i = 0; + while (i < 256) { + int now = (secp256k1_rand32() % 15) + 1; + if (now + i > 256) { + now = 256 - i; + } + secp256k1_scalar_t t; + secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_var(&s, 256 - now - i, now)); + for (int j = 0; j < now; j++) { + secp256k1_scalar_add(&n, &n, &n); + } + secp256k1_scalar_add(&n, &n, &t); + i += now; + } + CHECK(secp256k1_scalar_eq(&n, &s)); } { @@ -382,6 +361,24 @@ void scalar_test(void) { CHECK(secp256k1_scalar_eq(&r1, &r2)); } + { + /* Test add_bit. */ + int bit = secp256k1_rand32() % 256; + secp256k1_scalar_t b; + secp256k1_scalar_set_int(&b, 1); + CHECK(secp256k1_scalar_is_one(&b)); + for (int i = 0; i < bit; i++) { + secp256k1_scalar_add(&b, &b, &b); + } + secp256k1_scalar_t r1 = s1, r2 = s1; + secp256k1_scalar_add(&r1, &r1, &b); + if (!(secp256k1_scalar_get_bits(&s1, 255, 1) == 1 && secp256k1_scalar_get_bits(&r1, 255, 1) == 0)) { + /* No overflow happened. */ + secp256k1_scalar_add_bit(&r2, bit); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + } + { /* Test commutativity of mul. */ secp256k1_scalar_t r1, r2; @@ -705,35 +702,47 @@ void run_ecmult_chain(void) { secp256k1_fe_t ay; VERIFY_CHECK(secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64)); secp256k1_gej_t a; secp256k1_gej_set_xy(&a, &ax, &ay); /* two random initial factors xn and gn */ - secp256k1_num_t xn; - secp256k1_num_set_hex(&xn, "84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407", 64); - secp256k1_num_t gn; - secp256k1_num_set_hex(&gn, "a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de", 64); + static const unsigned char xni[32] = { + 0x84, 0xcc, 0x54, 0x52, 0xf7, 0xfd, 0xe1, 0xed, + 0xb4, 0xd3, 0x8a, 0x8c, 0xe9, 0xb1, 0xb8, 0x4c, + 0xce, 0xf3, 0x1f, 0x14, 0x6e, 0x56, 0x9b, 0xe9, + 0x70, 0x5d, 0x35, 0x7a, 0x42, 0x98, 0x54, 0x07 + }; + secp256k1_scalar_t xn; + secp256k1_scalar_set_b32(&xn, xni, NULL); + static const unsigned char gni[32] = { + 0xa1, 0xe5, 0x8d, 0x22, 0x55, 0x3d, 0xcd, 0x42, + 0xb2, 0x39, 0x80, 0x62, 0x5d, 0x4c, 0x57, 0xa9, + 0x6e, 0x93, 0x23, 0xd4, 0x2b, 0x31, 0x52, 0xe5, + 0xca, 0x2c, 0x39, 0x90, 0xed, 0xc7, 0xc9, 0xde + }; + secp256k1_scalar_t gn; + secp256k1_scalar_set_b32(&gn, gni, NULL); /* two small multipliers to be applied to xn and gn in every iteration: */ - secp256k1_num_t xf; - secp256k1_num_set_hex(&xf, "1337", 4); - secp256k1_num_t gf; - secp256k1_num_set_hex(&gf, "7113", 4); + static const unsigned char xfi[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x13,0x37}; + secp256k1_scalar_t xf; + secp256k1_scalar_set_b32(&xf, xfi, NULL); + static const unsigned char gfi[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x71,0x13}; + secp256k1_scalar_t gf; + secp256k1_scalar_set_b32(&gf, gfi, NULL); /* accumulators with the resulting coefficients to A and G */ - secp256k1_num_t ae; - secp256k1_num_set_int(&ae, 1); - secp256k1_num_t ge; - secp256k1_num_set_int(&ge, 0); + secp256k1_scalar_t ae; + secp256k1_scalar_set_int(&ae, 1); + secp256k1_scalar_t ge; + secp256k1_scalar_set_int(&ge, 0); /* the point being computed */ secp256k1_gej_t x = a; - const secp256k1_num_t *order = &secp256k1_ge_consts->order; for (int i=0; i<200*count; i++) { /* in each iteration, compute X = xn*X + gn*G; */ secp256k1_ecmult(&x, &x, &xn, &gn); /* also compute ae and ge: the actual accumulated factors for A and G */ /* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */ - secp256k1_num_mod_mul(&ae, &ae, &xn, order); - secp256k1_num_mod_mul(&ge, &ge, &xn, order); - secp256k1_num_add(&ge, &ge, &gn); - secp256k1_num_mod(&ge, order); + secp256k1_scalar_mul(&ae, &ae, &xn); + secp256k1_scalar_mul(&ge, &ge, &xn); + secp256k1_scalar_add(&ge, &ge, &gn); /* modify xn and gn */ - secp256k1_num_mod_mul(&xn, &xn, &xf, order); - secp256k1_num_mod_mul(&gn, &gn, &gf, order); + secp256k1_scalar_mul(&xn, &xn, &xf); + secp256k1_scalar_mul(&gn, &gn, &gf); /* verify */ if (i == 19999) { @@ -753,13 +762,16 @@ void run_ecmult_chain(void) { } void test_point_times_order(const secp256k1_gej_t *point) { - /* multiplying a point by the order results in O */ - const secp256k1_num_t *order = &secp256k1_ge_consts->order; - secp256k1_num_t zero; - secp256k1_num_set_int(&zero, 0); - secp256k1_gej_t res; - secp256k1_ecmult(&res, point, order, order); /* calc res = order * point + order * G; */ - CHECK(secp256k1_gej_is_infinity(&res)); + /* X * (point + G) + (order-X) * (pointer + G) = 0 */ + secp256k1_scalar_t x; + random_scalar_order_test(&x); + secp256k1_scalar_t nx; + secp256k1_scalar_negate(&nx, &x); + secp256k1_gej_t res1, res2; + secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */ + secp256k1_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ + secp256k1_gej_add_var(&res1, &res1, &res2); + CHECK(secp256k1_gej_is_infinity(&res1)); } void run_point_times_order(void) { @@ -780,15 +792,16 @@ void run_point_times_order(void) { CHECK(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0); } -void test_wnaf(const secp256k1_num_t *number, int w) { - secp256k1_num_t x, two, t; - secp256k1_num_set_int(&x, 0); - secp256k1_num_set_int(&two, 2); - int wnaf[257]; +void test_wnaf(const secp256k1_scalar_t *number, int w) { + secp256k1_scalar_t x, two, t; + secp256k1_scalar_set_int(&x, 0); + secp256k1_scalar_set_int(&two, 2); + int wnaf[256]; int bits = secp256k1_ecmult_wnaf(wnaf, number, w); + CHECK(bits <= 256); int zeroes = -1; for (int i=bits-1; i>=0; i--) { - secp256k1_num_mul(&x, &x, &two); + secp256k1_scalar_mul(&x, &x, &two); int v = wnaf[i]; if (v) { CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */ @@ -800,18 +813,23 @@ void test_wnaf(const secp256k1_num_t *number, int w) { CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */ zeroes++; } - secp256k1_num_set_int(&t, v); - secp256k1_num_add(&x, &x, &t); + if (v >= 0) { + secp256k1_scalar_set_int(&t, v); + } else { + secp256k1_scalar_set_int(&t, -v); + secp256k1_scalar_negate(&t, &t); + } + secp256k1_scalar_add(&x, &x, &t); } - CHECK(secp256k1_num_eq(&x, number)); /* check that wnaf represents number */ + CHECK(secp256k1_scalar_eq(&x, number)); /* check that wnaf represents number */ } void run_wnaf(void) { - secp256k1_num_t n; + secp256k1_scalar_t n; for (int i=0; i