diff --git a/src/bench_internal.c b/src/bench_internal.c index 0809f77b..6fdd9f9c 100644 --- a/src/bench_internal.c +++ b/src/bench_internal.c @@ -251,7 +251,7 @@ void bench_wnaf_const(void* arg) { bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 20000; i++) { - secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A); + secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A, 256, 1); secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } diff --git a/src/bench_rangeproof.c b/src/bench_rangeproof.c index 54776b72..f3faafb5 100644 --- a/src/bench_rangeproof.c +++ b/src/bench_rangeproof.c @@ -53,8 +53,6 @@ int main(void) { bench_rangeproof_t data; data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - secp256k1_pedersen_context_initialize(data.ctx); - secp256k1_rangeproof_context_initialize(data.ctx); data.min_bits = 32; diff --git a/src/ecmult_const.h b/src/ecmult_const.h index 2b009765..ce2bc5e0 100644 --- a/src/ecmult_const.h +++ b/src/ecmult_const.h @@ -10,6 +10,6 @@ #include "scalar.h" #include "group.h" -static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); +static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q, int bits); #endif diff --git a/src/ecmult_const_impl.h b/src/ecmult_const_impl.h index 0db314c4..5281d134 100644 --- a/src/ecmult_const_impl.h +++ b/src/ecmult_const_impl.h @@ -12,12 +12,7 @@ #include "ecmult_const.h" #include "ecmult_impl.h" -#ifdef USE_ENDOMORPHISM - #define WNAF_BITS 128 -#else - #define WNAF_BITS 256 -#endif -#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w)) +#define WNAF_SIZE(bits, w) (((bits) + (w) - 1) / (w)) /* This is like `ECMULT_TABLE_GET_GE` but is constant time */ #define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ @@ -54,7 +49,7 @@ * * Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335 */ -static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { +static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w, int size, int maybe_negative) { int global_sign; int skew = 0; int word = 0; @@ -75,26 +70,34 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { * or 2 (for odd) to the number we are encoding, returning a skew value indicating * this, and having the caller compensate after doing the multiplication. */ - /* Negative numbers will be negated to keep their bit representation below the maximum width */ - flip = secp256k1_scalar_is_high(&s); - /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ - bit = flip ^ !secp256k1_scalar_is_even(&s); - /* We check for negative one, since adding 2 to it will cause an overflow */ - secp256k1_scalar_negate(&neg_s, &s); - not_neg_one = !secp256k1_scalar_is_one(&neg_s); - secp256k1_scalar_cadd_bit(&s, bit, not_neg_one); - /* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects - * that we added two to it and flipped it. In fact for -1 these operations are - * identical. We only flipped, but since skewing is required (in the sense that - * the skew must be 1 or 2, never zero) and flipping is not, we need to change - * our flags to claim that we only skewed. */ - global_sign = secp256k1_scalar_cond_negate(&s, flip); - global_sign *= not_neg_one * 2 - 1; - skew = 1 << bit; + if (maybe_negative) { + /* Negative numbers will be negated to keep their bit representation below the maximum width */ + flip = maybe_negative ? secp256k1_scalar_is_high(&s) : 0; + /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ + bit = flip ^ !secp256k1_scalar_is_even(&s); + /* We check for negative one, since adding 2 to it will cause an overflow */ + secp256k1_scalar_negate(&neg_s, &s); + not_neg_one = !secp256k1_scalar_is_one(&neg_s); + secp256k1_scalar_cadd_bit(&s, bit, not_neg_one); + /* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects + * that we added two to it and flipped it. In fact for -1 these operations are + * identical. We only flipped, but since skewing is required (in the sense that + * the skew must be 1 or 2, never zero) and flipping is not, we need to change + * our flags to claim that we only skewed. */ + global_sign = secp256k1_scalar_cond_negate(&s, flip); + global_sign *= not_neg_one * 2 - 1; + skew = 1 << bit; + } else { + VERIFY_CHECK(!secp256k1_scalar_is_high(&s)); + bit = !secp256k1_scalar_is_even(&s); + skew = 1 << bit; + secp256k1_scalar_cadd_bit(&s, bit, 1); + global_sign = 1; + } /* 4 */ u_last = secp256k1_scalar_shr_int(&s, w); - while (word * w < WNAF_BITS) { + do { int sign; int even; @@ -110,41 +113,50 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { wnaf[word++] = u_last * global_sign; u_last = u; - } + } while(word * w < size); wnaf[word] = u * global_sign; VERIFY_CHECK(secp256k1_scalar_is_zero(&s)); - VERIFY_CHECK(word == WNAF_SIZE(w)); + VERIFY_CHECK(word == WNAF_SIZE(size, w)); return skew; } - -static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) { +static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar, int size) { secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_ge tmpa; secp256k1_fe Z; int skew_1; - int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; #ifdef USE_ENDOMORPHISM secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; - int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)]; + int wnaf_1[1 + WNAF_SIZE(128, WINDOW_A - 1)]; + int wnaf_lam[1 + WNAF_SIZE(128, WINDOW_A - 1)]; int skew_lam; secp256k1_scalar q_1, q_lam; +#else + int wnaf_1[1 + WNAF_SIZE(256, WINDOW_A - 1)]; #endif int i; secp256k1_scalar sc = *scalar; /* build wnaf representation for q. */ + int rsize = size; #ifdef USE_ENDOMORPHISM - /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ - secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc); - skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1); - skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1); -#else - skew_1 = secp256k1_wnaf_const(wnaf_1, sc, WINDOW_A - 1); + if (size > 128) { + rsize = 128; + /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ + secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc); + skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1, 128, 1); + skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1, 128, 1); + } else #endif + { + skew_1 = secp256k1_wnaf_const(wnaf_1, sc, WINDOW_A - 1, size, size == 256); +#ifdef USE_ENDOMORPHISM + skew_lam = 0; +#endif + } /* Calculate odd multiples of a. * All multiples are brought to the same Z 'denominator', which is stored @@ -158,26 +170,30 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons secp256k1_fe_normalize_weak(&pre_a[i].y); } #ifdef USE_ENDOMORPHISM - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); + if (size > 128) { + for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { + secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); + } } #endif /* first loop iteration (separated out so we can directly set r, rather * than having it start at infinity, get doubled several times, then have * its new value added to it) */ - i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)]; + i = wnaf_1[WNAF_SIZE(rsize, WINDOW_A - 1)]; VERIFY_CHECK(i != 0); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); secp256k1_gej_set_ge(r, &tmpa); #ifdef USE_ENDOMORPHISM - i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)]; - VERIFY_CHECK(i != 0); - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A); - secp256k1_gej_add_ge(r, r, &tmpa); + if (size > 128) { + i = wnaf_lam[WNAF_SIZE(rsize, WINDOW_A - 1)]; + VERIFY_CHECK(i != 0); + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A); + secp256k1_gej_add_ge(r, r, &tmpa); + } #endif /* remaining loop iterations */ - for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) { + for (i = WNAF_SIZE(rsize, WINDOW_A - 1) - 1; i >= 0; i--) { int n; int j; for (j = 0; j < WINDOW_A - 1; ++j) { @@ -189,10 +205,12 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons VERIFY_CHECK(n != 0); secp256k1_gej_add_ge(r, r, &tmpa); #ifdef USE_ENDOMORPHISM - n = wnaf_lam[i]; - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); - VERIFY_CHECK(n != 0); - secp256k1_gej_add_ge(r, r, &tmpa); + if (size > 128) { + n = wnaf_lam[i]; + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); + VERIFY_CHECK(n != 0); + secp256k1_gej_add_ge(r, r, &tmpa); + } #endif } @@ -212,14 +230,18 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons secp256k1_ge_set_gej(&correction, &tmpj); secp256k1_ge_to_storage(&correction_1_stor, a); #ifdef USE_ENDOMORPHISM - secp256k1_ge_to_storage(&correction_lam_stor, a); + if (size > 128) { + secp256k1_ge_to_storage(&correction_lam_stor, a); + } #endif secp256k1_ge_to_storage(&a2_stor, &correction); /* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */ secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2); #ifdef USE_ENDOMORPHISM - secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); + if (size > 128) { + secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); + } #endif /* Apply the correction */ @@ -228,10 +250,12 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons secp256k1_gej_add_ge(r, r, &correction); #ifdef USE_ENDOMORPHISM - secp256k1_ge_from_storage(&correction, &correction_lam_stor); - secp256k1_ge_neg(&correction, &correction); - secp256k1_ge_mul_lambda(&correction, &correction); - secp256k1_gej_add_ge(r, r, &correction); + if (size > 128) { + secp256k1_ge_from_storage(&correction, &correction_lam_stor); + secp256k1_ge_neg(&correction, &correction); + secp256k1_ge_mul_lambda(&correction, &correction); + secp256k1_gej_add_ge(r, r, &correction); + } #endif } } diff --git a/src/modules/ecdh/main_impl.h b/src/modules/ecdh/main_impl.h index 9e30fb73..42909a7d 100644 --- a/src/modules/ecdh/main_impl.h +++ b/src/modules/ecdh/main_impl.h @@ -30,7 +30,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se unsigned char y[1]; secp256k1_sha256_t sha; - secp256k1_ecmult_const(&res, &pt, &s); + secp256k1_ecmult_const(&res, &pt, &s, 256); secp256k1_ge_set_gej(&pt, &res); /* Compute a hash of the point in compressed form * Note we cannot use secp256k1_eckey_pubkey_serialize here since it does not diff --git a/src/modules/rangeproof/main_impl.h b/src/modules/rangeproof/main_impl.h index d6104fd2..20f05a05 100644 --- a/src/modules/rangeproof/main_impl.h +++ b/src/modules/rangeproof/main_impl.h @@ -11,10 +11,6 @@ #include "modules/rangeproof/borromean_impl.h" #include "modules/rangeproof/rangeproof_impl.h" -void secp256k1_pedersen_context_initialize(secp256k1_context* ctx) { - secp256k1_pedersen_context_build(&ctx->pedersen_ctx, &ctx->error_callback); -} - /* Generates a pedersen commitment: *commit = blind * G + value * G2. The commitment is 33 bytes, the blinding factor is 32 bytes.*/ int secp256k1_pedersen_commit(const secp256k1_context* ctx, unsigned char *commit, unsigned char *blind, uint64_t value) { secp256k1_gej rj; @@ -25,12 +21,11 @@ int secp256k1_pedersen_commit(const secp256k1_context* ctx, unsigned char *commi int ret = 0; ARG_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx)); ARG_CHECK(commit != NULL); ARG_CHECK(blind != NULL); secp256k1_scalar_set_b32(&sec, blind, &overflow); if (!overflow) { - secp256k1_pedersen_ecmult(&ctx->ecmult_gen_ctx, &ctx->pedersen_ctx, &rj, &sec, value); + secp256k1_pedersen_ecmult(&ctx->ecmult_gen_ctx, &rj, &sec, value); if (!secp256k1_gej_is_infinity(&rj)) { secp256k1_ge_set_gej(&r, &rj); sz = 33; @@ -80,14 +75,13 @@ int secp256k1_pedersen_verify_tally(const secp256k1_context* ctx, const unsigned ARG_CHECK(ctx != NULL); ARG_CHECK(!pcnt || (commits != NULL)); ARG_CHECK(!ncnt || (ncommits != NULL)); - ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx)); secp256k1_gej_set_infinity(&accj); if (excess) { uint64_t ex; int neg; /* Take the absolute value, and negate the result if the input was negative. */ neg = secp256k1_sign_and_abs64(&ex, excess); - secp256k1_pedersen_ecmult_small(&ctx->pedersen_ctx, &accj, ex); + secp256k1_pedersen_ecmult_small(&accj, ex); if (neg) { secp256k1_gej_neg(&accj, &accj); } @@ -108,10 +102,6 @@ int secp256k1_pedersen_verify_tally(const secp256k1_context* ctx, const unsigned return secp256k1_gej_is_infinity(&accj); } -void secp256k1_rangeproof_context_initialize(secp256k1_context* ctx) { - secp256k1_rangeproof_context_build(&ctx->rangeproof_ctx, &ctx->error_callback); -} - int secp256k1_rangeproof_info(const secp256k1_context* ctx, int *exp, int *mantissa, uint64_t *min_value, uint64_t *max_value, const unsigned char *proof, int plen) { int offset; @@ -137,9 +127,7 @@ int secp256k1_rangeproof_rewind(const secp256k1_context* ctx, ARG_CHECK(max_value != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx)); - ARG_CHECK(secp256k1_rangeproof_context_is_built(&ctx->rangeproof_ctx)); - return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, &ctx->pedersen_ctx, &ctx->rangeproof_ctx, + return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, blind_out, value_out, message_out, outlen, nonce, min_value, max_value, commit, proof, plen); } @@ -151,9 +139,7 @@ int secp256k1_rangeproof_verify(const secp256k1_context* ctx, uint64_t *min_valu ARG_CHECK(min_value != NULL); ARG_CHECK(max_value != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx)); - ARG_CHECK(secp256k1_rangeproof_context_is_built(&ctx->rangeproof_ctx)); - return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, NULL, &ctx->pedersen_ctx, &ctx->rangeproof_ctx, + return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, NULL, NULL, NULL, NULL, NULL, NULL, min_value, max_value, commit, proof, plen); } @@ -167,9 +153,7 @@ int secp256k1_rangeproof_sign(const secp256k1_context* ctx, unsigned char *proof ARG_CHECK(nonce != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx)); - ARG_CHECK(secp256k1_rangeproof_context_is_built(&ctx->rangeproof_ctx)); - return secp256k1_rangeproof_sign_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, &ctx->pedersen_ctx, &ctx->rangeproof_ctx, + return secp256k1_rangeproof_sign_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, proof, plen, min_value, commit, blind, nonce, exp, min_bits, value); } diff --git a/src/modules/rangeproof/pedersen.h b/src/modules/rangeproof/pedersen.h index f167d4df..cdfe2f8e 100644 --- a/src/modules/rangeproof/pedersen.h +++ b/src/modules/rangeproof/pedersen.h @@ -12,23 +12,10 @@ #include -typedef struct { - secp256k1_ge_storage (*prec)[16][16]; /* prec[j][i] = 16^j * i * G + U_i */ -} secp256k1_pedersen_context; - -static void secp256k1_pedersen_context_init(secp256k1_pedersen_context* ctx); -static void secp256k1_pedersen_context_build(secp256k1_pedersen_context* ctx, const secp256k1_callback* cb); -static void secp256k1_pedersen_context_clone(secp256k1_pedersen_context *dst, - const secp256k1_pedersen_context* src, const secp256k1_callback* cb); -static void secp256k1_pedersen_context_clear(secp256k1_pedersen_context* ctx); - -static int secp256k1_pedersen_context_is_built(const secp256k1_pedersen_context* ctx); - /** Multiply a small number with the generator: r = gn*G2 */ -static void secp256k1_pedersen_ecmult_small(const secp256k1_pedersen_context *ctx, secp256k1_gej *r, uint64_t gn); +static void secp256k1_pedersen_ecmult_small(secp256k1_gej *r, uint64_t gn); /* sec * G + value * G2. */ -static void secp256k1_pedersen_ecmult(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, - const secp256k1_pedersen_context *pedersen_ctx, secp256k1_gej *rj, const secp256k1_scalar *sec, uint64_t value); +static void secp256k1_pedersen_ecmult(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_gej *rj, const secp256k1_scalar *sec, uint64_t value); #endif diff --git a/src/modules/rangeproof/pedersen_impl.h b/src/modules/rangeproof/pedersen_impl.h index c2a169af..3ce2767c 100644 --- a/src/modules/rangeproof/pedersen_impl.h +++ b/src/modules/rangeproof/pedersen_impl.h @@ -20,117 +20,32 @@ static const secp256k1_ge secp256k1_ge_const_g2 = SECP256K1_GE_CONST( 0x36dac28aUL, 0xf1766968UL, 0xc30c2313UL, 0xf3a38904UL ); -static void secp256k1_pedersen_context_init(secp256k1_pedersen_context *ctx) { - ctx->prec = NULL; +static void secp256k1_pedersen_scalar_set_u64(secp256k1_scalar *sec, uint64_t value) { + unsigned char data[32]; + int i; + for (i = 0; i < 24; i++) { + data[i] = 0; + } + for (; i < 32; i++) { + data[i] = value >> 56; + value <<= 8; + } + secp256k1_scalar_set_b32(sec, data, NULL); + memset(data, 0, 32); } -static void secp256k1_pedersen_context_build(secp256k1_pedersen_context *ctx, const secp256k1_callback *cb) { - secp256k1_ge prec[256]; - secp256k1_gej gj; - secp256k1_gej nums_gej; - int i, j; - - if (ctx->prec != NULL) { - return; - } - - ctx->prec = (secp256k1_ge_storage (*)[16][16])checked_malloc(cb, sizeof(*ctx->prec)); - - /* get the generator */ - secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g2); - - /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ - { - static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; - secp256k1_fe nums_x; - secp256k1_ge nums_ge; - VERIFY_CHECK(secp256k1_fe_set_b32(&nums_x, nums_b32)); - VERIFY_CHECK(secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0)); - secp256k1_gej_set_ge(&nums_gej, &nums_ge); - /* Add G to make the bits in x uniformly distributed. */ - secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g2, NULL); - } - - /* compute prec. */ - { - secp256k1_gej precj[256]; /* Jacobian versions of prec. */ - secp256k1_gej gbase; - secp256k1_gej numsbase; - gbase = gj; /* 16^j * G */ - numsbase = nums_gej; /* 2^j * nums. */ - for (j = 0; j < 16; j++) { - /* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */ - precj[j*16] = numsbase; - for (i = 1; i < 16; i++) { - secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase, NULL); - } - /* Multiply gbase by 16. */ - for (i = 0; i < 4; i++) { - secp256k1_gej_double_var(&gbase, &gbase, NULL); - } - /* Multiply numbase by 2. */ - secp256k1_gej_double_var(&numsbase, &numsbase, NULL); - if (j == 14) { - /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ - secp256k1_gej_neg(&numsbase, &numsbase); - secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); - } - } - secp256k1_ge_set_all_gej_var(prec, precj, 256, cb); - } - for (j = 0; j < 16; j++) { - for (i = 0; i < 16; i++) { - secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]); - } - } -} - -static int secp256k1_pedersen_context_is_built(const secp256k1_pedersen_context* ctx) { - return ctx->prec != NULL; -} - -static void secp256k1_pedersen_context_clone(secp256k1_pedersen_context *dst, - const secp256k1_pedersen_context *src, const secp256k1_callback *cb) { - if (src->prec == NULL) { - dst->prec = NULL; - } else { - dst->prec = (secp256k1_ge_storage (*)[16][16])checked_malloc(cb, sizeof(*dst->prec)); - memcpy(dst->prec, src->prec, sizeof(*dst->prec)); - } -} - -static void secp256k1_pedersen_context_clear(secp256k1_pedersen_context *ctx) { - free(ctx->prec); - ctx->prec = NULL; -} - -/* Version of secp256k1_ecmult_gen using the second generator and working only on numbers in the range [0 .. 2^64). */ -static void secp256k1_pedersen_ecmult_small(const secp256k1_pedersen_context *ctx, secp256k1_gej *r, uint64_t gn) { - secp256k1_ge add; - secp256k1_ge_storage adds; - int bits; - int i, j; - memset(&adds, 0, sizeof(adds)); - secp256k1_gej_set_infinity(r); - add.infinity = 0; - for (j = 0; j < 16; j++) { - bits = (gn >> (j * 4)) & 15; - for (i = 0; i < 16; i++) { - secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits); - } - secp256k1_ge_from_storage(&add, &adds); - secp256k1_gej_add_ge(r, r, &add); - } - bits = 0; - secp256k1_ge_clear(&add); +static void secp256k1_pedersen_ecmult_small(secp256k1_gej *r, uint64_t gn) { + secp256k1_scalar s; + secp256k1_pedersen_scalar_set_u64(&s, gn); + secp256k1_ecmult_const(r, &secp256k1_ge_const_g2, &s, 64); + secp256k1_scalar_clear(&s); } /* sec * G + value * G2. */ -SECP256K1_INLINE static void secp256k1_pedersen_ecmult(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, - const secp256k1_pedersen_context *pedersen_ctx, secp256k1_gej *rj, const secp256k1_scalar *sec, uint64_t value) { +SECP256K1_INLINE static void secp256k1_pedersen_ecmult(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_gej *rj, const secp256k1_scalar *sec, uint64_t value) { secp256k1_gej vj; secp256k1_ecmult_gen(ecmult_gen_ctx, rj, sec); - secp256k1_pedersen_ecmult_small(pedersen_ctx, &vj, value); + secp256k1_pedersen_ecmult_small(&vj, value); /* FIXME: constant time. */ secp256k1_gej_add_var(rj, rj, &vj, NULL); secp256k1_gej_clear(&vj); diff --git a/src/modules/rangeproof/rangeproof.h b/src/modules/rangeproof/rangeproof.h index e6d99717..b0f53696 100644 --- a/src/modules/rangeproof/rangeproof.h +++ b/src/modules/rangeproof/rangeproof.h @@ -10,21 +10,8 @@ #include "scalar.h" #include "group.h" -typedef struct { - secp256k1_ge_storage (*prec)[1005]; -} secp256k1_rangeproof_context; - - -static void secp256k1_rangeproof_context_init(secp256k1_rangeproof_context* ctx); -static void secp256k1_rangeproof_context_build(secp256k1_rangeproof_context* ctx, const secp256k1_callback* cb); -static void secp256k1_rangeproof_context_clone(secp256k1_rangeproof_context *dst, - const secp256k1_rangeproof_context* src, const secp256k1_callback* cb); -static void secp256k1_rangeproof_context_clear(secp256k1_rangeproof_context* ctx); -static int secp256k1_rangeproof_context_is_built(const secp256k1_rangeproof_context* ctx); - static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_context* ecmult_ctx, const secp256k1_ecmult_gen_context* ecmult_gen_ctx, - const secp256k1_pedersen_context* pedersen_ctx, const secp256k1_rangeproof_context* rangeproof_ctx, unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, int *outlen, const unsigned char *nonce, uint64_t *min_value, uint64_t *max_value, const unsigned char *commit, const unsigned char *proof, int plen); diff --git a/src/modules/rangeproof/rangeproof_impl.h b/src/modules/rangeproof/rangeproof_impl.h index a1d20fc8..94956eb8 100644 --- a/src/modules/rangeproof/rangeproof_impl.h +++ b/src/modules/rangeproof/rangeproof_impl.h @@ -15,107 +15,9 @@ #include "modules/rangeproof/pedersen.h" #include "modules/rangeproof/borromean.h" -static const int secp256k1_rangeproof_offsets[20] = { - 0, 96, 189, 276, 360, 438, 510, 579, 642, - 699, 753, 801, 843, 882, 915, 942, 966, 984, - 996, 1005, -}; - -static void secp256k1_rangeproof_context_init(secp256k1_rangeproof_context *ctx) { - ctx->prec = NULL; -} - -static void secp256k1_rangeproof_context_build(secp256k1_rangeproof_context *ctx, const secp256k1_callback* cb) { - secp256k1_ge *prec; - secp256k1_gej *precj; - secp256k1_gej gj; - secp256k1_gej one; - int i, pos; - - if (ctx->prec != NULL) { - return; - } - - precj = (secp256k1_gej (*))checked_malloc(cb, sizeof(*precj) * 1005); - if (precj == NULL) { - return; - } - prec = (secp256k1_ge (*))checked_malloc(cb, sizeof(*prec) * 1005); - if (prec == NULL) { - free(precj); - return; - } - - /* get the generator */ - secp256k1_gej_set_ge(&one, &secp256k1_ge_const_g2); - secp256k1_gej_neg(&one, &one); - - /* compute prec. */ - pos = 0; - for (i = 0; i < 19; i++) { - int pmax; - pmax = secp256k1_rangeproof_offsets[i + 1]; - gj = one; - while (pos < pmax) { - precj[pos] = gj; - pos++; - secp256k1_gej_double_var(&precj[pos], &gj, NULL); - pos++; - secp256k1_gej_add_var(&precj[pos], &precj[pos - 1], &gj, NULL); - pos++; - if (pos < pmax - 1) { - secp256k1_gej_double_var(&gj, &precj[pos - 2], NULL); - } - } - if (i < 18) { - secp256k1_gej_double_var(&gj, &one, NULL); - one = gj; - secp256k1_gej_double_var(&gj, &gj, NULL); - secp256k1_gej_double_var(&gj, &gj, NULL); - secp256k1_gej_add_var(&one, &one, &gj, NULL); - } - } - VERIFY_CHECK(pos == 1005); - secp256k1_ge_set_all_gej_var(prec, precj, 1005, cb); - - free(precj); - - ctx->prec = (secp256k1_ge_storage (*)[1005])checked_malloc(cb, sizeof(*ctx->prec)); - if (ctx->prec == NULL) { - free(prec); - return; - } - - for (i = 0; i < 1005; i++) { - secp256k1_ge_to_storage(&(*ctx->prec)[i], &prec[i]); - } - free(prec); -} - - -static int secp256k1_rangeproof_context_is_built(const secp256k1_rangeproof_context* ctx) { - return ctx->prec != NULL; -} - -static void secp256k1_rangeproof_context_clone(secp256k1_rangeproof_context *dst, - const secp256k1_rangeproof_context *src, const secp256k1_callback* cb) { - if (src->prec == NULL) { - dst->prec = NULL; - } else { - dst->prec = (secp256k1_ge_storage (*)[1005])checked_malloc(cb, sizeof(*dst->prec)); - memcpy(dst->prec, src->prec, sizeof(*dst->prec)); - } -} - -static void secp256k1_rangeproof_context_clear(secp256k1_rangeproof_context *ctx) { - free(ctx->prec); - ctx->prec = NULL; -} - -SECP256K1_INLINE static void secp256k1_rangeproof_pub_expand(const secp256k1_rangeproof_context *ctx, secp256k1_gej *pubs, +SECP256K1_INLINE static void secp256k1_rangeproof_pub_expand(secp256k1_gej *pubs, int exp, int *rsizes, int rings) { - secp256k1_ge ge; - secp256k1_ge_storage *basis; + secp256k1_gej base; int i; int j; int npub; @@ -123,12 +25,24 @@ SECP256K1_INLINE static void secp256k1_rangeproof_pub_expand(const secp256k1_ran if (exp < 0) { exp = 0; } - basis = &(*ctx->prec)[secp256k1_rangeproof_offsets[exp]]; + secp256k1_gej_set_ge(&base, &secp256k1_ge_const_g2); + secp256k1_gej_neg(&base, &base); + while (exp--) { + /* Multiplication by 10 */ + secp256k1_gej tmp; + secp256k1_gej_double_var(&tmp, &base, NULL); + secp256k1_gej_double_var(&base, &tmp, NULL); + secp256k1_gej_double_var(&base, &base, NULL); + secp256k1_gej_add_var(&base, &base, &tmp, NULL); + } npub = 0; for (i = 0; i < rings; i++) { for (j = 1; j < rsizes[i]; j++) { - secp256k1_ge_from_storage(&ge, &basis[i * 3 + j - 1]); - secp256k1_gej_add_ge_var(&pubs[npub + j], &pubs[npub], &ge, NULL); + secp256k1_gej_add_var(&pubs[npub + j], &pubs[npub + j - 1], &base, NULL); + } + if (i < rings - 1) { + secp256k1_gej_double_var(&base, &base, NULL); + secp256k1_gej_double_var(&base, &base, NULL); } npub += rsizes[i]; } @@ -264,8 +178,8 @@ SECP256K1_INLINE static int secp256k1_range_proveparams(uint64_t *v, int *rings, /* strawman interface, writes proof in proof, a buffer of plen, proves with respect to min_value the range for commit which has the provided blinding factor and value. */ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmult_context* ecmult_ctx, - const secp256k1_ecmult_gen_context* ecmult_gen_ctx, const secp256k1_pedersen_context* pedersen_ctx, - const secp256k1_rangeproof_context* rangeproof_ctx, unsigned char *proof, int *plen, uint64_t min_value, + const secp256k1_ecmult_gen_context* ecmult_gen_ctx, + unsigned char *proof, int *plen, uint64_t min_value, const unsigned char *commit, const unsigned char *blind, const unsigned char *nonce, int exp, int min_bits, uint64_t value){ secp256k1_gej pubs[128]; /* Candidate digits for our proof, most inferred. */ secp256k1_scalar s[128]; /* Signatures in our proof, most forged. */ @@ -357,7 +271,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul npub = 0; for (i = 0; i < rings; i++) { /*OPT: Use the precomputed gen2 basis?*/ - secp256k1_pedersen_ecmult(ecmult_gen_ctx, pedersen_ctx, &pubs[npub], &sec[i], ((uint64_t)secidx[i] * scale) << (i*2)); + secp256k1_pedersen_ecmult(ecmult_gen_ctx, &pubs[npub], &sec[i], ((uint64_t)secidx[i] * scale) << (i*2)); if (secp256k1_gej_is_infinity(&pubs[npub])) { return 0; } @@ -376,7 +290,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul } npub += rsizes[i]; } - secp256k1_rangeproof_pub_expand(rangeproof_ctx, pubs, exp, rsizes, rings); + secp256k1_rangeproof_pub_expand(pubs, exp, rsizes, rings); secp256k1_sha256_finalize(&sha256_m, tmp); if (!secp256k1_borromean_sign(ecmult_ctx, ecmult_gen_ctx, &proof[len], s, pubs, k, sec, rsizes, secidx, rings, tmp, 32)) { return 0; @@ -596,7 +510,6 @@ SECP256K1_INLINE static int secp256k1_rangeproof_getheader_impl(int *offset, int /* Verifies range proof (len plen) for 33-byte commit, the min/max values proven are put in the min/max arguments; returns 0 on failure 1 on success.*/ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_context* ecmult_ctx, const secp256k1_ecmult_gen_context* ecmult_gen_ctx, - const secp256k1_pedersen_context* pedersen_ctx, const secp256k1_rangeproof_context* rangeproof_ctx, unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, int *outlen, const unsigned char *nonce, uint64_t *min_value, uint64_t *max_value, const unsigned char *commit, const unsigned char *proof, int plen) { secp256k1_gej accj; @@ -660,7 +573,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm npub = 0; secp256k1_gej_set_infinity(&accj); if (*min_value) { - secp256k1_pedersen_ecmult_small(pedersen_ctx, &accj, *min_value); + secp256k1_pedersen_ecmult_small(&accj, *min_value); } for(i = 0; i < rings - 1; i++) { memcpy(&m[1], &proof[offset], 32); @@ -682,7 +595,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm if (secp256k1_gej_is_infinity(&pubs[npub])) { return 0; } - secp256k1_rangeproof_pub_expand(rangeproof_ctx, pubs, exp, rsizes, rings); + secp256k1_rangeproof_pub_expand(pubs, exp, rsizes, rings); npub += rsizes[rings - 1]; e0 = &proof[offset]; offset += 32; @@ -713,7 +626,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm /* Unwind apparently successful, see if the commitment can be reconstructed. */ /* FIXME: should check vv is in the mantissa's range. */ vv = (vv * scale) + *min_value; - secp256k1_pedersen_ecmult(ecmult_gen_ctx, pedersen_ctx, &accj, &blind, vv); + secp256k1_pedersen_ecmult(ecmult_gen_ctx, &accj, &blind, vv); if (secp256k1_gej_is_infinity(&accj)) { return 0; } diff --git a/src/modules/rangeproof/tests_impl.h b/src/modules/rangeproof/tests_impl.h index e764e69f..4e601697 100644 --- a/src/modules/rangeproof/tests_impl.h +++ b/src/modules/rangeproof/tests_impl.h @@ -267,8 +267,6 @@ void test_rangeproof(void) { void run_rangeproof_tests(void) { int i; - secp256k1_pedersen_context_initialize(ctx); - secp256k1_rangeproof_context_initialize(ctx); for (i = 0; i < 10*count; i++) { test_pedersen(); } diff --git a/src/secp256k1.c b/src/secp256k1.c index 3a8ea58a..95759ba7 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -56,10 +56,6 @@ static const secp256k1_callback default_error_callback = { struct secp256k1_context_struct { secp256k1_ecmult_context ecmult_ctx; secp256k1_ecmult_gen_context ecmult_gen_ctx; -#ifdef ENABLE_MODULE_RANGEPROOF - secp256k1_pedersen_context pedersen_ctx; - secp256k1_rangeproof_context rangeproof_ctx; -#endif secp256k1_callback illegal_callback; secp256k1_callback error_callback; }; @@ -78,10 +74,6 @@ secp256k1_context* secp256k1_context_create(unsigned int flags) { secp256k1_ecmult_context_init(&ret->ecmult_ctx); secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); -#ifdef ENABLE_MODULE_RANGEPROOF - secp256k1_pedersen_context_init(&ret->pedersen_ctx); - secp256k1_rangeproof_context_init(&ret->rangeproof_ctx); -#endif if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback); @@ -99,10 +91,6 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { ret->error_callback = ctx->error_callback; secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback); secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback); -#ifdef ENABLE_MODULE_RANGEPROOF - secp256k1_pedersen_context_clone(&ret->pedersen_ctx, &ctx->pedersen_ctx, &ctx->error_callback); - secp256k1_rangeproof_context_clone(&ret->rangeproof_ctx, &ctx->rangeproof_ctx, &ctx->error_callback); -#endif return ret; } @@ -110,10 +98,6 @@ void secp256k1_context_destroy(secp256k1_context* ctx) { if (ctx != NULL) { secp256k1_ecmult_context_clear(&ctx->ecmult_ctx); secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); -#ifdef ENABLE_MODULE_RANGEPROOF - secp256k1_pedersen_context_clear(&ctx->pedersen_ctx); - secp256k1_rangeproof_context_clear(&ctx->rangeproof_ctx); -#endif free(ctx); } diff --git a/src/tests.c b/src/tests.c index 9c913e4a..6b1dcb2e 100644 --- a/src/tests.c +++ b/src/tests.c @@ -2451,7 +2451,7 @@ void ecmult_const_random_mult(void) { 0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956 ); secp256k1_gej b; - secp256k1_ecmult_const(&b, &a, &xn); + secp256k1_ecmult_const(&b, &a, &xn, 256); CHECK(secp256k1_ge_is_valid_var(&a)); ge_equals_gej(&expected_b, &b); @@ -2467,12 +2467,12 @@ void ecmult_const_commutativity(void) { random_scalar_order_test(&a); random_scalar_order_test(&b); - secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a); - secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b); + secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a, 256); + secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b, 256); secp256k1_ge_set_gej(&mid1, &res1); secp256k1_ge_set_gej(&mid2, &res2); - secp256k1_ecmult_const(&res1, &mid1, &b); - secp256k1_ecmult_const(&res2, &mid2, &a); + secp256k1_ecmult_const(&res1, &mid1, &b, 256); + secp256k1_ecmult_const(&res2, &mid2, &a, 256); secp256k1_ge_set_gej(&mid1, &res1); secp256k1_ge_set_gej(&mid2, &res2); ge_equals_ge(&mid1, &mid2); @@ -2488,13 +2488,13 @@ void ecmult_const_mult_zero_one(void) { secp256k1_scalar_negate(&negone, &one); random_group_element_test(&point); - secp256k1_ecmult_const(&res1, &point, &zero); + secp256k1_ecmult_const(&res1, &point, &zero, 3); secp256k1_ge_set_gej(&res2, &res1); CHECK(secp256k1_ge_is_infinity(&res2)); - secp256k1_ecmult_const(&res1, &point, &one); + secp256k1_ecmult_const(&res1, &point, &one, 2); secp256k1_ge_set_gej(&res2, &res1); ge_equals_ge(&res2, &point); - secp256k1_ecmult_const(&res1, &point, &negone); + secp256k1_ecmult_const(&res1, &point, &negone, 256); secp256k1_gej_neg(&res1, &res1); secp256k1_ge_set_gej(&res2, &res1); ge_equals_ge(&res2, &point); @@ -2520,7 +2520,7 @@ void ecmult_const_chain_multiply(void) { for (i = 0; i < 100; ++i) { secp256k1_ge tmp; secp256k1_ge_set_gej(&tmp, &point); - secp256k1_ecmult_const(&point, &tmp, &scalar); + secp256k1_ecmult_const(&point, &tmp, &scalar, 256); } secp256k1_ge_set_gej(&res, &point); ge_equals_gej(&res, &expected_point); @@ -2587,6 +2587,7 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) { int wnaf[256] = {0}; int i; int skew; + int bits = 256; secp256k1_scalar num = *number; secp256k1_scalar_set_int(&x, 0); @@ -2596,10 +2597,11 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) { for (i = 0; i < 16; ++i) { secp256k1_scalar_shr_int(&num, 8); } + bits = 128; #endif - skew = secp256k1_wnaf_const(wnaf, num, w); + skew = secp256k1_wnaf_const(wnaf, num, w, bits, 1); - for (i = WNAF_SIZE(w); i >= 0; --i) { + for (i = WNAF_SIZE(bits, w); i >= 0; --i) { secp256k1_scalar t; int v = wnaf[i]; CHECK(v != 0); /* check nonzero */