Merge bitcoin/bitcoin#36203: Update secp256k1 subtree to latest master
What changed, and why it matters
This commit updates Bitcoin Core's embedded secp256k1 cryptography library to a newer version. The visible changes are mostly internal cleanups: renaming functions, moving public-key parsing/serialization code into a different file, replacing an internal accessor with direct structure access, and adding compile-time checks. The only user-visible behavior change mentioned by the project is a small API convenience fix in the experimental silentpayments module: callers can now pass either NULL or a non-NULL pointer when an array argument is empty. The commit also adds a size overflow guard when allocating a scratch buffer. There is no direct evidence in the commit message or diff of a critical vulnerability being fixed, but any change to low-level cryptographic code warrants careful review and testing before deployment.
Treat this as a routine dependency update that should go through normal Bitcoin Core review, CI, and release processes. Because it touches secp256k1 internals, operators should upgrade to the release containing this commit once it is part of an official Bitcoin Core release, and should monitor the secp256k1 project for any subsequent security advisories. No emergency action is indicated by the materials provided.
Security signals we found
Low-level cryptographic library subtree update
Secret-key loading changed from overflow+zero check to secp256k1_scalar_set_b32_seckey in ECDH and EllSwift XDH
Memory allocation size overflow guard added to scratch space creation
API argument validation relaxed for empty arrays in silentpayments sender/recipient functions
No explicit security advisory, CVE, or vulnerability description present in commit or PR text
Evidence from the diff
The commit is a subtree merge of bitcoin-core/secp256k1 master into src/secp256k1. Key technical deltas include: (1) removal of secp256k1_get_hash_context() and direct use of &ctx->hash_ctx / &secp256k1_context_static->hash_ctx throughout; (2) relocation of public-key parse/serialize helpers from eckey.h/impl to group.h/impl with new names (secp256k1_ge_parse, secp256k1_ge_serialize33/65, secp256k1_ge_parse_ext33, secp256k1_ge_serialize_ext33); (3) renaming privkey tweak helpers to seckey variants; (4) splitting several group/elliptic-curve functions into SECP256K1_INLINE impl_ variants wrapped by verifying stubs; (5) adding ASSERT_INT_CONST_AND_DO around secp256k1_fe_set_int and updating fe_half documentation; (6) changing ECDH and EllSwift XDH secret-key loading to use secp256k1_scalar_set_b32_seckey and returning is_sec_valid; (7) silentpayments API relaxation so empty key arrays need not be NULL; (8) adding a SIZE_MAX - base_alloc overflow check in secp256k1_scratch_create; (9) new tests for DER long-form length parsing and scratch-space overflow. The PR description says the update was primarily prompted by secp256k1 PR 1932, but the commit/PR text does not characterize that PR as a security fix.
Changed components
src/secp256k1 (embedded secp256k1 library)src/secp256k1/src/modules/ecdh/main_impl.hsrc/secp256k1/src/modules/ellswift/main_impl.hsrc/secp256k1/src/modules/silentpayments/main_impl.hsrc/secp256k1/src/scratch_impl.hsrc/secp256k1/src/group.hsrc/secp256k1/src/group_impl.hsrc/secp256k1/src/eckey.hsrc/secp256k1/src/eckey_impl.hsrc/secp256k1/src/secp256k1.cInspect captured patch +680 / −404
### src/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/secp256k1/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/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/secp256k1/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/secp256k1/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 47/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.