Skip to content

Commit e7c1b44

Browse files
committed
Squashed 'src/secp256k1/' changes from 8225239..84973d3
84973d3 Merge bitcoin-core#454: Remove residual parts from the schnorr expirement. 5e95bf2 Remove residual parts from the schnorr expirement. cbc20b8 Merge bitcoin-core#452: Minor optimizations to _scalar_inverse to save 4M 4cc8f52 Merge bitcoin-core#437: Unroll secp256k1_fe_(get|set)_b32 to make them much faster. 465159c Further shorten the addition chain for scalar inversion. a2b6b19 Fix benchmark print_number infinite loop. 8b7680a Unroll secp256k1_fe_(get|set)_b32 for 10x26. aa84990 Unroll secp256k1_fe_(get|set)_b32 for 5x52. cf12fa1 Minor optimizations to _scalar_inverse to save 4M 1199492 Merge bitcoin-core#408: Add `secp256k1_ec_pubkey_negate` and `secp256k1_ec_privkey_negate` 6af0871 Merge bitcoin-core#441: secp256k1_context_randomize: document. ab31a52 Merge bitcoin-core#444: test: Use checked_alloc eda5c1a Merge bitcoin-core#449: Remove executable bit from secp256k1.c 51b77ae Remove executable bit from secp256k1.c 5eb030c test: Use checked_alloc 72d952c FIXUP: Missing "is" 70ff29b secp256k1_context_randomize: document. 9d560f9 Merge bitcoin-core#428: Exhaustive recovery 8e48aa6 Add `secp256k1_ec_pubkey_negate` and `secp256k1_ec_privkey_negate` 2cee5fd exhaustive tests: add recovery module 678b0e5 exhaustive tests: remove erroneous comment from ecdsa_sig_sign 03ff8c2 group_impl.h: remove unused `secp256k1_ge_set_infinity` function a724d72 configure: add --enable-coverage to set options for coverage analysis b595163 recovery: add tests to cover API misusage 6f8ae2f ecdh: test NULL-checking of arguments 25e3cfb ecdsa_impl: replace scalar if-checks with VERIFY_CHECKs in ecdsa_sig_sign git-subtree-dir: src/secp256k1 git-subtree-split: 84973d393ac240a90b2e1a6538c5368202bc2224
1 parent 7b49f22 commit e7c1b44

18 files changed

+623
-278
lines changed

Makefile.am

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,10 @@ TESTS =
9393
if USE_TESTS
9494
noinst_PROGRAMS += tests
9595
tests_SOURCES = src/tests.c
96-
tests_CPPFLAGS = -DSECP256K1_BUILD -DVERIFY -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES)
96+
tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES)
97+
if !ENABLE_COVERAGE
98+
tests_CPPFLAGS += -DVERIFY
99+
endif
97100
tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB)
98101
tests_LDFLAGS = -static
99102
TESTS += tests
@@ -102,7 +105,10 @@ endif
102105
if USE_EXHAUSTIVE_TESTS
103106
noinst_PROGRAMS += exhaustive_tests
104107
exhaustive_tests_SOURCES = src/tests_exhaustive.c
105-
exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -DVERIFY -I$(top_srcdir)/src $(SECP_INCLUDES)
108+
exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES)
109+
if !ENABLE_COVERAGE
110+
exhaustive_tests_CPPFLAGS += -DVERIFY
111+
endif
106112
exhaustive_tests_LDADD = $(SECP_LIBS)
107113
exhaustive_tests_LDFLAGS = -static
108114
TESTS += exhaustive_tests

configure.ac

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ AC_PATH_TOOL(STRIP, strip)
2020
AX_PROG_CC_FOR_BUILD
2121

2222
if test "x$CFLAGS" = "x"; then
23-
CFLAGS="-O3 -g"
23+
CFLAGS="-g"
2424
fi
2525

2626
AM_PROG_CC_C_O
@@ -89,6 +89,11 @@ AC_ARG_ENABLE(benchmark,
8989
[use_benchmark=$enableval],
9090
[use_benchmark=no])
9191

92+
AC_ARG_ENABLE(coverage,
93+
AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis]),
94+
[enable_coverage=$enableval],
95+
[enable_coverage=no])
96+
9297
AC_ARG_ENABLE(tests,
9398
AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]),
9499
[use_tests=$enableval],
@@ -154,6 +159,14 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() {__builtin_expect(0,0);}]])],
154159
[ AC_MSG_RESULT([no])
155160
])
156161

162+
if test x"$enable_coverage" = x"yes"; then
163+
AC_DEFINE(COVERAGE, 1, [Define this symbol to compile out all VERIFY code])
164+
CFLAGS="$CFLAGS -O0 --coverage"
165+
LDFLAGS="--coverage"
166+
else
167+
CFLAGS="$CFLAGS -O3"
168+
fi
169+
157170
if test x"$use_ecmult_static_precomputation" != x"no"; then
158171
save_cross_compiling=$cross_compiling
159172
cross_compiling=no
@@ -434,6 +447,7 @@ AC_MSG_NOTICE([Using field implementation: $set_field])
434447
AC_MSG_NOTICE([Using bignum implementation: $set_bignum])
435448
AC_MSG_NOTICE([Using scalar implementation: $set_scalar])
436449
AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism])
450+
AC_MSG_NOTICE([Building for coverage analysis: $enable_coverage])
437451
AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh])
438452
AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery])
439453
AC_MSG_NOTICE([Using jni: $use_jni])
@@ -460,6 +474,7 @@ AC_SUBST(SECP_INCLUDES)
460474
AC_SUBST(SECP_LIBS)
461475
AC_SUBST(SECP_TEST_LIBS)
462476
AC_SUBST(SECP_TEST_INCLUDES)
477+
AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"])
463478
AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"])
464479
AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$use_exhaustive_tests" != x"no"])
465480
AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"])

include/secp256k1.h

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ typedef int (*secp256k1_nonce_function)(
163163
*
164164
* Returns: a newly created context object.
165165
* In: flags: which parts of the context to initialize.
166+
*
167+
* See also secp256k1_context_randomize.
166168
*/
167169
SECP256K1_API secp256k1_context* secp256k1_context_create(
168170
unsigned int flags
@@ -485,6 +487,28 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
485487
const unsigned char *seckey
486488
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
487489

490+
/** Negates a private key in place.
491+
*
492+
* Returns: 1 always
493+
* Args: ctx: pointer to a context object
494+
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL)
495+
*/
496+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate(
497+
const secp256k1_context* ctx,
498+
unsigned char *seckey
499+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
500+
501+
/** Negates a public key in place.
502+
*
503+
* Returns: 1 always
504+
* Args: ctx: pointer to a context object
505+
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL)
506+
*/
507+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
508+
const secp256k1_context* ctx,
509+
secp256k1_pubkey *pubkey
510+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
511+
488512
/** Tweak a private key by adding tweak to it.
489513
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
490514
* uniformly random 32-byte arrays, or if the resulting private key
@@ -543,11 +567,24 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
543567
const unsigned char *tweak
544568
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
545569

546-
/** Updates the context randomization.
570+
/** Updates the context randomization to protect against side-channel leakage.
547571
* Returns: 1: randomization successfully updated
548572
* 0: error
549573
* Args: ctx: pointer to a context object (cannot be NULL)
550574
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state)
575+
*
576+
* While secp256k1 code is written to be constant-time no matter what secret
577+
* values are, it's possible that a future compiler may output code which isn't,
578+
* and also that the CPU may not emit the same radio frequencies or draw the same
579+
* amount power for all values.
580+
*
581+
* This function provides a seed which is combined into the blinding value: that
582+
* blinding value is added before each multiplication (and removed afterwards) so
583+
* that it does not affect function results, but shields against attacks which
584+
* rely on any input-dependent behaviour.
585+
*
586+
* You should call this after secp256k1_context_create or
587+
* secp256k1_context_clone, and may call this repeatedly afterwards.
551588
*/
552589
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
553590
secp256k1_context* ctx,

src/bench.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ void print_number(double x) {
2323
if (y < 0.0) {
2424
y = -y;
2525
}
26-
while (y < 100.0) {
26+
while (y > 0 && y < 100.0) {
2727
y *= 10.0;
2828
c++;
2929
}

src/bench_schnorr_verify.c

Lines changed: 0 additions & 73 deletions
This file was deleted.

src/ecdsa_impl.h

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,12 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const
225225
#if defined(EXHAUSTIVE_TEST_ORDER)
226226
{
227227
secp256k1_scalar computed_r;
228-
int overflow = 0;
229228
secp256k1_ge pr_ge;
230229
secp256k1_ge_set_gej(&pr_ge, &pr);
231230
secp256k1_fe_normalize(&pr_ge.x);
232231

233232
secp256k1_fe_get_b32(c, &pr_ge.x);
234-
secp256k1_scalar_set_b32(&computed_r, c, &overflow);
235-
/* we fully expect overflow */
233+
secp256k1_scalar_set_b32(&computed_r, c, NULL);
236234
return secp256k1_scalar_eq(sigr, &computed_r);
237235
}
238236
#else
@@ -285,14 +283,10 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec
285283
secp256k1_fe_normalize(&r.y);
286284
secp256k1_fe_get_b32(b, &r.x);
287285
secp256k1_scalar_set_b32(sigr, b, &overflow);
288-
if (secp256k1_scalar_is_zero(sigr)) {
289-
/* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature.
290-
* This branch is cryptographically unreachable as hitting it requires finding the discrete log of P.x = N.
291-
*/
292-
secp256k1_gej_clear(&rp);
293-
secp256k1_ge_clear(&r);
294-
return 0;
295-
}
286+
/* These two conditions should be checked before calling */
287+
VERIFY_CHECK(!secp256k1_scalar_is_zero(sigr));
288+
VERIFY_CHECK(overflow == 0);
289+
296290
if (recid) {
297291
/* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log
298292
* of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria.

src/field_10x26_impl.h

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) {
3838
}
3939
VERIFY_CHECK(r == 1);
4040
}
41-
#else
42-
static void secp256k1_fe_verify(const secp256k1_fe *a) {
43-
(void)a;
44-
}
4541
#endif
4642

4743
static void secp256k1_fe_normalize(secp256k1_fe *r) {
@@ -325,17 +321,17 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
325321
}
326322

327323
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
328-
int i;
329-
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
330-
r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
331-
for (i=0; i<32; i++) {
332-
int j;
333-
for (j=0; j<4; j++) {
334-
int limb = (8*i+2*j)/26;
335-
int shift = (8*i+2*j)%26;
336-
r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift;
337-
}
338-
}
324+
r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24);
325+
r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22);
326+
r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20);
327+
r->n[3] = (uint32_t)((a[22] >> 6) & 0x3) | ((uint32_t)a[21] << 2) | ((uint32_t)a[20] << 10) | ((uint32_t)a[19] << 18);
328+
r->n[4] = (uint32_t)a[18] | ((uint32_t)a[17] << 8) | ((uint32_t)a[16] << 16) | ((uint32_t)(a[15] & 0x3) << 24);
329+
r->n[5] = (uint32_t)((a[15] >> 2) & 0x3f) | ((uint32_t)a[14] << 6) | ((uint32_t)a[13] << 14) | ((uint32_t)(a[12] & 0xf) << 22);
330+
r->n[6] = (uint32_t)((a[12] >> 4) & 0xf) | ((uint32_t)a[11] << 4) | ((uint32_t)a[10] << 12) | ((uint32_t)(a[9] & 0x3f) << 20);
331+
r->n[7] = (uint32_t)((a[9] >> 6) & 0x3) | ((uint32_t)a[8] << 2) | ((uint32_t)a[7] << 10) | ((uint32_t)a[6] << 18);
332+
r->n[8] = (uint32_t)a[5] | ((uint32_t)a[4] << 8) | ((uint32_t)a[3] << 16) | ((uint32_t)(a[2] & 0x3) << 24);
333+
r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14);
334+
339335
if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) {
340336
return 0;
341337
}
@@ -349,21 +345,42 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
349345

350346
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
351347
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
352-
int i;
353348
#ifdef VERIFY
354349
VERIFY_CHECK(a->normalized);
355350
secp256k1_fe_verify(a);
356351
#endif
357-
for (i=0; i<32; i++) {
358-
int j;
359-
int c = 0;
360-
for (j=0; j<4; j++) {
361-
int limb = (8*i+2*j)/26;
362-
int shift = (8*i+2*j)%26;
363-
c |= ((a->n[limb] >> shift) & 0x3) << (2 * j);
364-
}
365-
r[31-i] = c;
366-
}
352+
r[0] = (a->n[9] >> 14) & 0xff;
353+
r[1] = (a->n[9] >> 6) & 0xff;
354+
r[2] = ((a->n[9] & 0x3F) << 2) | ((a->n[8] >> 24) & 0x3);
355+
r[3] = (a->n[8] >> 16) & 0xff;
356+
r[4] = (a->n[8] >> 8) & 0xff;
357+
r[5] = a->n[8] & 0xff;
358+
r[6] = (a->n[7] >> 18) & 0xff;
359+
r[7] = (a->n[7] >> 10) & 0xff;
360+
r[8] = (a->n[7] >> 2) & 0xff;
361+
r[9] = ((a->n[7] & 0x3) << 6) | ((a->n[6] >> 20) & 0x3f);
362+
r[10] = (a->n[6] >> 12) & 0xff;
363+
r[11] = (a->n[6] >> 4) & 0xff;
364+
r[12] = ((a->n[6] & 0xf) << 4) | ((a->n[5] >> 22) & 0xf);
365+
r[13] = (a->n[5] >> 14) & 0xff;
366+
r[14] = (a->n[5] >> 6) & 0xff;
367+
r[15] = ((a->n[5] & 0x3f) << 2) | ((a->n[4] >> 24) & 0x3);
368+
r[16] = (a->n[4] >> 16) & 0xff;
369+
r[17] = (a->n[4] >> 8) & 0xff;
370+
r[18] = a->n[4] & 0xff;
371+
r[19] = (a->n[3] >> 18) & 0xff;
372+
r[20] = (a->n[3] >> 10) & 0xff;
373+
r[21] = (a->n[3] >> 2) & 0xff;
374+
r[22] = ((a->n[3] & 0x3) << 6) | ((a->n[2] >> 20) & 0x3f);
375+
r[23] = (a->n[2] >> 12) & 0xff;
376+
r[24] = (a->n[2] >> 4) & 0xff;
377+
r[25] = ((a->n[2] & 0xf) << 4) | ((a->n[1] >> 22) & 0xf);
378+
r[26] = (a->n[1] >> 14) & 0xff;
379+
r[27] = (a->n[1] >> 6) & 0xff;
380+
r[28] = ((a->n[1] & 0x3f) << 2) | ((a->n[0] >> 24) & 0x3);
381+
r[29] = (a->n[0] >> 16) & 0xff;
382+
r[30] = (a->n[0] >> 8) & 0xff;
383+
r[31] = a->n[0] & 0xff;
367384
}
368385

369386
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {

0 commit comments

Comments
 (0)