Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 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 @@ -92,6 +93,7 @@ typedef struct secp256k1_ecdsa_signature {
* the message, the algorithm, the key and the attempt.
*/
typedef int (*secp256k1_nonce_function)(
const secp256k1_context *ctx,
Comment on lines 95 to +96
Copy link
Contributor

@real-or-random real-or-random Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Argh, that's a breaking change. I didn't see that coming.

But I think it can be avoided. If the user wants to pass a custom nonce function, they anyway have no way of calling our internal function (whether it uses a custom SHA256 transform or not).

So we can keep the struct here and add the context arg only to our built-in nonce function. Our ECDSA signing function (and Schnorr signing, and ECDH, etc.) will need to special-case the built-in nonce function because it has a different function signature. Not elegant but it will do the job.

Maybe we can come up with something nicer if we (ever) add a modern ECDSA module and deprecate the ECDSA stuff in the main secp256k1.h file. edit: Probably no because this affects not just ECDSA.

unsigned char *nonce32,
const unsigned char *msg32,
const unsigned char *key32,
Expand Down Expand Up @@ -403,6 +405,29 @@ SECP256K1_API void secp256k1_context_set_error_callback(
const void *data
) SECP256K1_ARG_NONNULL(1);

/**
* Set a callback function to override the internal SHA-256 transform.
*
* This installs a function to replace the built-in block-compression
* step used by the library's internal SHA-256 implementation.
* The provided callback must be functionally identical (bit-for-bit)
* to the default transform. Any deviation will cause incorrect results
* and undefined behaviour.
*
* This API exists to support environments that wish to route the
* SHA-256 compression step through a hardware-accelerated or otherwise
* specialized implementation. It is not meant for modifying the
* semantics of SHA-256.
*
* Args: ctx: pointer to a context object.
* In: callback: pointer to a function implementing the transform step.
* (passing NULL restores the default implementation)
*/
SECP256K1_API void secp256k1_context_set_sha256_transform_callback(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming: I wonder whether it makes sense to avoid the word callback here. Sure, it's a callback, but whenever we said callback in the past 10 years of this library, it was about error handling. We even have type secp256k1_callback (which probably should have been called secp256k1_error_callback but it's too late now.)

Maybe we can just call it "function " and "function pointer", like we do in the bring-your-own-nonce-function interfaces.

secp256k1_context *ctx,
void (*sha256_transform_callback)(uint32_t *state, const unsigned char *block, size_t rounds)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering whether it makes sense to allow for a real return value here to make it possible for the callback to indicate some kind of failure (e.g., couldn't access external hardware, or malloc failed). We could then fall back to our implementation or simply call the error callback in order to crash.

My current conclusion is no: I can't imagine this being useful in practice. (If you call external hardware, this will be super slow anyway. If you use malloc for SHA256, you're doing it wrong.) Even if there's some failure, the callback will still have the possibility to crash the process.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the motivation for the rounds arg? (Do you think we'll ever call this with any other value than 1?)

) 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
1 change: 1 addition & 0 deletions include/secp256k1_ecdh.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ extern "C" {
* data: arbitrary data pointer that is passed through
*/
typedef int (*secp256k1_ecdh_hash_function)(
const secp256k1_context *ctx,
unsigned char *output,
const unsigned char *x32,
const unsigned char *y32,
Expand Down
1 change: 1 addition & 0 deletions include/secp256k1_ellswift.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ extern "C" {
* data: arbitrary data pointer that is passed through
*/
typedef int (*secp256k1_ellswift_xdh_hash_function)(
const secp256k1_context *ctx,
unsigned char *output,
const unsigned char *x32,
const unsigned char *ell_a64,
Expand Down
1 change: 1 addition & 0 deletions include/secp256k1_schnorrsig.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ extern "C" {
* the message, the key, the pubkey, the algorithm description, and data.
*/
typedef int (*secp256k1_nonce_function_hardened)(
const secp256k1_context *ctx,
unsigned char *nonce32,
const unsigned char *msg,
size_t msglen,
Expand Down
2 changes: 1 addition & 1 deletion src/bench_ecmult.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ static void generate_scalar(uint32_t num, secp256k1_scalar* scalar) {
c[7] = num >> 8;
c[8] = num >> 16;
c[9] = num >> 24;
secp256k1_sha256_initialize(&sha256);
secp256k1_sha256_initialize(&sha256, /*fn_transform=*/NULL);
secp256k1_sha256_write(&sha256, c, sizeof(c));
secp256k1_sha256_finalize(&sha256, buf);
secp256k1_scalar_set_b32(scalar, buf, &overflow);
Expand Down
12 changes: 8 additions & 4 deletions src/bench_internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static void help(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 @@ -346,7 +350,7 @@ static void bench_sha256(void* arg, int iters) {
secp256k1_sha256 sha;

for (i = 0; i < iters; i++) {
secp256k1_sha256_initialize(&sha);
secp256k1_sha256_initialize(&sha, data->ctx->hash_context.fn_sha256_transform);
secp256k1_sha256_write(&sha, data->data, 32);
secp256k1_sha256_finalize(&sha, data->data);
}
Expand All @@ -358,7 +362,7 @@ static void bench_hmac_sha256(void* arg, int iters) {
secp256k1_hmac_sha256 hmac;

for (i = 0; i < iters; i++) {
secp256k1_hmac_sha256_initialize(&hmac, data->data, 32);
secp256k1_hmac_sha256_initialize(&hmac, data->data, 32, data->ctx->hash_context.fn_sha256_transform);
secp256k1_hmac_sha256_write(&hmac, data->data, 32);
secp256k1_hmac_sha256_finalize(&hmac, data->data);
}
Expand All @@ -370,8 +374,8 @@ static void bench_rfc6979_hmac_sha256(void* arg, int iters) {
secp256k1_rfc6979_hmac_sha256 rng;

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(&rng, data->data, 64, data->ctx->hash_context.fn_sha256_transform);
secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32, data->ctx->hash_context.fn_sha256_transform);
}
}

Expand Down
9 changes: 6 additions & 3 deletions src/ecmult_gen_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,9 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
secp256k1_rfc6979_hmac_sha256 rng;
unsigned char keydata[64];

/* future: use context callback */
const sha256_transform_callback fn_sha256_transform = NULL;

/* Compute the (2^COMB_BITS - 1)/2 term once. */
secp256k1_ecmult_gen_scalar_diff(&diff);

Expand All @@ -309,17 +312,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(&rng, keydata, 64, fn_sha256_transform);
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(&rng, nonce32, 32, fn_sha256_transform);
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(&rng, nonce32, 32, fn_sha256_transform);
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
15 changes: 11 additions & 4 deletions src/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@
#include <stdlib.h>
#include <stdint.h>

typedef void (*sha256_transform_callback)(uint32_t *state, const unsigned char *block, size_t rounds);

/* Validate user-supplied SHA-256 transform by comparing its output against
* the library's linked implementation */
static int secp256k1_sha256_check_transform(sha256_transform_callback fn_transform);
Comment on lines +15 to +17
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this function given that there's already secp256k1_selftest_sha256(void), which is run when a context is created? The existing one seems a bit simpler than your function and it's already there, so using that will make the diff smaller (but it will need to be modified to obtain an optional context). And perhaps the existing one is a bit slower than yours. I'd say either function is fine but keeping both seems overkill.

(The existing selftest is currently in selftest.h. That's already wrong; it should have been put in a selftest_impl.h. But your approach is better: the SHA256 test function should be exposed from the internal hash module and then called from selftest.)

edit: Okay, I see now. It's annoying than I thought. We expose secp256k1_selftest(void) which doesn't get a context object... The reason it's exposed is that you can use it when using the static context.

So I believe it makes sense to check the SHA256 at two places:

  • In secp256k1_selftest(void) because this will catch bugs in the built-in SHA256. This is particularly important with this PR given that it makes possible overriding the built-in implementation it at build time.
  • When setting a custom SHA256 transform.

This means we may perform two checks in the worst case, but that won't be the end of the world. You get the overhead only at library initialization time. But the question remains: How should the test look like? And I still think what I said above is true: It's okay to have a single secp256k1_sha256_selftest function in the hash module, and this can be called from the selftest module and from secp256k1_context_set_sha256_transform_callback.


typedef struct {
uint32_t s[8];
unsigned char buf[64];
uint64_t bytes;
sha256_transform_callback fn_transform;
} secp256k1_sha256;

static void secp256k1_sha256_initialize(secp256k1_sha256 *hash);
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash, sha256_transform_callback fn_transform);
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);
Comment on lines -19 to 28
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A potential problem with storing the callback in the secp256k1_sha256 struct is that you could have this series of events:

  • User sets callback to cb1.
  • User calls API function that calls secp256k1_sha256_initialize, which outputs some opaque object that contains the secp256k1_sha256 struct.
  • User sets callback go cb2.
  • Users passes the opaque object to another API function, which calls secp256k1_sha256_write, which calls cb1. UB.

(I believe) this cannot happen in the current code because there's no pair of API functions that behaves in this way, but it's a potential footgun for the future.

My suggestion is just passing the context object to every internal function that needs the SHA256 callback. (Another angle: State is annoying. We have state already in the context, so let's try to keep it there.)

static void secp256k1_sha256_clear(secp256k1_sha256 *hash);
Expand All @@ -25,7 +32,7 @@ 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_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size, sha256_transform_callback fn_sha256_transform);
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_clear(secp256k1_hmac_sha256 *hash);
Expand All @@ -36,8 +43,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(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen, sha256_transform_callback fn_sha256_transform);
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen, sha256_transform_callback fn_sha256_transform);
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
78 changes: 60 additions & 18 deletions src/hash_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <stdint.h>
#include <string.h>

static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) {
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash, sha256_transform_callback fn_transform) {
hash->s[0] = 0x6a09e667ul;
hash->s[1] = 0xbb67ae85ul;
hash->s[2] = 0x3c6ef372ul;
Expand All @@ -26,6 +26,7 @@ static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) {
hash->s[6] = 0x1f83d9abul;
hash->s[7] = 0x5be0cd19ul;
hash->bytes = 0;
hash->fn_transform = fn_transform == NULL ? secp256k1_sha256_transform : fn_transform;
}

static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) {
Expand All @@ -38,7 +39,7 @@ static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *
memcpy(hash->buf + bufsize, data, chunk_len);
data += chunk_len;
len -= chunk_len;
secp256k1_sha256_transform(hash->s, hash->buf, 1);
hash->fn_transform(hash->s, hash->buf, 1);
bufsize = 0;
}
if (len) {
Expand All @@ -63,15 +64,56 @@ static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out
}
}

static int secp256k1_sha256_check_transform(sha256_transform_callback fn_transform) {
secp256k1_sha256 sha256;
unsigned char out[2][32];

/* Four messages of different sizes: 1, 24, 64 and 81 bytes */
unsigned char* msgs[4];
size_t lens[4];
unsigned char msg_0 = 0;
unsigned char msg_1[24] = "secp256k1_verif_round_i";
unsigned char msg_2[64] = "For this test, this 63-byte string will be used as input data i";
unsigned char msg_3[81] = "Genesis: The Times 03/Jan/2009 Chancellor on brink of second bailout for banks i";
msgs[0] = &msg_0; lens[0] = sizeof(msg_0);
msgs[1] = msg_1; lens[1] = sizeof(msg_1);
msgs[2] = msg_2; lens[2] = sizeof(msg_2);
msgs[3] = msg_3; lens[3] = sizeof(msg_3);

/* Compare hashes between built-in transform vs the one provided by the user */
{
unsigned char i, j, k;
sha256_transform_callback funcs[2];
funcs[0] = secp256k1_sha256_transform; /* Built-in */
funcs[1] = fn_transform; /* User provided */

for (i = 0; i < 10; i++) {
msg_0 = i;
msg_1[23] = i;
msg_2[63] = i;
msg_3[80] = i;
for (j = 0; j < 4; j++) {
for (k = 0; k < 2; k++) {
secp256k1_sha256_initialize(&sha256, funcs[k]);
secp256k1_sha256_write(&sha256, msgs[j], lens[j]);
secp256k1_sha256_finalize(&sha256, out[k]);
}
if (memcmp(out[0], out[1], 32) != 0) return 0;
}
}
}
return 1;
}

/* Initializes a sha256 struct and writes the 64 byte string
* SHA256(tag)||SHA256(tag) into it. */
static void secp256k1_sha256_initialize_tagged(secp256k1_sha256 *hash, const unsigned char *tag, size_t taglen) {
static void secp256k1_sha256_initialize_tagged(secp256k1_sha256 *hash, const unsigned char *tag, size_t taglen, sha256_transform_callback fn_sha256_transform) {
unsigned char buf[32];
secp256k1_sha256_initialize(hash);
secp256k1_sha256_initialize(hash, fn_sha256_transform);
secp256k1_sha256_write(hash, tag, taglen);
secp256k1_sha256_finalize(hash, buf);

secp256k1_sha256_initialize(hash);
secp256k1_sha256_initialize(hash, fn_sha256_transform);
secp256k1_sha256_write(hash, buf, 32);
secp256k1_sha256_write(hash, buf, 32);
}
Expand All @@ -80,27 +122,27 @@ static void secp256k1_sha256_clear(secp256k1_sha256 *hash) {
secp256k1_memclear_explicit(hash, sizeof(*hash));
}

static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) {
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen, sha256_transform_callback fn_sha256_transform) {
size_t n;
unsigned char rkey[64];
if (keylen <= sizeof(rkey)) {
memcpy(rkey, key, keylen);
memset(rkey + keylen, 0, sizeof(rkey) - keylen);
} else {
secp256k1_sha256 sha256;
secp256k1_sha256_initialize(&sha256);
secp256k1_sha256_initialize(&sha256, fn_sha256_transform);
secp256k1_sha256_write(&sha256, key, keylen);
secp256k1_sha256_finalize(&sha256, rkey);
memset(rkey + 32, 0, 32);
}

secp256k1_sha256_initialize(&hash->outer);
secp256k1_sha256_initialize(&hash->outer, fn_sha256_transform);
for (n = 0; n < sizeof(rkey); n++) {
rkey[n] ^= 0x5c;
}
secp256k1_sha256_write(&hash->outer, rkey, sizeof(rkey));

secp256k1_sha256_initialize(&hash->inner);
secp256k1_sha256_initialize(&hash->inner, fn_sha256_transform);
for (n = 0; n < sizeof(rkey); n++) {
rkey[n] ^= 0x5c ^ 0x36;
}
Expand All @@ -124,7 +166,7 @@ static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash) {
secp256k1_memclear_explicit(hash, sizeof(*hash));
}

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_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen, sha256_transform_callback fn_sha256_transform) {
secp256k1_hmac_sha256 hmac;
static const unsigned char zero[1] = {0x00};
static const unsigned char one[1] = {0x01};
Expand All @@ -133,45 +175,45 @@ static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha2
memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */

/* RFC6979 3.2.d. */
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
secp256k1_hmac_sha256_write(&hmac, zero, 1);
secp256k1_hmac_sha256_write(&hmac, key, keylen);
secp256k1_hmac_sha256_finalize(&hmac, rng->k);
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
secp256k1_hmac_sha256_finalize(&hmac, rng->v);

/* RFC6979 3.2.f. */
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
secp256k1_hmac_sha256_write(&hmac, one, 1);
secp256k1_hmac_sha256_write(&hmac, key, keylen);
secp256k1_hmac_sha256_finalize(&hmac, rng->k);
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
secp256k1_hmac_sha256_finalize(&hmac, rng->v);
rng->retry = 0;
}

static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) {
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen, sha256_transform_callback fn_sha256_transform) {
/* RFC6979 3.2.h. */
static const unsigned char zero[1] = {0x00};
if (rng->retry) {
secp256k1_hmac_sha256 hmac;
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
secp256k1_hmac_sha256_write(&hmac, zero, 1);
secp256k1_hmac_sha256_finalize(&hmac, rng->k);
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
secp256k1_hmac_sha256_finalize(&hmac, rng->v);
}

while (outlen > 0) {
secp256k1_hmac_sha256 hmac;
size_t now = outlen;
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
secp256k1_hmac_sha256_finalize(&hmac, rng->v);
if (now > 32) {
Expand Down
Loading
Loading