-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add scalar blinding for ecmult_gen() #190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| /********************************************************************** | ||
| * Copyright (c) 2013, 2014 Pieter Wuille * | ||
| * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * | ||
| * Distributed under the MIT software license, see the accompanying * | ||
| * file COPYING or http://www.opensource.org/licenses/mit-license.php.* | ||
| **********************************************************************/ | ||
|
|
@@ -10,6 +10,7 @@ | |
| #include "scalar.h" | ||
| #include "group.h" | ||
| #include "ecmult_gen.h" | ||
| #include "hash_impl.h" | ||
|
|
||
| static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context_t *ctx) { | ||
| ctx->prec = NULL; | ||
|
|
@@ -74,6 +75,7 @@ static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t *c | |
| secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]); | ||
| } | ||
| } | ||
| secp256k1_ecmult_gen_blind(ctx, NULL); | ||
| } | ||
|
|
||
| static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context_t* ctx) { | ||
|
|
@@ -87,24 +89,31 @@ static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context_t *d | |
| } else { | ||
| dst->prec = (secp256k1_ge_storage_t (*)[64][16])checked_malloc(sizeof(*dst->prec)); | ||
| memcpy(dst->prec, src->prec, sizeof(*dst->prec)); | ||
| dst->initial = src->initial; | ||
| dst->blind = src->blind; | ||
| } | ||
| } | ||
|
|
||
| static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context_t *ctx) { | ||
| free(ctx->prec); | ||
| secp256k1_scalar_clear(&ctx->blind); | ||
| secp256k1_gej_clear(&ctx->initial); | ||
| ctx->prec = NULL; | ||
| } | ||
|
|
||
| static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_gej_t *r, const secp256k1_scalar_t *gn) { | ||
| secp256k1_ge_t add; | ||
| secp256k1_ge_storage_t adds; | ||
| secp256k1_scalar_t gnb; | ||
| int bits; | ||
| int i, j; | ||
| memset(&adds, 0, sizeof(adds)); | ||
| secp256k1_gej_set_infinity(r); | ||
| *r = ctx->initial; | ||
| /* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */ | ||
| secp256k1_scalar_add(&gnb, gn, &ctx->blind); | ||
| add.infinity = 0; | ||
| for (j = 0; j < 64; j++) { | ||
| bits = secp256k1_scalar_get_bits(gn, j * 4, 4); | ||
| bits = secp256k1_scalar_get_bits(&gnb, j * 4, 4); | ||
| for (i = 0; i < 16; i++) { | ||
| /** This uses a conditional move to avoid any secret data in array indexes. | ||
| * _Any_ use of secret indexes has been demonstrated to result in timing | ||
|
|
@@ -123,6 +132,53 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context_t *ctx, secp | |
| } | ||
| bits = 0; | ||
| secp256k1_ge_clear(&add); | ||
| secp256k1_scalar_clear(&gnb); | ||
| } | ||
|
|
||
| /* Setup blinding values for secp256k1_ecmult_gen. */ | ||
| static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context_t *ctx, const unsigned char *seed32) { | ||
| secp256k1_scalar_t b; | ||
| secp256k1_gej_t gb; | ||
| secp256k1_fe_t s; | ||
| unsigned char nonce32[32]; | ||
| secp256k1_rfc6979_hmac_sha256_t rng; | ||
| int retry; | ||
| if (!seed32) { | ||
| /* When seed is NULL, reset the initial point and blinding value. */ | ||
| secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This, and the next line are actually redundant. (I'm fine with keeping them for clarity, though). |
||
| secp256k1_gej_neg(&ctx->initial, &ctx->initial); | ||
| secp256k1_scalar_set_int(&ctx->blind, 1); | ||
| } | ||
| /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ | ||
| secp256k1_scalar_get_b32(nonce32, &ctx->blind); | ||
| /** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data, | ||
| * and guards against weak or adversarial seeds. This is a simpler and safer interface than | ||
| * asking the caller for blinding values directly and expecting them to retry on failure. | ||
| */ | ||
| secp256k1_rfc6979_hmac_sha256_initialize(&rng, seed32 ? seed32 : nonce32, 32, nonce32, 32, NULL, 0); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How does this cause a reset if seed32=NULL is passed? The previous ctx->blind is used as PRNG seed. EDIT: nevermind. ctx->blind is reset to 1 first. |
||
| /* Retry for out of range results to achieve uniformity. */ | ||
| do { | ||
| secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); | ||
| retry = !secp256k1_fe_set_b32(&s, nonce32); | ||
| retry |= secp256k1_fe_is_zero(&s); | ||
| } while (retry); | ||
| /* Randomize the projection to defend against multiplier sidechannels. */ | ||
| secp256k1_gej_rescale(&ctx->initial, &s); | ||
| secp256k1_fe_clear(&s); | ||
| do { | ||
| secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); | ||
| secp256k1_scalar_set_b32(&b, nonce32, &retry); | ||
| /* A blinding value of 0 works, but would undermine the projection hardening. */ | ||
| retry |= secp256k1_scalar_is_zero(&b); | ||
| } while (retry); | ||
| secp256k1_rfc6979_hmac_sha256_finalize(&rng); | ||
| memset(nonce32, 0, 32); | ||
| secp256k1_ecmult_gen(ctx, &gb, &b); | ||
| secp256k1_scalar_negate(&b, &b); | ||
| ctx->blind = b; | ||
| ctx->initial = gb; | ||
| secp256k1_scalar_clear(&b); | ||
| secp256k1_gej_clear(&gb); | ||
| } | ||
|
|
||
| #endif | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About time.