Squashed 'src/secp256k1/' changes from 687155df6b..a7f264373e
What changed, and why it matters
This is a routine subtree update of the secp256k1 cryptographic library inside Bitcoin Core. Most changes are internal cleanups: renaming variables, moving helper functions between files, adding compile-time checks, and expanding test coverage. The only user-visible behavior change is in the experimental silentpayments module, where two functions no longer require callers to pass NULL for empty key arrays. A small hardening change also prevents an integer overflow when allocating a scratch workspace. There is no evidence in the commit of an active security vulnerability being patched.
Treat as a normal dependency update. Review the silentpayments API change if your code previously relied on passing NULL for empty arrays, and verify that the scratch-space hardening does not affect any callers that previously passed extremely large sizes. No urgent security patch is indicated by the commit itself.
Security signals we found
Hardening: scratch space allocation now rejects size_t overflow when adding aligned header
Hardening: secp256k1_fe_set_int argument now enforced as compile-time constant
API behavior change: silentpayments empty key arrays no longer required to be NULL
Defensive refactor: group/ge helpers moved and wrapped with VERIFY checks
Test additions: DER long-form length, exact-size DER serialization, invalid seckey rejection
Evidence from the diff
The commit squashes upstream secp256k1 changes into Bitcoin Core’s src/secp256k1 subtree. Key technical themes: (1) refactor: replace secp256k1_get_hash_context() with direct &ctx->hash_ctx access and rename ctx parameters to ecmult_gen_ctx; (2) refactor: move public-key parse/serialize helpers from eckey to group and rename privkey helpers to seckey; (3) hardening: add ASSERT_INT_CONST_AND_DO compile-time check for secp256k1_fe_set_int argument and reject scratch sizes that would wrap when added to the header; (4) API fix in silentpayments: allow non-NULL pointers for empty key arrays when the corresponding size is 0; (5) tests: add coverage for DER long-form length encoding, exact-size DER serialization, invalid plain seckeys alongside valid ones, and exhaustive group VERIFY checks. No CVE, advisory, or vendor security disclosure is present in the supplied materials.
Changed components
src/secp256k1/src/scratch_impl.hsrc/secp256k1/src/field.hsrc/secp256k1/src/field_impl.hsrc/secp256k1/src/field_10x26_impl.hsrc/secp256k1/src/field_5x52_impl.hsrc/secp256k1/src/group.hsrc/secp256k1/src/group_impl.hsrc/secp256k1/src/modules/silentpayments/main_impl.hsrc/secp256k1/src/modules/silentpayments/tests_impl.hsrc/secp256k1/src/eckey.hsrc/secp256k1/src/eckey_impl.hsrc/secp256k1/src/ecdsa.hsrc/secp256k1/src/ecdsa_impl.hsrc/secp256k1/src/ecmult_gen.hsrc/secp256k1/src/ecmult_gen_impl.hsrc/secp256k1/src/modules/ecdh/main_impl.hsrc/secp256k1/src/modules/ellswift/main_impl.hsrc/secp256k1/src/modules/musig/keyagg_impl.hsrc/secp256k1/src/modules/musig/session_impl.hsrc/secp256k1/src/modules/schnorrsig/main_impl.hsrc/secp256k1/src/secp256k1.cInspect captured patch +680 / −404
### CHANGELOG.md
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+#### Fixed
+ - Module `silentpayments`: `secp256k1_silentpayments_sender_create_outputs` and `secp256k1_silentpayments_recipient_prevouts_summary_create` no longer require empty key arrays to be passed as `NULL`. If the corresponding size argument is 0, the array pointer is ignored. This matches the API documentation, which only states that unused arrays *can* be `NULL`, and spares callers from special-casing empty arrays.
+
## [0.8.0] - 2026-08-03
#### Added
### src/bench_ecmult.c
@@ -269,8 +269,8 @@ static void generate_scalar(const secp256k1_context *ctx, uint32_t num, secp256k
c[8] = num >> 16;
c[9] = num >> 24;
secp256k1_sha256_initialize(&sha256);
- secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &sha256, c, sizeof(c));
- secp256k1_sha256_finalize(secp256k1_get_hash_context(ctx), &sha256, buf);
+ secp256k1_sha256_write(&ctx->hash_ctx, &sha256, c, sizeof(c));
+ secp256k1_sha256_finalize(&ctx->hash_ctx, &sha256, buf);
secp256k1_scalar_set_b32(scalar, buf, &overflow);
CHECK(!overflow);
}
### src/bench_internal.c
@@ -359,7 +359,7 @@ 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);
+ const secp256k1_hash_ctx *hash_ctx = &data->ctx->hash_ctx;
for (i = 0; i < iters; i++) {
secp256k1_sha256_initialize(&sha);
@@ -372,7 +372,7 @@ 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);
+ const secp256k1_hash_ctx *hash_ctx = &data->ctx->hash_ctx;
for (i = 0; i < iters; i++) {
secp256k1_hmac_sha256_initialize(hash_ctx, &hmac, data->data, 32);
@@ -385,7 +385,7 @@ 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);
+ const secp256k1_hash_ctx *hash_ctx = &data->ctx->hash_ctx;
for (i = 0; i < iters; i++) {
secp256k1_rfc6979_hmac_sha256_initialize(hash_ctx, &rng, data->data, 64);
### src/ecdsa.h
@@ -16,6 +16,6 @@
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size);
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s);
static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message);
-static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid);
+static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_scalar *r, secp256k1_scalar *s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid);
#endif /* SECP256K1_ECDSA_H */
### src/ecdsa_impl.h
@@ -271,14 +271,14 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar *sigr, const secp25
#endif
}
-static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) {
+static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) {
unsigned char b[32];
secp256k1_ge r;
secp256k1_scalar n;
int overflow = 0;
int high;
- secp256k1_ecmult_gen_ge(ctx, &r, nonce);
+ secp256k1_ecmult_gen_ge(ecmult_gen_ctx, &r, nonce);
secp256k1_fe_normalize(&r.x);
secp256k1_fe_normalize(&r.y);
secp256k1_fe_get_b32(b, &r.x);
### src/eckey.h
@@ -14,15 +14,9 @@
#include "ecmult.h"
#include "ecmult_gen.h"
-static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size);
-/** Serialize a group element (that is not allowed to be infinity) to a compressed public key (33 bytes). */
-static void secp256k1_eckey_pubkey_serialize33(secp256k1_ge *elem, unsigned char *pub33);
-/** Serialize a group element (that is not allowed to be infinity) to an uncompressed public key (65 bytes). */
-static void secp256k1_eckey_pubkey_serialize65(secp256k1_ge *elem, unsigned char *pub65);
-
-static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak);
+static int secp256k1_eckey_seckey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak);
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak);
-static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak);
+static int secp256k1_eckey_seckey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak);
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak);
#endif /* SECP256K1_ECKEY_H */
### src/eckey_impl.h
@@ -15,46 +15,7 @@
#include "group.h"
#include "ecmult_gen.h"
-static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) {
- if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) {
- secp256k1_fe x;
- return secp256k1_fe_set_b32_limit(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD);
- } else if (size == 65 && (pub[0] == SECP256K1_TAG_PUBKEY_UNCOMPRESSED || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) {
- secp256k1_fe x, y;
- if (!secp256k1_fe_set_b32_limit(&x, pub+1) || !secp256k1_fe_set_b32_limit(&y, pub+33)) {
- return 0;
- }
- secp256k1_ge_set_xy(elem, &x, &y);
- if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) &&
- secp256k1_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) {
- return 0;
- }
- return secp256k1_ge_is_valid_var(elem);
- } else {
- return 0;
- }
-}
-
-static void secp256k1_eckey_pubkey_serialize33(secp256k1_ge *elem, unsigned char *pub33) {
- VERIFY_CHECK(!secp256k1_ge_is_infinity(elem));
-
- secp256k1_fe_normalize_var(&elem->x);
- secp256k1_fe_normalize_var(&elem->y);
- pub33[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN;
- secp256k1_fe_get_b32(&pub33[1], &elem->x);
-}
-
-static void secp256k1_eckey_pubkey_serialize65(secp256k1_ge *elem, unsigned char *pub65) {
- VERIFY_CHECK(!secp256k1_ge_is_infinity(elem));
-
- secp256k1_fe_normalize_var(&elem->x);
- secp256k1_fe_normalize_var(&elem->y);
- pub65[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED;
- secp256k1_fe_get_b32(&pub65[1], &elem->x);
- secp256k1_fe_get_b32(&pub65[33], &elem->y);
-}
-
-static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) {
+static int secp256k1_eckey_seckey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) {
secp256k1_scalar_add(key, key, tweak);
return !secp256k1_scalar_is_zero(key);
}
@@ -71,7 +32,7 @@ static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_s
return 1;
}
-static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) {
+static int secp256k1_eckey_seckey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) {
int ret;
ret = !secp256k1_scalar_is_zero(tweak);
### src/ecmult_gen.h
@@ -133,13 +133,13 @@ typedef struct {
secp256k1_fe proj_blind;
} secp256k1_ecmult_gen_context;
-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);
+static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ecmult_gen_ctx, const secp256k1_hash_ctx *hash_ctx);
+static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ecmult_gen_ctx);
/** Multiply with the generator: R = a*G */
-static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a);
-static void secp256k1_ecmult_gen_ge(const secp256k1_ecmult_gen_context* ctx, secp256k1_ge *r, const secp256k1_scalar *a);
+static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_gej *r, const secp256k1_scalar *a);
+static void secp256k1_ecmult_gen_ge(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_ge *r, const secp256k1_scalar *a);
-static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32);
+static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ecmult_gen_ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32);
#endif /* SECP256K1_ECMULT_GEN_H */
### src/ecmult_gen_impl.h
@@ -14,20 +14,20 @@
#include "hash_impl.h"
#include "precomputed_ecmult_gen.h"
-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;
+static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ecmult_gen_ctx, const secp256k1_hash_ctx *hash_ctx) {
+ secp256k1_ecmult_gen_blind(ecmult_gen_ctx, hash_ctx, NULL);
+ ecmult_gen_ctx->built = 1;
}
-static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx) {
- return ctx->built;
+static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context *ecmult_gen_ctx) {
+ return ecmult_gen_ctx->built;
}
-static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) {
- ctx->built = 0;
- secp256k1_scalar_clear(&ctx->scalar_offset);
- secp256k1_ge_clear(&ctx->ge_offset);
- secp256k1_fe_clear(&ctx->proj_blind);
+static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ecmult_gen_ctx) {
+ ecmult_gen_ctx->built = 0;
+ secp256k1_scalar_clear(&ecmult_gen_ctx->scalar_offset);
+ secp256k1_ge_clear(&ecmult_gen_ctx->ge_offset);
+ secp256k1_fe_clear(&ecmult_gen_ctx->proj_blind);
}
/* Compute the scalar (2^COMB_BITS - 1) / 2, the difference between the gn argument to
@@ -51,7 +51,7 @@ static void secp256k1_ecmult_gen_scalar_diff(secp256k1_scalar* diff) {
secp256k1_scalar_add(diff, diff, &neghalf);
}
-static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) {
+static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_gej *r, const secp256k1_scalar *gn) {
uint32_t comb_off;
secp256k1_ge add;
secp256k1_fe neg;
@@ -97,17 +97,17 @@ static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context *ctx, se
*
* Adding precomputation, our final equations become:
*
- * ctx->scalar_offset = (2^COMB_BITS - 1)/2 - b (mod order)
- * ctx->ge_offset = b*G
- * d = gn + ctx->scalar_offset (mod order)
- * R = comb(d, G/2) + ctx->ge_offset
+ * ecmult_gen_ctx->scalar_offset = (2^COMB_BITS - 1)/2 - b (mod order)
+ * ecmult_gen_ctx->ge_offset = b*G
+ * d = gn + ecmult_gen_ctx->scalar_offset (mod order)
+ * R = comb(d, G/2) + ecmult_gen_ctx->ge_offset
*
* comb(d, G/2) function is then computed by summing + or - 2^(i-1)*G, for i=0..COMB_BITS-1,
* depending on the value of the bits d[i] of the binary representation of scalar d.
*/
- /* Compute the scalar d = (gn + ctx->scalar_offset). */
- secp256k1_scalar_add(&d, &ctx->scalar_offset, gn);
+ /* Compute the scalar d = (gn + ecmult_gen_ctx->scalar_offset). */
+ secp256k1_scalar_add(&d, &ecmult_gen_ctx->scalar_offset, gn);
/* Convert to recoded array. */
for (i = 0; i < 8 && i < ((COMB_BITS + 31) >> 5); ++i) {
recoded[i] = secp256k1_scalar_get_bits_limb32(&d, 32 * i, 32);
@@ -168,10 +168,10 @@ static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context *ctx, se
* c = 2*c
* return c
*
- * This computes c = comb(d, G/2), and thus finally R = c + ctx->ge_offset. Note that it would
- * be possible to apply an initial offset instead of a final offset (moving ge_offset to take
- * the place of infinity above), but the chosen approach allows using (in a future improvement)
- * an incomplete addition formula for most of the multiplication.
+ * This computes c = comb(d, G/2), and thus finally R = c + ecmult_gen_ctx->ge_offset. Note that
+ * it would be possible to apply an initial offset instead of a final offset (moving ge_offset
+ * to take the place of infinity above), but the chosen approach allows using (in a future
+ * improvement) an incomplete addition formula for most of the multiplication.
*
* The last question is how to implement the table(b, m) function. For any value of b,
* m=(d & mask(b)) can only take on at most 2^COMB_TEETH possible values (the last one may have
@@ -258,7 +258,7 @@ static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context *ctx, se
/* If this is the first table lookup, we can skip addition. */
secp256k1_gej_set_ge(r, &add);
/* Give the entry a random Z coordinate to blind intermediary results. */
- secp256k1_gej_rescale(r, &ctx->proj_blind);
+ secp256k1_gej_rescale(r, &ecmult_gen_ctx->proj_blind);
first = 0;
} else {
secp256k1_gej_add_ge(r, r, &add);
@@ -272,7 +272,7 @@ static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context *ctx, se
/* Correct for the scalar_offset added at the start (ge_offset = b*G, while b was
* subtracted from the input scalar gn). */
- secp256k1_gej_add_ge(r, r, &ctx->ge_offset);
+ secp256k1_gej_add_ge(r, r, &ecmult_gen_ctx->ge_offset);
/* Cleanup. */
secp256k1_fe_clear(&neg);
@@ -281,17 +281,17 @@ static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context *ctx, se
secp256k1_memclear_explicit(&recoded, sizeof(recoded));
}
-SECP256K1_INLINE static void secp256k1_ecmult_gen_ge(const secp256k1_ecmult_gen_context *ctx, secp256k1_ge *r, const secp256k1_scalar *a) {
+SECP256K1_INLINE static void secp256k1_ecmult_gen_ge(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_ge *r, const secp256k1_scalar *a) {
secp256k1_gej rj;
- secp256k1_ecmult_gen_gej(ctx, &rj, a);
+ secp256k1_ecmult_gen_gej(ecmult_gen_ctx, &rj, a);
secp256k1_ge_set_gej(r, &rj);
/* Jacobian coordinates resulting from our multiplication algorithm could potentially leak
* information about the secret input scalar, so clear the memory out to be on the safe side. */
secp256k1_gej_clear(&rj);
}
/* Setup blinding values for secp256k1_ecmult_gen. */
-static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32) {
+static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ecmult_gen_ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32) {
secp256k1_scalar b;
secp256k1_scalar diff;
secp256k1_fe f;
@@ -304,13 +304,13 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
if (seed32 == NULL) {
/* When seed is NULL, reset the final point and blinding value. */
- secp256k1_ge_neg(&ctx->ge_offset, &secp256k1_ge_const_g);
- secp256k1_scalar_add(&ctx->scalar_offset, &secp256k1_scalar_one, &diff);
- ctx->proj_blind = secp256k1_fe_one;
+ secp256k1_ge_neg(&ecmult_gen_ctx->ge_offset, &secp256k1_ge_const_g);
+ secp256k1_scalar_add(&ecmult_gen_ctx->scalar_offset, &secp256k1_scalar_one, &diff);
+ ecmult_gen_ctx->proj_blind = secp256k1_fe_one;
return;
}
/* The prior blinding value (if not reset) is chained forward by including it in the hash. */
- secp256k1_scalar_get_b32(keydata, &ctx->scalar_offset);
+ secp256k1_scalar_get_b32(keydata, &ecmult_gen_ctx->scalar_offset);
/** 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.
@@ -324,7 +324,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
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;
+ ecmult_gen_ctx->proj_blind = f;
/* For a random blinding value b, set scalar_offset=diff-b, ge_offset=bG */
secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, nonce32, 32);
@@ -333,9 +333,9 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
* which secp256k1_gej_add_ge cannot handle. */
secp256k1_scalar_cmov(&b, &secp256k1_scalar_one, secp256k1_scalar_is_zero(&b));
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
- secp256k1_ecmult_gen_ge(ctx, &ctx->ge_offset, &b);
+ secp256k1_ecmult_gen_ge(ecmult_gen_ctx, &ecmult_gen_ctx->ge_offset, &b);
secp256k1_scalar_negate(&b, &b);
- secp256k1_scalar_add(&ctx->scalar_offset, &b, &diff);
+ secp256k1_scalar_add(&ecmult_gen_ctx->scalar_offset, &b, &diff);
/* Clean up. */
secp256k1_memclear_explicit(nonce32, sizeof(nonce32));
### src/field.h
@@ -80,7 +80,7 @@ static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST(
# define secp256k1_fe_normalize_var secp256k1_fe_impl_normalize_var
# define secp256k1_fe_normalizes_to_zero secp256k1_fe_impl_normalizes_to_zero
# define secp256k1_fe_normalizes_to_zero_var secp256k1_fe_impl_normalizes_to_zero_var
-# define secp256k1_fe_set_int secp256k1_fe_impl_set_int
+# define secp256k1_fe_set_int_unchecked secp256k1_fe_impl_set_int_unchecked
# define secp256k1_fe_is_zero secp256k1_fe_impl_is_zero
# define secp256k1_fe_is_odd secp256k1_fe_impl_is_odd
# define secp256k1_fe_cmp_var secp256k1_fe_impl_cmp_var
@@ -138,10 +138,17 @@ static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r);
/** Set a field element to an integer in range [0,0x7FFF].
*
- * On input, r does not need to be initialized, a must be in [0,0x7FFF].
+ * On input, r does not need to be initialized, and a must be an integer
+ * constant expression in [0,0x7FFF].
* On output, r represents value a, is normalized and has magnitude (a!=0).
*/
-static void secp256k1_fe_set_int(secp256k1_fe *r, int a);
+#define secp256k1_fe_set_int(r, a) ASSERT_INT_CONST_AND_DO(a, secp256k1_fe_set_int_unchecked(r, a))
+
+/** Like secp256k1_fe_set_int but a is not checked to be an integer constant expression.
+ *
+ * Should not be called directly outside of tests.
+ */
+static void secp256k1_fe_set_int_unchecked(secp256k1_fe *r, int a);
/** Clear a field element to prevent leaking sensitive information. */
static void secp256k1_fe_clear(secp256k1_fe *a);
@@ -210,7 +217,7 @@ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a);
*/
#define secp256k1_fe_negate(r, a, m) ASSERT_INT_CONST_AND_DO(m, secp256k1_fe_negate_unchecked(r, a, m))
-/** Like secp256k1_fe_negate_unchecked but m is not checked to be an integer constant expression.
+/** Like secp256k1_fe_negate but m is not checked to be an integer constant expression.
*
* Should not be called directly outside of tests.
*/
@@ -323,8 +330,8 @@ static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
/** Halve the value of a field element modulo the field prime in constant-time.
*
- * On input, r must be a valid field element.
- * On output, r will be normalized and have magnitude floor(m/2) + 1 where m is
+ * On input, r must be a valid field element with magnitude not exceeding 31.
+ * On output, r will not be normalized, and have magnitude floor(m/2) + 1 where m is
* the magnitude of r on input.
*/
static void secp256k1_fe_half(secp256k1_fe *r);
### src/field_10x26_impl.h
@@ -256,7 +256,7 @@ static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r) {
return (z0 == 0) | (z1 == 0x3FFFFFFUL);
}
-SECP256K1_INLINE static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a) {
+SECP256K1_INLINE static void secp256k1_fe_impl_set_int_unchecked(secp256k1_fe *r, int a) {
r->n[0] = a;
r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
}
### src/field_5x52_impl.h
@@ -198,7 +198,7 @@ static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r) {
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
}
-SECP256K1_INLINE static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a) {
+SECP256K1_INLINE static void secp256k1_fe_impl_set_int_unchecked(secp256k1_fe *r, int a) {
r->n[0] = a;
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
}
### src/field_impl.h
@@ -213,11 +213,11 @@ SECP256K1_INLINE static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_
return secp256k1_fe_impl_normalizes_to_zero_var(r);
}
-static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a);
-SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
+static void secp256k1_fe_impl_set_int_unchecked(secp256k1_fe *r, int a);
+SECP256K1_INLINE static void secp256k1_fe_set_int_unchecked(secp256k1_fe *r, int a) {
VERIFY_CHECK(0 <= a && a <= 0x7FFF);
- secp256k1_fe_impl_set_int(r, a);
+ secp256k1_fe_impl_set_int_unchecked(r, a);
r->magnitude = (a != 0);
r->normalized = 1;
### src/group.h
@@ -87,6 +87,15 @@ static void secp256k1_ge_set_all_gej(secp256k1_ge *r, const secp256k1_gej *a, si
/** Set group elements r[0:len] (affine) equal to group elements a[0:len] (jacobian). */
static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len);
+
+/** Set r to the affine coordinates of the Jacobian point (a.x, a.y, 1/zi).
+ * a must not be infinity. */
+static void secp256k1_ge_set_ge_zinv(secp256k1_ge *r, const secp256k1_ge *a, const secp256k1_fe *zi);
+
+/** Set r to the affine coordinates of the Jacobian point (a.x, a.y, 1/zi), ignoring a.z.
+ * a must not be infinity. */
+static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi);
+
/** Bring a batch of inputs to the same global z "denominator", based on ratios between
* (omitted) z coordinates of adjacent elements.
*
@@ -196,6 +205,23 @@ static void secp256k1_ge_to_bytes_ext(unsigned char *data, const secp256k1_ge *g
* provided buffer is the output of secp256k1_ge_to_bytes_ext. */
static void secp256k1_ge_from_bytes_ext(secp256k1_ge *ge, const unsigned char *data);
+/** Parse a group element from a 33-byte compressed or 65-byte uncompressed public key. */
+static int secp256k1_ge_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size);
+
+/** Serialize a group element (that is not allowed to be infinity) to a compressed public key (33 bytes). */
+static void secp256k1_ge_serialize33(secp256k1_ge *elem, unsigned char *pub33);
+
+/** Serialize a group element (that is not allowed to be infinity) to an uncompressed public key (65 bytes). */
+static void secp256k1_ge_serialize65(secp256k1_ge *elem, unsigned char *pub65);
+
+/** Outputs 33 zero bytes if the given group element is the point at infinity and
+ * otherwise outputs the compressed serialization */
+static void secp256k1_ge_serialize_ext33(unsigned char *out33, secp256k1_ge *ge);
+
+/** Outputs the point at infinity if the given byte array is all zero, otherwise
+ * attempts to parse compressed point serialization. */
+static int secp256k1_ge_parse_ext33(secp256k1_ge *ge, const unsigned char *in33);
+
/** Determine if a point (which is assumed to be on the curve) is in the correct (sub)group of the curve.
*
* In normal mode, the used group is secp256k1, which has cofactor=1 meaning that every point on the curve is in the
### src/group_impl.h
@@ -95,70 +95,72 @@ static void secp256k1_gej_verify(const secp256k1_gej *a) {
(void)a;
}
-/* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */
-static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) {
+SECP256K1_INLINE static void secp256k1_ge_impl_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) {
secp256k1_fe zi2;
secp256k1_fe zi3;
- SECP256K1_GEJ_VERIFY(a);
- SECP256K1_FE_VERIFY(zi);
VERIFY_CHECK(!a->infinity);
secp256k1_fe_sqr(&zi2, zi);
secp256k1_fe_mul(&zi3, &zi2, zi);
secp256k1_fe_mul(&r->x, &a->x, &zi2);
secp256k1_fe_mul(&r->y, &a->y, &zi3);
- r->infinity = a->infinity;
-
+ r->infinity = 0;
+}
+static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) {
+ SECP256K1_GEJ_VERIFY(a); SECP256K1_FE_VERIFY(zi);
+ secp256k1_ge_impl_set_gej_zinv(r, a, zi);
SECP256K1_GE_VERIFY(r);
}
-/* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */
-static void secp256k1_ge_set_ge_zinv(secp256k1_ge *r, const secp256k1_ge *a, const secp256k1_fe *zi) {
+SECP256K1_INLINE static void secp256k1_ge_impl_set_ge_zinv(secp256k1_ge *r, const secp256k1_ge *a, const secp256k1_fe *zi) {
secp256k1_fe zi2;
secp256k1_fe zi3;
- SECP256K1_GE_VERIFY(a);
- SECP256K1_FE_VERIFY(zi);
VERIFY_CHECK(!a->infinity);
secp256k1_fe_sqr(&zi2, zi);
secp256k1_fe_mul(&zi3, &zi2, zi);
secp256k1_fe_mul(&r->x, &a->x, &zi2);
secp256k1_fe_mul(&r->y, &a->y, &zi3);
- r->infinity = a->infinity;
-
+ r->infinity = 0;
+}
+static void secp256k1_ge_set_ge_zinv(secp256k1_ge *r, const secp256k1_ge *a, const secp256k1_fe *zi) {
+ SECP256K1_GE_VERIFY(a); SECP256K1_FE_VERIFY(zi);
+ secp256k1_ge_impl_set_ge_zinv(r, a, zi);
SECP256K1_GE_VERIFY(r);
}
-static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) {
- SECP256K1_FE_VERIFY(x);
- SECP256K1_FE_VERIFY(y);
-
+SECP256K1_INLINE static void secp256k1_ge_impl_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) {
r->infinity = 0;
r->x = *x;
r->y = *y;
-
+}
+static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) {
+ SECP256K1_FE_VERIFY(x); SECP256K1_FE_VERIFY(y);
+ secp256k1_ge_impl_set_xy(r, x, y);
SECP256K1_GE_VERIFY(r);
}
-static int secp256k1_ge_is_infinity(const secp256k1_ge *a) {
- SECP256K1_GE_VERIFY(a);
-
+SECP256K1_INLINE static int secp256k1_ge_impl_is_infinity(const secp256k1_ge *a) {
return a->infinity;
}
-
-static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) {
+static int secp256k1_ge_is_infinity(const secp256k1_ge *a) {
SECP256K1_GE_VERIFY(a);
+ return secp256k1_ge_impl_is_infinity(a);
+}
+SECP256K1_INLINE static void secp256k1_ge_impl_neg(secp256k1_ge *r, const secp256k1_ge *a) {
*r = *a;
secp256k1_fe_normalize_weak(&r->y);
secp256k1_fe_negate(&r->y, &r->y, 1);
-
+}
+static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) {
+ SECP256K1_GE_VERIFY(a);
+ secp256k1_ge_impl_neg(r, a);
SECP256K1_GE_VERIFY(r);
}
-static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) {
+SECP256K1_INLINE static void secp256k1_ge_impl_set_gej(secp256k1_ge *r, secp256k1_gej *a) {
secp256k1_fe z2, z3;
- SECP256K1_GEJ_VERIFY(a);
r->infinity = a->infinity;
secp256k1_fe_inv(&a->z, &a->z);
@@ -169,14 +171,15 @@ static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) {
secp256k1_fe_set_int(&a->z, 1);
r->x = a->x;
r->y = a->y;
-
+}
+static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) {
SECP256K1_GEJ_VERIFY(a);
- SECP256K1_GE_VERIFY(r);
+ secp256k1_ge_impl_set_gej(r, a);
+ SECP256K1_GEJ_VERIFY(a); SECP256K1_GE_VERIFY(r);
}
-static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) {
+SECP256K1_INLINE static void secp256k1_ge_impl_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) {
secp256k1_fe z2, z3;
- SECP256K1_GEJ_VERIFY(a);
if (secp256k1_gej_is_infinity(a)) {
secp256k1_ge_set_infinity(r);
@@ -190,20 +193,16 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) {
secp256k1_fe_mul(&a->y, &a->y, &z3);
secp256k1_fe_set_int(&a->z, 1);
secp256k1_ge_set_xy(r, &a->x, &a->y);
-
+}
+static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) {
SECP256K1_GEJ_VERIFY(a);
- SECP256K1_GE_VERIFY(r);
+ secp256k1_ge_impl_set_gej_var(r, a);
+ SECP256K1_GEJ_VERIFY(a); SECP256K1_GE_VERIFY(r);
}
-static void secp256k1_ge_set_all_gej(secp256k1_ge *r, const secp256k1_gej *a, size_t len) {
+SECP256K1_INLINE static void secp256k1_ge_impl_set_all_gej(secp256k1_ge *r, const secp256k1_gej *a, size_t len) {
secp256k1_fe u;
size_t i;
-#ifdef VERIFY
- for (i = 0; i < len; i++) {
- SECP256K1_GEJ_VERIFY(&a[i]);
- VERIFY_CHECK(!secp256k1_gej_is_infinity(&a[i]));
- }
-#endif
if (len == 0) {
return;
@@ -225,23 +224,27 @@ static void secp256k1_ge_set_all_gej(secp256k1_ge *r, const secp256k1_gej *a, si
for (i = 0; i < len; i++) {
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x);
}
-
+}
+static void secp256k1_ge_set_all_gej(secp256k1_ge *r, const secp256k1_gej *a, size_t len) {
+#ifdef VERIFY
+ size_t i;
+ for (i = 0; i < len; i++) {
+ SECP256K1_GEJ_VERIFY(&a[i]);
+ VERIFY_CHECK(!secp256k1_gej_is_infinity(&a[i]));
+ }
+#endif
+ secp256k1_ge_impl_set_all_gej(r, a, len);
#ifdef VERIFY
for (i = 0; i < len; i++) {
SECP256K1_GE_VERIFY(&r[i]);
}
#endif
}
-static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) {
+SECP256K1_INLINE static void secp256k1_ge_impl_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) {
secp256k1_fe u;
size_t i;
size_t last_i = SIZE_MAX;
-#ifdef VERIFY
- for (i = 0; i < len; i++) {
- SECP256K1_GEJ_VERIFY(&a[i]);
- }
-#endif
for (i = 0; i < len; i++) {
if (a[i].infinity) {
@@ -278,23 +281,25 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x);
}
}
-
+}
+static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) {
+#ifdef VERIFY
+ size_t i;
+ for (i = 0; i < len; i++) {
+ SECP256K1_GEJ_VERIFY(&a[i]);
+ }
+#endif
+ secp256k1_ge_impl_set_all_gej_var(r, a, len);
#ifdef VERIFY
for (i = 0; i < len; i++) {
SECP256K1_GE_VERIFY(&r[i]);
}
#endif
}
-static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const secp256k1_fe *zr) {
+SECP256K1_INLINE static void secp256k1_ge_impl_table_set_globalz(size_t len, secp256k1_ge *a, const secp256k1_fe *zr) {
size_t i;
secp256k1_fe zs;
-#ifdef VERIFY
- for (i = 0; i < len; i++) {
- SECP256K1_GE_VERIFY(&a[i]);
- SECP256K1_FE_VERIFY(&zr[i]);
- }
-#endif
if (len > 0) {
i = len - 1;
@@ -311,7 +316,16 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se
secp256k1_ge_set_ge_zinv(&a[i], &a[i], &zs);
}
}
-
+}
+static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const secp256k1_fe *zr) {
+#ifdef VERIFY
+ size_t i;
+ for (i = 0; i < len; i++) {
+ SECP256K1_GE_VERIFY(&a[i]);
+ SECP256K1_FE_VERIFY(&zr[i]);
+ }
+#endif
+ secp256k1_ge_impl_table_set_globalz(len, a, zr);
#ifdef VERIFY
for (i = 0; i < len; i++) {
SECP256K1_GE_VERIFY(&a[i]);
@@ -344,10 +358,9 @@ static void secp256k1_ge_clear(secp256k1_ge *r) {
secp256k1_memclear_explicit(r, sizeof(secp256k1_ge));
}
-static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) {
+SECP256K1_INLINE static int secp256k1_ge_impl_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) {
secp256k1_fe x2, x3;
int ret;
- SECP256K1_FE_VERIFY(x);
r->x = *x;
secp256k1_fe_sqr(&x2, x);
@@ -360,45 +373,54 @@ static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int o
secp256k1_fe_negate(&r->y, &r->y, 1);
}
+ return ret;
+}
+static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) {
+ int ret;
+ SECP256K1_FE_VERIFY(x);
+ ret = secp256k1_ge_impl_set_xo_var(r, x, odd);
SECP256K1_GE_VERIFY(r);
return ret;
}
-static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) {
- SECP256K1_GE_VERIFY(a);
-
+SECP256K1_INLINE static void secp256k1_gej_impl_set_ge(secp256k1_gej *r, const secp256k1_ge *a) {
r->infinity = a->infinity;
r->x = a->x;
r->y = a->y;
secp256k1_fe_set_int(&r->z, 1);
-
+}
+static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) {
+ SECP256K1_GE_VERIFY(a);
+ secp256k1_gej_impl_set_ge(r, a);
SECP256K1_GEJ_VERIFY(r);
}
-static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) {
+SECP256K1_INLINE static int secp256k1_gej_impl_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) {
secp256k1_gej tmp;
- SECP256K1_GEJ_VERIFY(b);
- SECP256K1_GEJ_VERIFY(a);
secp256k1_gej_neg(&tmp, a);
secp256k1_gej_add_var(&tmp, &tmp, b, NULL);
return secp256k1_gej_is_infinity(&tmp);
}
+static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) {
+ SECP256K1_GEJ_VERIFY(b); SECP256K1_GEJ_VERIFY(a);
+ return secp256k1_gej_impl_eq_var(a, b);
+}
-static int secp256k1_gej_eq_ge_var(const secp256k1_gej *a, const secp256k1_ge *b) {
+SECP256K1_INLINE static int secp256k1_gej_impl_eq_ge_var(const secp256k1_gej *a, const secp256k1_ge *b) {
secp256k1_gej tmp;
- SECP256K1_GEJ_VERIFY(a);
- SECP256K1_GE_VERIFY(b);
secp256k1_gej_neg(&tmp, a);
secp256k1_gej_add_ge_var(&tmp, &tmp, b, NULL);
return secp256k1_gej_is_infinity(&tmp);
}
+static int secp256k1_gej_eq_ge_var(const secp256k1_gej *a, const secp256k1_ge *b) {
+ SECP256K1_GEJ_VERIFY(a); SECP256K1_GE_VERIFY(b);
+ return secp256k1_gej_impl_eq_ge_var(a, b);
+}
-static int secp256k1_ge_eq_var(const secp256k1_ge *a, const secp256k1_ge *b) {
+SECP256K1_INLINE static int secp256k1_ge_impl_eq_var(const secp256k1_ge *a, const secp256k1_ge *b) {
secp256k1_fe tmp;
- SECP256K1_GE_VERIFY(a);
- SECP256K1_GE_VERIFY(b);
if (a->infinity != b->infinity) return 0;
if (a->infinity) return 1;
@@ -413,39 +435,47 @@ static int secp256k1_ge_eq_var(const secp256k1_ge *a, const secp256k1_ge *b) {
return 1;
}
+static int secp256k1_ge_eq_var(const secp256k1_ge *a, const secp256k1_ge *b) {
+ SECP256K1_GE_VERIFY(a); SECP256K1_GE_VERIFY(b);
+ return secp256k1_ge_impl_eq_var(a, b);
+}
-static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
+SECP256K1_INLINE static int secp256k1_gej_impl_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
secp256k1_fe r;
- SECP256K1_FE_VERIFY(x);
- SECP256K1_GEJ_VERIFY(a);
VERIFY_CHECK(!a->infinity);
secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
return secp256k1_fe_equal(&r, &a->x);
}
+static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
+ SECP256K1_FE_VERIFY(x); SECP256K1_GEJ_VERIFY(a);
+ return secp256k1_gej_impl_eq_x_var(x, a);
+}
-static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) {
- SECP256K1_GEJ_VERIFY(a);
-
+SECP256K1_INLINE static void secp256k1_gej_impl_neg(secp256k1_gej *r, const secp256k1_gej *a) {
r->infinity = a->infinity;
r->x = a->x;
r->y = a->y;
r->z = a->z;
secp256k1_fe_normalize_weak(&r->y);
secp256k1_fe_negate(&r->y, &r->y, 1);
-
+}
+static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) {
+ SECP256K1_GEJ_VERIFY(a);
+ secp256k1_gej_impl_neg(r, a);
SECP256K1_GEJ_VERIFY(r);
}
+SECP256K1_INLINE static int secp256k1_gej_impl_is_infinity(const secp256k1_gej *a) {
+ return a->infinity;
+}
static int secp256k1_gej_is_infinity(const secp256k1_gej *a) {
SECP256K1_GEJ_VERIFY(a);
-
- return a->infinity;
+ return secp256k1_gej_impl_is_infinity(a);
}
-static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
+SECP256K1_INLINE static int secp256k1_ge_impl_is_valid_var(const secp256k1_ge *a) {
secp256k1_fe y2, x3;
- SECP256K1_GE_VERIFY(a);
if (a->infinity) {
return 0;
@@ -456,11 +486,14 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
secp256k1_fe_add_int(&x3, SECP256K1_B);
return secp256k1_fe_equal(&y2, &x3);
}
+static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
+ SECP256K1_GE_VERIFY(a);
+ return secp256k1_ge_impl_is_valid_var(a);
+}
-static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp256k1_gej *a) {
+SECP256K1_INLINE static void secp256k1_gej_impl_double(secp256k1_gej *r, const secp256k1_gej *a) {
/* Operations: 3 mul, 4 sqr, 8 add/half/mul_int/negate */
secp256k1_fe l, s, t;
- SECP256K1_GEJ_VERIFY(a);
r->infinity = a->infinity;
@@ -488,13 +521,14 @@ static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp25
secp256k1_fe_mul(&r->y, &t, &l); /* Y3 = L*(X3 + T) (1) */
secp256k1_fe_add(&r->y, &s); /* Y3 = L*(X3 + T) + S^2 (2) */
secp256k1_fe_negate(&r->y, &r->y, 2); /* Y3 = -(L*(X3 + T) + S^2) (3) */
-
- SECP256K1_GEJ_VERIFY(r);
}
-
-static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) {
+SECP256K1_INLINE static void secp256k1_gej_double(secp256k1_gej *r, const secp256k1_gej *a) {
SECP256K1_GEJ_VERIFY(a);
+ secp256k1_gej_impl_double(r, a);
+ SECP256K1_GEJ_VERIFY(r);
+}
+SECP256K1_INLINE static void secp256k1_gej_impl_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) {
/** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity,
* Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have
* y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p.
@@ -519,15 +553,16 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s
}
secp256k1_gej_double(r, a);
-
- SECP256K1_GEJ_VERIFY(r);
+}
+static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) {
+ SECP256K1_GEJ_VERIFY(a);
+ secp256k1_gej_impl_double_var(r, a, rzr);
+ SECP256K1_GEJ_VERIFY(r); if (rzr != NULL) SECP256K1_FE_VERIFY(rzr);
}
-static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) {
+SECP256K1_INLINE static void secp256k1_gej_impl_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) {
/* 12 mul, 4 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */
secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, h2, h3, t;
- SECP256K1_GEJ_VERIFY(a);
- SECP256K1_GEJ_VERIFY(b);
if (a->infinity) {
VERIFY_CHECK(rzr == NULL);
@@ -583,15 +618,16 @@ static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, cons
secp256k1_fe_mul(&r->y, &t, &i);
secp256k1_fe_mul(&h3, &h3, &s1);
secp256k1_fe_add(&r->y, &h3);
-
- SECP256K1_GEJ_VERIFY(r);
+}
+static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) {
+ SECP256K1_GEJ_VERIFY(a); SECP256K1_GEJ_VERIFY(b);
+ secp256k1_gej_impl_add_var(r, a, b, rzr);
+ SECP256K1_GEJ_VERIFY(r); if (rzr != NULL) SECP256K1_FE_VERIFY(rzr);
}
-static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) {
+SECP256K1_INLINE static void secp256k1_gej_impl_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) {
/* Operations: 8 mul, 3 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */
secp256k1_fe z12, u1, u2, s1, s2, h, i, h2, h3, t;
- SECP256K1_GEJ_VERIFY(a);
- SECP256K1_GE_VERIFY(b);
if (a->infinity) {
VERIFY_CHECK(rzr == NULL);
@@ -645,17 +681,16 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, c
secp256k1_fe_mul(&r->y, &t, &i);
secp256k1_fe_mul(&h3, &h3, &s1);
secp256k1_fe_add(&r->y, &h3);
-
- SECP256K1_GEJ_VERIFY(r);
- if (rzr != NULL) SECP256K1_FE_VERIFY(rzr);
+}
+static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) {
+ SECP256K1_GEJ_VERIFY(a); SECP256K1_GE_VERIFY(b);
+ secp256k1_gej_impl_add_ge_var(r, a, b, rzr);
+ SECP256K1_GEJ_VERIFY(r); if (rzr != NULL) SECP256K1_FE_VERIFY(rzr);
}
-static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) {
+SECP256K1_INLINE static void secp256k1_gej_impl_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) {
/* Operations: 9 mul, 3 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */
secp256k1_fe az, z12, u1, u2, s1, s2, h, i, h2, h3, t;
- SECP256K1_GEJ_VERIFY(a);
- SECP256K1_GE_VERIFY(b);
- SECP256K1_FE_VERIFY(bzinv);
if (a->infinity) {
secp256k1_fe bzinv2, bzinv3;
@@ -665,7 +700,6 @@ static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a,
secp256k1_fe_mul(&r->x, &b->x, &bzinv2);
secp256k1_fe_mul(&r->y, &b->y, &bzinv3);
secp256k1_fe_set_int(&r->z, 1);
- SECP256K1_GEJ_VERIFY(r);
return;
}
if (b->infinity) {
@@ -716,18 +750,19 @@ static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a,
secp256k1_fe_mul(&r->y, &t, &i);
secp256k1_fe_mul(&h3, &h3, &s1);
secp256k1_fe_add(&r->y, &h3);
-
+}
+static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) {
+ SECP256K1_GEJ_VERIFY(a); SECP256K1_GE_VERIFY(b); SECP256K1_FE_VERIFY(bzinv);
+ secp256k1_gej_impl_add_zinv_var(r, a, b, bzinv);
SECP256K1_GEJ_VERIFY(r);
}
-static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) {
+SECP256K1_INLINE static void secp256k1_gej_impl_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) {
/* Operations: 7 mul, 5 sqr, 21 add/cmov/half/mul_int/negate/normalizes_to_zero */
secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr;
secp256k1_fe m_alt, rr_alt;
int degenerate;
- SECP256K1_GEJ_VERIFY(a);
- SECP256K1_GE_VERIFY(b);
VERIFY_CHECK(!b->infinity);
/* In:
@@ -854,29 +889,32 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
* We have degenerate = false, r->z = (y1 + y2) * Z.
* Then r->infinity = ((y1 + y2)Z == 0) = (y1 == -y2) = false. */
r->infinity = secp256k1_fe_normalizes_to_zero(&r->z);
-
+}
+static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) {
+ SECP256K1_GEJ_VERIFY(a); SECP256K1_GE_VERIFY(b);
+ secp256k1_gej_impl_add_ge(r, a, b);
SECP256K1_GEJ_VERIFY(r);
}
-static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) {
+SECP256K1_INLINE static void secp256k1_gej_impl_rescale(secp256k1_gej *r, const secp256k1_fe *s) {
/* Operations: 4 mul, 1 sqr */
secp256k1_fe zz;
- SECP256K1_GEJ_VERIFY(r);
- SECP256K1_FE_VERIFY(s);
VERIFY_CHECK(!secp256k1_fe_normalizes_to_zero_var(s));
secp256k1_fe_sqr(&zz, s);
secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */
secp256k1_fe_mul(&r->y, &r->y, &zz);
secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */
secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */
-
+}
+static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) {
+ SECP256K1_GEJ_VERIFY(r); SECP256K1_FE_VERIFY(s);
+ secp256k1_gej_impl_rescale(r, s);
SECP256K1_GEJ_VERIFY(r);
}
-static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) {
+SECP256K1_INLINE static void secp256k1_ge_impl_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) {
secp256k1_fe x, y;
- SECP256K1_GE_VERIFY(a);
VERIFY_CHECK(!a->infinity);
x = a->x;
@@ -886,6 +924,10 @@ static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge
secp256k1_fe_to_storage(&r->x, &x);
secp256k1_fe_to_storage(&r->y, &y);
}
+static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) {
+ SECP256K1_GE_VERIFY(a);
+ secp256k1_ge_impl_to_storage(r, a);
+}
static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a) {
secp256k1_fe_from_storage(&r->x, &a->x);
@@ -895,39 +937,39 @@ static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storag
SECP256K1_GE_VERIFY(r);
}
-static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) {
- SECP256K1_GEJ_VERIFY(r);
- SECP256K1_GEJ_VERIFY(a);
+SECP256K1_INLINE static void secp256k1_gej_impl_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) {
VERIFY_CHECK(flag == 0 || flag == 1);
-
secp256k1_fe_cmov(&r->x, &a->x, flag);
secp256k1_fe_cmov(&r->y, &a->y, flag);
secp256k1_fe_cmov(&r->z, &a->z, flag);
r->infinity ^= (r->infinity ^ a->infinity) & flag;
-
+}
+SECP256K1_INLINE static void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) {
+ SECP256K1_GEJ_VERIFY(r); SECP256K1_GEJ_VERIFY(a);
+ secp256k1_gej_impl_cmov(r, a, flag);
SECP256K1_GEJ_VERIFY(r);
}
-static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) {
+SECP256K1_INLINE static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) {
VERIFY_CHECK(flag == 0 || flag == 1);
secp256k1_fe_storage_cmov(&r->x, &a->x, flag);
secp256k1_fe_storage_cmov(&r->y, &a->y, flag);
}
-static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
- SECP256K1_GE_VERIFY(a);
-
+SECP256K1_INLINE static void secp256k1_ge_impl_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
*r = *a;
secp256k1_fe_mul(&r->x, &r->x, &secp256k1_const_beta);
-
+}
+static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
+ SECP256K1_GE_VERIFY(a);
+ secp256k1_ge_impl_mul_lambda(r, a);
SECP256K1_GE_VERIFY(r);
}
-static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
+SECP256K1_INLINE static int secp256k1_ge_impl_is_in_correct_subgroup(const secp256k1_ge* ge) {
#ifdef EXHAUSTIVE_TEST_ORDER
secp256k1_gej out;
int i;
- SECP256K1_GE_VERIFY(ge);
/* A very simple EC multiplication ladder that avoids a dependency on ecmult. */
secp256k1_gej_set_infinity(&out);
@@ -939,23 +981,30 @@ static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
}
return secp256k1_gej_is_infinity(&out);
#else
- SECP256K1_GE_VERIFY(ge);
-
(void)ge;
/* The real secp256k1 group has cofactor 1, so the subgroup is the entire curve. */
return 1;
#endif
}
+static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
+ SECP256K1_GE_VERIFY(ge);
+ return secp256k1_ge_impl_is_in_correct_subgroup(ge);
+}
-static int secp256k1_ge_x_on_curve_var(const secp256k1_fe *x) {
+SECP256K1_INLINE static int secp256k1_ge_impl_x_on_curve_var(const secp256k1_fe *x) {
secp256k1_fe c;
+
secp256k1_fe_sqr(&c, x);
secp256k1_fe_mul(&c, &c, x);
secp256k1_fe_add_int(&c, SECP256K1_B);
return secp256k1_fe_is_square_var(&c);
}
+static int secp256k1_ge_x_on_curve_var(const secp256k1_fe *x) {
+ SECP256K1_FE_VERIFY(x);
+ return secp256k1_ge_impl_x_on_curve_var(x);
+}
-static int secp256k1_ge_x_frac_on_curve_var(const secp256k1_fe *xn, const secp256k1_fe *xd) {
+SECP256K1_INLINE static int secp256k1_ge_impl_x_frac_on_curve_var(const secp256k1_fe *xn, const secp256k1_fe *xd) {
/* We want to determine whether (xn/xd) is on the curve.
*
* (xn/xd)^3 + 7 is square <=> xd*xn^3 + 7*xd^4 is square (multiplying by xd^4, a square).
@@ -974,41 +1023,152 @@ static int secp256k1_ge_x_frac_on_curve_var(const secp256k1_fe *xn, const secp25
return secp256k1_fe_is_square_var(&r);
}
-static void secp256k1_ge_to_bytes(unsigned char *buf, const secp256k1_ge *a) {
+static int secp256k1_ge_x_frac_on_curve_var(const secp256k1_fe *xn, const secp256k1_fe *xd) {
+ SECP256K1_FE_VERIFY(xn); SECP256K1_FE_VERIFY(xd);
+ return secp256k1_ge_impl_x_frac_on_curve_var(xn, xd);
+}
+
+SECP256K1_INLINE static void secp256k1_ge_impl_to_bytes(unsigned char *buf, const secp256k1_ge *a) {
secp256k1_ge_storage s;
+ VERIFY_CHECK(!a->infinity);
/* We require that the secp256k1_ge_storage type is exactly 64 bytes.
* This is formally not guaranteed by the C standard, but should hold on any
* sane compiler in the real world. */
STATIC_ASSERT(sizeof(secp256k1_ge_storage) == 64);
- VERIFY_CHECK(!secp256k1_ge_is_infinity(a));
secp256k1_ge_to_storage(&s, a);
memcpy(buf, &s, 64);
}
+static void secp256k1_ge_to_bytes(unsigned char *buf, const secp256k1_ge *a) {
+ SECP256K1_GE_VERIFY(a);
+ secp256k1_ge_impl_to_bytes(buf, a);
+}
-static void secp256k1_ge_from_bytes(secp256k1_ge *r, const unsigned char *buf) {
+SECP256K1_INLINE static void secp256k1_ge_impl_from_bytes(secp256k1_ge *r, const unsigned char *buf) {
secp256k1_ge_storage s;
STATIC_ASSERT(sizeof(secp256k1_ge_storage) == 64);
memcpy(&s, buf, 64);
secp256k1_ge_from_storage(r, &s);
}
+static void secp256k1_ge_from_bytes(secp256k1_ge *r, const unsigned char *buf) {
+ secp256k1_ge_impl_from_bytes(r, buf);
+ SECP256K1_GE_VERIFY(r);
+}
-static void secp256k1_ge_to_bytes_ext(unsigned char *data, const secp256k1_ge *ge) {
- if (secp256k1_ge_is_infinity(ge)) {
+SECP256K1_INLINE static void secp256k1_ge_impl_to_bytes_ext(unsigned char *data, const secp256k1_ge *ge) {
+ if (ge->infinity) {
memset(data, 0, 64);
} else {
secp256k1_ge_to_bytes(data, ge);
}
}
+static void secp256k1_ge_to_bytes_ext(unsigned char *data, const secp256k1_ge *ge) {
+ SECP256K1_GE_VERIFY(ge);
+ secp256k1_ge_impl_to_bytes_ext(data, ge);
+}
-static void secp256k1_ge_from_bytes_ext(secp256k1_ge *ge, const unsigned char *data) {
+SECP256K1_INLINE static void secp256k1_ge_impl_from_bytes_ext(secp256k1_ge *ge, const unsigned char *data) {
static const unsigned char zeros[64] = { 0 };
if (secp256k1_memcmp_var(data, zeros, sizeof(zeros)) == 0) {
secp256k1_ge_set_infinity(ge);
} else {
secp256k1_ge_from_bytes(ge, data);
}
}
+static void secp256k1_ge_from_bytes_ext(secp256k1_ge *ge, const unsigned char *data) {
+ secp256k1_ge_impl_from_bytes_ext(ge, data);
+ SECP256K1_GE_VERIFY(ge);
+}
+
+SECP256K1_INLINE static int secp256k1_ge_impl_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) {
+ if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) {
+ secp256k1_fe x;
+ return secp256k1_fe_set_b32_limit(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD);
+ } else if (size == 65 && (pub[0] == SECP256K1_TAG_PUBKEY_UNCOMPRESSED || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) {
+ secp256k1_fe x, y;
+ if (!secp256k1_fe_set_b32_limit(&x, pub+1) || !secp256k1_fe_set_b32_limit(&y, pub+33)) {
+ return 0;
+ }
+ secp256k1_ge_set_xy(elem, &x, &y);
+ if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) &&
+ secp256k1_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) {
+ return 0;
+ }
+ return secp256k1_ge_is_valid_var(elem);
+ } else {
+ return 0;
+ }
+}
+static int secp256k1_ge_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) {
+ int ret = secp256k1_ge_impl_parse(elem, pub, size);
+ if (ret) {
+ SECP256K1_GE_VERIFY(elem);
+ }
+ return ret;
+}
+
+SECP256K1_INLINE static void secp256k1_ge_impl_serialize33(secp256k1_ge *elem, unsigned char *pub33) {
+ VERIFY_CHECK(!elem->infinity);
+
+ secp256k1_fe_normalize_var(&elem->x);
+ secp256k1_fe_normalize_var(&elem->y);
+ pub33[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN;
+ secp256k1_fe_get_b32(&pub33[1], &elem->x);
+}
+static void secp256k1_ge_serialize33(secp256k1_ge *elem, unsigned char *pub33) {
+ SECP256K1_GE_VERIFY(elem);
+ secp256k1_ge_impl_serialize33(elem, pub33);
+ SECP256K1_GE_VERIFY(elem);
+}
+
+SECP256K1_INLINE static void secp256k1_ge_impl_serialize65(secp256k1_ge *elem, unsigned char *pub65) {
+ VERIFY_CHECK(!elem->infinity);
+
+ secp256k1_fe_normalize_var(&elem->x);
+ secp256k1_fe_normalize_var(&elem->y);
+ pub65[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED;
+ secp256k1_fe_get_b32(&pub65[1], &elem->x);
+ secp256k1_fe_get_b32(&pub65[33], &elem->y);
+}
+static void secp256k1_ge_serialize65(secp256k1_ge *elem, unsigned char *pub65) {
+ SECP256K1_GE_VERIFY(elem);
+ secp256k1_ge_impl_serialize65(elem, pub65);
+ SECP256K1_GE_VERIFY(elem);
+}
+
+SECP256K1_INLINE static void secp256k1_ge_impl_serialize_ext33(unsigned char *out33, secp256k1_ge *ge) {
+ if (ge->infinity) {
+ memset(out33, 0, 33);
+ } else {
+ /* Serialize must succeed because the point is not at infinity */
+ secp256k1_ge_serialize33(ge, out33);
+ }
+}
+static void secp256k1_ge_serialize_ext33(unsigned char *out33, secp256k1_ge *ge) {
+ SECP256K1_GE_VERIFY(ge);
+ secp256k1_ge_impl_serialize_ext33(out33, ge);
+ SECP256K1_GE_VERIFY(ge);
+}
+
+SECP256K1_INLINE static int secp256k1_ge_impl_parse_ext33(secp256k1_ge *ge, const unsigned char *in33) {
+ unsigned char zeros[33] = { 0 };
+
+ if (secp256k1_memcmp_var(in33, zeros, sizeof(zeros)) == 0) {
+ secp256k1_ge_set_infinity(ge);
+ return 1;
+ }
+ if (!secp256k1_ge_parse(ge, in33, 33)) {
+ return 0;
+ }
+ return secp256k1_ge_is_in_correct_subgroup(ge);
+}
+static int secp256k1_ge_parse_ext33(secp256k1_ge *ge, const unsigned char *in33) {
+ int ret = secp256k1_ge_impl_parse_ext33(ge, in33);
+ if (ret) {
+ SECP256K1_GE_VERIFY(ge);
+ }
+ return ret;
+}
#endif /* SECP256K1_GROUP_IMPL_H */
### src/modules/ecdh/main_impl.h
@@ -25,15 +25,15 @@ static int ecdh_hash_function_sha256_impl(const secp256k1_hash_ctx *hash_ctx, un
}
static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) {
- return ecdh_hash_function_sha256_impl(secp256k1_get_hash_context(secp256k1_context_static), output, x32, y32, data);
+ return ecdh_hash_function_sha256_impl(&secp256k1_context_static->hash_ctx, output, x32, y32, data);
}
const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256 = ecdh_hash_function_sha256;
const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default = ecdh_hash_function_sha256;
int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const secp256k1_pubkey *point, const unsigned char *scalar, secp256k1_ecdh_hash_function hashfp, void *data) {
int ret = 0;
- int overflow = 0;
+ int is_sec_valid;
secp256k1_gej res;
secp256k1_ge pt;
secp256k1_scalar s;
@@ -46,10 +46,8 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se
ARG_CHECK(scalar != NULL);
secp256k1_pubkey_load(ctx, &pt, point);
- secp256k1_scalar_set_b32(&s, scalar, &overflow);
-
- overflow |= secp256k1_scalar_is_zero(&s);
- secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow);
+ is_sec_valid = secp256k1_scalar_set_b32_seckey(&s, scalar);
+ secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, !is_sec_valid);
secp256k1_ecmult_const(&res, &pt, &s);
secp256k1_ge_set_gej(&pt, &res);
@@ -62,7 +60,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se
if (hashfp == NULL || hashfp == secp256k1_ecdh_hash_function_sha256) {
/* Use ctx-aware function by default */
- ret = ecdh_hash_function_sha256_impl(secp256k1_get_hash_context(ctx), output, x, y, data);
+ ret = ecdh_hash_function_sha256_impl(&ctx->hash_ctx, output, x, y, data);
} else {
ret = hashfp(output, x, y, data);
}
@@ -73,7 +71,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se
secp256k1_ge_clear(&pt);
secp256k1_gej_clear(&res);
- return !!ret & !overflow;
+ return (!!ret) & is_sec_valid;
}
#endif /* SECP256K1_MODULE_ECDH_MAIN_H */
### src/modules/ecdh/tests_impl.h
@@ -84,8 +84,8 @@ static void test_ecdh_generator_basepoint(void) {
/* compute "explicitly" */
CHECK(secp256k1_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1);
secp256k1_sha256_initialize(&sha);
- secp256k1_sha256_write(secp256k1_get_hash_context(CTX), &sha, point_ser, point_ser_len);
- secp256k1_sha256_finalize(secp256k1_get_hash_context(CTX), &sha, output_ser);
+ secp256k1_sha256_write(&CTX->hash_ctx, &sha, point_ser, point_ser_len);
+ secp256k1_sha256_finalize(&CTX->hash_ctx, &sha, output_ser);
/* compare */
CHECK(secp256k1_memcmp_var(output_ecdh, output_ser, 32) == 0);
}
### src/modules/ellswift/main_impl.h
@@ -346,14 +346,14 @@ static void secp256k1_ellswift_xelligatorswift_var(const secp256k1_context *ctx,
secp256k1_fe u;
/* If the pool of branch values is empty, populate it. */
if (branches_left == 0) {
- secp256k1_ellswift_prng(secp256k1_get_hash_context(ctx), branch_hash, hasher, cnt++);
+ secp256k1_ellswift_prng(&ctx->hash_ctx, branch_hash, hasher, cnt++);
branches_left = 64;
}
/* Take a 3-bit branch value from the branch pool (top bit is discarded). */
--branches_left;
branch = (branch_hash[branches_left >> 1] >> ((branches_left & 1) << 2)) & 7;
/* Compute a new u value by hashing. */
- secp256k1_ellswift_prng(secp256k1_get_hash_context(ctx), u32, hasher, cnt++);
+ secp256k1_ellswift_prng(&ctx->hash_ctx, u32, hasher, cnt++);
/* overflow is not a problem (we prefer uniform u32 over uniform u). */
secp256k1_fe_set_b32_mod(&u, u32);
/* Since u is the output of a hash, it should practically never be 0. We could apply the
@@ -405,9 +405,9 @@ int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64
/* Set up hasher state; the used RNG is H(pubkey || "\x00"*31 || rnd32 || cnt++), using
* BIP340 tagged hash with tag "secp256k1_ellswift_encode". */
secp256k1_ellswift_sha256_init_encode(&hash);
- secp256k1_eckey_pubkey_serialize33(&p, p64);
- secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, p64, sizeof(p64));
- secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, rnd32, 32);
+ secp256k1_ge_serialize33(&p, p64);
+ secp256k1_sha256_write(&ctx->hash_ctx, &hash, p64, sizeof(p64));
+ secp256k1_sha256_write(&ctx->hash_ctx, &hash, rnd32, 32);
/* Compute ElligatorSwift encoding and construct output. */
secp256k1_ellswift_elligatorswift_var(ctx, ell64, &t, &p, &hash); /* puts u in ell64[0..32] */
@@ -452,11 +452,11 @@ int secp256k1_ellswift_create(const secp256k1_context *ctx, unsigned char *ell64
/* Set up hasher state. The used RNG is H(seckey32 || "\x00"*32 [|| auxrnd32] || cnt++),
* using BIP340 tagged hash with tag "secp256k1_ellswift_create". */
secp256k1_ellswift_sha256_init_create(&hash);
- secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, seckey32, 32);
- secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, zero32, sizeof(zero32));
+ secp256k1_sha256_write(&ctx->hash_ctx, &hash, seckey32, 32);
+ secp256k1_sha256_write(&ctx->hash_ctx, &hash, zero32, sizeof(zero32));
/* Declassify only hash state. seckey32 has been hashed, but copy remains in the hash buffer */
secp256k1_declassify(ctx, &hash.s, sizeof(hash.s));
- if (auxrnd32) secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, auxrnd32, 32);
+ if (auxrnd32) secp256k1_sha256_write(&ctx->hash_ctx, &hash, auxrnd32, 32);
/* Compute ElligatorSwift encoding and construct output. */
secp256k1_ellswift_elligatorswift_var(ctx, ell64, &t, &p, &hash); /* puts u in ell64[0..32] */
@@ -499,7 +499,7 @@ static int ellswift_xdh_hash_function_prefix_impl(const secp256k1_hash_ctx *hash
}
static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) {
- return ellswift_xdh_hash_function_prefix_impl(secp256k1_get_hash_context(secp256k1_context_static), output, x32, ell_a64, ell_b64, data);
+ return ellswift_xdh_hash_function_prefix_impl(&secp256k1_context_static->hash_ctx, output, x32, ell_a64, ell_b64, data);
}
/** Set hash state to the BIP340 tagged hash midstate for "bip324_ellswift_xonly_ecdh". */
@@ -527,15 +527,15 @@ static int ellswift_xdh_hash_function_bip324_impl(const secp256k1_hash_ctx *hash
}
static int ellswift_xdh_hash_function_bip324(unsigned char* output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) {
- return ellswift_xdh_hash_function_bip324_impl(secp256k1_get_hash_context(secp256k1_context_static), output, x32, ell_a64, ell_b64, data);
+ return ellswift_xdh_hash_function_bip324_impl(&secp256k1_context_static->hash_ctx, output, x32, ell_a64, ell_b64, data);
}
const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix = ellswift_xdh_hash_function_prefix;
const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324 = ellswift_xdh_hash_function_bip324;
int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output, const unsigned char *ell_a64, const unsigned char *ell_b64, const unsigned char *seckey32, int party, secp256k1_ellswift_xdh_hash_function hashfp, void *data) {
int ret = 0;
- int overflow;
+ int is_sec_valid;
secp256k1_scalar s;
secp256k1_fe xn, xd, px, u, t;
unsigned char sx[32];
@@ -555,9 +555,8 @@ int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output,
secp256k1_ellswift_xswiftec_frac_var(&xn, &xd, &u, &t);
/* Load private key (using one if invalid). */
- secp256k1_scalar_set_b32(&s, seckey32, &overflow);
- overflow |= secp256k1_scalar_is_zero(&s);
- secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow);
+ is_sec_valid = secp256k1_scalar_set_b32_seckey(&s, seckey32);
+ secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, !is_sec_valid);
/* Compute shared X coordinate. */
secp256k1_ecmult_const_xonly(&px, &xn, &xd, &s, 1);
@@ -566,9 +565,9 @@ int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output,
/* Invoke hasher. Use ctx-aware function by default */
if (hashfp == secp256k1_ellswift_xdh_hash_function_bip324) {
- ret = ellswift_xdh_hash_function_bip324_impl(secp256k1_get_hash_context(ctx), output, sx, ell_a64, ell_b64, data);
+ ret = ellswift_xdh_hash_function_bip324_impl(&ctx->hash_ctx, output, sx, ell_a64, ell_b64, data);
} else if (hashfp == secp256k1_ellswift_xdh_hash_function_prefix) {
- ret = ellswift_xdh_hash_function_prefix_impl(secp256k1_get_hash_context(ctx), output, sx, ell_a64, ell_b64, data);
+ ret = ellswift_xdh_hash_function_prefix_impl(&ctx->hash_ctx, output, sx, ell_a64, ell_b64, data);
} else {
ret = hashfp(output, sx, ell_a64, ell_b64, data);
}
@@ -577,7 +576,7 @@ int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output,
secp256k1_fe_clear(&px);
secp256k1_scalar_clear(&s);
- return !!ret & !overflow;
+ return (!!ret) & is_sec_valid;
}
#endif
### src/modules/ellswift/tests_impl.h
@@ -473,7 +473,7 @@ void ellswift_xdh_ctx_sha256_tests(void) {
/* Test hash initializers */
void ellswift_hash_init_tests(void) {
secp256k1_sha256 sha_optimized;
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
+ const secp256k1_hash_ctx *hash_ctx = &CTX->hash_ctx;
/* "secp256k1_ellswift_encode" */
static const unsigned char encode_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'e', 'n', 'c', 'o', 'd', 'e'};
/* "secp256k1_ellswift_create" */
### src/modules/musig/keyagg_impl.h
@@ -82,9 +82,9 @@ static int secp256k1_musig_compute_pks_hash(const secp256k1_context *ctx, unsign
return 0;
}
VERIFY_CHECK(ser_len == sizeof(ser));
- secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &sha, ser, sizeof(ser));
+ secp256k1_sha256_write(&ctx->hash_ctx, &sha, ser, sizeof(ser));
}
- secp256k1_sha256_finalize(secp256k1_get_hash_context(ctx), &sha, pks_hash);
+ secp256k1_sha256_finalize(&ctx->hash_ctx, &sha, pks_hash);
return 1;
}
@@ -116,7 +116,7 @@ static void secp256k1_musig_keyaggcoef_internal(const secp256k1_hash_ctx *hash_c
secp256k1_sha256_write(hash_ctx, &sha, pks_hash, 32);
/* Serialization does not fail since the pk is not the point at infinity
* (according to this function's precondition). */
- secp256k1_eckey_pubkey_serialize33(pk, buf);
+ secp256k1_ge_serialize33(pk, buf);
secp256k1_sha256_write(hash_ctx, &sha, buf, sizeof(buf));
secp256k1_sha256_finalize(hash_ctx, &sha, buf);
secp256k1_scalar_set_b32(r, buf, NULL);
@@ -149,7 +149,7 @@ static int secp256k1_musig_pubkey_agg_callback(secp256k1_scalar *sc, secp256k1_g
#else
(void) ret;
#endif
- secp256k1_musig_keyaggcoef_internal(secp256k1_get_hash_context(ctx->ctx), sc, ctx->pks_hash, pt, &ctx->second_pk);
+ secp256k1_musig_keyaggcoef_internal(&ctx->ctx->hash_ctx, sc, ctx->pks_hash, pt, &ctx->second_pk);
return 1;
}
### src/modules/musig/session_impl.h
@@ -19,32 +19,6 @@
#include "../../scalar.h"
#include "../../util.h"
-/* Outputs 33 zero bytes if the given group element is the point at infinity and
- * otherwise outputs the compressed serialization */
-static void secp256k1_musig_ge_serialize_ext(unsigned char *out33, secp256k1_ge* ge) {
- if (secp256k1_ge_is_infinity(ge)) {
- memset(out33, 0, 33);
- } else {
- /* Serialize must succeed because the point is not at infinity */
- secp256k1_eckey_pubkey_serialize33(ge, out33);
- }
-}
-
-/* Outputs the point at infinity if the given byte array is all zero, otherwise
- * attempts to parse compressed point serialization. */
-static int secp256k1_musig_ge_parse_ext(secp256k1_ge* ge, const unsigned char *in33) {
- unsigned char zeros[33] = { 0 };
-
- if (secp256k1_memcmp_var(in33, zeros, sizeof(zeros)) == 0) {
- secp256k1_ge_set_infinity(ge);
- return 1;
- }
- if (!secp256k1_eckey_pubkey_parse(ge, in33, 33)) {
- return 0;
- }
- return secp256k1_ge_is_in_correct_subgroup(ge);
-}
-
static const unsigned char secp256k1_musig_secnonce_magic[4] = { 0x22, 0x0e, 0xdc, 0xf1 };
static void secp256k1_musig_secnonce_save(secp256k1_musig_secnonce *secnonce, const secp256k1_scalar *k, const secp256k1_ge *pk) {
@@ -194,7 +168,7 @@ int secp256k1_musig_pubnonce_parse(const secp256k1_context* ctx, secp256k1_musig
ARG_CHECK(in66 != NULL);
for (i = 0; i < 2; i++) {
- if (!secp256k1_eckey_pubkey_parse(&ges[i], &in66[33*i], 33)) {
+ if (!secp256k1_ge_parse(&ges[i], &in66[33*i], 33)) {
return 0;
}
if (!secp256k1_ge_is_in_correct_subgroup(&ges[i])) {
@@ -219,7 +193,7 @@ int secp256k1_musig_pubnonce_serialize(const secp256k1_context* ctx, unsigned ch
}
for (i = 0; i < 2; i++) {
/* serialize must succeed because the point was just loaded */
- secp256k1_eckey_pubkey_serialize33(&ges[i], &out66[33*i]);
+ secp256k1_ge_serialize33(&ges[i], &out66[33*i]);
}
return 1;
}
@@ -233,7 +207,7 @@ int secp256k1_musig_aggnonce_parse(const secp256k1_context* ctx, secp256k1_musig
ARG_CHECK(in66 != NULL);
for (i = 0; i < 2; i++) {
- if (!secp256k1_musig_ge_parse_ext(&ges[i], &in66[33*i])) {
+ if (!secp256k1_ge_parse_ext33(&ges[i], &in66[33*i])) {
return 0;
}
}
@@ -254,7 +228,7 @@ int secp256k1_musig_aggnonce_serialize(const secp256k1_context* ctx, unsigned ch
return 0;
}
for (i = 0; i < 2; i++) {
- secp256k1_musig_ge_serialize_ext(&out66[33*i], &ges[i]);
+ secp256k1_ge_serialize_ext33(&out66[33*i], &ges[i]);
}
return 1;
}
@@ -405,9 +379,9 @@ static int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp
return 0;
}
/* A pubkey cannot be the point at infinity */
- secp256k1_eckey_pubkey_serialize33(&pk, pk_ser);
+ secp256k1_ge_serialize33(&pk, pk_ser);
- secp256k1_nonce_function_musig(secp256k1_get_hash_context(ctx), k, input_nonce, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32);
+ secp256k1_nonce_function_musig(&ctx->hash_ctx, k, input_nonce, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32);
VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[0]));
VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[1]));
secp256k1_musig_secnonce_save(secnonce, k, &pk);
@@ -546,7 +520,7 @@ static void secp256k1_musig_compute_noncehash(const secp256k1_hash_ctx *hash_ctx
secp256k1_musig_compute_noncehash_sha256_tagged(&sha);
for (i = 0; i < 2; i++) {
- secp256k1_musig_ge_serialize_ext(buf, &aggnonce[i]);
+ secp256k1_ge_serialize_ext33(buf, &aggnonce[i]);
secp256k1_sha256_write(hash_ctx, &sha, buf, sizeof(buf));
}
secp256k1_sha256_write(hash_ctx, &sha, agg_pk32, 32);
@@ -568,7 +542,7 @@ static void secp256k1_musig_nonce_process_internal(const secp256k1_context *ctx,
secp256k1_ge fin_nonce_pt;
secp256k1_gej fin_nonce_ptj;
- secp256k1_musig_compute_noncehash(secp256k1_get_hash_context(ctx), noncehash, aggnonce_pts, agg_pk32, msg);
+ secp256k1_musig_compute_noncehash(&ctx->hash_ctx, noncehash, aggnonce_pts, agg_pk32, msg);
secp256k1_scalar_set_b32(b, noncehash, NULL);
/* fin_nonce = aggnonce_pts[0] + b*aggnonce_pts[1] */
secp256k1_effective_nonce(&fin_nonce_ptj, aggnonce_pts, b);
@@ -606,7 +580,7 @@ int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_
}
secp256k1_musig_nonce_process_internal(ctx, &session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_pts, agg_pk32, msg32);
- secp256k1_schnorrsig_challenge(secp256k1_get_hash_context(ctx), &session_i.challenge, fin_nonce, msg32, 32, agg_pk32);
+ secp256k1_schnorrsig_challenge(&ctx->hash_ctx, &session_i.challenge, fin_nonce, msg32, 32, agg_pk32);
/* If there is a tweak then set `challenge` times `tweak` to the `s`-part.*/
secp256k1_scalar_set_int(&session_i.s_part, 0);
@@ -676,7 +650,7 @@ int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_p
}
/* Multiply KeyAgg coefficient */
- secp256k1_musig_keyaggcoef(secp256k1_get_hash_context(ctx), &mu, &cache_i, &pk);
+ secp256k1_musig_keyaggcoef(&ctx->hash_ctx, &mu, &cache_i, &pk);
secp256k1_scalar_mul(&sk, &sk, &mu);
if (!secp256k1_musig_session_load(ctx, &session_i, session)) {
@@ -736,7 +710,7 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2
/* Multiplying the challenge by the KeyAgg coefficient is equivalent
* to multiplying the signer's public key by the coefficient, except
* much easier to do. */
- secp256k1_musig_keyaggcoef(secp256k1_get_hash_context(ctx), &mu, &cache_i, &pkp);
+ secp256k1_musig_keyaggcoef(&ctx->hash_ctx, &mu, &cache_i, &pkp);
secp256k1_scalar_mul(&e, &session_i.challenge, &mu);
/* Negate e if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc.
### src/modules/musig/tests_impl.h
@@ -526,7 +526,7 @@ static void musig_nonce_test(void) {
int i, j;
secp256k1_scalar k[6][2];
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
+ const secp256k1_hash_ctx *hash_ctx = &CTX->hash_ctx;
testrand_bytes_test(session_secrand, sizeof(session_secrand));
testrand_bytes_test(sk, sizeof(sk));
testrand_bytes_test(pk, sizeof(pk));
@@ -575,7 +575,7 @@ static void musig_nonce_test(void) {
* state. */
static void sha256_tag_test(void) {
secp256k1_sha256 sha;
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
+ const secp256k1_hash_ctx *hash_ctx = &CTX->hash_ctx;
{
/* "KeyAgg list" */
static const unsigned char tag[] = {'K', 'e', 'y', 'A', 'g', 'g', ' ', 'l', 'i', 's', 't'};
### src/modules/schnorrsig/main_impl.h
@@ -88,7 +88,7 @@ static int nonce_function_bip340_impl(const secp256k1_hash_ctx *hash_ctx, unsign
}
static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) {
- return nonce_function_bip340_impl(secp256k1_get_hash_context(secp256k1_context_static), nonce32, msg, msglen, key32, xonly_pk32, algo, algolen, data);
+ return nonce_function_bip340_impl(&secp256k1_context_static->hash_ctx, nonce32, msg, msglen, key32, xonly_pk32, algo, algolen, data);
}
const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340 = nonce_function_bip340;
@@ -150,7 +150,7 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi
/* Compute nonce */
if (noncefp == NULL || noncefp == secp256k1_nonce_function_bip340) {
/* Use context-aware nonce function by default */
- ret &= nonce_function_bip340_impl(secp256k1_get_hash_context(ctx), nonce32, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata);
+ ret &= nonce_function_bip340_impl(&ctx->hash_ctx, nonce32, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata);
} else {
ret &= !!noncefp(nonce32, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata);
}
@@ -171,7 +171,7 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi
secp256k1_fe_normalize_var(&r.x);
secp256k1_fe_get_b32(&sig64[0], &r.x);
- secp256k1_schnorrsig_challenge(secp256k1_get_hash_context(ctx), &e, &sig64[0], msg, msglen, pk_buf);
+ secp256k1_schnorrsig_challenge(&ctx->hash_ctx, &e, &sig64[0], msg, msglen, pk_buf);
secp256k1_scalar_mul(&e, &e, &sk);
secp256k1_scalar_add(&e, &e, &k);
secp256k1_scalar_get_b32(&sig64[32], &e);
@@ -236,7 +236,7 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha
/* Compute e. */
secp256k1_fe_get_b32(buf, &pk.x);
- secp256k1_schnorrsig_challenge(secp256k1_get_hash_context(ctx), &e, &sig64[0], msg, msglen, buf);
+ secp256k1_schnorrsig_challenge(&ctx->hash_ctx, &e, &sig64[0], msg, msglen, buf);
/* Compute rj = s*G + (-e)*pkj */
secp256k1_scalar_negate(&e, &e);
### src/modules/schnorrsig/tests_exhaustive_impl.h
@@ -105,7 +105,7 @@ static void test_exhaustive_schnorrsig_verify(const secp256k1_context *ctx, cons
secp256k1_scalar e;
unsigned char msg32[32];
testrand256(msg32);
- secp256k1_schnorrsig_challenge(secp256k1_get_hash_context(ctx), &e, sig64, msg32, sizeof(msg32), pk32);
+ secp256k1_schnorrsig_challenge(&ctx->hash_ctx, &e, sig64, msg32, sizeof(msg32), pk32);
/* Only do work if we hit a challenge we haven't tried before. */
if (!e_done[e]) {
/* Iterate over the possible valid last 32 bytes in the signature.
@@ -162,7 +162,7 @@ static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsign
while (e_count_done < EXHAUSTIVE_TEST_ORDER) {
secp256k1_scalar e;
testrand256(msg32);
- secp256k1_schnorrsig_challenge(secp256k1_get_hash_context(ctx), &e, xonly_pubkey_bytes[k - 1], msg32, sizeof(msg32), xonly_pubkey_bytes[d - 1]);
+ secp256k1_schnorrsig_challenge(&ctx->hash_ctx, &e, xonly_pubkey_bytes[k - 1], msg32, sizeof(msg32), xonly_pubkey_bytes[d - 1]);
/* Only do work if we hit a challenge we haven't tried before. */
if (!e_done[e]) {
secp256k1_scalar expected_s = (actual_k + e * actual_d) % EXHAUSTIVE_TEST_ORDER;
### src/modules/schnorrsig/tests_impl.h
@@ -38,7 +38,7 @@ static void run_nonce_function_bip340_tests(void) {
unsigned char *args[5];
int i;
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
+ const secp256k1_hash_ctx *hash_ctx = &CTX->hash_ctx;
/* Check that hash initialized by
* secp256k1_nonce_function_bip340_sha256_tagged has the expected
@@ -164,7 +164,7 @@ static void test_schnorrsig_sha256_tagged(void) {
unsigned char tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'c', 'h', 'a', 'l', 'l', 'e', 'n', 'g', 'e'};
secp256k1_sha256 sha;
secp256k1_sha256 sha_optimized;
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
+ const secp256k1_hash_ctx *hash_ctx = &CTX->hash_ctx;
secp256k1_sha256_initialize_tagged(hash_ctx, &sha, (unsigned char *) tag, sizeof(tag));
secp256k1_schnorrsig_sha256_tagged(&sha_optimized);
### src/modules/silentpayments/main_impl.h
@@ -71,7 +71,7 @@ static int secp256k1_silentpayments_calculate_input_hash_scalar(const secp256k1_
secp256k1_silentpayments_sha256_init_inputs(&hash);
secp256k1_sha256_write(hash_ctx, &hash, outpoint_smallest36, 36);
- secp256k1_eckey_pubkey_serialize33(pubkey_sum, pubkey_sum_ser);
+ secp256k1_ge_serialize33(pubkey_sum, pubkey_sum_ser);
secp256k1_sha256_write(hash_ctx, &hash, pubkey_sum_ser, sizeof(pubkey_sum_ser));
secp256k1_sha256_finalize(hash_ctx, &hash, input_hash);
/* Convert input_hash to a scalar.
@@ -116,7 +116,7 @@ static void secp256k1_silentpayments_sha256_init_sharedsecret(secp256k1_sha256*
}
static int secp256k1_silentpayments_create_output_tweak(const secp256k1_context *ctx, secp256k1_scalar *t_k_scalar, const unsigned char *shared_secret33, uint32_t k) {
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx);
+ const secp256k1_hash_ctx *hash_ctx = &ctx->hash_ctx;
secp256k1_sha256 hash;
unsigned char hash_ser[32];
unsigned char k_serialized[4];
@@ -210,22 +210,18 @@ int secp256k1_silentpayments_sender_create_outputs(
ARG_CHECK(recipients != NULL);
ARG_CHECK(n_recipients > 0);
ARG_CHECK(outpoint_smallest36 != NULL);
- ARG_CHECK((seckeys != NULL) || (keypairs != NULL));
- if (keypairs != NULL) {
- ARG_CHECK(n_keypairs > 0);
+ ARG_CHECK((n_seckeys > 0) || (n_keypairs > 0));
+ if (n_keypairs > 0) {
+ ARG_CHECK(keypairs != NULL);
for (i = 0; i < n_keypairs; i++) {
ARG_CHECK(keypairs[i] != NULL);
}
- } else {
- ARG_CHECK(n_keypairs == 0);
}
- if (seckeys != NULL) {
- ARG_CHECK(n_seckeys > 0);
+ if (n_seckeys > 0) {
+ ARG_CHECK(seckeys != NULL);
for (i = 0; i < n_seckeys; i++) {
ARG_CHECK(seckeys[i] != NULL);
}
- } else {
- ARG_CHECK(n_seckeys == 0);
}
for (i = 0; i < n_recipients; i++) {
ARG_CHECK(generated_outputs[i] != NULL);
@@ -281,7 +277,7 @@ int secp256k1_silentpayments_sender_create_outputs(
* curve order, which is statistically improbable. Returning an error here results in an untestable branch in the
* code, but we do this anyways to ensure strict compliance with BIP0352.
*/
- if (!secp256k1_silentpayments_calculate_input_hash_scalar(secp256k1_get_hash_context(ctx), &input_hash_scalar, outpoint_smallest36, &prevouts_pubkey_sum_ge)) {
+ if (!secp256k1_silentpayments_calculate_input_hash_scalar(&ctx->hash_ctx, &input_hash_scalar, outpoint_smallest36, &prevouts_pubkey_sum_ge)) {
secp256k1_scalar_clear(&seckey_sum_scalar);
return 0;
}
@@ -367,7 +363,7 @@ int secp256k1_silentpayments_recipient_label_parse(const secp256k1_context* ctx,
memset(label, 0, sizeof(*label));
ARG_CHECK(in33 != NULL);
- if (!secp256k1_eckey_pubkey_parse(&ge, in33, 33)) {
+ if (!secp256k1_ge_parse(&ge, in33, 33)) {
return 0;
}
@@ -386,7 +382,7 @@ int secp256k1_silentpayments_recipient_label_serialize(const secp256k1_context*
if (!secp256k1_silentpayments_label_load(ctx, &ge, label)) {
return 0;
}
- secp256k1_eckey_pubkey_serialize33(&ge, out33);
+ secp256k1_ge_serialize33(&ge, out33);
return 1;
}
@@ -410,10 +406,10 @@ int secp256k1_silentpayments_recipient_label_create(const secp256k1_context *ctx
/* Compute hash(ser_256(b_scan) || ser_32(m)) [sha256 with tag "BIP0352/Label"] */
secp256k1_silentpayments_sha256_init_label(&hash);
- secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, scan_key32, 32);
+ secp256k1_sha256_write(&ctx->hash_ctx, &hash, scan_key32, 32);
secp256k1_write_be32(m_serialized, m);
- secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, m_serialized, sizeof(m_serialized));
- secp256k1_sha256_finalize(secp256k1_get_hash_context(ctx), &hash, label_tweak32);
+ secp256k1_sha256_write(&ctx->hash_ctx, &hash, m_serialized, sizeof(m_serialized));
+ secp256k1_sha256_finalize(&ctx->hash_ctx, &hash, label_tweak32);
ret &= secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &label_tweak_scalar, &label_ge, label_tweak32);
secp256k1_silentpayments_label_save(label, &label_ge);
@@ -504,22 +500,18 @@ int secp256k1_silentpayments_recipient_prevouts_summary_create(
ARG_CHECK(prevouts_summary != NULL);
memset(prevouts_summary, 0, sizeof(*prevouts_summary));
ARG_CHECK(outpoint_smallest36 != NULL);
- ARG_CHECK((pubkeys != NULL) || (xonly_pubkeys != NULL));
- if (xonly_pubkeys != NULL) {
- ARG_CHECK(n_xonly_pubkeys > 0);
+ ARG_CHECK((n_pubkeys > 0) || (n_xonly_pubkeys > 0));
+ if (n_xonly_pubkeys > 0) {
+ ARG_CHECK(xonly_pubkeys != NULL);
for (i = 0; i < n_xonly_pubkeys; i++) {
ARG_CHECK(xonly_pubkeys[i] != NULL);
}
- } else {
- ARG_CHECK(n_xonly_pubkeys == 0);
}
- if (pubkeys != NULL) {
- ARG_CHECK(n_pubkeys > 0);
+ if (n_pubkeys > 0) {
+ ARG_CHECK(pubkeys != NULL);
for (i = 0; i < n_pubkeys; i++) {
ARG_CHECK(pubkeys[i] != NULL);
}
- } else {
- ARG_CHECK(n_pubkeys == 0);
}
/* Compute prevouts_pubkey_sum = A_1 + A_2 + ... + A_n.
@@ -552,7 +544,7 @@ int secp256k1_silentpayments_recipient_prevouts_summary_create(
* curve order, which is statistically improbable. Returning an error here results in an untestable branch in the
* code, but we do this anyways to ensure strict compliance with BIP0352.
*/
- if (!secp256k1_silentpayments_calculate_input_hash_scalar(secp256k1_get_hash_context(ctx), &input_hash_scalar, outpoint_smallest36, &prevouts_pubkey_sum_ge)) {
+ if (!secp256k1_silentpayments_calculate_input_hash_scalar(&ctx->hash_ctx, &input_hash_scalar, outpoint_smallest36, &prevouts_pubkey_sum_ge)) {
return 0;
}
memcpy(&prevouts_summary->data[0], secp256k1_silentpayments_prevouts_summary_magic, 4);
@@ -593,7 +585,7 @@ static int secp256k1_silentpayments_check_label_batch(
* we know that label_candidate = tx_output - unlabeled_output cannot be the point at infinity.
*/
VERIFY_CHECK(!secp256k1_ge_is_infinity(&label_candidates_ge[i]));
- secp256k1_eckey_pubkey_serialize33(&label_candidates_ge[i], label33);
+ secp256k1_ge_serialize33(&label_candidates_ge[i], label33);
*label_tweak = label_lookup(label33, label_context);
if (*label_tweak != NULL) {
*label_ge = label_candidates_ge[i];
### src/modules/silentpayments/tests_impl.h
@@ -254,8 +254,13 @@ static void test_send_api(void) {
/* Check that array arguments are verified */
CHECK_ILLEGAL(CTX, secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, NULL, 0, NULL, 0));
CHECK_ILLEGAL(CTX, secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 0, SMALLEST_OUTPOINT, NULL, 0, p, 1));
- CHECK_ILLEGAL(CTX, secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, t, 0, p, 1));
- CHECK_ILLEGAL(CTX, secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, t, 1, p, 0));
+ /* Empty key arrays can have both NULL or non-NULL as pointer value */
+ CHECK(secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, NULL, 0, p, 1));
+ CHECK(secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, t, 0, p, 1));
+ CHECK(secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, t, 1, NULL, 0));
+ CHECK(secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, t, 1, p, 0));
+ CHECK_ILLEGAL(CTX, secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, t, 0, NULL, 1));
+ CHECK_ILLEGAL(CTX, secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, NULL, 1, p, 0));
/* Create malformed keys for Alice by using a key that will overflow */
CHECK(secp256k1_ec_seckey_verify(CTX, secp256k1_group_order_bytes) == 0);
@@ -273,6 +278,23 @@ static void test_send_api(void) {
p[0] = MALFORMED_SECKEY;
CHECK(secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, NULL, 0, p, 1) == 0);
p[0] = ALICE_SECKEY;
+ /* Check that an invalid plain secret key is caught even when it is passed alongside a valid one.
+ * With a single invalid key, the failure would also be caught by the subsequent zero-sum check,
+ * so use two keys to ensure the seckey loop itself rejects the invalid key. The invalid key is
+ * tested in both positions so that neither the first nor the last key is skipped by the check. */
+ {
+ unsigned char const *p2[2];
+ p2[0] = ALICE_SECKEY;
+ p2[1] = MALFORMED_SECKEY;
+ CHECK(secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, NULL, 0, p2, 2) == 0);
+ p2[1] = secp256k1_group_order_bytes;
+ CHECK(secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, NULL, 0, p2, 2) == 0);
+ p2[0] = MALFORMED_SECKEY;
+ p2[1] = ALICE_SECKEY;
+ CHECK(secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, NULL, 0, p2, 2) == 0);
+ p2[0] = secp256k1_group_order_bytes;
+ CHECK(secp256k1_silentpayments_sender_create_outputs(CTX, op, rp, 2, SMALLEST_OUTPOINT, NULL, 0, p2, 2) == 0);
+ }
/* Create malformed recipients by setting all of the public key bytes to zero.
* Realistically, this would never happen since a bad public key would get caught when
* trying to parse the public key with _ec_pubkey_parse
@@ -511,8 +533,11 @@ static void test_recipient_api(void) {
CHECK_ILLEGAL(CTX, secp256k1_silentpayments_recipient_prevouts_summary_create(CTX, &ps, SMALLEST_OUTPOINT, NULL, 1, pp, 1));
CHECK_ILLEGAL(CTX, secp256k1_silentpayments_recipient_prevouts_summary_create(CTX, &ps, SMALLEST_OUTPOINT, tp, 1, NULL, 1));
- CHECK_ILLEGAL(CTX, secp256k1_silentpayments_recipient_prevouts_summary_create(CTX, &ps, SMALLEST_OUTPOINT, tp, 0, pp, 1));
- CHECK_ILLEGAL(CTX, secp256k1_silentpayments_recipient_prevouts_summary_create(CTX, &ps, SMALLEST_OUTPOINT, tp, 1, pp, 0));
+ /* Empty key arrays can have both NULL or non-NULL as pointer value */
+ CHECK(secp256k1_silentpayments_recipient_prevouts_summary_create(CTX, &ps, SMALLEST_OUTPOINT, NULL, 0, pp, 1));
+ CHECK(secp256k1_silentpayments_recipient_prevouts_summary_create(CTX, &ps, SMALLEST_OUTPOINT, tp, 0, pp, 1));
+ CHECK(secp256k1_silentpayments_recipient_prevouts_summary_create(CTX, &ps, SMALLEST_OUTPOINT, tp, 1, NULL, 0));
+ CHECK(secp256k1_silentpayments_recipient_prevouts_summary_create(CTX, &ps, SMALLEST_OUTPOINT, tp, 1, pp, 0));
CHECK_ILLEGAL(CTX, secp256k1_silentpayments_recipient_prevouts_summary_create(CTX, &ps, SMALLEST_OUTPOINT, NULL, 0, pp, 0));
CHECK_ILLEGAL(CTX, secp256k1_silentpayments_recipient_prevouts_summary_create(CTX, &ps, SMALLEST_OUTPOINT, NULL, 0, NULL, 0));
CHECK(secp256k1_silentpayments_recipient_prevouts_summary_create(CTX, &ps, SMALLEST_OUTPOINT, tp, 1, pp, 1));
### src/scratch_impl.h
@@ -12,8 +12,14 @@
static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t size) {
const size_t base_alloc = ROUND_TO_ALIGN(sizeof(secp256k1_scratch));
- void *alloc = checked_malloc(error_callback, base_alloc + size);
- secp256k1_scratch* ret = (secp256k1_scratch *)alloc;
+ void *alloc;
+ secp256k1_scratch* ret;
+ /* Reject sizes that would wrap when added to the aligned header. */
+ if (size > SIZE_MAX - base_alloc) {
+ return NULL;
+ }
+ alloc = checked_malloc(error_callback, base_alloc + size);
+ ret = (secp256k1_scratch *)alloc;
if (ret != NULL) {
memset(ret, 0, sizeof(*ret));
memcpy(ret->magic, "scratch", 8);
### src/secp256k1.c
@@ -234,10 +234,6 @@ void secp256k1_context_set_sha256_compression(secp256k1_context *ctx, secp256k1_
ctx->hash_ctx.fn_sha256_compression = fn_compression;
}
-static SECP256K1_INLINE const secp256k1_hash_ctx* secp256k1_get_hash_context(const secp256k1_context *ctx) {
- return &ctx->hash_ctx;
-}
-
static secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t max_size) {
VERIFY_CHECK(ctx != NULL);
return secp256k1_scratch_create(&ctx->error_callback, max_size);
@@ -272,7 +268,7 @@ int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pu
ARG_CHECK(pubkey != NULL);
memset(pubkey, 0, sizeof(*pubkey));
ARG_CHECK(input != NULL);
- if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) {
+ if (!secp256k1_ge_parse(&Q, input, inputlen)) {
return 0;
}
if (!secp256k1_ge_is_in_correct_subgroup(&Q)) {
@@ -298,10 +294,10 @@ int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *o
ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION);
if (secp256k1_pubkey_load(ctx, &Q, pubkey)) {
if (flags & SECP256K1_FLAGS_BIT_COMPRESSION) {
- secp256k1_eckey_pubkey_serialize33(&Q, output);
+ secp256k1_ge_serialize33(&Q, output);
*outputlen = 33;
} else {
- secp256k1_eckey_pubkey_serialize65(&Q, output);
+ secp256k1_ge_serialize65(&Q, output);
*outputlen = 65;
}
return 1;
@@ -532,7 +528,7 @@ static int nonce_function_rfc6979_impl(const secp256k1_hash_ctx *hash_ctx, unsig
}
static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) {
- return nonce_function_rfc6979_impl(secp256k1_get_hash_context(secp256k1_context_static), nonce32, msg32, key32, algo16, data, counter);
+ return nonce_function_rfc6979_impl(&secp256k1_context_static->hash_ctx, nonce32, msg32, key32, algo16, data, counter);
}
const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979;
@@ -560,7 +556,7 @@ static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_sc
if (noncefp == NULL || noncefp == secp256k1_nonce_function_rfc6979) {
/* Use ctx-aware function by default */
- ret = nonce_function_rfc6979_impl(secp256k1_get_hash_context(ctx), nonce32, msg32, seckey, NULL, (void*)noncedata, count);
+ ret = nonce_function_rfc6979_impl(&ctx->hash_ctx, nonce32, msg32, seckey, NULL, (void*)noncedata, count);
} else {
ret = !!noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count);
}
@@ -688,7 +684,7 @@ static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const uns
int ret = 0;
secp256k1_scalar_set_b32(&term, tweak32, &overflow);
- ret = (!overflow) & secp256k1_eckey_privkey_tweak_add(sec, &term);
+ ret = (!overflow) & secp256k1_eckey_seckey_tweak_add(sec, &term);
secp256k1_scalar_clear(&term);
return ret;
}
@@ -744,7 +740,7 @@ int secp256k1_ec_seckey_tweak_mul(const secp256k1_context* ctx, unsigned char *s
secp256k1_scalar_set_b32(&factor, tweak32, &overflow);
ret = secp256k1_scalar_set_b32_seckey(&sec, seckey);
- ret &= (!overflow) & secp256k1_eckey_privkey_tweak_mul(&sec, &factor);
+ ret &= (!overflow) & secp256k1_eckey_seckey_tweak_mul(&sec, &factor);
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret);
secp256k1_scalar_get_b32(seckey, &sec);
@@ -781,7 +777,7 @@ int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *see
ARG_CHECK(secp256k1_context_is_proper(ctx));
if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) {
- secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, secp256k1_get_hash_context(ctx), seed32);
+ secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, &ctx->hash_ctx, seed32);
}
return 1;
}
@@ -819,9 +815,9 @@ int secp256k1_tagged_sha256(const secp256k1_context* ctx, unsigned char *hash32,
ARG_CHECK(tag != NULL);
ARG_CHECK(msg != NULL);
- secp256k1_sha256_initialize_tagged(secp256k1_get_hash_context(ctx), &sha, tag, taglen);
- secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &sha, msg, msglen);
- secp256k1_sha256_finalize(secp256k1_get_hash_context(ctx), &sha, hash32);
+ secp256k1_sha256_initialize_tagged(&ctx->hash_ctx, &sha, tag, taglen);
+ secp256k1_sha256_write(&ctx->hash_ctx, &sha, msg, msglen);
+ secp256k1_sha256_finalize(&ctx->hash_ctx, &sha, hash32);
secp256k1_sha256_clear(&sha);
return 1;
}
### src/testrand_impl.h
@@ -22,7 +22,7 @@ SECP256K1_INLINE static void testrand_seed(const unsigned char *seed16) {
unsigned char out32[32];
secp256k1_sha256 hash;
int i;
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(secp256k1_context_static);
+ const secp256k1_hash_ctx *hash_ctx = &secp256k1_context_static->hash_ctx;
/* Use SHA256(PREFIX || seed16) as initial state. */
secp256k1_sha256_initialize(&hash);
### src/tests.c
@@ -420,6 +420,12 @@ static void run_scratch_tests(void) {
CHECK(secp256k1_scratch_alloc(&CTX->error_callback, scratch, SIZE_MAX) == NULL);
secp256k1_scratch_space_destroy(CTX, scratch);
+ /* Creating a scratch space whose size would wrap around when the aligned
+ * header size is added to it fails, both for SIZE_MAX and for the smallest
+ * size that still wraps. */
+ CHECK(secp256k1_scratch_space_create(CTX, SIZE_MAX) == NULL);
+ CHECK(secp256k1_scratch_space_create(CTX, SIZE_MAX - ROUND_TO_ALIGN(sizeof(secp256k1_scratch)) + 1) == NULL);
+
/* cleanup */
secp256k1_scratch_space_destroy(CTX, NULL); /* no-op */
}
@@ -474,8 +480,8 @@ static void run_plug_sha256_compression_tests(void) {
/* 5) A hash operation should invoke the installed callback */
own_transform_called = 0;
secp256k1_sha256_initialize(&sha);
- secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &sha, (const unsigned char*)"a", 1);
- secp256k1_sha256_finalize(secp256k1_get_hash_context(ctx), &sha, sha_out);
+ secp256k1_sha256_write(&ctx->hash_ctx, &sha, (const unsigned char*)"a", 1);
+ secp256k1_sha256_finalize(&ctx->hash_ctx, &sha, sha_out);
CHECK(own_transform_called);
/* 6) Unset sha256 and verify the default one is set again */
@@ -674,7 +680,7 @@ static void run_ctz_tests(void) {
/***** HASH TESTS *****/
static void run_sha256_known_output_tests(void) {
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
+ const secp256k1_hash_ctx *hash_ctx = &CTX->hash_ctx;
static const char *inputs[] = {
"", "abc", "message digest", "secure hash algorithm", "SHA256 is considered to be safe",
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
@@ -823,7 +829,7 @@ static void run_sha256_counter_tests(void) {
{0x2c, 0xf3, 0xa9, 0xf6, 0x15, 0x25, 0x80, 0x70, 0x76, 0x99, 0x7d, 0xf1, 0xc3, 0x2f, 0xa3, 0x31, 0xff, 0x92, 0x35, 0x2e, 0x8d, 0x04, 0x13, 0x33, 0xd8, 0x0d, 0xdb, 0x4a, 0xf6, 0x8c, 0x03, 0x34},
{0xec, 0x12, 0x24, 0x9f, 0x35, 0xa4, 0x29, 0x8b, 0x9e, 0x4a, 0x95, 0xf8, 0x61, 0xaf, 0x61, 0xc5, 0x66, 0x55, 0x3e, 0x3f, 0x2a, 0x98, 0xea, 0x71, 0x16, 0x6b, 0x1c, 0xd9, 0xe4, 0x09, 0xd2, 0x8e},
};
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
+ const secp256k1_hash_ctx *hash_ctx = &CTX->hash_ctx;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(midstates); i++) {
unsigned char out[32];
@@ -878,7 +884,7 @@ static void run_hmac_sha256_tests(void) {
{0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2}
};
int i;
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
+ const secp256k1_hash_ctx *hash_ctx = &CTX->hash_ctx;
for (i = 0; i < 6; i++) {
secp256k1_hmac_sha256 hasher;
unsigned char out[32];
@@ -912,7 +918,7 @@ static void run_rfc6979_hmac_sha256_tests(void) {
{0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94}
};
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
+ const secp256k1_hash_ctx *hash_ctx = &CTX->hash_ctx;
secp256k1_rfc6979_hmac_sha256 rng;
unsigned char out[32];
int i;
@@ -970,7 +976,7 @@ static void run_sha256_initialize_midstate_tests(void) {
0xa9ec59eaul, 0x9b4c2ffful, 0x400821e2ul, 0x0dcf3847ul,
0xbe7ea179ul, 0xa5772bdcul, 0x7d29bfe3ul, 0xa486b855ul
};
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
+ const secp256k1_hash_ctx *hash_ctx = &CTX->hash_ctx;
secp256k1_sha256 sha;
secp256k1_sha256_initialize_midstate(&sha, 64, midstate);
@@ -3318,7 +3324,7 @@ static void run_field_misc(void) {
testutil_random_fe_non_zero(&y);
v = testrand_bits(15);
/* Test that fe_add_int is equivalent to fe_set_int + fe_add. */
- secp256k1_fe_set_int(&q, v); /* q = v */
+ secp256k1_fe_set_int_unchecked(&q, v); /* q = v */
z = x; /* z = x */
secp256k1_fe_add(&z, &q); /* z = x+v */
q = x; /* q = x */
@@ -3525,7 +3531,7 @@ static void run_sqrt(void) {
/* Check sqrt of small squares (and their negatives) */
for (i = 1; i <= 100; i++) {
- secp256k1_fe_set_int(&x, i);
+ secp256k1_fe_set_int_unchecked(&x, i);
secp256k1_fe_sqr(&s, &x);
test_sqrt(&s, &x);
secp256k1_fe_negate(&t, &s, 1);
@@ -5744,11 +5750,11 @@ static void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar
if (secp256k1_ge_is_infinity(&r)) {
/* Store infinity as 0x00 */
const unsigned char zerobyte[1] = {0};
- secp256k1_sha256_write(secp256k1_get_hash_context(CTX), acc, zerobyte, 1);
+ secp256k1_sha256_write(&CTX->hash_ctx, acc, zerobyte, 1);
} else {
/* Store other points using their uncompressed serialization. */
- secp256k1_eckey_pubkey_serialize65(&r, bytes);
- secp256k1_sha256_write(secp256k1_get_hash_context(CTX), acc, bytes, sizeof(bytes));
+ secp256k1_ge_serialize65(&r, bytes);
+ secp256k1_sha256_write(&CTX->hash_ctx, acc, bytes, sizeof(bytes));
}
}
@@ -5790,7 +5796,7 @@ static void test_ecmult_constants_2bit(void) {
test_ecmult_accumulate(&acc, &x, scratch);
}
}
- secp256k1_sha256_finalize(secp256k1_get_hash_context(CTX), &acc, b32);
+ secp256k1_sha256_finalize(&CTX->hash_ctx, &acc, b32);
CHECK(secp256k1_memcmp_var(b32, expected32, 32) == 0);
secp256k1_scratch_space_destroy(CTX, scratch);
@@ -5809,7 +5815,7 @@ static void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsign
unsigned char b32[32];
unsigned char inp[6];
size_t i;
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
+ const secp256k1_hash_ctx *hash_ctx = &CTX->hash_ctx;
secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(CTX, 65536);
inp[0] = prefix & 0xFF;
@@ -5907,7 +5913,7 @@ static void test_ecmult_gen_blind(void) {
testrand256(seed32);
b = CTX->ecmult_gen_ctx.scalar_offset;
p = CTX->ecmult_gen_ctx.ge_offset;
- secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, secp256k1_get_hash_context(CTX), seed32);
+ secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, &CTX->hash_ctx, seed32);
CHECK(!secp256k1_scalar_eq(&b, &CTX->ecmult_gen_ctx.scalar_offset));
secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &pgej2, &key);
CHECK(!gej_xyz_equals_gej(&pgej, &pgej2));
@@ -5920,10 +5926,10 @@ static void test_ecmult_gen_blind_reset(void) {
/* Test ecmult_gen() blinding reset and confirm that the blinding is consistent. */
secp256k1_scalar b;
secp256k1_ge p1, p2;
- secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, secp256k1_get_hash_context(CTX), 0);
+ secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, &CTX->hash_ctx, 0);
b = CTX->ecmult_gen_ctx.scalar_offset;
p1 = CTX->ecmult_gen_ctx.ge_offset;
- secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, secp256k1_get_hash_context(CTX), 0);
+ secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, &CTX->hash_ctx, 0);
CHECK(secp256k1_scalar_eq(&b, &CTX->ecmult_gen_ctx.scalar_offset));
p2 = CTX->ecmult_gen_ctx.ge_offset;
CHECK(secp256k1_ge_eq_var(&p1, &p2));
@@ -6822,6 +6828,18 @@ static void test_ecdsa_end_to_end(void) {
memset(&signature[0], 0, sizeof(signature[0]));
CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &signature[0], sig, siglen) == 1);
CHECK(secp256k1_ecdsa_verify(CTX, &signature[0], message, &pubkey) == 1);
+ /* Serializing into a buffer of exactly the required size succeeds and
+ * yields the same encoding; one byte less fails and reports the size. */
+ {
+ unsigned char sig2[74];
+ size_t siglen2 = siglen;
+ CHECK(secp256k1_ecdsa_signature_serialize_der(CTX, sig2, &siglen2, &signature[0]) == 1);
+ CHECK(siglen2 == siglen);
+ CHECK(secp256k1_memcmp_var(sig2, sig, siglen) == 0);
+ siglen2 = siglen - 1;
+ CHECK(secp256k1_ecdsa_signature_serialize_der(CTX, sig2, &siglen2, &signature[0]) == 0);
+ CHECK(siglen2 == siglen);
+ }
/* Serialize/destroy/parse DER and verify again. */
siglen = 74;
CHECK(secp256k1_ecdsa_signature_serialize_der(CTX, sig, &siglen, &signature[0]) == 1);
@@ -6853,30 +6871,30 @@ static void test_random_pubkeys(void) {
if (len > 33) {
testrand256(&in[33]);
}
- if (secp256k1_eckey_pubkey_parse(&elem, in, len)) {
+ if (secp256k1_ge_parse(&elem, in, len)) {
unsigned char out[65];
unsigned char firstb;
int res;
size_t size = len;
firstb = in[0];
/* If the pubkey can be parsed, it should round-trip... */
if (len == 33) {
- secp256k1_eckey_pubkey_serialize33(&elem, out);
+ secp256k1_ge_serialize33(&elem, out);
} else {
- secp256k1_eckey_pubkey_serialize65(&elem, out);
+ secp256k1_ge_serialize65(&elem, out);
}
CHECK(secp256k1_memcmp_var(&in[1], &out[1], len-1) == 0);
/* ... except for the type of hybrid inputs. */
if ((in[0] != 6) && (in[0] != 7)) {
CHECK(in[0] == out[0]);
}
size = 65;
- secp256k1_eckey_pubkey_serialize65(&elem, in);
- CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size));
+ secp256k1_ge_serialize65(&elem, in);
+ CHECK(secp256k1_ge_parse(&elem2, in, size));
CHECK(secp256k1_ge_eq_var(&elem2, &elem));
/* Check that the X9.62 hybrid type is checked. */
in[0] = testrand_bits(1) ? 6 : 7;
- res = secp256k1_eckey_pubkey_parse(&elem2, in, size);
+ res = secp256k1_ge_parse(&elem2, in, size);
if (firstb == 2 || firstb == 3) {
if (in[0] == firstb + 4) {
CHECK(res);
@@ -6886,7 +6904,7 @@ static void test_random_pubkeys(void) {
}
if (res) {
CHECK(secp256k1_ge_eq_var(&elem, &elem2));
- secp256k1_eckey_pubkey_serialize65(&elem, out);
+ secp256k1_ge_serialize65(&elem, out);
CHECK(secp256k1_memcmp_var(&in[1], &out[1], 64) == 0);
}
}
@@ -7382,6 +7400,122 @@ static void run_ecdsa_der_parse(void) {
}
}
+/* Appends the body of a signature holding a 122-byte R integer, which exceeds
+ * 32 bytes and therefore overflows to zero, and the 2-byte S integer 0x0123.
+ * The body is exactly 128 bytes long, the smallest length whose encoding
+ * requires the long form. */
+static size_t der_long_form_body(unsigned char *buf) {
+ size_t len = 0;
+ size_t i;
+ buf[len++] = 0x02;
+ buf[len++] = 0x7A;
+ for (i = 0; i < 0x7A; i++) {
+ buf[len++] = 0x01;
+ }
+ buf[len++] = 0x02;
+ buf[len++] = 0x02;
+ buf[len++] = 0x01;
+ buf[len++] = 0x23;
+ CHECK(len == 128);
+ return len;
+}
+
+/* Appends the 35-byte encoding of an INTEGER holding a zero pad followed by 32
+ * bytes whose top bit is set. */
+static size_t der_padded_integer(unsigned char *buf) {
+ size_t len = 0;
+ size_t i;
+ buf[len++] = 0x02;
+ buf[len++] = 0x21;
+ buf[len++] = 0x00;
+ buf[len++] = 0x80;
+ for (i = 0; i < 31; i++) {
+ buf[len++] = 0x01;
+ }
+ CHECK(len == 35);
+ return len;
+}
+
+/* Checks that sig holds the values encoded by der_long_form_body. */
+static void der_long_form_check(const secp256k1_ecdsa_signature *sig) {
+ static const unsigned char zeroes[62] = {0};
+ unsigned char compact[64];
+ CHECK(secp256k1_ecdsa_signature_serialize_compact(CTX, compact, sig) == 1);
+ CHECK(secp256k1_memcmp_var(compact, zeroes, 62) == 0);
+ CHECK(compact[62] == 0x01);
+ CHECK(compact[63] == 0x23);
+}
+
+/* Tests the long form length encoding (X.690-0207 8.1.3.5).
+ *
+ * random_ber_signature only emits long form lengths in signatures it marks as
+ * certainly_not_der, so run_ecdsa_der_parse never asserts that a long form
+ * length is accepted. Note that the long form is only valid in DER for lengths
+ * of at least 128, which is more than a signature with two in-range scalars
+ * needs, so the R integers below are longer than 32 bytes. Such integers are
+ * not rejected: secp256k1_der_parse_integer flags them as overflowing and, as
+ * for any overflow, sets the scalar to zero. */
+static void run_ecdsa_der_parse_long_form(void) {
+ unsigned char buf[256];
+ secp256k1_ecdsa_signature sig;
+ size_t len;
+ size_t i;
+
+ /* A sequence of length 128, the shortest length using the long form. */
+ len = 0;
+ buf[len++] = 0x30;
+ buf[len++] = 0x81;
+ buf[len++] = 0x80;
+ len += der_long_form_body(buf + len);
+ CHECK(len == 131);
+ CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, buf, len) == 1);
+ der_long_form_check(&sig);
+
+ /* The same, with the R integer's own length in the long form as well. */
+ len = 0;
+ buf[len++] = 0x30;
+ buf[len++] = 0x81;
+ buf[len++] = 0x87;
+ buf[len++] = 0x02;
+ buf[len++] = 0x81;
+ buf[len++] = 0x80;
+ for (i = 0; i < 0x80; i++) {
+ buf[len++] = 0x01;
+ }
+ buf[len++] = 0x02;
+ buf[len++] = 0x02;
+ buf[len++] = 0x01;
+ buf[len++] = 0x23;
+ CHECK(len == 138);
+ CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, buf, len) == 1);
+ der_long_form_check(&sig);
+
+ /* Lengths below 128 must use the short form. */
+ len = 0;
+ buf[len++] = 0x30;
+ buf[len++] = 0x81;
+ buf[len++] = 0x46;
+ len += der_padded_integer(buf + len);
+ len += der_padded_integer(buf + len);
+ CHECK(len == 73);
+ CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, buf, len) == 0);
+ /* The same body with a short form length is accepted, so the encoding of
+ * the length is the only reason the signature above is rejected. */
+ memmove(buf + 1, buf + 2, len - 2);
+ len--;
+ CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, buf, len) == 1);
+
+ /* The long form length octets may not have a leading zero. */
+ len = 0;
+ buf[len++] = 0x30;
+ buf[len++] = 0x82;
+ buf[len++] = 0x00;
+ buf[len++] = 0x80;
+ len += der_long_form_body(buf + len);
+ CHECK(len == 132);
+ CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, buf, len) == 0);
+}
+
/* Tests several edge cases. */
static void run_ecdsa_edge_cases(void) {
int t;
@@ -7416,7 +7550,7 @@ static void run_ecdsa_edge_cases(void) {
secp256k1_scalar_set_int(&ss, 1);
secp256k1_scalar_set_int(&msg, 0);
secp256k1_scalar_set_int(&sr, 0);
- CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33));
+ CHECK(secp256k1_ge_parse(&key, pubkey_mods_zero, 33));
CHECK(secp256k1_ecdsa_sig_verify( &sr, &ss, &key, &msg) == 0);
}
@@ -7435,7 +7569,7 @@ static void run_ecdsa_edge_cases(void) {
secp256k1_scalar_set_int(&ss, 0);
secp256k1_scalar_set_int(&msg, 0);
secp256k1_scalar_set_int(&sr, 1);
- CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
+ CHECK(secp256k1_ge_parse(&key, pubkey, 33));
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
}
@@ -7462,8 +7596,8 @@ static void run_ecdsa_edge_cases(void) {
secp256k1_scalar_set_int(&ss, 2);
secp256k1_scalar_set_int(&msg, 0);
secp256k1_scalar_set_int(&sr, 2);
- CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
- CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33));
+ CHECK(secp256k1_ge_parse(&key, pubkey, 33));
+ CHECK(secp256k1_ge_parse(&key2, pubkey2, 33));
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
secp256k1_scalar_negate(&ss, &ss);
@@ -7503,8 +7637,8 @@ static void run_ecdsa_edge_cases(void) {
secp256k1_scalar_set_int(&ss, 1);
secp256k1_scalar_set_int(&msg, 1);
secp256k1_scalar_set_b32(&sr, csr, NULL);
- CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
- CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33));
+ CHECK(secp256k1_ge_parse(&key, pubkey, 33));
+ CHECK(secp256k1_ge_parse(&key2, pubkey2, 33));
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
secp256k1_scalar_negate(&ss, &ss);
@@ -7538,7 +7672,7 @@ static void run_ecdsa_edge_cases(void) {
secp256k1_scalar_set_int(&msg, 1);
secp256k1_scalar_negate(&msg, &msg);
secp256k1_scalar_set_b32(&sr, csr, NULL);
- CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
+ CHECK(secp256k1_ge_parse(&key, pubkey, 33));
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
secp256k1_scalar_negate(&ss, &ss);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
@@ -7743,7 +7877,7 @@ static void test_ecdsa_wycheproof(void) {
#include "wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h"
int t;
- const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
+ const secp256k1_hash_ctx *hash_ctx = &CTX->hash_ctx;
for (t = 0; t < SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS; t++) {
secp256k1_ecdsa_signature signature;
secp256k1_sha256 hasher;
@@ -8099,6 +8233,7 @@ static const struct tf_test_entry tests_ecdsa[] = {
CASE(pubkey_sort),
CASE(random_pubkeys),
CASE(ecdsa_der_parse),
+ CASE(ecdsa_der_parse_long_form),
CASE(ecdsa_sign_verify),
CASE(ecdsa_end_to_end),
CASE(ecdsa_edge_cases),Why this scored 29/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.