Skip to content
41 changes: 41 additions & 0 deletions include/secp256k1.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ extern "C" {
#endif

#include <stddef.h>
#include <stdint.h>

/** Unless explicitly stated all pointer arguments must not be NULL.
*
Expand Down Expand Up @@ -404,6 +405,46 @@ SECP256K1_API void secp256k1_context_set_error_callback(
const void *data
) SECP256K1_ARG_NONNULL(1);

/** A pointer to a function implementing SHA256's internal compression function.
*
* This function processes one or more contiguous 64-byte message blocks and
* updates the internal SHA256 state accordingly. The function is not responsible
* for counting consumed blocks or bytes, nor for performing padding.
*
* In/Out: state: pointer to eight 32-bit words representing the current internal state;
* the state is updated in place.
* In: blocks64: pointer to concatenation of n_blocks blocks, of 64 bytes each.
* no alignment guarantees are made for this pointer.
* n_blocks: number of contiguous 64-byte blocks to process.
*/
typedef void (*secp256k1_sha256_compression_function)(
uint32_t *state,
const unsigned char *blocks64,
size_t n_blocks
);

/**
* Set a callback function to override the internal SHA256 compression function.
*
* This installs a function to replace the built-in block-compression
* step used by the library's internal SHA256 implementation.
* The provided callback must exactly implement the effect of n_blocks
* repeated applications of the SHA256 compression function.
*
* This API exists to support environments that wish to route the
* SHA256 compression step through a hardware-accelerated or otherwise
* specialized implementation. It is NOT meant for replacing SHA256
* with a different hash function.
*
* Args: ctx: pointer to a context object.
* In: fn_compression: pointer to a function implementing the compression function;
* passing NULL restores the default implementation.
*/
SECP256K1_API void secp256k1_context_set_sha256_compression(
secp256k1_context *ctx,
secp256k1_sha256_compression_function fn_compression
) SECP256K1_ARG_NONNULL(1);

/** Parse a variable-length public key into the pubkey object.
*
* Returns: 1 if the public key was fully valid.
Expand Down
3 changes: 1 addition & 2 deletions src/bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,7 @@ int main(int argc, char** argv) {
"ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign", "ec",
"keygen", "ec_keygen", "ellswift", "encode", "ellswift_encode", "decode",
"ellswift_decode", "ellswift_keygen", "ellswift_ecdh"};
size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]);
int invalid_args = have_invalid_args(argc, argv, valid_args, valid_args_size);
int invalid_args = have_invalid_args(argc, argv, valid_args, ARRAY_SIZE(valid_args));

int default_iters = 20000;
int iters = get_iters(default_iters);
Expand Down
8 changes: 4 additions & 4 deletions src/bench_ecmult.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ static void bench_ecmult_multi_teardown(void* arg, int iters) {
}
}

static void generate_scalar(uint32_t num, secp256k1_scalar* scalar) {
static void generate_scalar(const secp256k1_context *ctx, uint32_t num, secp256k1_scalar* scalar) {
secp256k1_sha256 sha256;
unsigned char c[10] = {'e', 'c', 'm', 'u', 'l', 't', 0, 0, 0, 0};
unsigned char buf[32];
Expand All @@ -269,8 +269,8 @@ static void generate_scalar(uint32_t num, secp256k1_scalar* scalar) {
c[8] = num >> 16;
c[9] = num >> 24;
secp256k1_sha256_initialize(&sha256);
secp256k1_sha256_write(&sha256, c, sizeof(c));
secp256k1_sha256_finalize(&sha256, buf);
secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &sha256, c, sizeof(c));
secp256k1_sha256_finalize(secp256k1_get_hash_context(ctx), &sha256, buf);
secp256k1_scalar_set_b32(scalar, buf, &overflow);
CHECK(!overflow);
}
Expand Down Expand Up @@ -362,7 +362,7 @@ int main(int argc, char **argv) {
secp256k1_gej_set_ge(&data.pubkeys_gej[0], &secp256k1_ge_const_g);
secp256k1_scalar_set_int(&data.seckeys[0], 1);
for (i = 0; i < POINTS; ++i) {
generate_scalar(i, &data.scalars[i]);
generate_scalar(data.ctx, i, &data.scalars[i]);
if (i) {
secp256k1_gej_double_var(&data.pubkeys_gej[i], &data.pubkeys_gej[i - 1], NULL);
secp256k1_scalar_add(&data.seckeys[i], &data.seckeys[i - 1], &data.seckeys[i - 1]);
Expand Down
21 changes: 14 additions & 7 deletions src/bench_internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static void help(const char *executable_path, int default_iters) {
}

typedef struct {
const secp256k1_context* ctx;
secp256k1_scalar scalar[2];
secp256k1_fe fe[4];
secp256k1_ge ge[2];
Expand Down Expand Up @@ -82,6 +83,9 @@ static void bench_setup(void* arg) {
}
};

/* Customize context if needed */
data->ctx = secp256k1_context_static;

secp256k1_scalar_set_b32(&data->scalar[0], init[0], NULL);
secp256k1_scalar_set_b32(&data->scalar[1], init[1], NULL);
secp256k1_fe_set_b32_limit(&data->fe[0], init[0]);
Expand Down Expand Up @@ -344,34 +348,37 @@ static void bench_sha256(void* arg, int iters) {
int i;
bench_inv *data = (bench_inv*)arg;
secp256k1_sha256 sha;
const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(data->ctx);

for (i = 0; i < iters; i++) {
secp256k1_sha256_initialize(&sha);
secp256k1_sha256_write(&sha, data->data, 32);
secp256k1_sha256_finalize(&sha, data->data);
secp256k1_sha256_write(hash_ctx, &sha, data->data, 32);
secp256k1_sha256_finalize(hash_ctx, &sha, data->data);
}
}

static void bench_hmac_sha256(void* arg, int iters) {
int i;
bench_inv *data = (bench_inv*)arg;
secp256k1_hmac_sha256 hmac;
const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(data->ctx);

for (i = 0; i < iters; i++) {
secp256k1_hmac_sha256_initialize(&hmac, data->data, 32);
secp256k1_hmac_sha256_write(&hmac, data->data, 32);
secp256k1_hmac_sha256_finalize(&hmac, data->data);
secp256k1_hmac_sha256_initialize(hash_ctx, &hmac, data->data, 32);
secp256k1_hmac_sha256_write(hash_ctx, &hmac, data->data, 32);
secp256k1_hmac_sha256_finalize(hash_ctx, &hmac, data->data);
}
}

static void bench_rfc6979_hmac_sha256(void* arg, int iters) {
int i;
bench_inv *data = (bench_inv*)arg;
secp256k1_rfc6979_hmac_sha256 rng;
const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(data->ctx);

for (i = 0; i < iters; i++) {
secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64);
secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32);
secp256k1_rfc6979_hmac_sha256_initialize(hash_ctx, &rng, data->data, 64);
secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, data->data, 32);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/eckey_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_s
}

secp256k1_gej_set_ge(&pt, key);
secp256k1_ecmult(&pt, &pt, tweak, &secp256k1_scalar_zero);
secp256k1_ecmult(&pt, &pt, tweak, NULL);
secp256k1_ge_set_gej(key, &pt);
return 1;
}
Expand Down
5 changes: 4 additions & 1 deletion src/ecmult.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@
/** The number of entries a table with precomputed multiples needs to have. */
#define ECMULT_TABLE_SIZE(w) ((size_t)1 << ((w)-2))

/** Double multiply: R = na*A + ng*G */
/** Double multiply: R = na*A + ng*G
*
* Passing NULL as ng is equivalent to the zero scalar but a tiny bit faster.
*/
static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng);

typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data);
Expand Down
5 changes: 3 additions & 2 deletions src/ecmult_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#ifndef SECP256K1_ECMULT_GEN_H
#define SECP256K1_ECMULT_GEN_H

#include "hash.h"
#include "scalar.h"
#include "group.h"

Expand Down Expand Up @@ -132,12 +133,12 @@ typedef struct {
secp256k1_fe proj_blind;
} secp256k1_ecmult_gen_context;

static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx);
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, const secp256k1_hash_ctx *hash_ctx);
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx);

/** Multiply with the generator: R = a*G */
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a);

static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32);
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32);

#endif /* SECP256K1_ECMULT_GEN_H */
12 changes: 6 additions & 6 deletions src/ecmult_gen_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
#include "hash_impl.h"
#include "precomputed_ecmult_gen.h"

static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx) {
secp256k1_ecmult_gen_blind(ctx, NULL);
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx) {
secp256k1_ecmult_gen_blind(ctx, hash_ctx, NULL);
ctx->built = 1;
}

Expand Down Expand Up @@ -282,7 +282,7 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
}

/* Setup blinding values for secp256k1_ecmult_gen. */
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) {
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32) {
secp256k1_scalar b;
secp256k1_scalar diff;
secp256k1_gej gb;
Expand All @@ -309,17 +309,17 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
*/
VERIFY_CHECK(seed32 != NULL);
memcpy(keydata + 32, seed32, 32);
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, 64);
secp256k1_rfc6979_hmac_sha256_initialize(hash_ctx, &rng, keydata, 64);
secp256k1_memclear_explicit(keydata, sizeof(keydata));

/* Compute projective blinding factor (cannot be 0). */
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, nonce32, 32);
secp256k1_fe_set_b32_mod(&f, nonce32);
secp256k1_fe_cmov(&f, &secp256k1_fe_one, secp256k1_fe_normalizes_to_zero(&f));
ctx->proj_blind = f;

/* For a random blinding value b, set scalar_offset=diff-b, ge_offset=bG */
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, nonce32, 32);
secp256k1_scalar_set_b32(&b, nonce32, NULL);
/* The blinding value cannot be zero, as that would mean ge_offset = infinity,
* which secp256k1_gej_add_ge cannot handle. */
Expand Down
20 changes: 13 additions & 7 deletions src/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
#include <stdlib.h>
#include <stdint.h>

typedef struct {
secp256k1_sha256_compression_function fn_sha256_compression;
} secp256k1_hash_ctx;

static void secp256k1_hash_ctx_init(secp256k1_hash_ctx *hash_ctx);

typedef struct {
uint32_t s[8];
unsigned char buf[64];
Expand All @@ -21,17 +27,17 @@ static void secp256k1_sha256_initialize(secp256k1_sha256 *hash);
* The byte counter must be a multiple of 64, i.e., there must be no unwritten
* bytes in the buffer. */
static void secp256k1_sha256_initialize_midstate(secp256k1_sha256 *hash, uint64_t bytes, const uint32_t state[8]);
static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size);
static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32);
static void secp256k1_sha256_write(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *hash, const unsigned char *data, size_t size);
static void secp256k1_sha256_finalize(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *hash, unsigned char *out32);
static void secp256k1_sha256_clear(secp256k1_sha256 *hash);

typedef struct {
secp256k1_sha256 inner, outer;
} secp256k1_hmac_sha256;

static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size);
static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size);
static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32);
static void secp256k1_hmac_sha256_initialize(const secp256k1_hash_ctx *hash_ctx, secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size);
static void secp256k1_hmac_sha256_write(const secp256k1_hash_ctx *hash_ctx, secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size);
static void secp256k1_hmac_sha256_finalize(const secp256k1_hash_ctx *hash_ctx, secp256k1_hmac_sha256 *hash, unsigned char *out32);
static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash);

typedef struct {
Expand All @@ -40,8 +46,8 @@ typedef struct {
int retry;
} secp256k1_rfc6979_hmac_sha256;

static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen);
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen);
static void secp256k1_rfc6979_hmac_sha256_initialize(const secp256k1_hash_ctx *hash_ctx, secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen);
static void secp256k1_rfc6979_hmac_sha256_generate(const secp256k1_hash_ctx *hash_ctx, secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen);
static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng);
static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *rng);

Expand Down
Loading
Loading