|
20 | 20 | #include "hash_impl.h"
|
21 | 21 | #include "scratch_impl.h"
|
22 | 22 |
|
| 23 | +#if defined(VALGRIND) |
| 24 | +# include <valgrind/memcheck.h> |
| 25 | +#endif |
| 26 | + |
23 | 27 | #define ARG_CHECK(cond) do { \
|
24 | 28 | if (EXPECT(!(cond), 0)) { \
|
25 | 29 | secp256k1_callback_call(&ctx->illegal_callback, #cond); \
|
@@ -66,13 +70,15 @@ struct secp256k1_context_struct {
|
66 | 70 | secp256k1_ecmult_gen_context ecmult_gen_ctx;
|
67 | 71 | secp256k1_callback illegal_callback;
|
68 | 72 | secp256k1_callback error_callback;
|
| 73 | + int declassify; |
69 | 74 | };
|
70 | 75 |
|
71 | 76 | static const secp256k1_context secp256k1_context_no_precomp_ = {
|
72 | 77 | { 0 },
|
73 | 78 | { 0 },
|
74 | 79 | { secp256k1_default_illegal_callback_fn, 0 },
|
75 |
| - { secp256k1_default_error_callback_fn, 0 } |
| 80 | + { secp256k1_default_error_callback_fn, 0 }, |
| 81 | + 0 |
76 | 82 | };
|
77 | 83 | const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_no_precomp_;
|
78 | 84 |
|
@@ -132,6 +138,7 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne
|
132 | 138 | if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {
|
133 | 139 | secp256k1_ecmult_context_build(&ret->ecmult_ctx, &prealloc);
|
134 | 140 | }
|
| 141 | + ret->declassify = !!(flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY); |
135 | 142 |
|
136 | 143 | return (secp256k1_context*) ret;
|
137 | 144 | }
|
@@ -215,6 +222,20 @@ void secp256k1_scratch_space_destroy(const secp256k1_context *ctx, secp256k1_scr
|
215 | 222 | secp256k1_scratch_destroy(&ctx->error_callback, scratch);
|
216 | 223 | }
|
217 | 224 |
|
| 225 | +/* Mark memory as no-longer-secret for the purpose of analysing constant-time behaviour |
| 226 | + * of the software. This is setup for use with valgrind but could be substituted with |
| 227 | + * the appropriate instrumentation for other analysis tools. |
| 228 | + */ |
| 229 | +static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, void *p, size_t len) { |
| 230 | +#if defined(VALGRIND) |
| 231 | + if (EXPECT(ctx->declassify,0)) VALGRIND_MAKE_MEM_DEFINED(p, len); |
| 232 | +#else |
| 233 | + (void)ctx; |
| 234 | + (void)p; |
| 235 | + (void)len; |
| 236 | +#endif |
| 237 | +} |
| 238 | + |
218 | 239 | static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) {
|
219 | 240 | if (sizeof(secp256k1_ge_storage) == 64) {
|
220 | 241 | /* When the secp256k1_ge_storage type is exactly 64 byte, use its
|
@@ -474,8 +495,14 @@ int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature
|
474 | 495 | break;
|
475 | 496 | }
|
476 | 497 | secp256k1_scalar_set_b32(&non, nonce32, &koverflow);
|
477 |
| - if (!koverflow && !secp256k1_scalar_is_zero(&non)) { |
478 |
| - if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) { |
| 498 | + koverflow |= secp256k1_scalar_is_zero(&non); |
| 499 | + /* The nonce is still secret here, but it overflowing or being zero is is less likely than 1:2^255. */ |
| 500 | + secp256k1_declassify(ctx, &koverflow, sizeof(koverflow)); |
| 501 | + if (!koverflow) { |
| 502 | + ret = secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL); |
| 503 | + /* The final signature is no longer a secret, nor is the fact that we were successful or not. */ |
| 504 | + secp256k1_declassify(ctx, &ret, sizeof(ret)); |
| 505 | + if (ret) { |
479 | 506 | break;
|
480 | 507 | }
|
481 | 508 | }
|
|
0 commit comments