Merge #830: Rip out non-endomorphism code + dependencies

c582abade1c50ef50dc7ee9f7b7af8e06e22065d Consistency improvements to the comments (Pieter Wuille)
63c6b71616816b19bec9cb3ab6b45ae5afd955f0 Reorder comments/function around scalar_split_lambda (Pieter Wuille)
2edc514c90293af8f602e4376e832773779c9426 WNAF of lambda_split output has max size 129 (Pieter Wuille)
4232e5b7da0a68adc14fa4b481f7e106403c200d Rip out non-endomorphism code (Pieter Wuille)
ebad8414b0e68041568d0b5ebe0bd395dbfbed9e Check correctness of lambda split without -DVERIFY (Gregory Maxwell)
fe7fc1fda8675aa9d79dae54a1b8b3cd06abcf81 Make lambda constant accessible (Pieter Wuille)
9d2f2b44d895509e8c4e7831fa917f13fa69f054 Add tests to exercise lambda split near bounds (Pieter Wuille)
9aca2f7f07b0563f8c65fcc22a0a91325cf6273b Add secp256k1_split_lambda_verify (Russell O'Connor)
acab934d24ff26289ab9930587c3fc51c30c6a2f Detailed comments for secp256k1_scalar_split_lambda (Russell O'Connor)
76ed922a5f09d63e0622825ca83d9301c1ef3efe Increase precision of g1 and g2 (Russell O'Connor)
6173839c90553385171d560be8a17cbe167e3bef Switch to our own memcmp function (Tim Ruffing)

Pull request description:

  This is a rebased/combined version of the following pull requests/commits with minor changes:
  * #825 Switch to our own memcmp function
    * Modification: `secp256k1_memcmp_var` is marked static inline
    * Modification: also replace `memcmp` with `secp256k1_memcmp_var` in exhaustive tests
    * Modification: add reference to GCC bug 95189
  * #822 Increase precision of g1 and g2
    * Modification: use the new `secp256k1_memcmp_var` function instead of `memcmp` (see https://github.com/bitcoin-core/secp256k1/pull/822#issuecomment-706610361)
    * Modification: drop the " Allow secp256k1_split_lambda_verify to pass even in the presence of GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95189." commit, as it's dealt with using `secp256k1_memcmp_var`.
    * Modification: rename secp256k1_gej_mul_lambda -> secp256k1_ge_mul_lambda
  * A new commit that moves the `lambda` constant out of `secp256k1_scalar_split_lambda` and (`_verify`).
  * The test commit suggested here: https://github.com/bitcoin-core/secp256k1/pull/822#issuecomment-706610276
    * Modification: use the new accessible `secp256k1_const_lambda` instead of duplicating it.
  * #826 Rip out non-endomorphism code
  * A new commit that reduces the size of the WNAF output to 129, as we now have proof that the split output is always 128 bits or less.
  * A new commit to more consistently use input:`k`, integer outputs:`k1`,`k2`, modulo n outputs:`r1`,`r2`

ACKs for top commit:
  real-or-random:
    ACK c582abade1c50ef50dc7ee9f7b7af8e06e22065d code inspection, some tests, verified the new g1/g2 constants
  jonasnick:
    ACK c582abade1c50ef50dc7ee9f7b7af8e06e22065d didn't verify the proof

Tree-SHA512: 323a3ee3884b7ac4fa85c8e7b785111b5c0638d718bc1c805a38963c87411e81a746c98e9a42a3e2197ab34a874544de5cc51326955d1c4d0ea45afd418e819f
This commit is contained in:
Pieter Wuille 2020-10-14 11:06:06 -07:00
commit c6b6b8f1bb
No known key found for this signature in database
GPG Key ID: A636E97631F767E0
28 changed files with 548 additions and 469 deletions

View File

@ -17,33 +17,29 @@ compiler:
- gcc - gcc
env: env:
global: global:
- WIDEMUL=auto BIGNUM=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ECMULTGENPRECISION=auto ASM=no BUILD=check WITH_VALGRIND=yes RUN_VALGRIND=no EXTRAFLAGS= HOST= ECDH=no RECOVERY=no SCHNORRSIG=no EXPERIMENTAL=no CTIMETEST=yes BENCH=yes ITERS=2 - WIDEMUL=auto BIGNUM=auto STATICPRECOMPUTATION=yes ECMULTGENPRECISION=auto ASM=no BUILD=check WITH_VALGRIND=yes RUN_VALGRIND=no EXTRAFLAGS= HOST= ECDH=no RECOVERY=no SCHNORRSIG=no EXPERIMENTAL=no CTIMETEST=yes BENCH=yes ITERS=2
matrix: matrix:
- WIDEMUL=int64 RECOVERY=yes - WIDEMUL=int64 RECOVERY=yes
- WIDEMUL=int64 ECDH=yes EXPERIMENTAL=yes SCHNORRSIG=yes - WIDEMUL=int64 ECDH=yes EXPERIMENTAL=yes SCHNORRSIG=yes
- WIDEMUL=int64 ENDOMORPHISM=yes
- WIDEMUL=int128 - WIDEMUL=int128
- WIDEMUL=int128 RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes - WIDEMUL=int128 RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes
- WIDEMUL=int128 ENDOMORPHISM=yes - WIDEMUL=int128 ECDH=yes EXPERIMENTAL=yes SCHNORRSIG=yes
- WIDEMUL=int128 ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes SCHNORRSIG=yes
- WIDEMUL=int128 ASM=x86_64 - WIDEMUL=int128 ASM=x86_64
- WIDEMUL=int128 ENDOMORPHISM=yes ASM=x86_64
- BIGNUM=no - BIGNUM=no
- BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes - BIGNUM=no RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes
- BIGNUM=no STATICPRECOMPUTATION=no - BIGNUM=no STATICPRECOMPUTATION=no
- BUILD=distcheck WITH_VALGRIND=no CTIMETEST=no BENCH=no - BUILD=distcheck WITH_VALGRIND=no CTIMETEST=no BENCH=no
- CPPFLAGS=-DDETERMINISTIC - CPPFLAGS=-DDETERMINISTIC
- CFLAGS=-O0 CTIMETEST=no - CFLAGS=-O0 CTIMETEST=no
- ECMULTGENPRECISION=2 - ECMULTGENPRECISION=2
- ECMULTGENPRECISION=8 - ECMULTGENPRECISION=8
- RUN_VALGRIND=yes ENDOMORPHISM=yes BIGNUM=no ASM=x86_64 EXPERIMENTAL=yes ECDH=yes RECOVERY=yes EXTRAFLAGS="--disable-openssl-tests" BUILD=
- RUN_VALGRIND=yes BIGNUM=no ASM=x86_64 EXPERIMENTAL=yes ECDH=yes RECOVERY=yes EXTRAFLAGS="--disable-openssl-tests" BUILD= - RUN_VALGRIND=yes BIGNUM=no ASM=x86_64 EXPERIMENTAL=yes ECDH=yes RECOVERY=yes EXTRAFLAGS="--disable-openssl-tests" BUILD=
matrix: matrix:
fast_finish: true fast_finish: true
include: include:
- compiler: clang - compiler: clang
os: linux os: linux
env: HOST=i686-linux-gnu ENDOMORPHISM=yes env: HOST=i686-linux-gnu
addons: addons:
apt: apt:
packages: packages:
@ -63,7 +59,7 @@ matrix:
- libtool-bin - libtool-bin
- libc6-dbg:i386 - libc6-dbg:i386
- compiler: gcc - compiler: gcc
env: HOST=i686-linux-gnu ENDOMORPHISM=yes env: HOST=i686-linux-gnu
os: linux os: linux
addons: addons:
apt: apt:

View File

@ -48,7 +48,7 @@ Implementation details
* Use wNAF notation for point multiplicands. * Use wNAF notation for point multiplicands.
* Use a much larger window for multiples of G, using precomputed multiples. * Use a much larger window for multiples of G, using precomputed multiples.
* Use Shamir's trick to do the multiplication with the public key and the generator simultaneously. * Use Shamir's trick to do the multiplication with the public key and the generator simultaneously.
* Optionally (off by default) use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones. * Use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones.
* Point multiplication for signing * Point multiplication for signing
* Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions. * Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions.
* Intended to be completely free of timing sidechannels for secret-key operations (on reasonable hardware/toolchains) * Intended to be completely free of timing sidechannels for secret-key operations (on reasonable hardware/toolchains)

View File

@ -116,11 +116,6 @@ AC_ARG_ENABLE(exhaustive_tests,
[use_exhaustive_tests=$enableval], [use_exhaustive_tests=$enableval],
[use_exhaustive_tests=yes]) [use_exhaustive_tests=yes])
AC_ARG_ENABLE(endomorphism,
AS_HELP_STRING([--enable-endomorphism],[enable endomorphism [default=no]]),
[use_endomorphism=$enableval],
[use_endomorphism=no])
AC_ARG_ENABLE(ecmult_static_precomputation, AC_ARG_ENABLE(ecmult_static_precomputation,
AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing [default=auto]]), AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing [default=auto]]),
[use_ecmult_static_precomputation=$enableval], [use_ecmult_static_precomputation=$enableval],
@ -164,8 +159,7 @@ AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto],
AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto], AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto],
[window size for ecmult precomputation for verification, specified as integer in range [2..24].] [window size for ecmult precomputation for verification, specified as integer in range [2..24].]
[Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.] [Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.]
[The table will store 2^(SIZE-2) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.] [The table will store 2^(SIZE-1) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.]
[If the endomorphism optimization is enabled, two tables of this size are used instead of only one.]
["auto" is a reasonable setting for desktop machines (currently 15). [default=auto]] ["auto" is a reasonable setting for desktop machines (currently 15). [default=auto]]
)], )],
[req_ecmult_window=$withval], [req_ecmult_window=auto]) [req_ecmult_window=$withval], [req_ecmult_window=auto])
@ -429,10 +423,6 @@ if test x"$set_bignum" = x"gmp"; then
SECP_INCLUDES="$SECP_INCLUDES $GMP_CPPFLAGS" SECP_INCLUDES="$SECP_INCLUDES $GMP_CPPFLAGS"
fi fi
if test x"$use_endomorphism" = x"yes"; then
AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization])
fi
if test x"$set_precomp" = x"yes"; then if test x"$set_precomp" = x"yes"; then
AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table]) AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table])
fi fi
@ -514,7 +504,6 @@ AC_OUTPUT
echo echo
echo "Build Options:" echo "Build Options:"
echo " with endomorphism = $use_endomorphism"
echo " with ecmult precomp = $set_precomp" echo " with ecmult precomp = $set_precomp"
echo " with external callbacks = $use_external_default_callbacks" echo " with external callbacks = $use_external_default_callbacks"
echo " with benchmarks = $use_benchmark" echo " with benchmarks = $use_benchmark"

View File

@ -13,7 +13,7 @@ then
fi fi
./configure \ ./configure \
--enable-experimental="$EXPERIMENTAL" --enable-endomorphism="$ENDOMORPHISM" \ --enable-experimental="$EXPERIMENTAL" \
--with-test-override-wide-multiply="$WIDEMUL" --with-bignum="$BIGNUM" --with-asm="$ASM" \ --with-test-override-wide-multiply="$WIDEMUL" --with-bignum="$BIGNUM" --with-asm="$ASM" \
--enable-ecmult-static-precomputation="$STATICPRECOMPUTATION" --with-ecmult-gen-precision="$ECMULTGENPRECISION" \ --enable-ecmult-static-precomputation="$STATICPRECOMPUTATION" --with-ecmult-gen-precision="$ECMULTGENPRECISION" \
--enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \ --enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \

View File

@ -11,7 +11,6 @@
#undef USE_ASM_X86_64 #undef USE_ASM_X86_64
#undef USE_ECMULT_STATIC_PRECOMPUTATION #undef USE_ECMULT_STATIC_PRECOMPUTATION
#undef USE_ENDOMORPHISM
#undef USE_EXTERNAL_ASM #undef USE_EXTERNAL_ASM
#undef USE_EXTERNAL_DEFAULT_CALLBACKS #undef USE_EXTERNAL_DEFAULT_CALLBACKS
#undef USE_FIELD_INV_BUILTIN #undef USE_FIELD_INV_BUILTIN

View File

@ -117,7 +117,6 @@ void bench_scalar_mul(void* arg, int iters) {
} }
} }
#ifdef USE_ENDOMORPHISM
void bench_scalar_split(void* arg, int iters) { void bench_scalar_split(void* arg, int iters) {
int i, j = 0; int i, j = 0;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -128,7 +127,6 @@ void bench_scalar_split(void* arg, int iters) {
} }
CHECK(j <= iters); CHECK(j <= iters);
} }
#endif
void bench_scalar_inverse(void* arg, int iters) { void bench_scalar_inverse(void* arg, int iters) {
int i, j = 0; int i, j = 0;
@ -397,9 +395,7 @@ int main(int argc, char **argv) {
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, iters*100); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, iters*100);
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, iters*10); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, iters*10);
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, iters*10); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, iters*10);
#ifdef USE_ENDOMORPHISM
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, iters); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, iters);
#endif
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, 2000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, 2000);
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, 2000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, 2000);

View File

@ -15,9 +15,7 @@
typedef struct { typedef struct {
/* For accelerating the computation of a*P + b*G: */ /* For accelerating the computation of a*P + b*G: */
secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */ secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */
#ifdef USE_ENDOMORPHISM
secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */ secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */
#endif
} secp256k1_ecmult_context; } secp256k1_ecmult_context;
static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE; static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;

View File

@ -140,19 +140,16 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
secp256k1_fe Z; secp256k1_fe Z;
int skew_1; int skew_1;
#ifdef USE_ENDOMORPHISM
secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)]; int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)];
int skew_lam; int skew_lam;
secp256k1_scalar q_1, q_lam; secp256k1_scalar q_1, q_lam;
#endif
int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)];
int i; int i;
/* build wnaf representation for q. */ /* build wnaf representation for q. */
int rsize = size; int rsize = size;
#ifdef USE_ENDOMORPHISM
if (size > 128) { if (size > 128) {
rsize = 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) */ /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
@ -160,12 +157,9 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
skew_1 = secp256k1_wnaf_const(wnaf_1, &q_1, WINDOW_A - 1, 128); skew_1 = secp256k1_wnaf_const(wnaf_1, &q_1, WINDOW_A - 1, 128);
skew_lam = secp256k1_wnaf_const(wnaf_lam, &q_lam, WINDOW_A - 1, 128); skew_lam = secp256k1_wnaf_const(wnaf_lam, &q_lam, WINDOW_A - 1, 128);
} else } else
#endif
{ {
skew_1 = secp256k1_wnaf_const(wnaf_1, scalar, WINDOW_A - 1, size); skew_1 = secp256k1_wnaf_const(wnaf_1, scalar, WINDOW_A - 1, size);
#ifdef USE_ENDOMORPHISM
skew_lam = 0; skew_lam = 0;
#endif
} }
/* Calculate odd multiples of a. /* Calculate odd multiples of a.
@ -179,14 +173,12 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
secp256k1_fe_normalize_weak(&pre_a[i].y); secp256k1_fe_normalize_weak(&pre_a[i].y);
} }
#ifdef USE_ENDOMORPHISM
if (size > 128) { if (size > 128) {
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_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 /* first loop iteration (separated out so we can directly set r, rather
* than having it start at infinity, get doubled several times, then have * than having it start at infinity, get doubled several times, then have
@ -195,14 +187,12 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
VERIFY_CHECK(i != 0); VERIFY_CHECK(i != 0);
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A);
secp256k1_gej_set_ge(r, &tmpa); secp256k1_gej_set_ge(r, &tmpa);
#ifdef USE_ENDOMORPHISM
if (size > 128) { if (size > 128) {
i = wnaf_lam[WNAF_SIZE_BITS(rsize, WINDOW_A - 1)]; i = wnaf_lam[WNAF_SIZE_BITS(rsize, WINDOW_A - 1)];
VERIFY_CHECK(i != 0); VERIFY_CHECK(i != 0);
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A);
secp256k1_gej_add_ge(r, r, &tmpa); secp256k1_gej_add_ge(r, r, &tmpa);
} }
#endif
/* remaining loop iterations */ /* remaining loop iterations */
for (i = WNAF_SIZE_BITS(rsize, WINDOW_A - 1) - 1; i >= 0; i--) { for (i = WNAF_SIZE_BITS(rsize, WINDOW_A - 1) - 1; i >= 0; i--) {
int n; int n;
@ -215,14 +205,12 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A);
VERIFY_CHECK(n != 0); VERIFY_CHECK(n != 0);
secp256k1_gej_add_ge(r, r, &tmpa); secp256k1_gej_add_ge(r, r, &tmpa);
#ifdef USE_ENDOMORPHISM
if (size > 128) { if (size > 128) {
n = wnaf_lam[i]; n = wnaf_lam[i];
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A);
VERIFY_CHECK(n != 0); VERIFY_CHECK(n != 0);
secp256k1_gej_add_ge(r, r, &tmpa); secp256k1_gej_add_ge(r, r, &tmpa);
} }
#endif
} }
secp256k1_fe_mul(&r->z, &r->z, &Z); secp256k1_fe_mul(&r->z, &r->z, &Z);
@ -231,43 +219,35 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
/* Correct for wNAF skew */ /* Correct for wNAF skew */
secp256k1_ge correction = *a; secp256k1_ge correction = *a;
secp256k1_ge_storage correction_1_stor; secp256k1_ge_storage correction_1_stor;
#ifdef USE_ENDOMORPHISM
secp256k1_ge_storage correction_lam_stor; secp256k1_ge_storage correction_lam_stor;
#endif
secp256k1_ge_storage a2_stor; secp256k1_ge_storage a2_stor;
secp256k1_gej tmpj; secp256k1_gej tmpj;
secp256k1_gej_set_ge(&tmpj, &correction); secp256k1_gej_set_ge(&tmpj, &correction);
secp256k1_gej_double_var(&tmpj, &tmpj, NULL); secp256k1_gej_double_var(&tmpj, &tmpj, NULL);
secp256k1_ge_set_gej(&correction, &tmpj); secp256k1_ge_set_gej(&correction, &tmpj);
secp256k1_ge_to_storage(&correction_1_stor, a); secp256k1_ge_to_storage(&correction_1_stor, a);
#ifdef USE_ENDOMORPHISM
if (size > 128) { if (size > 128) {
secp256k1_ge_to_storage(&correction_lam_stor, a); secp256k1_ge_to_storage(&correction_lam_stor, a);
} }
#endif
secp256k1_ge_to_storage(&a2_stor, &correction); secp256k1_ge_to_storage(&a2_stor, &correction);
/* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */ /* 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); secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2);
#ifdef USE_ENDOMORPHISM
if (size > 128) { if (size > 128) {
secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2);
} }
#endif
/* Apply the correction */ /* Apply the correction */
secp256k1_ge_from_storage(&correction, &correction_1_stor); secp256k1_ge_from_storage(&correction, &correction_1_stor);
secp256k1_ge_neg(&correction, &correction); secp256k1_ge_neg(&correction, &correction);
secp256k1_gej_add_ge(r, r, &correction); secp256k1_gej_add_ge(r, r, &correction);
#ifdef USE_ENDOMORPHISM
if (size > 128) { if (size > 128) {
secp256k1_ge_from_storage(&correction, &correction_lam_stor); secp256k1_ge_from_storage(&correction, &correction_lam_stor);
secp256k1_ge_neg(&correction, &correction); secp256k1_ge_neg(&correction, &correction);
secp256k1_ge_mul_lambda(&correction, &correction); secp256k1_ge_mul_lambda(&correction, &correction);
secp256k1_gej_add_ge(r, r, &correction); secp256k1_gej_add_ge(r, r, &correction);
} }
#endif
} }
} }

View File

@ -38,8 +38,8 @@
* (1 << (WINDOW_G - 2)) * sizeof(secp256k1_ge_storage) bytes, * (1 << (WINDOW_G - 2)) * sizeof(secp256k1_ge_storage) bytes,
* where sizeof(secp256k1_ge_storage) is typically 64 bytes but can * where sizeof(secp256k1_ge_storage) is typically 64 bytes but can
* be larger due to platform-specific padding and alignment. * be larger due to platform-specific padding and alignment.
* If the endomorphism optimization is enabled (USE_ENDOMORMPHSIM) * Two tables of this size are used (due to the endomorphism
* two tables of this size are used instead of only one. * optimization).
*/ */
# define WINDOW_G ECMULT_WINDOW_SIZE # define WINDOW_G ECMULT_WINDOW_SIZE
#endif #endif
@ -59,11 +59,7 @@
# error Set ECMULT_WINDOW_SIZE to an integer in range [2..24]. # error Set ECMULT_WINDOW_SIZE to an integer in range [2..24].
#endif #endif
#ifdef USE_ENDOMORPHISM #define WNAF_BITS 128
#define WNAF_BITS 128
#else
#define WNAF_BITS 256
#endif
#define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w)) #define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w))
#define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w) #define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w)
@ -77,17 +73,9 @@
#define PIPPENGER_MAX_BUCKET_WINDOW 12 #define PIPPENGER_MAX_BUCKET_WINDOW 12
/* Minimum number of points for which pippenger_wnaf is faster than strauss wnaf */ /* Minimum number of points for which pippenger_wnaf is faster than strauss wnaf */
#ifdef USE_ENDOMORPHISM #define ECMULT_PIPPENGER_THRESHOLD 88
#define ECMULT_PIPPENGER_THRESHOLD 88
#else
#define ECMULT_PIPPENGER_THRESHOLD 160
#endif
#ifdef USE_ENDOMORPHISM #define ECMULT_MAX_POINTS_PER_BATCH 5000000
#define ECMULT_MAX_POINTS_PER_BATCH 5000000
#else
#define ECMULT_MAX_POINTS_PER_BATCH 10000000
#endif
/** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain /** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain
* the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will * the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will
@ -313,16 +301,12 @@ static void secp256k1_ecmult_odd_multiples_table_storage_var(const int n, secp25
static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE = static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE =
ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)) ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G))
#ifdef USE_ENDOMORPHISM
+ ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)) + ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G))
#endif
; ;
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) { static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) {
ctx->pre_g = NULL; ctx->pre_g = NULL;
#ifdef USE_ENDOMORPHISM
ctx->pre_g_128 = NULL; ctx->pre_g_128 = NULL;
#endif
} }
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc) { static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc) {
@ -347,7 +331,6 @@ static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void *
/* precompute the tables with odd multiples */ /* precompute the tables with odd multiples */
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj); secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj);
#ifdef USE_ENDOMORPHISM
{ {
secp256k1_gej g_128j; secp256k1_gej g_128j;
int i; int i;
@ -364,7 +347,6 @@ static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void *
} }
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j); secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j);
} }
#endif
} }
static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src) { static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src) {
@ -372,11 +354,9 @@ static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *d
/* We cast to void* first to suppress a -Wcast-align warning. */ /* We cast to void* first to suppress a -Wcast-align warning. */
dst->pre_g = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g) - (unsigned char*)src)); dst->pre_g = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g) - (unsigned char*)src));
} }
#ifdef USE_ENDOMORPHISM
if (src->pre_g_128 != NULL) { if (src->pre_g_128 != NULL) {
dst->pre_g_128 = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g_128) - (unsigned char*)src)); dst->pre_g_128 = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g_128) - (unsigned char*)src));
} }
#endif
} }
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) { static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) {
@ -447,16 +427,11 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a,
} }
struct secp256k1_strauss_point_state { struct secp256k1_strauss_point_state {
#ifdef USE_ENDOMORPHISM
secp256k1_scalar na_1, na_lam; secp256k1_scalar na_1, na_lam;
int wnaf_na_1[130]; int wnaf_na_1[129];
int wnaf_na_lam[130]; int wnaf_na_lam[129];
int bits_na_1; int bits_na_1;
int bits_na_lam; int bits_na_lam;
#else
int wnaf_na[256];
int bits_na;
#endif
size_t input_pos; size_t input_pos;
}; };
@ -464,26 +439,19 @@ struct secp256k1_strauss_state {
secp256k1_gej* prej; secp256k1_gej* prej;
secp256k1_fe* zr; secp256k1_fe* zr;
secp256k1_ge* pre_a; secp256k1_ge* pre_a;
#ifdef USE_ENDOMORPHISM
secp256k1_ge* pre_a_lam; secp256k1_ge* pre_a_lam;
#endif
struct secp256k1_strauss_point_state* ps; struct secp256k1_strauss_point_state* ps;
}; };
static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, const struct secp256k1_strauss_state *state, secp256k1_gej *r, int num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, const struct secp256k1_strauss_state *state, secp256k1_gej *r, int num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
secp256k1_ge tmpa; secp256k1_ge tmpa;
secp256k1_fe Z; secp256k1_fe Z;
#ifdef USE_ENDOMORPHISM
/* Splitted G factors. */ /* Splitted G factors. */
secp256k1_scalar ng_1, ng_128; secp256k1_scalar ng_1, ng_128;
int wnaf_ng_1[129]; int wnaf_ng_1[129];
int bits_ng_1 = 0; int bits_ng_1 = 0;
int wnaf_ng_128[129]; int wnaf_ng_128[129];
int bits_ng_128 = 0; int bits_ng_128 = 0;
#else
int wnaf_ng[256];
int bits_ng = 0;
#endif
int i; int i;
int bits = 0; int bits = 0;
int np; int np;
@ -494,28 +462,20 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
continue; continue;
} }
state->ps[no].input_pos = np; state->ps[no].input_pos = np;
#ifdef USE_ENDOMORPHISM
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ /* 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_scalar_split_lambda(&state->ps[no].na_1, &state->ps[no].na_lam, &na[np]); secp256k1_scalar_split_lambda(&state->ps[no].na_1, &state->ps[no].na_lam, &na[np]);
/* build wnaf representation for na_1 and na_lam. */ /* build wnaf representation for na_1 and na_lam. */
state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_1, 130, &state->ps[no].na_1, WINDOW_A); state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_1, 129, &state->ps[no].na_1, WINDOW_A);
state->ps[no].bits_na_lam = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_lam, 130, &state->ps[no].na_lam, WINDOW_A); state->ps[no].bits_na_lam = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_lam, 129, &state->ps[no].na_lam, WINDOW_A);
VERIFY_CHECK(state->ps[no].bits_na_1 <= 130); VERIFY_CHECK(state->ps[no].bits_na_1 <= 129);
VERIFY_CHECK(state->ps[no].bits_na_lam <= 130); VERIFY_CHECK(state->ps[no].bits_na_lam <= 129);
if (state->ps[no].bits_na_1 > bits) { if (state->ps[no].bits_na_1 > bits) {
bits = state->ps[no].bits_na_1; bits = state->ps[no].bits_na_1;
} }
if (state->ps[no].bits_na_lam > bits) { if (state->ps[no].bits_na_lam > bits) {
bits = state->ps[no].bits_na_lam; bits = state->ps[no].bits_na_lam;
} }
#else
/* build wnaf representation for na. */
state->ps[no].bits_na = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na, 256, &na[np], WINDOW_A);
if (state->ps[no].bits_na > bits) {
bits = state->ps[no].bits_na;
}
#endif
++no; ++no;
} }
@ -547,7 +507,6 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
secp256k1_fe_set_int(&Z, 1); secp256k1_fe_set_int(&Z, 1);
} }
#ifdef USE_ENDOMORPHISM
for (np = 0; np < no; ++np) { for (np = 0; np < no; ++np) {
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
secp256k1_ge_mul_lambda(&state->pre_a_lam[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i]); secp256k1_ge_mul_lambda(&state->pre_a_lam[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i]);
@ -568,21 +527,12 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
bits = bits_ng_128; bits = bits_ng_128;
} }
} }
#else
if (ng) {
bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G);
if (bits_ng > bits) {
bits = bits_ng;
}
}
#endif
secp256k1_gej_set_infinity(r); secp256k1_gej_set_infinity(r);
for (i = bits - 1; i >= 0; i--) { for (i = bits - 1; i >= 0; i--) {
int n; int n;
secp256k1_gej_double_var(r, r, NULL); secp256k1_gej_double_var(r, r, NULL);
#ifdef USE_ENDOMORPHISM
for (np = 0; np < no; ++np) { for (np = 0; np < no; ++np) {
if (i < state->ps[np].bits_na_1 && (n = state->ps[np].wnaf_na_1[i])) { if (i < state->ps[np].bits_na_1 && (n = state->ps[np].wnaf_na_1[i])) {
ECMULT_TABLE_GET_GE(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); ECMULT_TABLE_GET_GE(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A);
@ -601,18 +551,6 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G); ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G);
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
} }
#else
for (np = 0; np < no; ++np) {
if (i < state->ps[np].bits_na && (n = state->ps[np].wnaf_na[i])) {
ECMULT_TABLE_GET_GE(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A);
secp256k1_gej_add_ge_var(r, r, &tmpa, NULL);
}
}
if (i < bits_ng && (n = wnaf_ng[i])) {
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G);
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
}
#endif
} }
if (!r->infinity) { if (!r->infinity) {
@ -625,27 +563,19 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
struct secp256k1_strauss_point_state ps[1]; struct secp256k1_strauss_point_state ps[1];
#ifdef USE_ENDOMORPHISM
secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
#endif
struct secp256k1_strauss_state state; struct secp256k1_strauss_state state;
state.prej = prej; state.prej = prej;
state.zr = zr; state.zr = zr;
state.pre_a = pre_a; state.pre_a = pre_a;
#ifdef USE_ENDOMORPHISM
state.pre_a_lam = pre_a_lam; state.pre_a_lam = pre_a_lam;
#endif
state.ps = ps; state.ps = ps;
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, 1, a, na, ng); secp256k1_ecmult_strauss_wnaf(ctx, &state, r, 1, a, na, ng);
} }
static size_t secp256k1_strauss_scratch_size(size_t n_points) { static size_t secp256k1_strauss_scratch_size(size_t n_points) {
#ifdef USE_ENDOMORPHISM
static const size_t point_size = (2 * sizeof(secp256k1_ge) + sizeof(secp256k1_gej) + sizeof(secp256k1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct secp256k1_strauss_point_state) + sizeof(secp256k1_gej) + sizeof(secp256k1_scalar); static const size_t point_size = (2 * sizeof(secp256k1_ge) + sizeof(secp256k1_gej) + sizeof(secp256k1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct secp256k1_strauss_point_state) + sizeof(secp256k1_gej) + sizeof(secp256k1_scalar);
#else
static const size_t point_size = (sizeof(secp256k1_ge) + sizeof(secp256k1_gej) + sizeof(secp256k1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct secp256k1_strauss_point_state) + sizeof(secp256k1_gej) + sizeof(secp256k1_scalar);
#endif
return n_points*point_size; return n_points*point_size;
} }
@ -665,12 +595,8 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
scalars = (secp256k1_scalar*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_scalar)); scalars = (secp256k1_scalar*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_scalar));
state.prej = (secp256k1_gej*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_gej)); state.prej = (secp256k1_gej*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_gej));
state.zr = (secp256k1_fe*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_fe)); state.zr = (secp256k1_fe*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_fe));
#ifdef USE_ENDOMORPHISM
state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(error_callback, scratch, n_points * 2 * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge)); state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(error_callback, scratch, n_points * 2 * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge));
state.pre_a_lam = state.pre_a + n_points * ECMULT_TABLE_SIZE(WINDOW_A); state.pre_a_lam = state.pre_a + n_points * ECMULT_TABLE_SIZE(WINDOW_A);
#else
state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge));
#endif
state.ps = (struct secp256k1_strauss_point_state*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(struct secp256k1_strauss_point_state)); state.ps = (struct secp256k1_strauss_point_state*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(struct secp256k1_strauss_point_state));
if (points == NULL || scalars == NULL || state.prej == NULL || state.zr == NULL || state.pre_a == NULL) { if (points == NULL || scalars == NULL || state.prej == NULL || state.zr == NULL || state.pre_a == NULL) {
@ -868,7 +794,6 @@ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_wi
* set of buckets) for a given number of points. * set of buckets) for a given number of points.
*/ */
static int secp256k1_pippenger_bucket_window(size_t n) { static int secp256k1_pippenger_bucket_window(size_t n) {
#ifdef USE_ENDOMORPHISM
if (n <= 1) { if (n <= 1) {
return 1; return 1;
} else if (n <= 4) { } else if (n <= 4) {
@ -892,33 +817,6 @@ static int secp256k1_pippenger_bucket_window(size_t n) {
} else { } else {
return PIPPENGER_MAX_BUCKET_WINDOW; return PIPPENGER_MAX_BUCKET_WINDOW;
} }
#else
if (n <= 1) {
return 1;
} else if (n <= 11) {
return 2;
} else if (n <= 45) {
return 3;
} else if (n <= 100) {
return 4;
} else if (n <= 275) {
return 5;
} else if (n <= 625) {
return 6;
} else if (n <= 1850) {
return 7;
} else if (n <= 3400) {
return 8;
} else if (n <= 9630) {
return 9;
} else if (n <= 17900) {
return 10;
} else if (n <= 32800) {
return 11;
} else {
return PIPPENGER_MAX_BUCKET_WINDOW;
}
#endif
} }
/** /**
@ -926,7 +824,6 @@ static int secp256k1_pippenger_bucket_window(size_t n) {
*/ */
static size_t secp256k1_pippenger_bucket_window_inv(int bucket_window) { static size_t secp256k1_pippenger_bucket_window_inv(int bucket_window) {
switch(bucket_window) { switch(bucket_window) {
#ifdef USE_ENDOMORPHISM
case 1: return 1; case 1: return 1;
case 2: return 4; case 2: return 4;
case 3: return 20; case 3: return 20;
@ -939,26 +836,11 @@ static size_t secp256k1_pippenger_bucket_window_inv(int bucket_window) {
case 10: return 7880; case 10: return 7880;
case 11: return 16050; case 11: return 16050;
case PIPPENGER_MAX_BUCKET_WINDOW: return SIZE_MAX; case PIPPENGER_MAX_BUCKET_WINDOW: return SIZE_MAX;
#else
case 1: return 1;
case 2: return 11;
case 3: return 45;
case 4: return 100;
case 5: return 275;
case 6: return 625;
case 7: return 1850;
case 8: return 3400;
case 9: return 9630;
case 10: return 17900;
case 11: return 32800;
case PIPPENGER_MAX_BUCKET_WINDOW: return SIZE_MAX;
#endif
} }
return 0; return 0;
} }
#ifdef USE_ENDOMORPHISM
SECP256K1_INLINE static void secp256k1_ecmult_endo_split(secp256k1_scalar *s1, secp256k1_scalar *s2, secp256k1_ge *p1, secp256k1_ge *p2) { SECP256K1_INLINE static void secp256k1_ecmult_endo_split(secp256k1_scalar *s1, secp256k1_scalar *s2, secp256k1_ge *p1, secp256k1_ge *p2) {
secp256k1_scalar tmp = *s1; secp256k1_scalar tmp = *s1;
secp256k1_scalar_split_lambda(s1, s2, &tmp); secp256k1_scalar_split_lambda(s1, s2, &tmp);
@ -973,32 +855,23 @@ SECP256K1_INLINE static void secp256k1_ecmult_endo_split(secp256k1_scalar *s1, s
secp256k1_ge_neg(p2, p2); secp256k1_ge_neg(p2, p2);
} }
} }
#endif
/** /**
* Returns the scratch size required for a given number of points (excluding * Returns the scratch size required for a given number of points (excluding
* base point G) without considering alignment. * base point G) without considering alignment.
*/ */
static size_t secp256k1_pippenger_scratch_size(size_t n_points, int bucket_window) { static size_t secp256k1_pippenger_scratch_size(size_t n_points, int bucket_window) {
#ifdef USE_ENDOMORPHISM
size_t entries = 2*n_points + 2; size_t entries = 2*n_points + 2;
#else
size_t entries = n_points + 1;
#endif
size_t entry_size = sizeof(secp256k1_ge) + sizeof(secp256k1_scalar) + sizeof(struct secp256k1_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int); size_t entry_size = sizeof(secp256k1_ge) + sizeof(secp256k1_scalar) + sizeof(struct secp256k1_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int);
return (sizeof(secp256k1_gej) << bucket_window) + sizeof(struct secp256k1_pippenger_state) + entries * entry_size; return (sizeof(secp256k1_gej) << bucket_window) + sizeof(struct secp256k1_pippenger_state) + entries * entry_size;
} }
static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch); const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch);
/* Use 2(n+1) with the endomorphism, n+1 without, when calculating batch /* Use 2(n+1) with the endomorphism, when calculating batch
* sizes. The reason for +1 is that we add the G scalar to the list of * sizes. The reason for +1 is that we add the G scalar to the list of
* other scalars. */ * other scalars. */
#ifdef USE_ENDOMORPHISM
size_t entries = 2*n_points + 2; size_t entries = 2*n_points + 2;
#else
size_t entries = n_points + 1;
#endif
secp256k1_ge *points; secp256k1_ge *points;
secp256k1_scalar *scalars; secp256k1_scalar *scalars;
secp256k1_gej *buckets; secp256k1_gej *buckets;
@ -1035,10 +908,8 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
scalars[0] = *inp_g_sc; scalars[0] = *inp_g_sc;
points[0] = secp256k1_ge_const_g; points[0] = secp256k1_ge_const_g;
idx++; idx++;
#ifdef USE_ENDOMORPHISM
secp256k1_ecmult_endo_split(&scalars[0], &scalars[1], &points[0], &points[1]); secp256k1_ecmult_endo_split(&scalars[0], &scalars[1], &points[0], &points[1]);
idx++; idx++;
#endif
} }
while (point_idx < n_points) { while (point_idx < n_points) {
@ -1047,10 +918,8 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
return 0; return 0;
} }
idx++; idx++;
#ifdef USE_ENDOMORPHISM
secp256k1_ecmult_endo_split(&scalars[idx - 1], &scalars[idx], &points[idx - 1], &points[idx]); secp256k1_ecmult_endo_split(&scalars[idx - 1], &scalars[idx], &points[idx - 1], &points[idx]);
idx++; idx++;
#endif
point_idx++; point_idx++;
} }
@ -1093,9 +962,7 @@ static size_t secp256k1_pippenger_max_points(const secp256k1_callback* error_cal
size_t space_overhead; size_t space_overhead;
size_t entry_size = sizeof(secp256k1_ge) + sizeof(secp256k1_scalar) + sizeof(struct secp256k1_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int); size_t entry_size = sizeof(secp256k1_ge) + sizeof(secp256k1_scalar) + sizeof(struct secp256k1_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int);
#ifdef USE_ENDOMORPHISM
entry_size = 2*entry_size; entry_size = 2*entry_size;
#endif
space_overhead = (sizeof(secp256k1_gej) << bucket_window) + entry_size + sizeof(struct secp256k1_pippenger_state); space_overhead = (sizeof(secp256k1_gej) << bucket_window) + entry_size + sizeof(struct secp256k1_pippenger_state);
if (space_overhead > max_alloc) { if (space_overhead > max_alloc) {
break; break;

View File

@ -116,10 +116,8 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, c
/** Set r equal to the sum of a and b (with the inverse of b's Z coordinate passed as bzinv). */ /** Set r equal to the sum of a and b (with the inverse of b's Z coordinate passed as bzinv). */
static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv); static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv);
#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. */ /** 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_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a); static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a);
#endif
/** Clear a secp256k1_gej to prevent leaking sensitive information. */ /** Clear a secp256k1_gej to prevent leaking sensitive information. */
static void secp256k1_gej_clear(secp256k1_gej *r); static void secp256k1_gej_clear(secp256k1_gej *r);

View File

@ -646,7 +646,6 @@ static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r,
secp256k1_fe_storage_cmov(&r->y, &a->y, flag); secp256k1_fe_storage_cmov(&r->y, &a->y, flag);
} }
#ifdef USE_ENDOMORPHISM
static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
static const secp256k1_fe beta = SECP256K1_FE_CONST( static const secp256k1_fe beta = SECP256K1_FE_CONST(
0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul,
@ -655,7 +654,6 @@ static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
*r = *a; *r = *a;
secp256k1_fe_mul(&r->x, &r->x, &beta); secp256k1_fe_mul(&r->x, &r->x, &beta);
} }
#endif
static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) { static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) {
secp256k1_fe yz; secp256k1_fe yz;

View File

@ -80,7 +80,7 @@ void test_ecdh_generator_basepoint(void) {
/* compute "explicitly" */ /* compute "explicitly" */
CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1); CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1);
/* compare */ /* compare */
CHECK(memcmp(output_ecdh, point_ser, 65) == 0); CHECK(secp256k1_memcmp_var(output_ecdh, point_ser, 65) == 0);
/* compute using ECDH function with default hash function */ /* compute using ECDH function with default hash function */
CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32, NULL, NULL) == 1); CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32, NULL, NULL) == 1);
@ -90,7 +90,7 @@ void test_ecdh_generator_basepoint(void) {
secp256k1_sha256_write(&sha, point_ser, point_ser_len); secp256k1_sha256_write(&sha, point_ser, point_ser_len);
secp256k1_sha256_finalize(&sha, output_ser); secp256k1_sha256_finalize(&sha, output_ser);
/* compare */ /* compare */
CHECK(memcmp(output_ecdh, output_ser, 32) == 0); CHECK(secp256k1_memcmp_var(output_ecdh, output_ser, 32) == 0);
} }
} }

View File

@ -124,7 +124,7 @@ int secp256k1_xonly_pubkey_tweak_add_check(const secp256k1_context* ctx, const u
secp256k1_fe_normalize_var(&pk.y); secp256k1_fe_normalize_var(&pk.y);
secp256k1_fe_get_b32(pk_expected32, &pk.x); secp256k1_fe_get_b32(pk_expected32, &pk.x);
return memcmp(&pk_expected32, tweaked_pubkey32, 32) == 0 return secp256k1_memcmp_var(&pk_expected32, tweaked_pubkey32, 32) == 0
&& secp256k1_fe_is_odd(&pk.y) == tweaked_pk_parity; && secp256k1_fe_is_odd(&pk.y) == tweaked_pk_parity;
} }

View File

@ -38,13 +38,13 @@ static void test_exhaustive_extrakeys(const secp256k1_context *ctx, const secp25
/* Parse the xonly_pubkey back and verify it matches the previously serialized value. */ /* Parse the xonly_pubkey back and verify it matches the previously serialized value. */
CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pubkey[i - 1], xonly_pubkey_bytes[i - 1])); CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pubkey[i - 1], xonly_pubkey_bytes[i - 1]));
CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1]));
CHECK(memcmp(xonly_pubkey_bytes[i - 1], buf, 32) == 0); CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0);
/* Construct the xonly_pubkey from the pubkey, and verify it matches the same. */ /* Construct the xonly_pubkey from the pubkey, and verify it matches the same. */
CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pubkey[i - 1], &parity, &pubkey[i - 1])); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pubkey[i - 1], &parity, &pubkey[i - 1]));
CHECK(parity == parities[i - 1]); CHECK(parity == parities[i - 1]);
CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1]));
CHECK(memcmp(xonly_pubkey_bytes[i - 1], buf, 32) == 0); CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0);
/* Compare the xonly_pubkey bytes against the precomputed group. */ /* Compare the xonly_pubkey bytes against the precomputed group. */
secp256k1_fe_set_b32(&fe, xonly_pubkey_bytes[i - 1]); secp256k1_fe_set_b32(&fe, xonly_pubkey_bytes[i - 1]);
@ -57,7 +57,7 @@ static void test_exhaustive_extrakeys(const secp256k1_context *ctx, const secp25
/* Verify that the higher half is identical to the lower half mirrored. */ /* Verify that the higher half is identical to the lower half mirrored. */
if (i > EXHAUSTIVE_TEST_ORDER / 2) { if (i > EXHAUSTIVE_TEST_ORDER / 2) {
CHECK(memcmp(xonly_pubkey_bytes[i - 1], xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - i - 1], 32) == 0); CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - i - 1], 32) == 0);
CHECK(parities[i - 1] == 1 - parities[EXHAUSTIVE_TEST_ORDER - i - 1]); CHECK(parities[i - 1] == 1 - parities[EXHAUSTIVE_TEST_ORDER - i - 1]);
} }
} }

View File

@ -60,7 +60,7 @@ void test_xonly_pubkey(void) {
sk[0] = 1; sk[0] = 1;
CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1);
CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1);
CHECK(memcmp(&pk, &xonly_pk, sizeof(pk)) == 0); CHECK(secp256k1_memcmp_var(&pk, &xonly_pk, sizeof(pk)) == 0);
CHECK(pk_parity == 0); CHECK(pk_parity == 0);
/* Choose a secret key such that pubkey and xonly_pubkey are each others /* Choose a secret key such that pubkey and xonly_pubkey are each others
@ -68,7 +68,7 @@ void test_xonly_pubkey(void) {
sk[0] = 2; sk[0] = 2;
CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1);
CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1);
CHECK(memcmp(&xonly_pk, &pk, sizeof(xonly_pk)) != 0); CHECK(secp256k1_memcmp_var(&xonly_pk, &pk, sizeof(xonly_pk)) != 0);
CHECK(pk_parity == 1); CHECK(pk_parity == 1);
secp256k1_pubkey_load(ctx, &pk1, &pk); secp256k1_pubkey_load(ctx, &pk1, &pk);
secp256k1_pubkey_load(ctx, &pk2, (secp256k1_pubkey *) &xonly_pk); secp256k1_pubkey_load(ctx, &pk2, (secp256k1_pubkey *) &xonly_pk);
@ -81,7 +81,7 @@ void test_xonly_pubkey(void) {
CHECK(secp256k1_xonly_pubkey_serialize(none, NULL, &xonly_pk) == 0); CHECK(secp256k1_xonly_pubkey_serialize(none, NULL, &xonly_pk) == 0);
CHECK(ecount == 1); CHECK(ecount == 1);
CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, NULL) == 0); CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, NULL) == 0);
CHECK(memcmp(buf32, zeros64, 32) == 0); CHECK(secp256k1_memcmp_var(buf32, zeros64, 32) == 0);
CHECK(ecount == 2); CHECK(ecount == 2);
{ {
/* A pubkey filled with 0s will fail to serialize due to pubkey_load /* A pubkey filled with 0s will fail to serialize due to pubkey_load
@ -104,17 +104,17 @@ void test_xonly_pubkey(void) {
CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1);
CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &xonly_pk) == 1); CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &xonly_pk) == 1);
CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk_tmp, buf32) == 1); CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk_tmp, buf32) == 1);
CHECK(memcmp(&xonly_pk, &xonly_pk_tmp, sizeof(xonly_pk)) == 0); CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(xonly_pk)) == 0);
/* Test parsing invalid field elements */ /* Test parsing invalid field elements */
memset(&xonly_pk, 1, sizeof(xonly_pk)); memset(&xonly_pk, 1, sizeof(xonly_pk));
/* Overflowing field element */ /* Overflowing field element */
CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, ones32) == 0); CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, ones32) == 0);
CHECK(memcmp(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0);
memset(&xonly_pk, 1, sizeof(xonly_pk)); memset(&xonly_pk, 1, sizeof(xonly_pk));
/* There's no point with x-coordinate 0 on secp256k1 */ /* There's no point with x-coordinate 0 on secp256k1 */
CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, zeros64) == 0); CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, zeros64) == 0);
CHECK(memcmp(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0);
/* If a random 32-byte string can not be parsed with ec_pubkey_parse /* If a random 32-byte string can not be parsed with ec_pubkey_parse
* (because interpreted as X coordinate it does not correspond to a point on * (because interpreted as X coordinate it does not correspond to a point on
* the curve) then xonly_pubkey_parse should fail as well. */ * the curve) then xonly_pubkey_parse should fail as well. */
@ -125,7 +125,7 @@ void test_xonly_pubkey(void) {
if (!secp256k1_ec_pubkey_parse(ctx, &pk, rand33, 33)) { if (!secp256k1_ec_pubkey_parse(ctx, &pk, rand33, 33)) {
memset(&xonly_pk, 1, sizeof(xonly_pk)); memset(&xonly_pk, 1, sizeof(xonly_pk));
CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, &rand33[1]) == 0); CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, &rand33[1]) == 0);
CHECK(memcmp(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0);
} else { } else {
CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, &rand33[1]) == 1); CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, &rand33[1]) == 1);
} }
@ -170,15 +170,15 @@ void test_xonly_pubkey_tweak(void) {
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0);
CHECK(ecount == 4); CHECK(ecount == 4);
/* NULL internal_xonly_pk zeroes the output_pk */ /* NULL internal_xonly_pk zeroes the output_pk */
CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0);
CHECK(ecount == 5); CHECK(ecount == 5);
/* NULL tweak zeroes the output_pk */ /* NULL tweak zeroes the output_pk */
CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
/* Invalid tweak zeroes the output_pk */ /* Invalid tweak zeroes the output_pk */
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, overflows) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, overflows) == 0);
CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
/* A zero tweak is fine */ /* A zero tweak is fine */
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, zeros64) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, zeros64) == 1);
@ -193,7 +193,7 @@ void test_xonly_pubkey_tweak(void) {
secp256k1_scalar_get_b32(tweak, &scalar_tweak); secp256k1_scalar_get_b32(tweak, &scalar_tweak);
CHECK((secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, sk) == 0) CHECK((secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, sk) == 0)
|| (secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0)); || (secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0));
CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
} }
/* Invalid pk with a valid tweak */ /* Invalid pk with a valid tweak */
@ -202,7 +202,7 @@ void test_xonly_pubkey_tweak(void) {
ecount = 0; ecount = 0;
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 1); CHECK(ecount == 1);
CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
secp256k1_context_destroy(none); secp256k1_context_destroy(none);
secp256k1_context_destroy(sign); secp256k1_context_destroy(sign);
@ -268,7 +268,7 @@ void test_xonly_pubkey_tweak_check(void) {
/* Overflowing tweak not allowed */ /* Overflowing tweak not allowed */
CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0);
CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
CHECK(ecount == 5); CHECK(ecount == 5);
secp256k1_context_destroy(none); secp256k1_context_destroy(none);
@ -329,23 +329,23 @@ void test_keypair(void) {
ecount = 0; ecount = 0;
secp256k1_testrand256(sk); secp256k1_testrand256(sk);
CHECK(secp256k1_keypair_create(none, &keypair, sk) == 0); CHECK(secp256k1_keypair_create(none, &keypair, sk) == 0);
CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
CHECK(ecount == 1); CHECK(ecount == 1);
CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 0); CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 0);
CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0); CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0);
CHECK(ecount == 3); CHECK(ecount == 3);
CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0); CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0);
CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
CHECK(ecount == 4); CHECK(ecount == 4);
/* Invalid secret key */ /* Invalid secret key */
CHECK(secp256k1_keypair_create(sign, &keypair, zeros96) == 0); CHECK(secp256k1_keypair_create(sign, &keypair, zeros96) == 0);
CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
CHECK(secp256k1_keypair_create(sign, &keypair, overflows) == 0); CHECK(secp256k1_keypair_create(sign, &keypair, overflows) == 0);
CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
/* Test keypair_pub */ /* Test keypair_pub */
ecount = 0; ecount = 0;
@ -356,18 +356,18 @@ void test_keypair(void) {
CHECK(ecount == 1); CHECK(ecount == 1);
CHECK(secp256k1_keypair_pub(none, &pk, NULL) == 0); CHECK(secp256k1_keypair_pub(none, &pk, NULL) == 0);
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(memcmp(zeros96, &pk, sizeof(pk)) == 0); CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0);
/* Using an invalid keypair is fine for keypair_pub */ /* Using an invalid keypair is fine for keypair_pub */
memset(&keypair, 0, sizeof(keypair)); memset(&keypair, 0, sizeof(keypair));
CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1); CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1);
CHECK(memcmp(zeros96, &pk, sizeof(pk)) == 0); CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0);
/* keypair holds the same pubkey as pubkey_create */ /* keypair holds the same pubkey as pubkey_create */
CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1); CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1);
CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
CHECK(secp256k1_keypair_pub(none, &pk_tmp, &keypair) == 1); CHECK(secp256k1_keypair_pub(none, &pk_tmp, &keypair) == 1);
CHECK(memcmp(&pk, &pk_tmp, sizeof(pk)) == 0); CHECK(secp256k1_memcmp_var(&pk, &pk_tmp, sizeof(pk)) == 0);
/** Test keypair_xonly_pub **/ /** Test keypair_xonly_pub **/
ecount = 0; ecount = 0;
@ -379,13 +379,13 @@ void test_keypair(void) {
CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, NULL, &keypair) == 1); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, NULL, &keypair) == 1);
CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, NULL) == 0); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, NULL) == 0);
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(memcmp(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0);
/* Using an invalid keypair will set the xonly_pk to 0 (first reset /* Using an invalid keypair will set the xonly_pk to 0 (first reset
* xonly_pk). */ * xonly_pk). */
CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1);
memset(&keypair, 0, sizeof(keypair)); memset(&keypair, 0, sizeof(keypair));
CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 0); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 0);
CHECK(memcmp(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0);
CHECK(ecount == 3); CHECK(ecount == 3);
/** keypair holds the same xonly pubkey as pubkey_create **/ /** keypair holds the same xonly pubkey as pubkey_create **/
@ -393,7 +393,7 @@ void test_keypair(void) {
CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1);
CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1);
CHECK(memcmp(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0); CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0);
CHECK(pk_parity == pk_parity_tmp); CHECK(pk_parity == pk_parity_tmp);
secp256k1_context_destroy(none); secp256k1_context_destroy(none);
@ -429,12 +429,12 @@ void test_keypair_add(void) {
CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0); CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0);
CHECK(ecount == 4); CHECK(ecount == 4);
/* This does not set the keypair to zeroes */ /* This does not set the keypair to zeroes */
CHECK(memcmp(&keypair, zeros96, sizeof(keypair)) != 0); CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0);
/* Invalid tweak zeroes the keypair */ /* Invalid tweak zeroes the keypair */
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, overflows) == 0); CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, overflows) == 0);
CHECK(memcmp(&keypair, zeros96, sizeof(keypair)) == 0); CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0);
/* A zero tweak is fine */ /* A zero tweak is fine */
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
@ -454,8 +454,8 @@ void test_keypair_add(void) {
secp256k1_scalar_get_b32(tweak, &scalar_tweak); secp256k1_scalar_get_b32(tweak, &scalar_tweak);
CHECK((secp256k1_keypair_xonly_tweak_add(ctx, &keypair, sk) == 0) CHECK((secp256k1_keypair_xonly_tweak_add(ctx, &keypair, sk) == 0)
|| (secp256k1_keypair_xonly_tweak_add(ctx, &keypair_tmp, tweak) == 0)); || (secp256k1_keypair_xonly_tweak_add(ctx, &keypair_tmp, tweak) == 0));
CHECK(memcmp(&keypair, zeros96, sizeof(keypair)) == 0 CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0
|| memcmp(&keypair_tmp, zeros96, sizeof(keypair_tmp)) == 0); || secp256k1_memcmp_var(&keypair_tmp, zeros96, sizeof(keypair_tmp)) == 0);
} }
/* Invalid keypair with a valid tweak */ /* Invalid keypair with a valid tweak */
@ -464,7 +464,7 @@ void test_keypair_add(void) {
ecount = 0; ecount = 0;
CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0);
CHECK(ecount == 1); CHECK(ecount == 1);
CHECK(memcmp(&keypair, zeros96, sizeof(keypair)) == 0); CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0);
/* Only seckey part of keypair invalid */ /* Only seckey part of keypair invalid */
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
memset(&keypair, 0, 32); memset(&keypair, 0, 32);
@ -498,11 +498,11 @@ void test_keypair_add(void) {
/* Check that the resulting pubkey matches xonly_pubkey_tweak_add */ /* Check that the resulting pubkey matches xonly_pubkey_tweak_add */
CHECK(secp256k1_keypair_pub(ctx, &output_pk_xy, &keypair) == 1); CHECK(secp256k1_keypair_pub(ctx, &output_pk_xy, &keypair) == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk_expected, &internal_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk_expected, &internal_pk, tweak) == 1);
CHECK(memcmp(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0);
/* Check that the secret key in the keypair is tweaked correctly */ /* Check that the secret key in the keypair is tweaked correctly */
CHECK(secp256k1_ec_pubkey_create(ctx, &output_pk_expected, &keypair.data[0]) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &output_pk_expected, &keypair.data[0]) == 1);
CHECK(memcmp(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0);
} }
secp256k1_context_destroy(none); secp256k1_context_destroy(none);
secp256k1_context_destroy(sign); secp256k1_context_destroy(sign);

View File

@ -184,7 +184,7 @@ void test_ecdsa_recovery_end_to_end(void) {
CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[3], message, privkey, NULL, extra) == 1); CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[3], message, privkey, NULL, extra) == 1);
CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1);
CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1);
CHECK(memcmp(&signature[4], &signature[0], 64) == 0); CHECK(secp256k1_memcmp_var(&signature[4], &signature[0], 64) == 0);
CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1);
memset(&rsignature[4], 0, sizeof(rsignature[4])); memset(&rsignature[4], 0, sizeof(rsignature[4]));
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1);
@ -193,7 +193,7 @@ void test_ecdsa_recovery_end_to_end(void) {
/* Parse compact (with recovery id) and recover. */ /* Parse compact (with recovery id) and recover. */
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1);
CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 1); CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 1);
CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) == 0);
/* Serialize/destroy/parse signature and verify again. */ /* Serialize/destroy/parse signature and verify again. */
CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1);
sig[secp256k1_testrand_bits(6)] += 1 + secp256k1_testrand_int(255); sig[secp256k1_testrand_bits(6)] += 1 + secp256k1_testrand_int(255);
@ -202,7 +202,7 @@ void test_ecdsa_recovery_end_to_end(void) {
CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 0); CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 0);
/* Recover again */ /* Recover again */
CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 0 || CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 0 ||
memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0); secp256k1_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) != 0);
} }
/* Tests several edge cases. */ /* Tests several edge cases. */

View File

@ -68,7 +68,7 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms
/* Tag the hash with algo16 which is important to avoid nonce reuse across /* Tag the hash with algo16 which is important to avoid nonce reuse across
* algorithms. If this nonce function is used in BIP-340 signing as defined * algorithms. If this nonce function is used in BIP-340 signing as defined
* in the spec, an optimized tagging implementation is used. */ * in the spec, an optimized tagging implementation is used. */
if (memcmp(algo16, bip340_algo16, 16) == 0) { if (secp256k1_memcmp_var(algo16, bip340_algo16, 16) == 0) {
secp256k1_nonce_function_bip340_sha256_tagged(&sha); secp256k1_nonce_function_bip340_sha256_tagged(&sha);
} else { } else {
int algo16_len = 16; int algo16_len = 16;

View File

@ -163,9 +163,9 @@ static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsign
/* Invoke the real function to construct a signature. */ /* Invoke the real function to construct a signature. */
CHECK(secp256k1_schnorrsig_sign(ctx, sig64, msg32, &keypairs[d - 1], secp256k1_hardened_nonce_function_smallint, &k)); CHECK(secp256k1_schnorrsig_sign(ctx, sig64, msg32, &keypairs[d - 1], secp256k1_hardened_nonce_function_smallint, &k));
/* The first 32 bytes must match the xonly pubkey for the specified k. */ /* The first 32 bytes must match the xonly pubkey for the specified k. */
CHECK(memcmp(sig64, xonly_pubkey_bytes[k - 1], 32) == 0); CHECK(secp256k1_memcmp_var(sig64, xonly_pubkey_bytes[k - 1], 32) == 0);
/* The last 32 bytes must match the expected s value. */ /* The last 32 bytes must match the expected s value. */
CHECK(memcmp(sig64 + 32, expected_s_bytes, 32) == 0); CHECK(secp256k1_memcmp_var(sig64 + 32, expected_s_bytes, 32) == 0);
/* Don't retry other messages that result in the same challenge. */ /* Don't retry other messages that result in the same challenge. */
e_done[e] = 1; e_done[e] = 1;
++e_count_done; ++e_count_done;

View File

@ -17,7 +17,7 @@ void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, size_t n
CHECK(nonce_function_bip340(nonces[0], args[0], args[1], args[2], args[3], args[4]) == 1); CHECK(nonce_function_bip340(nonces[0], args[0], args[1], args[2], args[3], args[4]) == 1);
secp256k1_testrand_flip(args[n_flip], n_bytes); secp256k1_testrand_flip(args[n_flip], n_bytes);
CHECK(nonce_function_bip340(nonces[1], args[0], args[1], args[2], args[3], args[4]) == 1); CHECK(nonce_function_bip340(nonces[1], args[0], args[1], args[2], args[3], args[4]) == 1);
CHECK(memcmp(nonces[0], nonces[1], 32) != 0); CHECK(secp256k1_memcmp_var(nonces[0], nonces[1], 32) != 0);
} }
/* Tests for the equality of two sha256 structs. This function only produces a /* Tests for the equality of two sha256 structs. This function only produces a
@ -28,7 +28,7 @@ void test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2)
CHECK((sha1->bytes & 0x3F) == 0); CHECK((sha1->bytes & 0x3F) == 0);
CHECK(sha1->bytes == sha2->bytes); CHECK(sha1->bytes == sha2->bytes);
CHECK(memcmp(sha1->s, sha2->s, sizeof(sha1->s)) == 0); CHECK(secp256k1_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0);
} }
void run_nonce_function_bip340_tests(void) { void run_nonce_function_bip340_tests(void) {
@ -197,11 +197,11 @@ void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const un
CHECK(secp256k1_keypair_create(ctx, &keypair, sk)); CHECK(secp256k1_keypair_create(ctx, &keypair, sk));
CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, aux_rand)); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, aux_rand));
CHECK(memcmp(sig, expected_sig, 64) == 0); CHECK(secp256k1_memcmp_var(sig, expected_sig, 64) == 0);
CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk_expected, pk_serialized)); CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk_expected, pk_serialized));
CHECK(secp256k1_keypair_xonly_pub(ctx, &pk, NULL, &keypair)); CHECK(secp256k1_keypair_xonly_pub(ctx, &pk, NULL, &keypair));
CHECK(memcmp(&pk, &pk_expected, sizeof(pk)) == 0); CHECK(secp256k1_memcmp_var(&pk, &pk_expected, sizeof(pk)) == 0);
CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, &pk)); CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, &pk));
} }
@ -682,12 +682,12 @@ void test_schnorrsig_sign(void) {
/* Test different nonce functions */ /* Test different nonce functions */
memset(sig, 1, sizeof(sig)); memset(sig, 1, sizeof(sig));
CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_failing, NULL) == 0); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_failing, NULL) == 0);
CHECK(memcmp(sig, zeros64, sizeof(sig)) == 0); CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0);
memset(&sig, 1, sizeof(sig)); memset(&sig, 1, sizeof(sig));
CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_0, NULL) == 0); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_0, NULL) == 0);
CHECK(memcmp(sig, zeros64, sizeof(sig)) == 0); CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0);
CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_overflowing, NULL) == 1); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_overflowing, NULL) == 1);
CHECK(memcmp(sig, zeros64, sizeof(sig)) != 0); CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) != 0);
} }
#define N_SIGS 3 #define N_SIGS 3

View File

@ -102,12 +102,11 @@ static void secp256k1_scalar_order_get_num(secp256k1_num *r);
/** Compare two scalars. */ /** Compare two scalars. */
static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b); static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b);
#ifdef USE_ENDOMORPHISM /** Find r1 and r2 such that r1+r2*2^128 = k. */
/** Find r1 and r2 such that r1+r2*2^128 = a. */ static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k);
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); /** Find r1 and r2 such that r1+r2*lambda = k,
/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */ * where r1 and r2 or their negations are maximum 128 bits long (see secp256k1_ge_mul_lambda). */
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k);
#endif
/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ /** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */
static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift);

View File

@ -912,18 +912,16 @@ static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a)
secp256k1_scalar_reduce_512(r, l); secp256k1_scalar_reduce_512(r, l);
} }
#ifdef USE_ENDOMORPHISM static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) {
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { r1->d[0] = k->d[0];
r1->d[0] = a->d[0]; r1->d[1] = k->d[1];
r1->d[1] = a->d[1];
r1->d[2] = 0; r1->d[2] = 0;
r1->d[3] = 0; r1->d[3] = 0;
r2->d[0] = a->d[2]; r2->d[0] = k->d[2];
r2->d[1] = a->d[3]; r2->d[1] = k->d[3];
r2->d[2] = 0; r2->d[2] = 0;
r2->d[3] = 0; r2->d[3] = 0;
} }
#endif
SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *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; 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;

View File

@ -672,26 +672,24 @@ static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a)
secp256k1_scalar_reduce_512(r, l); secp256k1_scalar_reduce_512(r, l);
} }
#ifdef USE_ENDOMORPHISM static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) {
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { r1->d[0] = k->d[0];
r1->d[0] = a->d[0]; r1->d[1] = k->d[1];
r1->d[1] = a->d[1]; r1->d[2] = k->d[2];
r1->d[2] = a->d[2]; r1->d[3] = k->d[3];
r1->d[3] = a->d[3];
r1->d[4] = 0; r1->d[4] = 0;
r1->d[5] = 0; r1->d[5] = 0;
r1->d[6] = 0; r1->d[6] = 0;
r1->d[7] = 0; r1->d[7] = 0;
r2->d[0] = a->d[4]; r2->d[0] = k->d[4];
r2->d[1] = a->d[5]; r2->d[1] = k->d[5];
r2->d[2] = a->d[6]; r2->d[2] = k->d[6];
r2->d[3] = a->d[7]; r2->d[3] = k->d[7];
r2->d[4] = 0; r2->d[4] = 0;
r2->d[5] = 0; r2->d[5] = 0;
r2->d[6] = 0; r2->d[6] = 0;
r2->d[7] = 0; r2->d[7] = 0;
} }
#endif
SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *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; 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;

View File

@ -7,6 +7,10 @@
#ifndef SECP256K1_SCALAR_IMPL_H #ifndef SECP256K1_SCALAR_IMPL_H
#define SECP256K1_SCALAR_IMPL_H #define SECP256K1_SCALAR_IMPL_H
#ifdef VERIFY
#include <string.h>
#endif
#include "scalar.h" #include "scalar.h"
#include "util.h" #include "util.h"
@ -252,7 +256,6 @@ static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_sc
#endif #endif
} }
#ifdef USE_ENDOMORPHISM
/* These parameters are generated using sage/gen_exhaustive_groups.sage. */ /* These parameters are generated using sage/gen_exhaustive_groups.sage. */
#if defined(EXHAUSTIVE_TEST_ORDER) #if defined(EXHAUSTIVE_TEST_ORDER)
# if EXHAUSTIVE_TEST_ORDER == 13 # if EXHAUSTIVE_TEST_ORDER == 13
@ -264,34 +267,54 @@ static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_sc
# endif # endif
/** /**
* Find k1 and k2 given k, such that k1 + k2 * lambda == k mod n; unlike in the * Find r1 and r2 given k, such that r1 + r2 * lambda == k mod n; unlike in the
* full case we don't bother making k1 and k2 be small, we just want them to be * full case we don't bother making r1 and r2 be small, we just want them to be
* nontrivial to get full test coverage for the exhaustive tests. We therefore * nontrivial to get full test coverage for the exhaustive tests. We therefore
* (arbitrarily) set k2 = k + 5 and k1 = k - k2 * lambda. * (arbitrarily) set r2 = k + 5 (mod n) and r1 = k - r2 * lambda (mod n).
*/ */
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) {
*r2 = (*a + 5) % EXHAUSTIVE_TEST_ORDER; *r2 = (*k + 5) % EXHAUSTIVE_TEST_ORDER;
*r1 = (*a + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER; *r1 = (*k + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER;
} }
#else #else
/** /**
* The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where
* lambda is {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, * lambda is: */
* 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72} static const secp256k1_scalar secp256k1_const_lambda = SECP256K1_SCALAR_CONST(
0x5363AD4CUL, 0xC05C30E0UL, 0xA5261C02UL, 0x8812645AUL,
0x122E22EAUL, 0x20816678UL, 0xDF02967CUL, 0x1B23BD72UL
);
#ifdef VERIFY
static void secp256k1_scalar_split_lambda_verify(const secp256k1_scalar *r1, const secp256k1_scalar *r2, const secp256k1_scalar *k);
#endif
/*
* Both lambda and beta are primitive cube roots of unity. That is lamba^3 == 1 mod n and
* beta^3 == 1 mod p, where n is the curve order and p is the field order.
* *
* "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm * Futhermore, because (X^3 - 1) = (X - 1)(X^2 + X + 1), the primitive cube roots of unity are
* (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1 * roots of X^2 + X + 1. Therefore lambda^2 + lamba == -1 mod n and beta^2 + beta == -1 mod p.
* and k2 have a small size. * (The other primitive cube roots of unity are lambda^2 and beta^2 respectively.)
* It relies on constants a1, b1, a2, b2. These constants for the value of lambda above are: *
* Let l = -1/2 + i*sqrt(3)/2, the complex root of X^2 + X + 1. We can define a ring
* homomorphism phi : Z[l] -> Z_n where phi(a + b*l) == a + b*lambda mod n. The kernel of phi
* is a lattice over Z[l] (considering Z[l] as a Z-module). This lattice is generated by a
* reduced basis {a1 + b1*l, a2 + b2*l} where
* *
* - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} * - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15}
* - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3} * - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3}
* - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8} * - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8}
* - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} * - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15}
* *
* The algorithm then computes c1 = round(b1 * k / n) and c2 = round(b2 * k / n), and gives * "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm
* (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1
* and k2 are small in absolute value.
*
* The algorithm computes c1 = round(b2 * k / n) and c2 = round((-b1) * k / n), and gives
* k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and * k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and
* compute k1 as k - k2 * lambda, avoiding the need for constants a1 and a2. * compute r2 = k2 mod n, and r1 = k1 mod n = (k - r2 * lambda) mod n, avoiding the need for
* the constants a1 and a2.
* *
* g1, g2 are precomputed constants used to replace division with a rounded multiplication * g1, g2 are precomputed constants used to replace division with a rounded multiplication
* when decomposing the scalar for an endomorphism-based point multiplication. * when decomposing the scalar for an endomorphism-based point multiplication.
@ -303,21 +326,21 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
* Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez), * Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez),
* Section 4.3 (here we use a somewhat higher-precision estimate): * Section 4.3 (here we use a somewhat higher-precision estimate):
* d = a1*b2 - b1*a2 * d = a1*b2 - b1*a2
* g1 = round((2^272)*b2/d) * g1 = round(2^384 * b2/d)
* g2 = round((2^272)*b1/d) * g2 = round(2^384 * (-b1)/d)
* *
* (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found * (Note that d is also equal to the curve order, n, here because [a1,b1] and [a2,b2]
* as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda'). * can be found as outputs of the Extended Euclidean Algorithm on inputs n and lambda).
* *
* The function below splits a in r1 and r2, such that r1 + lambda * r2 == a (mod order). * The function below splits k into r1 and r2, such that
* - r1 + lambda * r2 == k (mod n)
* - either r1 < 2^128 or -r1 mod n < 2^128
* - either r2 < 2^128 or -r2 mod n < 2^128
*
* See proof below.
*/ */
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) {
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) {
secp256k1_scalar c1, c2; secp256k1_scalar c1, c2;
static const secp256k1_scalar minus_lambda = SECP256K1_SCALAR_CONST(
0xAC9C52B3UL, 0x3FA3CF1FUL, 0x5AD9E3FDUL, 0x77ED9BA4UL,
0xA880B9FCUL, 0x8EC739C2UL, 0xE0CFC810UL, 0xB51283CFUL
);
static const secp256k1_scalar minus_b1 = SECP256K1_SCALAR_CONST( static const secp256k1_scalar minus_b1 = SECP256K1_SCALAR_CONST(
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C3UL 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C3UL
@ -327,25 +350,167 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
0x8A280AC5UL, 0x0774346DUL, 0xD765CDA8UL, 0x3DB1562CUL 0x8A280AC5UL, 0x0774346DUL, 0xD765CDA8UL, 0x3DB1562CUL
); );
static const secp256k1_scalar g1 = SECP256K1_SCALAR_CONST( static const secp256k1_scalar g1 = SECP256K1_SCALAR_CONST(
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00003086UL, 0x3086D221UL, 0xA7D46BCDUL, 0xE86C90E4UL, 0x9284EB15UL,
0xD221A7D4UL, 0x6BCDE86CUL, 0x90E49284UL, 0xEB153DABUL 0x3DAA8A14UL, 0x71E8CA7FUL, 0xE893209AUL, 0x45DBB031UL
); );
static const secp256k1_scalar g2 = SECP256K1_SCALAR_CONST( static const secp256k1_scalar g2 = SECP256K1_SCALAR_CONST(
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x0000E443UL, 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C4UL,
0x7ED6010EUL, 0x88286F54UL, 0x7FA90ABFUL, 0xE4C42212UL 0x221208ACUL, 0x9DF506C6UL, 0x1571B4AEUL, 0x8AC47F71UL
); );
VERIFY_CHECK(r1 != a); VERIFY_CHECK(r1 != k);
VERIFY_CHECK(r2 != a); VERIFY_CHECK(r2 != k);
/* these _var calls are constant time since the shift amount is constant */ /* these _var calls are constant time since the shift amount is constant */
secp256k1_scalar_mul_shift_var(&c1, a, &g1, 272); secp256k1_scalar_mul_shift_var(&c1, k, &g1, 384);
secp256k1_scalar_mul_shift_var(&c2, a, &g2, 272); secp256k1_scalar_mul_shift_var(&c2, k, &g2, 384);
secp256k1_scalar_mul(&c1, &c1, &minus_b1); secp256k1_scalar_mul(&c1, &c1, &minus_b1);
secp256k1_scalar_mul(&c2, &c2, &minus_b2); secp256k1_scalar_mul(&c2, &c2, &minus_b2);
secp256k1_scalar_add(r2, &c1, &c2); secp256k1_scalar_add(r2, &c1, &c2);
secp256k1_scalar_mul(r1, r2, &minus_lambda); secp256k1_scalar_mul(r1, r2, &secp256k1_const_lambda);
secp256k1_scalar_add(r1, r1, a); secp256k1_scalar_negate(r1, r1);
secp256k1_scalar_add(r1, r1, k);
#ifdef VERIFY
secp256k1_scalar_split_lambda_verify(r1, r2, k);
#endif
} }
#endif
#endif #ifdef VERIFY
/*
* Proof for secp256k1_scalar_split_lambda's bounds.
*
* Let
* - epsilon1 = 2^256 * |g1/2^384 - b2/d|
* - epsilon2 = 2^256 * |g2/2^384 - (-b1)/d|
* - c1 = round(k*g1/2^384)
* - c2 = round(k*g2/2^384)
*
* Lemma 1: |c1 - k*b2/d| < 2^-1 + epsilon1
*
* |c1 - k*b2/d|
* =
* |c1 - k*g1/2^384 + k*g1/2^384 - k*b2/d|
* <= {triangle inequality}
* |c1 - k*g1/2^384| + |k*g1/2^384 - k*b2/d|
* =
* |c1 - k*g1/2^384| + k*|g1/2^384 - b2/d|
* < {rounding in c1 and 0 <= k < 2^256}
* 2^-1 + 2^256 * |g1/2^384 - b2/d|
* = {definition of epsilon1}
* 2^-1 + epsilon1
*
* Lemma 2: |c2 - k*(-b1)/d| < 2^-1 + epsilon2
*
* |c2 - k*(-b1)/d|
* =
* |c2 - k*g2/2^384 + k*g2/2^384 - k*(-b1)/d|
* <= {triangle inequality}
* |c2 - k*g2/2^384| + |k*g2/2^384 - k*(-b1)/d|
* =
* |c2 - k*g2/2^384| + k*|g2/2^384 - (-b1)/d|
* < {rounding in c2 and 0 <= k < 2^256}
* 2^-1 + 2^256 * |g2/2^384 - (-b1)/d|
* = {definition of epsilon2}
* 2^-1 + epsilon2
*
* Let
* - k1 = k - c1*a1 - c2*a2
* - k2 = - c1*b1 - c2*b2
*
* Lemma 3: |k1| < (a1 + a2 + 1)/2 < 2^128
*
* |k1|
* = {definition of k1}
* |k - c1*a1 - c2*a2|
* = {(a1*b2 - b1*a2)/n = 1}
* |k*(a1*b2 - b1*a2)/n - c1*a1 - c2*a2|
* =
* |a1*(k*b2/n - c1) + a2*(k*(-b1)/n - c2)|
* <= {triangle inequality}
* a1*|k*b2/n - c1| + a2*|k*(-b1)/n - c2|
* < {Lemma 1 and Lemma 2}
* a1*(2^-1 + epslion1) + a2*(2^-1 + epsilon2)
* < {rounding up to an integer}
* (a1 + a2 + 1)/2
* < {rounding up to a power of 2}
* 2^128
*
* Lemma 4: |k2| < (-b1 + b2)/2 + 1 < 2^128
*
* |k2|
* = {definition of k2}
* |- c1*a1 - c2*a2|
* = {(b1*b2 - b1*b2)/n = 0}
* |k*(b1*b2 - b1*b2)/n - c1*b1 - c2*b2|
* =
* |b1*(k*b2/n - c1) + b2*(k*(-b1)/n - c2)|
* <= {triangle inequality}
* (-b1)*|k*b2/n - c1| + b2*|k*(-b1)/n - c2|
* < {Lemma 1 and Lemma 2}
* (-b1)*(2^-1 + epslion1) + b2*(2^-1 + epsilon2)
* < {rounding up to an integer}
* (-b1 + b2)/2 + 1
* < {rounding up to a power of 2}
* 2^128
*
* Let
* - r2 = k2 mod n
* - r1 = k - r2*lambda mod n.
*
* Notice that r1 is defined such that r1 + r2 * lambda == k (mod n).
*
* Lemma 5: r1 == k1 mod n.
*
* r1
* == {definition of r1 and r2}
* k - k2*lambda
* == {definition of k2}
* k - (- c1*b1 - c2*b2)*lambda
* ==
* k + c1*b1*lambda + c2*b2*lambda
* == {a1 + b1*lambda == 0 mod n and a2 + b2*lambda == 0 mod n}
* k - c1*a1 - c2*a2
* == {definition of k1}
* k1
*
* From Lemma 3, Lemma 4, Lemma 5 and the definition of r2, we can conclude that
*
* - either r1 < 2^128 or -r1 mod n < 2^128
* - either r2 < 2^128 or -r2 mod n < 2^128.
*
* Q.E.D.
*/
static void secp256k1_scalar_split_lambda_verify(const secp256k1_scalar *r1, const secp256k1_scalar *r2, const secp256k1_scalar *k) {
secp256k1_scalar s;
unsigned char buf1[32];
unsigned char buf2[32];
/* (a1 + a2 + 1)/2 is 0xa2a8918ca85bafe22016d0b917e4dd77 */
static const unsigned char k1_bound[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa2, 0xa8, 0x91, 0x8c, 0xa8, 0x5b, 0xaf, 0xe2, 0x20, 0x16, 0xd0, 0xb9, 0x17, 0xe4, 0xdd, 0x77
};
/* (-b1 + b2)/2 + 1 is 0x8a65287bd47179fb2be08846cea267ed */
static const unsigned char k2_bound[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x8a, 0x65, 0x28, 0x7b, 0xd4, 0x71, 0x79, 0xfb, 0x2b, 0xe0, 0x88, 0x46, 0xce, 0xa2, 0x67, 0xed
};
secp256k1_scalar_mul(&s, &secp256k1_const_lambda, r2);
secp256k1_scalar_add(&s, &s, r1);
VERIFY_CHECK(secp256k1_scalar_eq(&s, k));
secp256k1_scalar_negate(&s, r1);
secp256k1_scalar_get_b32(buf1, r1);
secp256k1_scalar_get_b32(buf2, &s);
VERIFY_CHECK(secp256k1_memcmp_var(buf1, k1_bound, 32) < 0 || secp256k1_memcmp_var(buf2, k1_bound, 32) < 0);
secp256k1_scalar_negate(&s, r2);
secp256k1_scalar_get_b32(buf1, r2);
secp256k1_scalar_get_b32(buf2, &s);
VERIFY_CHECK(secp256k1_memcmp_var(buf1, k2_bound, 32) < 0 || secp256k1_memcmp_var(buf2, k2_bound, 32) < 0);
}
#endif /* VERIFY */
#endif /* !defined(EXHAUSTIVE_TEST_ORDER) */
#endif /* SECP256K1_SCALAR_IMPL_H */ #endif /* SECP256K1_SCALAR_IMPL_H */

View File

@ -26,7 +26,7 @@ static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* err
static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch) { static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch) {
if (scratch != NULL) { if (scratch != NULL) {
VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */ VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */
if (memcmp(scratch->magic, "scratch", 8) != 0) { if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) {
secp256k1_callback_call(error_callback, "invalid scratch space"); secp256k1_callback_call(error_callback, "invalid scratch space");
return; return;
} }
@ -36,7 +36,7 @@ static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback,
} }
static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch) { static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch) {
if (memcmp(scratch->magic, "scratch", 8) != 0) { if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) {
secp256k1_callback_call(error_callback, "invalid scratch space"); secp256k1_callback_call(error_callback, "invalid scratch space");
return 0; return 0;
} }
@ -44,7 +44,7 @@ static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callb
} }
static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint) { static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint) {
if (memcmp(scratch->magic, "scratch", 8) != 0) { if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) {
secp256k1_callback_call(error_callback, "invalid scratch space"); secp256k1_callback_call(error_callback, "invalid scratch space");
return; return;
} }
@ -56,7 +56,7 @@ static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_c
} }
static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t objects) { static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t objects) {
if (memcmp(scratch->magic, "scratch", 8) != 0) { if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) {
secp256k1_callback_call(error_callback, "invalid scratch space"); secp256k1_callback_call(error_callback, "invalid scratch space");
return 0; return 0;
} }
@ -81,7 +81,7 @@ static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, s
} }
size = rounded_size; size = rounded_size;
if (memcmp(scratch->magic, "scratch", 8) != 0) { if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) {
secp256k1_callback_call(error_callback, "invalid scratch space"); secp256k1_callback_call(error_callback, "invalid scratch space");
return NULL; return NULL;
} }

View File

@ -22,7 +22,7 @@ static int secp256k1_selftest_sha256(void) {
secp256k1_sha256_initialize(&hasher); secp256k1_sha256_initialize(&hasher);
secp256k1_sha256_write(&hasher, (const unsigned char*)input63, 63); secp256k1_sha256_write(&hasher, (const unsigned char*)input63, 63);
secp256k1_sha256_finalize(&hasher, out); secp256k1_sha256_finalize(&hasher, out);
return memcmp(out, output32, 32) == 0; return secp256k1_memcmp_var(out, output32, 32) == 0;
} }
static int secp256k1_selftest(void) { static int secp256k1_selftest(void) {

View File

@ -442,14 +442,14 @@ void run_sha256_tests(void) {
secp256k1_sha256_initialize(&hasher); secp256k1_sha256_initialize(&hasher);
secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i]));
secp256k1_sha256_finalize(&hasher, out); secp256k1_sha256_finalize(&hasher, out);
CHECK(memcmp(out, outputs[i], 32) == 0); CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0);
if (strlen(inputs[i]) > 0) { if (strlen(inputs[i]) > 0) {
int split = secp256k1_testrand_int(strlen(inputs[i])); int split = secp256k1_testrand_int(strlen(inputs[i]));
secp256k1_sha256_initialize(&hasher); secp256k1_sha256_initialize(&hasher);
secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split);
secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split);
secp256k1_sha256_finalize(&hasher, out); secp256k1_sha256_finalize(&hasher, out);
CHECK(memcmp(out, outputs[i], 32) == 0); CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0);
} }
} }
} }
@ -486,14 +486,14 @@ void run_hmac_sha256_tests(void) {
secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i]));
secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i]));
secp256k1_hmac_sha256_finalize(&hasher, out); secp256k1_hmac_sha256_finalize(&hasher, out);
CHECK(memcmp(out, outputs[i], 32) == 0); CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0);
if (strlen(inputs[i]) > 0) { if (strlen(inputs[i]) > 0) {
int split = secp256k1_testrand_int(strlen(inputs[i])); int split = secp256k1_testrand_int(strlen(inputs[i]));
secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i]));
secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split);
secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split);
secp256k1_hmac_sha256_finalize(&hasher, out); secp256k1_hmac_sha256_finalize(&hasher, out);
CHECK(memcmp(out, outputs[i], 32) == 0); CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0);
} }
} }
} }
@ -520,21 +520,21 @@ void run_rfc6979_hmac_sha256_tests(void) {
secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 64); secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 64);
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32);
CHECK(memcmp(out, out1[i], 32) == 0); CHECK(secp256k1_memcmp_var(out, out1[i], 32) == 0);
} }
secp256k1_rfc6979_hmac_sha256_finalize(&rng); secp256k1_rfc6979_hmac_sha256_finalize(&rng);
secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 65); secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 65);
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32);
CHECK(memcmp(out, out1[i], 32) != 0); CHECK(secp256k1_memcmp_var(out, out1[i], 32) != 0);
} }
secp256k1_rfc6979_hmac_sha256_finalize(&rng); secp256k1_rfc6979_hmac_sha256_finalize(&rng);
secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 64); secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 64);
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32);
CHECK(memcmp(out, out2[i], 32) == 0); CHECK(secp256k1_memcmp_var(out, out2[i], 32) == 0);
} }
secp256k1_rfc6979_hmac_sha256_finalize(&rng); secp256k1_rfc6979_hmac_sha256_finalize(&rng);
} }
@ -1158,7 +1158,7 @@ void run_scalar_tests(void) {
secp256k1_scalar_set_b32(&scalar, bin, &overflow); secp256k1_scalar_set_b32(&scalar, bin, &overflow);
CHECK(overflow == 0); CHECK(overflow == 0);
secp256k1_scalar_get_b32(bin_tmp, &scalar); secp256k1_scalar_get_b32(bin_tmp, &scalar);
CHECK(memcmp(bin, bin_tmp, 32) == 0); CHECK(secp256k1_memcmp_var(bin, bin_tmp, 32) == 0);
/* A scalar set to all 1s should overflow. */ /* A scalar set to all 1s should overflow. */
memset(bin, 0xFF, 32); memset(bin, 0xFF, 32);
@ -1846,18 +1846,18 @@ void run_field_convert(void) {
CHECK(secp256k1_fe_equal_var(&fe, &fe2)); CHECK(secp256k1_fe_equal_var(&fe, &fe2));
/* Check conversion from fe. */ /* Check conversion from fe. */
secp256k1_fe_get_b32(b322, &fe); secp256k1_fe_get_b32(b322, &fe);
CHECK(memcmp(b322, b32, 32) == 0); CHECK(secp256k1_memcmp_var(b322, b32, 32) == 0);
secp256k1_fe_to_storage(&fes2, &fe); secp256k1_fe_to_storage(&fes2, &fe);
CHECK(memcmp(&fes2, &fes, sizeof(fes)) == 0); CHECK(secp256k1_memcmp_var(&fes2, &fes, sizeof(fes)) == 0);
} }
int fe_memcmp(const secp256k1_fe *a, const secp256k1_fe *b) { int fe_secp256k1_memcmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
secp256k1_fe t = *b; secp256k1_fe t = *b;
#ifdef VERIFY #ifdef VERIFY
t.magnitude = a->magnitude; t.magnitude = a->magnitude;
t.normalized = a->normalized; t.normalized = a->normalized;
#endif #endif
return memcmp(a, &t, sizeof(secp256k1_fe)); return secp256k1_memcmp_var(a, &t, sizeof(secp256k1_fe));
} }
void run_field_misc(void) { void run_field_misc(void) {
@ -1883,13 +1883,13 @@ void run_field_misc(void) {
CHECK(x.normalized && x.magnitude == 1); CHECK(x.normalized && x.magnitude == 1);
#endif #endif
secp256k1_fe_cmov(&x, &x, 1); secp256k1_fe_cmov(&x, &x, 1);
CHECK(fe_memcmp(&x, &z) != 0); CHECK(fe_secp256k1_memcmp_var(&x, &z) != 0);
CHECK(fe_memcmp(&x, &q) == 0); CHECK(fe_secp256k1_memcmp_var(&x, &q) == 0);
secp256k1_fe_cmov(&q, &z, 1); secp256k1_fe_cmov(&q, &z, 1);
#ifdef VERIFY #ifdef VERIFY
CHECK(!q.normalized && q.magnitude == z.magnitude); CHECK(!q.normalized && q.magnitude == z.magnitude);
#endif #endif
CHECK(fe_memcmp(&q, &z) == 0); CHECK(fe_secp256k1_memcmp_var(&q, &z) == 0);
secp256k1_fe_normalize_var(&x); secp256k1_fe_normalize_var(&x);
secp256k1_fe_normalize_var(&z); secp256k1_fe_normalize_var(&z);
CHECK(!secp256k1_fe_equal_var(&x, &z)); CHECK(!secp256k1_fe_equal_var(&x, &z));
@ -1913,9 +1913,9 @@ void run_field_misc(void) {
secp256k1_fe_to_storage(&zs, &z); secp256k1_fe_to_storage(&zs, &z);
secp256k1_fe_storage_cmov(&zs, &xs, 0); secp256k1_fe_storage_cmov(&zs, &xs, 0);
secp256k1_fe_storage_cmov(&zs, &zs, 1); secp256k1_fe_storage_cmov(&zs, &zs, 1);
CHECK(memcmp(&xs, &zs, sizeof(xs)) != 0); CHECK(secp256k1_memcmp_var(&xs, &zs, sizeof(xs)) != 0);
secp256k1_fe_storage_cmov(&ys, &xs, 1); secp256k1_fe_storage_cmov(&ys, &xs, 1);
CHECK(memcmp(&xs, &ys, sizeof(xs)) == 0); CHECK(secp256k1_memcmp_var(&xs, &ys, sizeof(xs)) == 0);
secp256k1_fe_from_storage(&x, &xs); secp256k1_fe_from_storage(&x, &xs);
secp256k1_fe_from_storage(&y, &ys); secp256k1_fe_from_storage(&y, &ys);
secp256k1_fe_from_storage(&z, &zs); secp256k1_fe_from_storage(&z, &zs);
@ -2102,17 +2102,12 @@ void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) {
void test_ge(void) { void test_ge(void) {
int i, i1; int i, i1;
#ifdef USE_ENDOMORPHISM
int runs = 6; int runs = 6;
#else /* 25 points are used:
int runs = 4; * - infinity
#endif * - for each of four random points p1 p2 p3 p4, we add the point, its
/* Points: (infinity, p1, p1, -p1, -p1, p2, p2, -p2, -p2, p3, p3, -p3, -p3, p4, p4, -p4, -p4). * negation, and then those two again but with randomized Z coordinate.
* The second in each pair of identical points uses a random Z coordinate in the Jacobian form. * - The same is then done for lambda*p1 and lambda^2*p1.
* All magnitudes are randomized.
* All 17*17 combinations of points are added to each other, using all applicable methods.
*
* When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well.
*/ */
secp256k1_ge *ge = (secp256k1_ge *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs)); secp256k1_ge *ge = (secp256k1_ge *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs));
secp256k1_gej *gej = (secp256k1_gej *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs)); secp256k1_gej *gej = (secp256k1_gej *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs));
@ -2127,14 +2122,12 @@ void test_ge(void) {
int j; int j;
secp256k1_ge g; secp256k1_ge g;
random_group_element_test(&g); random_group_element_test(&g);
#ifdef USE_ENDOMORPHISM
if (i >= runs - 2) { if (i >= runs - 2) {
secp256k1_ge_mul_lambda(&g, &ge[1]); secp256k1_ge_mul_lambda(&g, &ge[1]);
} }
if (i >= runs - 1) { if (i >= runs - 1) {
secp256k1_ge_mul_lambda(&g, &g); secp256k1_ge_mul_lambda(&g, &g);
} }
#endif
ge[1 + 4 * i] = g; ge[1 + 4 * i] = g;
ge[2 + 4 * i] = g; ge[2 + 4 * i] = g;
secp256k1_ge_neg(&ge[3 + 4 * i], &g); secp256k1_ge_neg(&ge[3 + 4 * i], &g);
@ -2449,7 +2442,7 @@ void test_ec_combine(void) {
secp256k1_ge_set_gej(&Q, &Qj); secp256k1_ge_set_gej(&Q, &Qj);
secp256k1_pubkey_save(&sd, &Q); secp256k1_pubkey_save(&sd, &Q);
CHECK(secp256k1_ec_pubkey_combine(ctx, &sd2, d, i) == 1); CHECK(secp256k1_ec_pubkey_combine(ctx, &sd2, d, i) == 1);
CHECK(memcmp(&sd, &sd2, sizeof(sd)) == 0); CHECK(secp256k1_memcmp_var(&sd, &sd2, sizeof(sd)) == 0);
} }
} }
@ -2633,6 +2626,87 @@ void test_point_times_order(const secp256k1_gej *point) {
ge_equals_ge(&res3, &secp256k1_ge_const_g); ge_equals_ge(&res3, &secp256k1_ge_const_g);
} }
/* These scalars reach large (in absolute value) outputs when fed to secp256k1_scalar_split_lambda.
*
* They are computed as:
* - For a in [-2, -1, 0, 1, 2]:
* - For b in [-3, -1, 1, 3]:
* - Output (a*LAMBDA + (ORDER+b)/2) % ORDER
*/
static const secp256k1_scalar scalars_near_split_bounds[20] = {
SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6fc),
SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6fd),
SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6fe),
SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6ff),
SECP256K1_SCALAR_CONST(0x2c9c52b3, 0x3fa3cf1f, 0x5ad9e3fd, 0x77ed9ba5, 0xb294b893, 0x3722e9a5, 0x00e698ca, 0x4cf7632d),
SECP256K1_SCALAR_CONST(0x2c9c52b3, 0x3fa3cf1f, 0x5ad9e3fd, 0x77ed9ba5, 0xb294b893, 0x3722e9a5, 0x00e698ca, 0x4cf7632e),
SECP256K1_SCALAR_CONST(0x2c9c52b3, 0x3fa3cf1f, 0x5ad9e3fd, 0x77ed9ba5, 0xb294b893, 0x3722e9a5, 0x00e698ca, 0x4cf7632f),
SECP256K1_SCALAR_CONST(0x2c9c52b3, 0x3fa3cf1f, 0x5ad9e3fd, 0x77ed9ba5, 0xb294b893, 0x3722e9a5, 0x00e698ca, 0x4cf76330),
SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd576e735, 0x57a4501d, 0xdfe92f46, 0x681b209f),
SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd576e735, 0x57a4501d, 0xdfe92f46, 0x681b20a0),
SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd576e735, 0x57a4501d, 0xdfe92f46, 0x681b20a1),
SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd576e735, 0x57a4501d, 0xdfe92f46, 0x681b20a2),
SECP256K1_SCALAR_CONST(0xd363ad4c, 0xc05c30e0, 0xa5261c02, 0x88126459, 0xf85915d7, 0x7825b696, 0xbeebc5c2, 0x833ede11),
SECP256K1_SCALAR_CONST(0xd363ad4c, 0xc05c30e0, 0xa5261c02, 0x88126459, 0xf85915d7, 0x7825b696, 0xbeebc5c2, 0x833ede12),
SECP256K1_SCALAR_CONST(0xd363ad4c, 0xc05c30e0, 0xa5261c02, 0x88126459, 0xf85915d7, 0x7825b696, 0xbeebc5c2, 0x833ede13),
SECP256K1_SCALAR_CONST(0xd363ad4c, 0xc05c30e0, 0xa5261c02, 0x88126459, 0xf85915d7, 0x7825b696, 0xbeebc5c2, 0x833ede14),
SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a42),
SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a43),
SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a44),
SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a45)
};
void test_ecmult_target(const secp256k1_scalar* target, int mode) {
/* Mode: 0=ecmult_gen, 1=ecmult, 2=ecmult_const */
secp256k1_scalar n1, n2;
secp256k1_ge p;
secp256k1_gej pj, p1j, p2j, ptj;
static const secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0);
/* Generate random n1,n2 such that n1+n2 = -target. */
random_scalar_order_test(&n1);
secp256k1_scalar_add(&n2, &n1, target);
secp256k1_scalar_negate(&n2, &n2);
/* Generate a random input point. */
if (mode != 0) {
random_group_element_test(&p);
secp256k1_gej_set_ge(&pj, &p);
}
/* EC multiplications */
if (mode == 0) {
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &p1j, &n1);
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &p2j, &n2);
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &ptj, target);
} else if (mode == 1) {
secp256k1_ecmult(&ctx->ecmult_ctx, &p1j, &pj, &n1, &zero);
secp256k1_ecmult(&ctx->ecmult_ctx, &p2j, &pj, &n2, &zero);
secp256k1_ecmult(&ctx->ecmult_ctx, &ptj, &pj, target, &zero);
} else {
secp256k1_ecmult_const(&p1j, &p, &n1, 256);
secp256k1_ecmult_const(&p2j, &p, &n2, 256);
secp256k1_ecmult_const(&ptj, &p, target, 256);
}
/* Add them all up: n1*P + n2*P + target*P = (n1+n2+target)*P = (n1+n1-n1-n2)*P = 0. */
secp256k1_gej_add_var(&ptj, &ptj, &p1j, NULL);
secp256k1_gej_add_var(&ptj, &ptj, &p2j, NULL);
CHECK(secp256k1_gej_is_infinity(&ptj));
}
void run_ecmult_near_split_bound(void) {
int i;
unsigned j;
for (i = 0; i < 4*count; ++i) {
for (j = 0; j < sizeof(scalars_near_split_bounds) / sizeof(scalars_near_split_bounds[0]); ++j) {
test_ecmult_target(&scalars_near_split_bounds[j], 0);
test_ecmult_target(&scalars_near_split_bounds[j], 1);
test_ecmult_target(&scalars_near_split_bounds[j], 2);
}
}
}
void run_point_times_order(void) { void run_point_times_order(void) {
int i; int i;
secp256k1_fe x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2); secp256k1_fe x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2);
@ -3041,12 +3115,10 @@ void test_secp256k1_pippenger_bucket_window_inv(void) {
CHECK(secp256k1_pippenger_bucket_window_inv(0) == 0); CHECK(secp256k1_pippenger_bucket_window_inv(0) == 0);
for(i = 1; i <= PIPPENGER_MAX_BUCKET_WINDOW; i++) { for(i = 1; i <= PIPPENGER_MAX_BUCKET_WINDOW; i++) {
#ifdef USE_ENDOMORPHISM
/* Bucket_window of 8 is not used with endo */ /* Bucket_window of 8 is not used with endo */
if (i == 8) { if (i == 8) {
continue; continue;
} }
#endif
CHECK(secp256k1_pippenger_bucket_window(secp256k1_pippenger_bucket_window_inv(i)) == i); CHECK(secp256k1_pippenger_bucket_window(secp256k1_pippenger_bucket_window_inv(i)) == i);
if (i != PIPPENGER_MAX_BUCKET_WINDOW) { if (i != PIPPENGER_MAX_BUCKET_WINDOW) {
CHECK(secp256k1_pippenger_bucket_window(secp256k1_pippenger_bucket_window_inv(i)+1) > i); CHECK(secp256k1_pippenger_bucket_window(secp256k1_pippenger_bucket_window_inv(i)+1) > i);
@ -3289,13 +3361,10 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) {
secp256k1_scalar_set_int(&x, 0); secp256k1_scalar_set_int(&x, 0);
secp256k1_scalar_set_int(&shift, 1 << w); secp256k1_scalar_set_int(&shift, 1 << w);
/* With USE_ENDOMORPHISM on we only consider 128-bit numbers */
#ifdef USE_ENDOMORPHISM
for (i = 0; i < 16; ++i) { for (i = 0; i < 16; ++i) {
secp256k1_scalar_shr_int(&num, 8); secp256k1_scalar_shr_int(&num, 8);
} }
bits = 128; bits = 128;
#endif
skew = secp256k1_wnaf_const(wnaf, &num, w, bits); skew = secp256k1_wnaf_const(wnaf, &num, w, bits);
for (i = WNAF_SIZE_BITS(bits, w); i >= 0; --i) { for (i = WNAF_SIZE_BITS(bits, w); i >= 0; --i) {
@ -3330,12 +3399,9 @@ void test_fixed_wnaf(const secp256k1_scalar *number, int w) {
secp256k1_scalar_set_int(&x, 0); secp256k1_scalar_set_int(&x, 0);
secp256k1_scalar_set_int(&shift, 1 << w); secp256k1_scalar_set_int(&shift, 1 << w);
/* With USE_ENDOMORPHISM on we only consider 128-bit numbers */
#ifdef USE_ENDOMORPHISM
for (i = 0; i < 16; ++i) { for (i = 0; i < 16; ++i) {
secp256k1_scalar_shr_int(&num, 8); secp256k1_scalar_shr_int(&num, 8);
} }
#endif
skew = secp256k1_wnaf_fixed(wnaf, &num, w); skew = secp256k1_wnaf_fixed(wnaf, &num, w);
for (i = WNAF_SIZE(w)-1; i >= 0; --i) { for (i = WNAF_SIZE(w)-1; i >= 0; --i) {
@ -3551,16 +3617,18 @@ void run_ecmult_gen_blind(void) {
} }
} }
#ifdef USE_ENDOMORPHISM
/***** ENDOMORPHISH TESTS *****/ /***** ENDOMORPHISH TESTS *****/
void test_scalar_split(void) { void test_scalar_split(const secp256k1_scalar* full) {
secp256k1_scalar full; secp256k1_scalar s, s1, slam;
secp256k1_scalar s1, slam;
const unsigned char zero[32] = {0}; const unsigned char zero[32] = {0};
unsigned char tmp[32]; unsigned char tmp[32];
random_scalar_order_test(&full); secp256k1_scalar_split_lambda(&s1, &slam, full);
secp256k1_scalar_split_lambda(&s1, &slam, &full);
/* check slam*lambda + s1 == full */
secp256k1_scalar_mul(&s, &secp256k1_const_lambda, &slam);
secp256k1_scalar_add(&s, &s, &s1);
CHECK(secp256k1_scalar_eq(&s, full));
/* check that both are <= 128 bits in size */ /* check that both are <= 128 bits in size */
if (secp256k1_scalar_is_high(&s1)) { if (secp256k1_scalar_is_high(&s1)) {
@ -3571,15 +3639,32 @@ void test_scalar_split(void) {
} }
secp256k1_scalar_get_b32(tmp, &s1); secp256k1_scalar_get_b32(tmp, &s1);
CHECK(memcmp(zero, tmp, 16) == 0); CHECK(secp256k1_memcmp_var(zero, tmp, 16) == 0);
secp256k1_scalar_get_b32(tmp, &slam); secp256k1_scalar_get_b32(tmp, &slam);
CHECK(memcmp(zero, tmp, 16) == 0); CHECK(secp256k1_memcmp_var(zero, tmp, 16) == 0);
} }
void run_endomorphism_tests(void) { void run_endomorphism_tests(void) {
test_scalar_split(); unsigned i;
static secp256k1_scalar s;
test_scalar_split(&secp256k1_scalar_zero);
test_scalar_split(&secp256k1_scalar_one);
secp256k1_scalar_negate(&s,&secp256k1_scalar_one);
test_scalar_split(&s);
test_scalar_split(&secp256k1_const_lambda);
secp256k1_scalar_add(&s, &secp256k1_const_lambda, &secp256k1_scalar_one);
test_scalar_split(&s);
for (i = 0; i < 100U * count; ++i) {
secp256k1_scalar full;
random_scalar_order_test(&full);
test_scalar_split(&full);
}
for (i = 0; i < sizeof(scalars_near_split_bounds) / sizeof(scalars_near_split_bounds[0]); ++i) {
test_scalar_split(&scalars_near_split_bounds[i]);
}
} }
#endif
void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvalid) { void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvalid) {
unsigned char pubkeyc[65]; unsigned char pubkeyc[65];
@ -3621,7 +3706,7 @@ void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvali
CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_COMPRESSED) == 1); CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
VG_CHECK(pubkeyo, outl); VG_CHECK(pubkeyo, outl);
CHECK(outl == 33); CHECK(outl == 33);
CHECK(memcmp(&pubkeyo[1], &pubkeyc[1], 32) == 0); CHECK(secp256k1_memcmp_var(&pubkeyo[1], &pubkeyc[1], 32) == 0);
CHECK((pubkeyclen != 33) || (pubkeyo[0] == pubkeyc[0])); CHECK((pubkeyclen != 33) || (pubkeyo[0] == pubkeyc[0]));
if (ypass) { if (ypass) {
/* This test isn't always done because we decode with alternative signs, so the y won't match. */ /* This test isn't always done because we decode with alternative signs, so the y won't match. */
@ -3637,7 +3722,7 @@ void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvali
VG_CHECK(pubkeyo, outl); VG_CHECK(pubkeyo, outl);
CHECK(outl == 65); CHECK(outl == 65);
CHECK(pubkeyo[0] == 4); CHECK(pubkeyo[0] == 4);
CHECK(memcmp(&pubkeyo[1], input, 64) == 0); CHECK(secp256k1_memcmp_var(&pubkeyo[1], input, 64) == 0);
} }
CHECK(ecount == 0); CHECK(ecount == 0);
} else { } else {
@ -4006,7 +4091,7 @@ void run_eckey_edge_case_test(void) {
VG_UNDEF(&pubkey, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, orderc) == 0); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, orderc) == 0);
VG_CHECK(&pubkey, sizeof(pubkey)); VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
/* Maximum value is too large, reject. */ /* Maximum value is too large, reject. */
memset(ctmp, 255, 32); memset(ctmp, 255, 32);
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0);
@ -4014,7 +4099,7 @@ void run_eckey_edge_case_test(void) {
VG_UNDEF(&pubkey, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0);
VG_CHECK(&pubkey, sizeof(pubkey)); VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
/* Zero is too small, reject. */ /* Zero is too small, reject. */
memset(ctmp, 0, 32); memset(ctmp, 0, 32);
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0);
@ -4022,7 +4107,7 @@ void run_eckey_edge_case_test(void) {
VG_UNDEF(&pubkey, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0);
VG_CHECK(&pubkey, sizeof(pubkey)); VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
/* One must be accepted. */ /* One must be accepted. */
ctmp[31] = 0x01; ctmp[31] = 0x01;
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1);
@ -4030,7 +4115,7 @@ void run_eckey_edge_case_test(void) {
VG_UNDEF(&pubkey, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1);
VG_CHECK(&pubkey, sizeof(pubkey)); VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
pubkey_one = pubkey; pubkey_one = pubkey;
/* Group order + 1 is too large, reject. */ /* Group order + 1 is too large, reject. */
memcpy(ctmp, orderc, 32); memcpy(ctmp, orderc, 32);
@ -4040,7 +4125,7 @@ void run_eckey_edge_case_test(void) {
VG_UNDEF(&pubkey, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0);
VG_CHECK(&pubkey, sizeof(pubkey)); VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
/* -1 must be accepted. */ /* -1 must be accepted. */
ctmp[31] = 0x40; ctmp[31] = 0x40;
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1);
@ -4048,20 +4133,20 @@ void run_eckey_edge_case_test(void) {
VG_UNDEF(&pubkey, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1);
VG_CHECK(&pubkey, sizeof(pubkey)); VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
pubkey_negone = pubkey; pubkey_negone = pubkey;
/* Tweak of zero leaves the value unchanged. */ /* Tweak of zero leaves the value unchanged. */
memset(ctmp2, 0, 32); memset(ctmp2, 0, 32);
CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp, ctmp2) == 1); CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp, ctmp2) == 1);
CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); CHECK(secp256k1_memcmp_var(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40);
memcpy(&pubkey2, &pubkey, sizeof(pubkey)); memcpy(&pubkey2, &pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1);
CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0);
/* Multiply tweak of zero zeroizes the output. */ /* Multiply tweak of zero zeroizes the output. */
CHECK(secp256k1_ec_seckey_tweak_mul(ctx, ctmp, ctmp2) == 0); CHECK(secp256k1_ec_seckey_tweak_mul(ctx, ctmp, ctmp2) == 0);
CHECK(memcmp(zeros, ctmp, 32) == 0); CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0);
CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp2) == 0); CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp2) == 0);
CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0);
memcpy(&pubkey, &pubkey2, sizeof(pubkey)); memcpy(&pubkey, &pubkey2, sizeof(pubkey));
/* If seckey_tweak_add or seckey_tweak_mul are called with an overflowing /* If seckey_tweak_add or seckey_tweak_mul are called with an overflowing
seckey, the seckey is zeroized. */ seckey, the seckey is zeroized. */
@ -4071,29 +4156,29 @@ void run_eckey_edge_case_test(void) {
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp2) == 1); CHECK(secp256k1_ec_seckey_verify(ctx, ctmp2) == 1);
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0);
CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp, ctmp2) == 0); CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp, ctmp2) == 0);
CHECK(memcmp(zeros, ctmp, 32) == 0); CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0);
memcpy(ctmp, orderc, 32); memcpy(ctmp, orderc, 32);
CHECK(secp256k1_ec_seckey_tweak_mul(ctx, ctmp, ctmp2) == 0); CHECK(secp256k1_ec_seckey_tweak_mul(ctx, ctmp, ctmp2) == 0);
CHECK(memcmp(zeros, ctmp, 32) == 0); CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0);
/* If seckey_tweak_add or seckey_tweak_mul are called with an overflowing /* If seckey_tweak_add or seckey_tweak_mul are called with an overflowing
tweak, the seckey is zeroized. */ tweak, the seckey is zeroized. */
memcpy(ctmp, orderc, 32); memcpy(ctmp, orderc, 32);
ctmp[31] = 0x40; ctmp[31] = 0x40;
CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp, orderc) == 0); CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp, orderc) == 0);
CHECK(memcmp(zeros, ctmp, 32) == 0); CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0);
memcpy(ctmp, orderc, 32); memcpy(ctmp, orderc, 32);
ctmp[31] = 0x40; ctmp[31] = 0x40;
CHECK(secp256k1_ec_seckey_tweak_mul(ctx, ctmp, orderc) == 0); CHECK(secp256k1_ec_seckey_tweak_mul(ctx, ctmp, orderc) == 0);
CHECK(memcmp(zeros, ctmp, 32) == 0); CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0);
memcpy(ctmp, orderc, 32); memcpy(ctmp, orderc, 32);
ctmp[31] = 0x40; ctmp[31] = 0x40;
/* If pubkey_tweak_add or pubkey_tweak_mul are called with an overflowing /* If pubkey_tweak_add or pubkey_tweak_mul are called with an overflowing
tweak, the pubkey is zeroized. */ tweak, the pubkey is zeroized. */
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, orderc) == 0); CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, orderc) == 0);
CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0);
memcpy(&pubkey, &pubkey2, sizeof(pubkey)); memcpy(&pubkey, &pubkey2, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, orderc) == 0); CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, orderc) == 0);
CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0);
memcpy(&pubkey, &pubkey2, sizeof(pubkey)); memcpy(&pubkey, &pubkey2, sizeof(pubkey));
/* If the resulting key in secp256k1_ec_seckey_tweak_add and /* If the resulting key in secp256k1_ec_seckey_tweak_add and
* secp256k1_ec_pubkey_tweak_add is 0 the functions fail and in the latter * secp256k1_ec_pubkey_tweak_add is 0 the functions fail and in the latter
@ -4103,25 +4188,25 @@ void run_eckey_edge_case_test(void) {
memset(ctmp2, 0, 32); memset(ctmp2, 0, 32);
ctmp2[31] = 1; ctmp2[31] = 1;
CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp2, ctmp) == 0); CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp2, ctmp) == 0);
CHECK(memcmp(zeros, ctmp2, 32) == 0); CHECK(secp256k1_memcmp_var(zeros, ctmp2, 32) == 0);
ctmp2[31] = 1; ctmp2[31] = 1;
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0);
CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0);
memcpy(&pubkey, &pubkey2, sizeof(pubkey)); memcpy(&pubkey, &pubkey2, sizeof(pubkey));
/* Tweak computation wraps and results in a key of 1. */ /* Tweak computation wraps and results in a key of 1. */
ctmp2[31] = 2; ctmp2[31] = 2;
CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp2, ctmp) == 1); CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp2, ctmp) == 1);
CHECK(memcmp(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1); CHECK(secp256k1_memcmp_var(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1);
ctmp2[31] = 2; ctmp2[31] = 2;
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1);
ctmp2[31] = 1; ctmp2[31] = 1;
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, ctmp2) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, ctmp2) == 1);
CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0);
/* Tweak mul * 2 = 1+1. */ /* Tweak mul * 2 = 1+1. */
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1);
ctmp2[31] = 2; ctmp2[31] = 2;
CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 1); CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 1);
CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0);
/* Test argument errors. */ /* Test argument errors. */
ecount = 0; ecount = 0;
secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
@ -4130,12 +4215,12 @@ void run_eckey_edge_case_test(void) {
memset(&pubkey, 0, 32); memset(&pubkey, 0, 32);
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0);
CHECK(ecount == 1); CHECK(ecount == 1);
CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0);
memcpy(&pubkey, &pubkey2, sizeof(pubkey)); memcpy(&pubkey, &pubkey2, sizeof(pubkey));
memset(&pubkey2, 0, 32); memset(&pubkey2, 0, 32);
CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 0); CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 0);
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(memcmp(&pubkey2, zeros, sizeof(pubkey2)) == 0); CHECK(secp256k1_memcmp_var(&pubkey2, zeros, sizeof(pubkey2)) == 0);
/* Plain argument errors. */ /* Plain argument errors. */
ecount = 0; ecount = 0;
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1);
@ -4175,7 +4260,7 @@ void run_eckey_edge_case_test(void) {
memset(&pubkey, 1, sizeof(pubkey)); memset(&pubkey, 1, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0);
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
/* secp256k1_ec_pubkey_combine tests. */ /* secp256k1_ec_pubkey_combine tests. */
ecount = 0; ecount = 0;
pubkeys[0] = &pubkey_one; pubkeys[0] = &pubkey_one;
@ -4186,28 +4271,28 @@ void run_eckey_edge_case_test(void) {
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 0) == 0); CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 0) == 0);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
CHECK(ecount == 1); CHECK(ecount == 1);
CHECK(secp256k1_ec_pubkey_combine(ctx, NULL, pubkeys, 1) == 0); CHECK(secp256k1_ec_pubkey_combine(ctx, NULL, pubkeys, 1) == 0);
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
CHECK(ecount == 2); CHECK(ecount == 2);
memset(&pubkey, 255, sizeof(secp256k1_pubkey)); memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, NULL, 1) == 0); CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, NULL, 1) == 0);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
CHECK(ecount == 3); CHECK(ecount == 3);
pubkeys[0] = &pubkey_negone; pubkeys[0] = &pubkey_negone;
memset(&pubkey, 255, sizeof(secp256k1_pubkey)); memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 1) == 1); CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 1) == 1);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
CHECK(ecount == 3); CHECK(ecount == 3);
len = 33; len = 33;
CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_negone, SECP256K1_EC_COMPRESSED) == 1); CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_negone, SECP256K1_EC_COMPRESSED) == 1);
CHECK(memcmp(ctmp, ctmp2, 33) == 0); CHECK(secp256k1_memcmp_var(ctmp, ctmp2, 33) == 0);
/* Result is infinity. */ /* Result is infinity. */
pubkeys[0] = &pubkey_one; pubkeys[0] = &pubkey_one;
pubkeys[1] = &pubkey_negone; pubkeys[1] = &pubkey_negone;
@ -4215,7 +4300,7 @@ void run_eckey_edge_case_test(void) {
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 0); CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 0);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
CHECK(ecount == 3); CHECK(ecount == 3);
/* Passes through infinity but comes out one. */ /* Passes through infinity but comes out one. */
pubkeys[2] = &pubkey_one; pubkeys[2] = &pubkey_one;
@ -4223,19 +4308,19 @@ void run_eckey_edge_case_test(void) {
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 3) == 1); CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 3) == 1);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
CHECK(ecount == 3); CHECK(ecount == 3);
len = 33; len = 33;
CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1); CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1);
CHECK(memcmp(ctmp, ctmp2, 33) == 0); CHECK(secp256k1_memcmp_var(ctmp, ctmp2, 33) == 0);
/* Adds to two. */ /* Adds to two. */
pubkeys[1] = &pubkey_one; pubkeys[1] = &pubkey_one;
memset(&pubkey, 255, sizeof(secp256k1_pubkey)); memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 1); CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 1);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
CHECK(ecount == 3); CHECK(ecount == 3);
secp256k1_context_set_illegal_callback(ctx, NULL, NULL); secp256k1_context_set_illegal_callback(ctx, NULL, NULL);
} }
@ -4249,21 +4334,21 @@ void run_eckey_negate_test(void) {
/* Verify negation changes the key and changes it back */ /* Verify negation changes the key and changes it back */
CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 1); CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 1);
CHECK(memcmp(seckey, seckey_tmp, 32) != 0); CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) != 0);
CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 1); CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 1);
CHECK(memcmp(seckey, seckey_tmp, 32) == 0); CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0);
/* Check that privkey alias gives same result */ /* Check that privkey alias gives same result */
CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 1); CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 1);
CHECK(secp256k1_ec_privkey_negate(ctx, seckey_tmp) == 1); CHECK(secp256k1_ec_privkey_negate(ctx, seckey_tmp) == 1);
CHECK(memcmp(seckey, seckey_tmp, 32) == 0); CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0);
/* Negating all 0s fails */ /* Negating all 0s fails */
memset(seckey, 0, 32); memset(seckey, 0, 32);
memset(seckey_tmp, 0, 32); memset(seckey_tmp, 0, 32);
CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 0); CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 0);
/* Check that seckey is not modified */ /* Check that seckey is not modified */
CHECK(memcmp(seckey, seckey_tmp, 32) == 0); CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0);
/* Negating an overflowing seckey fails and the seckey is zeroed. In this /* Negating an overflowing seckey fails and the seckey is zeroed. In this
* test, the seckey has 16 random bytes to ensure that ec_seckey_negate * test, the seckey has 16 random bytes to ensure that ec_seckey_negate
@ -4272,7 +4357,7 @@ void run_eckey_negate_test(void) {
memset(seckey, 0xFF, 16); memset(seckey, 0xFF, 16);
memset(seckey_tmp, 0, 32); memset(seckey_tmp, 0, 32);
CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 0); CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 0);
CHECK(memcmp(seckey, seckey_tmp, 32) == 0); CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0);
} }
void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *key, const secp256k1_scalar *msg, int *recid) { void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *key, const secp256k1_scalar *msg, int *recid) {
@ -4361,7 +4446,7 @@ static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char
int is_empty_signature(const secp256k1_ecdsa_signature *sig) { int is_empty_signature(const secp256k1_ecdsa_signature *sig) {
static const unsigned char res[sizeof(secp256k1_ecdsa_signature)] = {0}; static const unsigned char res[sizeof(secp256k1_ecdsa_signature)] = {0};
return memcmp(sig, res, sizeof(secp256k1_ecdsa_signature)) == 0; return secp256k1_memcmp_var(sig, res, sizeof(secp256k1_ecdsa_signature)) == 0;
} }
void test_ecdsa_end_to_end(void) { void test_ecdsa_end_to_end(void) {
@ -4401,14 +4486,14 @@ void test_ecdsa_end_to_end(void) {
/* Verify negation changes the key and changes it back */ /* Verify negation changes the key and changes it back */
memcpy(&pubkey_tmp, &pubkey, sizeof(pubkey)); memcpy(&pubkey_tmp, &pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1); CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1);
CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0); CHECK(secp256k1_memcmp_var(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0);
CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1); CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1);
CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0);
/* Verify private key import and export. */ /* Verify private key import and export. */
CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_testrand_bits(1) == 1)); CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_testrand_bits(1) == 1));
CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1); CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1);
CHECK(memcmp(privkey, privkey2, 32) == 0); CHECK(secp256k1_memcmp_var(privkey, privkey2, 32) == 0);
/* Optionally tweak the keys using addition. */ /* Optionally tweak the keys using addition. */
if (secp256k1_testrand_int(3) == 0) { if (secp256k1_testrand_int(3) == 0) {
@ -4429,9 +4514,9 @@ void test_ecdsa_end_to_end(void) {
if (ret1 == 0) { if (ret1 == 0) {
return; return;
} }
CHECK(memcmp(privkey, privkey_tmp, 32) == 0); CHECK(secp256k1_memcmp_var(privkey, privkey_tmp, 32) == 0);
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1);
CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0);
} }
/* Optionally tweak the keys using multiplication. */ /* Optionally tweak the keys using multiplication. */
@ -4453,9 +4538,9 @@ void test_ecdsa_end_to_end(void) {
if (ret1 == 0) { if (ret1 == 0) {
return; return;
} }
CHECK(memcmp(privkey, privkey_tmp, 32) == 0); CHECK(secp256k1_memcmp_var(privkey, privkey_tmp, 32) == 0);
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1);
CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0);
} }
/* Sign. */ /* Sign. */
@ -4467,13 +4552,13 @@ void test_ecdsa_end_to_end(void) {
extra[31] = 0; extra[31] = 0;
extra[0] = 1; extra[0] = 1;
CHECK(secp256k1_ecdsa_sign(ctx, &signature[3], message, privkey, NULL, extra) == 1); CHECK(secp256k1_ecdsa_sign(ctx, &signature[3], message, privkey, NULL, extra) == 1);
CHECK(memcmp(&signature[0], &signature[4], sizeof(signature[0])) == 0); CHECK(secp256k1_memcmp_var(&signature[0], &signature[4], sizeof(signature[0])) == 0);
CHECK(memcmp(&signature[0], &signature[1], sizeof(signature[0])) != 0); CHECK(secp256k1_memcmp_var(&signature[0], &signature[1], sizeof(signature[0])) != 0);
CHECK(memcmp(&signature[0], &signature[2], sizeof(signature[0])) != 0); CHECK(secp256k1_memcmp_var(&signature[0], &signature[2], sizeof(signature[0])) != 0);
CHECK(memcmp(&signature[0], &signature[3], sizeof(signature[0])) != 0); CHECK(secp256k1_memcmp_var(&signature[0], &signature[3], sizeof(signature[0])) != 0);
CHECK(memcmp(&signature[1], &signature[2], sizeof(signature[0])) != 0); CHECK(secp256k1_memcmp_var(&signature[1], &signature[2], sizeof(signature[0])) != 0);
CHECK(memcmp(&signature[1], &signature[3], sizeof(signature[0])) != 0); CHECK(secp256k1_memcmp_var(&signature[1], &signature[3], sizeof(signature[0])) != 0);
CHECK(memcmp(&signature[2], &signature[3], sizeof(signature[0])) != 0); CHECK(secp256k1_memcmp_var(&signature[2], &signature[3], sizeof(signature[0])) != 0);
/* Verify. */ /* Verify. */
CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1);
CHECK(secp256k1_ecdsa_verify(ctx, &signature[1], message, &pubkey) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &signature[1], message, &pubkey) == 1);
@ -4494,7 +4579,7 @@ void test_ecdsa_end_to_end(void) {
secp256k1_ecdsa_signature_save(&signature[5], &r, &s); secp256k1_ecdsa_signature_save(&signature[5], &r, &s);
CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5]));
CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1);
CHECK(memcmp(&signature[5], &signature[0], 64) == 0); CHECK(secp256k1_memcmp_var(&signature[5], &signature[0], 64) == 0);
/* Serialize/parse DER and verify again */ /* Serialize/parse DER and verify again */
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1);
@ -4541,7 +4626,7 @@ void test_random_pubkeys(void) {
/* If the pubkey can be parsed, it should round-trip... */ /* If the pubkey can be parsed, it should round-trip... */
CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, len == 33)); CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, len == 33));
CHECK(size == len); CHECK(size == len);
CHECK(memcmp(&in[1], &out[1], len-1) == 0); CHECK(secp256k1_memcmp_var(&in[1], &out[1], len-1) == 0);
/* ... except for the type of hybrid inputs. */ /* ... except for the type of hybrid inputs. */
if ((in[0] != 6) && (in[0] != 7)) { if ((in[0] != 6) && (in[0] != 7)) {
CHECK(in[0] == out[0]); CHECK(in[0] == out[0]);
@ -4564,7 +4649,7 @@ void test_random_pubkeys(void) {
if (res) { if (res) {
ge_equals_ge(&elem,&elem2); ge_equals_ge(&elem,&elem2);
CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0)); CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0));
CHECK(memcmp(&in[1], &out[1], 64) == 0); CHECK(secp256k1_memcmp_var(&in[1], &out[1], 64) == 0);
} }
} }
} }
@ -4620,21 +4705,21 @@ int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_
parsed_der = secp256k1_ecdsa_signature_parse_der(ctx, &sig_der, sig, siglen); parsed_der = secp256k1_ecdsa_signature_parse_der(ctx, &sig_der, sig, siglen);
if (parsed_der) { if (parsed_der) {
ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der, &sig_der)) << 0; ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der, &sig_der)) << 0;
valid_der = (memcmp(compact_der, zeroes, 32) != 0) && (memcmp(compact_der + 32, zeroes, 32) != 0); valid_der = (secp256k1_memcmp_var(compact_der, zeroes, 32) != 0) && (secp256k1_memcmp_var(compact_der + 32, zeroes, 32) != 0);
} }
if (valid_der) { if (valid_der) {
ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der, &len_der, &sig_der)) << 1; ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der, &len_der, &sig_der)) << 1;
roundtrips_der = (len_der == siglen) && memcmp(roundtrip_der, sig, siglen) == 0; roundtrips_der = (len_der == siglen) && secp256k1_memcmp_var(roundtrip_der, sig, siglen) == 0;
} }
parsed_der_lax = ecdsa_signature_parse_der_lax(ctx, &sig_der_lax, sig, siglen); parsed_der_lax = ecdsa_signature_parse_der_lax(ctx, &sig_der_lax, sig, siglen);
if (parsed_der_lax) { if (parsed_der_lax) {
ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der_lax, &sig_der_lax)) << 10; ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der_lax, &sig_der_lax)) << 10;
valid_der_lax = (memcmp(compact_der_lax, zeroes, 32) != 0) && (memcmp(compact_der_lax + 32, zeroes, 32) != 0); valid_der_lax = (secp256k1_memcmp_var(compact_der_lax, zeroes, 32) != 0) && (secp256k1_memcmp_var(compact_der_lax + 32, zeroes, 32) != 0);
} }
if (valid_der_lax) { if (valid_der_lax) {
ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11; ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11;
roundtrips_der_lax = (len_der_lax == siglen) && memcmp(roundtrip_der_lax, sig, siglen) == 0; roundtrips_der_lax = (len_der_lax == siglen) && secp256k1_memcmp_var(roundtrip_der_lax, sig, siglen) == 0;
} }
if (certainly_der) { if (certainly_der) {
@ -4650,7 +4735,7 @@ int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_
if (valid_der) { if (valid_der) {
ret |= (!roundtrips_der_lax) << 12; ret |= (!roundtrips_der_lax) << 12;
ret |= (len_der != len_der_lax) << 13; ret |= (len_der != len_der_lax) << 13;
ret |= ((len_der != len_der_lax) || (memcmp(roundtrip_der_lax, roundtrip_der, len_der) != 0)) << 14; ret |= ((len_der != len_der_lax) || (secp256k1_memcmp_var(roundtrip_der_lax, roundtrip_der, len_der) != 0)) << 14;
} }
ret |= (roundtrips_der != roundtrips_der_lax) << 15; ret |= (roundtrips_der != roundtrips_der_lax) << 15;
if (parsed_der) { if (parsed_der) {
@ -4667,19 +4752,19 @@ int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_
if (valid_openssl) { if (valid_openssl) {
unsigned char tmp[32] = {0}; unsigned char tmp[32] = {0};
BN_bn2bin(r, tmp + 32 - BN_num_bytes(r)); BN_bn2bin(r, tmp + 32 - BN_num_bytes(r));
valid_openssl = memcmp(tmp, max_scalar, 32) < 0; valid_openssl = secp256k1_memcmp_var(tmp, max_scalar, 32) < 0;
} }
if (valid_openssl) { if (valid_openssl) {
unsigned char tmp[32] = {0}; unsigned char tmp[32] = {0};
BN_bn2bin(s, tmp + 32 - BN_num_bytes(s)); BN_bn2bin(s, tmp + 32 - BN_num_bytes(s));
valid_openssl = memcmp(tmp, max_scalar, 32) < 0; valid_openssl = secp256k1_memcmp_var(tmp, max_scalar, 32) < 0;
} }
} }
len_openssl = i2d_ECDSA_SIG(sig_openssl, NULL); len_openssl = i2d_ECDSA_SIG(sig_openssl, NULL);
if (len_openssl <= 2048) { if (len_openssl <= 2048) {
unsigned char *ptr = roundtrip_openssl; unsigned char *ptr = roundtrip_openssl;
CHECK(i2d_ECDSA_SIG(sig_openssl, &ptr) == len_openssl); CHECK(i2d_ECDSA_SIG(sig_openssl, &ptr) == len_openssl);
roundtrips_openssl = valid_openssl && ((size_t)len_openssl == siglen) && (memcmp(roundtrip_openssl, sig, siglen) == 0); roundtrips_openssl = valid_openssl && ((size_t)len_openssl == siglen) && (secp256k1_memcmp_var(roundtrip_openssl, sig, siglen) == 0);
} else { } else {
len_openssl = 0; len_openssl = 0;
} }
@ -4691,7 +4776,7 @@ int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_
ret |= (roundtrips_der != roundtrips_openssl) << 7; ret |= (roundtrips_der != roundtrips_openssl) << 7;
if (roundtrips_openssl) { if (roundtrips_openssl) {
ret |= (len_der != (size_t)len_openssl) << 8; ret |= (len_der != (size_t)len_openssl) << 8;
ret |= ((len_der != (size_t)len_openssl) || (memcmp(roundtrip_der, roundtrip_openssl, len_der) != 0)) << 9; ret |= ((len_der != (size_t)len_openssl) || (secp256k1_memcmp_var(roundtrip_der, roundtrip_openssl, len_der) != 0)) << 9;
} }
#endif #endif
return ret; return ret;
@ -5207,11 +5292,11 @@ void test_ecdsa_edge_cases(void) {
CHECK(!is_empty_signature(&sig)); CHECK(!is_empty_signature(&sig));
CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, nonce_function_rfc6979, extra) == 1); CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, nonce_function_rfc6979, extra) == 1);
CHECK(!is_empty_signature(&sig2)); CHECK(!is_empty_signature(&sig2));
CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); CHECK(secp256k1_memcmp_var(&sig, &sig2, sizeof(sig)) == 0);
/* The default nonce function is deterministic. */ /* The default nonce function is deterministic. */
CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1);
CHECK(!is_empty_signature(&sig2)); CHECK(!is_empty_signature(&sig2));
CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); CHECK(secp256k1_memcmp_var(&sig, &sig2, sizeof(sig)) == 0);
/* The default nonce function changes output with different messages. */ /* The default nonce function changes output with different messages. */
for(i = 0; i < 256; i++) { for(i = 0; i < 256; i++) {
int j; int j;
@ -5258,12 +5343,12 @@ void test_ecdsa_edge_cases(void) {
VG_CHECK(nonce3,32); VG_CHECK(nonce3,32);
CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1); CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1);
VG_CHECK(nonce4,32); VG_CHECK(nonce4,32);
CHECK(memcmp(nonce, nonce2, 32) != 0); CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0);
CHECK(memcmp(nonce, nonce3, 32) != 0); CHECK(secp256k1_memcmp_var(nonce, nonce3, 32) != 0);
CHECK(memcmp(nonce, nonce4, 32) != 0); CHECK(secp256k1_memcmp_var(nonce, nonce4, 32) != 0);
CHECK(memcmp(nonce2, nonce3, 32) != 0); CHECK(secp256k1_memcmp_var(nonce2, nonce3, 32) != 0);
CHECK(memcmp(nonce2, nonce4, 32) != 0); CHECK(secp256k1_memcmp_var(nonce2, nonce4, 32) != 0);
CHECK(memcmp(nonce3, nonce4, 32) != 0); CHECK(secp256k1_memcmp_var(nonce3, nonce4, 32) != 0);
} }
@ -5366,12 +5451,12 @@ void run_memczero_test(void) {
/* memczero(..., ..., 0) is a noop. */ /* memczero(..., ..., 0) is a noop. */
memcpy(buf2, buf1, sizeof(buf1)); memcpy(buf2, buf1, sizeof(buf1));
memczero(buf1, sizeof(buf1), 0); memczero(buf1, sizeof(buf1), 0);
CHECK(memcmp(buf1, buf2, sizeof(buf1)) == 0); CHECK(secp256k1_memcmp_var(buf1, buf2, sizeof(buf1)) == 0);
/* memczero(..., ..., 1) zeros the buffer. */ /* memczero(..., ..., 1) zeros the buffer. */
memset(buf2, 0, sizeof(buf2)); memset(buf2, 0, sizeof(buf2));
memczero(buf1, sizeof(buf1) , 1); memczero(buf1, sizeof(buf1) , 1);
CHECK(memcmp(buf1, buf2, sizeof(buf1)) == 0); CHECK(secp256k1_memcmp_var(buf1, buf2, sizeof(buf1)) == 0);
} }
void int_cmov_test(void) { void int_cmov_test(void) {
@ -5410,23 +5495,23 @@ void fe_cmov_test(void) {
secp256k1_fe a = zero; secp256k1_fe a = zero;
secp256k1_fe_cmov(&r, &a, 0); secp256k1_fe_cmov(&r, &a, 0);
CHECK(memcmp(&r, &max, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0);
r = zero; a = max; r = zero; a = max;
secp256k1_fe_cmov(&r, &a, 1); secp256k1_fe_cmov(&r, &a, 1);
CHECK(memcmp(&r, &max, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0);
a = zero; a = zero;
secp256k1_fe_cmov(&r, &a, 1); secp256k1_fe_cmov(&r, &a, 1);
CHECK(memcmp(&r, &zero, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &zero, sizeof(r)) == 0);
a = one; a = one;
secp256k1_fe_cmov(&r, &a, 1); secp256k1_fe_cmov(&r, &a, 1);
CHECK(memcmp(&r, &one, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0);
r = one; a = zero; r = one; a = zero;
secp256k1_fe_cmov(&r, &a, 0); secp256k1_fe_cmov(&r, &a, 0);
CHECK(memcmp(&r, &one, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0);
} }
void fe_storage_cmov_test(void) { void fe_storage_cmov_test(void) {
@ -5440,23 +5525,23 @@ void fe_storage_cmov_test(void) {
secp256k1_fe_storage a = zero; secp256k1_fe_storage a = zero;
secp256k1_fe_storage_cmov(&r, &a, 0); secp256k1_fe_storage_cmov(&r, &a, 0);
CHECK(memcmp(&r, &max, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0);
r = zero; a = max; r = zero; a = max;
secp256k1_fe_storage_cmov(&r, &a, 1); secp256k1_fe_storage_cmov(&r, &a, 1);
CHECK(memcmp(&r, &max, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0);
a = zero; a = zero;
secp256k1_fe_storage_cmov(&r, &a, 1); secp256k1_fe_storage_cmov(&r, &a, 1);
CHECK(memcmp(&r, &zero, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &zero, sizeof(r)) == 0);
a = one; a = one;
secp256k1_fe_storage_cmov(&r, &a, 1); secp256k1_fe_storage_cmov(&r, &a, 1);
CHECK(memcmp(&r, &one, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0);
r = one; a = zero; r = one; a = zero;
secp256k1_fe_storage_cmov(&r, &a, 0); secp256k1_fe_storage_cmov(&r, &a, 0);
CHECK(memcmp(&r, &one, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0);
} }
void scalar_cmov_test(void) { void scalar_cmov_test(void) {
@ -5470,23 +5555,23 @@ void scalar_cmov_test(void) {
secp256k1_scalar a = zero; secp256k1_scalar a = zero;
secp256k1_scalar_cmov(&r, &a, 0); secp256k1_scalar_cmov(&r, &a, 0);
CHECK(memcmp(&r, &max, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0);
r = zero; a = max; r = zero; a = max;
secp256k1_scalar_cmov(&r, &a, 1); secp256k1_scalar_cmov(&r, &a, 1);
CHECK(memcmp(&r, &max, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0);
a = zero; a = zero;
secp256k1_scalar_cmov(&r, &a, 1); secp256k1_scalar_cmov(&r, &a, 1);
CHECK(memcmp(&r, &zero, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &zero, sizeof(r)) == 0);
a = one; a = one;
secp256k1_scalar_cmov(&r, &a, 1); secp256k1_scalar_cmov(&r, &a, 1);
CHECK(memcmp(&r, &one, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0);
r = one; a = zero; r = one; a = zero;
secp256k1_scalar_cmov(&r, &a, 0); secp256k1_scalar_cmov(&r, &a, 0);
CHECK(memcmp(&r, &one, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0);
} }
void ge_storage_cmov_test(void) { void ge_storage_cmov_test(void) {
@ -5502,23 +5587,23 @@ void ge_storage_cmov_test(void) {
secp256k1_ge_storage a = zero; secp256k1_ge_storage a = zero;
secp256k1_ge_storage_cmov(&r, &a, 0); secp256k1_ge_storage_cmov(&r, &a, 0);
CHECK(memcmp(&r, &max, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0);
r = zero; a = max; r = zero; a = max;
secp256k1_ge_storage_cmov(&r, &a, 1); secp256k1_ge_storage_cmov(&r, &a, 1);
CHECK(memcmp(&r, &max, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0);
a = zero; a = zero;
secp256k1_ge_storage_cmov(&r, &a, 1); secp256k1_ge_storage_cmov(&r, &a, 1);
CHECK(memcmp(&r, &zero, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &zero, sizeof(r)) == 0);
a = one; a = one;
secp256k1_ge_storage_cmov(&r, &a, 1); secp256k1_ge_storage_cmov(&r, &a, 1);
CHECK(memcmp(&r, &one, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0);
r = one; a = zero; r = one; a = zero;
secp256k1_ge_storage_cmov(&r, &a, 0); secp256k1_ge_storage_cmov(&r, &a, 0);
CHECK(memcmp(&r, &one, sizeof(r)) == 0); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0);
} }
void run_cmov_tests(void) { void run_cmov_tests(void) {
@ -5589,6 +5674,7 @@ int main(int argc, char **argv) {
/* ecmult tests */ /* ecmult tests */
run_wnaf(); run_wnaf();
run_point_times_order(); run_point_times_order();
run_ecmult_near_split_bound();
run_ecmult_chain(); run_ecmult_chain();
run_ecmult_constants(); run_ecmult_constants();
run_ecmult_gen_blind(); run_ecmult_gen_blind();
@ -5597,9 +5683,7 @@ int main(int argc, char **argv) {
run_ec_combine(); run_ec_combine();
/* endomorphism tests */ /* endomorphism tests */
#ifdef USE_ENDOMORPHISM
run_endomorphism_tests(); run_endomorphism_tests();
#endif
/* EC point parser test */ /* EC point parser test */
run_ec_pubkey_parse_test(); run_ec_pubkey_parse_test();

View File

@ -95,7 +95,6 @@ int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned cha
return 1; return 1;
} }
#ifdef USE_ENDOMORPHISM
void test_exhaustive_endomorphism(const secp256k1_ge *group) { void test_exhaustive_endomorphism(const secp256k1_ge *group) {
int i; int i;
for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) {
@ -104,7 +103,6 @@ void test_exhaustive_endomorphism(const secp256k1_ge *group) {
ge_equals_ge(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res); ge_equals_ge(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res);
} }
} }
#endif
void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj) { void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj) {
int i, j; int i, j;
@ -429,9 +427,7 @@ int main(int argc, char** argv) {
} }
/* Run the tests */ /* Run the tests */
#ifdef USE_ENDOMORPHISM
test_exhaustive_endomorphism(group); test_exhaustive_endomorphism(group);
#endif
test_exhaustive_addition(group, groupj); test_exhaustive_addition(group, groupj);
test_exhaustive_ecmult(ctx, group, groupj); test_exhaustive_ecmult(ctx, group, groupj);
test_exhaustive_ecmult_multi(ctx, group); test_exhaustive_ecmult_multi(ctx, group);

View File

@ -216,6 +216,24 @@ static SECP256K1_INLINE void memczero(void *s, size_t len, int flag) {
} }
} }
/** Semantics like memcmp. Variable-time.
*
* We use this to avoid possible compiler bugs with memcmp, e.g.
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95189
*/
static SECP256K1_INLINE int secp256k1_memcmp_var(const void *s1, const void *s2, size_t n) {
const unsigned char *p1 = s1, *p2 = s2;
size_t i;
for (i = 0; i < n; i++) {
int diff = p1[i] - p2[i];
if (diff != 0) {
return diff;
}
}
return 0;
}
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized and non-negative.*/ /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized and non-negative.*/
static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag) { static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag) {
unsigned int mask0, mask1, r_masked, a_masked; unsigned int mask0, mask1, r_masked, a_masked;