diff --git a/Makefile b/Makefile index eebc6e9c..1c093f89 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,11 @@ OBJS := default: all +ifeq ($(CONF), gmpgmp) +FLAGS_COMMON := $(FLAGS_COMMON) -DUSE_NUM_GMP -DUSE_FIELD_GMP +LIBS := -lgmp +SECP256K1_FILES := $(SECP256K1_FILES) src/num_gmp.h src/num_gmp.c src/field_gmp.c src/field_gmp.h +else ifeq ($(CONF), gmp32) FLAGS_COMMON := $(FLAGS_COMMON) -DUSE_NUM_GMP -DUSE_FIELD_10X26 LIBS := -lgmp @@ -45,11 +50,12 @@ endif endif endif endif - +endif all: src/*.c src/*.asm src/*.h include/*.h +make CONF=openssl all-openssl +make CONF=gmp all-gmp + +make CONF=gmpgmp all-gmpgmp +make CONF=gmp32 all-gmp32 +make CONF=gmpasm all-gmpasm diff --git a/src/field.c b/src/field.c index e7c636e0..26c721b3 100644 --- a/src/field.c +++ b/src/field.c @@ -1,8 +1,12 @@ +#ifdef USE_FIELD_GMP +#include "field_gmp.c" +#else #ifdef USE_FIELD_10X26 #include "field_10x26.c" #else #include "field_5x52.c" #endif +#endif void static secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a) { if (*rlen < 65) { diff --git a/src/field.h b/src/field.h index a2896073..604873e6 100644 --- a/src/field.h +++ b/src/field.h @@ -12,11 +12,15 @@ * normality. */ +#ifdef USE_FIELD_GMP +#include "field_gmp.h" +#else #ifdef USE_FIELD_10X26 #include "field_10x26.h" #else #include "field_5x52.h" #endif +#endif typedef struct { secp256k1_num_t p; diff --git a/src/field_gmp.c b/src/field_gmp.c new file mode 100644 index 00000000..a34667b7 --- /dev/null +++ b/src/field_gmp.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include "num.h" +#include "field.h" + +void static secp256k1_fe_normalize(secp256k1_fe_t *r) { +#if (GMP_NUMB_BITS >= 40) + if (r->n[FIELD_LIMBS] == 0) + return; + mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * r->n[FIELD_LIMBS]); + mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * carry); + r->n[FIELD_LIMBS] = 0; + int overflow = 1; + for (int i=FIELD_LIMBS-1; i>0; i--) + overflow &= (r->n[i] == GMP_NUMB_MASK); + overflow &= (r->n[0] >= GMP_NUMB_MASK - 0x1000003D0ULL); + if (overflow) { + for (int i=FIELD_LIMBS-1; i>0; i--) + r->n[i] = 0; + r->n[0] -= (GMP_NUMB_MASK - 0x1000003D0ULL); + } +#else +# error "GMP_NUMB_BITS too low" +#endif +} + +void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) { + r->n[0] = a; + for (int i=1; in[i] = 0; +} + +// TODO: not constant time! +int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) { + int ret = 1; + for (int i=0; in[i] == 0); + return ret; +} + +int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) { + return a->n[0] & 1; +} + +// TODO: not constant time! +int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { + int ret = 1; + for (int i=0; in[i] == b->n[i]); + return ret; +} + +void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { + for (int i=0; in[i] = 0; + for (int i=0; i<256; i++) { + int limb = i/GMP_NUMB_BITS; + int shift = i%GMP_NUMB_BITS; + r->n[limb] |= (mp_limb_t)((a[31-i/8] >> (i%8)) & 0x1) << shift; + } +} + +/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ +void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) { + for (int i=0; i<32; i++) { + int c = 0; + for (int j=0; j<8; j++) { + int limb = (8*i+j)/GMP_NUMB_BITS; + int shift = (8*i+j)%GMP_NUMB_BITS; + c |= ((a->n[limb] >> shift) & 0x1) << j; + } + r[31-i] = c; + } +} + +void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) { + *r = *a; + secp256k1_fe_normalize(r); + for (int i=0; in[i] = ~(r->n[i]); +#if (GMP_NUMB_BITS >= 33) + mpn_sub_1(r->n, r->n, FIELD_LIMBS, 0x1000003D0ULL); +#else + mpn_sub_1(r->n, r->n, FIELD_LIMBS, 0x3D0UL); + mpn_sub_1(r->n+1, r->n+1, FIELD_LIMBS-1, 0x1); +#endif +} + +void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) { + mpn_mul_1(r->n, r->n, FIELD_LIMBS+1, a); +} + +void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) { + mpn_add(r->n, r->n, FIELD_LIMBS+1, a->n, FIELD_LIMBS+1); +} + +void static secp256k1_fe_reduce(secp256k1_fe_t *r, mp_limb_t *tmp) { + mp_limb_t o = mpn_addmul_1(tmp, tmp+FIELD_LIMBS, FIELD_LIMBS, 0x1000003D1); + mp_limb_t q[2]; + q[1] = mpn_mul_1(q, &o, 1, 0x1000003D1); + r->n[FIELD_LIMBS] = mpn_add(r->n, tmp, FIELD_LIMBS, q, 2); +} + +void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) { + secp256k1_fe_t ac = *a; + secp256k1_fe_t bc = *b; + secp256k1_fe_normalize(&ac); + secp256k1_fe_normalize(&bc); + mp_limb_t tmp[2*FIELD_LIMBS]; + mpn_mul_n(tmp, ac.n, bc.n, FIELD_LIMBS); + secp256k1_fe_reduce(r, tmp); +} + +void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) { + secp256k1_fe_t ac = *a; + secp256k1_fe_normalize(&ac); + mp_limb_t tmp[2*FIELD_LIMBS]; + mpn_sqr(tmp, ac.n, FIELD_LIMBS); + secp256k1_fe_reduce(r, tmp); +} diff --git a/src/field_gmp.h b/src/field_gmp.h new file mode 100644 index 00000000..03b83aac --- /dev/null +++ b/src/field_gmp.h @@ -0,0 +1,12 @@ +#ifndef _SECP256K1_FIELD_GMP_ +#define _SECP256K1_FIELD_GMP_ + +#include + +#define FIELD_LIMBS ((256 + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS) + +typedef struct { + mp_limb_t n[FIELD_LIMBS+1]; +} secp256k1_fe_t; + +#endif