From ee7341fbac1d159a198780c94aa8e0a025e28848 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 5 Jul 2022 22:36:28 +0200 Subject: [PATCH 01/12] docs: Never require a verification context --- include/secp256k1.h | 6 +++--- include/secp256k1_extrakeys.h | 6 +++--- include/secp256k1_recovery.h | 2 +- include/secp256k1_schnorrsig.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index dddab346ae272..e89db35cf0f8f 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -494,7 +494,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( * * Returns: 1: correct signature * 0: incorrect or unparseable signature - * Args: ctx: a secp256k1 context object, initialized for verification. + * Args: ctx: a secp256k1 context object. * In: sig: the signature being verified. * msghash32: the 32-byte message hash being verified. * The verifier must make sure to apply a cryptographic @@ -705,7 +705,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( * Returns: 0 if the arguments are invalid or the resulting public key would be * invalid (only when the tweak is the negation of the corresponding * secret key). 1 otherwise. - * Args: ctx: pointer to a context object initialized for validation. + * Args: ctx: pointer to a context object. * In/Out: pubkey: pointer to a public key object. pubkey will be set to an * invalid value if this function returns 0. * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to @@ -750,7 +750,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( /** Tweak a public key by multiplying it by a tweak value. * * Returns: 0 if the arguments are invalid. 1 otherwise. - * Args: ctx: pointer to a context object initialized for validation. + * Args: ctx: pointer to a context object. * In/Out: pubkey: pointer to a public key object. pubkey will be set to an * invalid value if this function returns 0. * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to diff --git a/include/secp256k1_extrakeys.h b/include/secp256k1_extrakeys.h index 09cbeaaa8007e..151e8c27848f6 100644 --- a/include/secp256k1_extrakeys.h +++ b/include/secp256k1_extrakeys.h @@ -108,7 +108,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubke * invalid (only when the tweak is the negation of the corresponding * secret key). 1 otherwise. * - * Args: ctx: pointer to a context object initialized for verification. + * Args: ctx: pointer to a context object. * Out: output_pubkey: pointer to a public key to store the result. Will be set * to an invalid value if this function returns 0. * In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to. @@ -137,7 +137,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add( * * Returns: 0 if the arguments are invalid or the tweaked pubkey is not the * result of tweaking the internal_pubkey with tweak32. 1 otherwise. - * Args: ctx: pointer to a context object initialized for verification. + * Args: ctx: pointer to a context object. * In: tweaked_pubkey32: pointer to a serialized xonly_pubkey. * tweaked_pk_parity: the parity of the tweaked pubkey (whose serialization * is passed in as tweaked_pubkey32). This must match the @@ -228,7 +228,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub( * invalid (only when the tweak is the negation of the keypair's * secret key). 1 otherwise. * - * Args: ctx: pointer to a context object initialized for verification. + * Args: ctx: pointer to a context object. * In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to * an invalid value if this function returns 0. * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according diff --git a/include/secp256k1_recovery.h b/include/secp256k1_recovery.h index 0e2847db96c69..d14f4fe691eaa 100644 --- a/include/secp256k1_recovery.h +++ b/include/secp256k1_recovery.h @@ -94,7 +94,7 @@ SECP256K1_API int secp256k1_ecdsa_sign_recoverable( * * Returns: 1: public key successfully recovered (which guarantees a correct signature). * 0: otherwise. - * Args: ctx: pointer to a context object, initialized for verification. + * Args: ctx: pointer to a context object. * Out: pubkey: pointer to the recovered public key. * In: sig: pointer to initialized signature that supports pubkey recovery. * msghash32: the 32-byte message hash assumed to be signed. diff --git a/include/secp256k1_schnorrsig.h b/include/secp256k1_schnorrsig.h index 5fedcb07b0519..41532868c119f 100644 --- a/include/secp256k1_schnorrsig.h +++ b/include/secp256k1_schnorrsig.h @@ -161,7 +161,7 @@ SECP256K1_API int secp256k1_schnorrsig_sign_custom( * * Returns: 1: correct signature * 0: incorrect signature - * Args: ctx: a secp256k1 context object, initialized for verification. + * Args: ctx: a secp256k1 context object. * In: sig64: pointer to the 64-byte signature to verify. * msg: the message being verified. Can only be NULL if msglen is 0. * msglen: length of the message From 1a553ee8be295f20aca3bc24d85732074b888b87 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 5 Jul 2022 22:41:49 +0200 Subject: [PATCH 02/12] docs: Change signature "validation" to "verification" --- include/secp256k1.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index e89db35cf0f8f..b68b16695d82c 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -426,8 +426,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_cmp( * encoding is invalid. R and S with value 0 are allowed in the encoding. * * After the call, sig will always be initialized. If parsing failed or R or - * S are zero, the resulting sig value is guaranteed to fail validation for any - * message and public key. + * S are zero, the resulting sig value is guaranteed to fail verification for + * any message and public key. */ SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( const secp256k1_context* ctx, @@ -447,7 +447,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( * encoded numbers are out of range. * * After the call, sig will always be initialized. If parsing failed or the - * encoded numbers are out of range, signature validation with it is + * encoded numbers are out of range, signature verification with it is * guaranteed to fail for every message and public key. */ SECP256K1_API int secp256k1_ecdsa_signature_parse_der( @@ -511,7 +511,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( * * If you need to accept ECDSA signatures from sources that do not obey this * rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to - * validation, but be aware that doing so results in malleable signatures. + * verification, but be aware that doing so results in malleable signatures. * * For details, see the comments for that function. */ From 316ac7625ad1fbfc5b5b317dfbc7bdab534aaa3e Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 6 Jul 2022 10:39:14 +0200 Subject: [PATCH 03/12] contexts: Deprecate all context flags except SECP256K1_CONTEXT_NONE --- doc/CHANGELOG.md | 3 +++ include/secp256k1.h | 26 ++++++++++++++++---------- include/secp256k1_preallocated.h | 2 ++ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 08c42a2cabc52..632a1b8975793 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -9,6 +9,9 @@ Each change falls into one of the following categories: Added, Changed, Deprecat ### Changed - Enable modules schnorrsig, extrakeys and ECDH by default in ./configure +### Deprecated + - Deprecated context flags `SECP256K1_CONTEXT_VERIFY` and `SECP256K1_CONTEXT_SIGN`. Use `SECP256K1_CONTEXT_NONE` instead. + ## [MAJOR.MINOR.PATCH] - YYYY-MM-DD ### Added/Changed/Deprecated/Removed/Fixed/Security diff --git a/include/secp256k1.h b/include/secp256k1.h index b68b16695d82c..ce0cae1febc4e 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -24,15 +24,13 @@ extern "C" { * 5. Opaque data pointers follow the function pointer they are to be passed to. */ -/** Opaque data structure that holds context information (precomputed tables etc.). +/** Opaque data structure that holds context information * - * The purpose of context structures is to cache large precomputed data tables - * that are expensive to construct, and also to maintain the randomization data - * for blinding. + * The purpose of context structures is to store the randomization data for + * blinding, see secp256k1_context_randomize. * * Do not create a new context object for each operation, as construction is - * far slower than all other API calls (~100 times slower than an ECDSA - * verification). + * far slower than all other API calls. * * A constructed context can safely be used from multiple threads * simultaneously, but API calls that take a non-const pointer to a context @@ -194,12 +192,16 @@ typedef int (*secp256k1_nonce_function)( #define SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY (1 << 10) #define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) -/** Flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and +/** Context flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and * secp256k1_context_preallocated_create. */ +#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) + +/** Deprecated context flags. These flags are treated equivalent to SECP256K1_CONTEXT_NONE. */ #define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) #define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) + +/* Testing flag. Do not use. */ #define SECP256K1_CONTEXT_DECLASSIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY) -#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) /** Flag to pass to secp256k1_ec_pubkey_serialize. */ #define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) @@ -226,9 +228,13 @@ SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp; * memory allocation entirely, see the functions in secp256k1_preallocated.h. * * Returns: a newly created context object. - * In: flags: which parts of the context to initialize. + * In: flags: Always set to SECP256K1_CONTEXT_NONE (see below). * - * See also secp256k1_context_randomize. + * The only valid non-deprecated flag in recent library versions is + * SECP256K1_CONTEXT_NONE, which will create a context sufficient for all functionality + * offered by the library. All other (deprecated) flags will be treated as equivalent + * to the SECP256K1_CONTEXT_NONE flag. Though the flags parameter primarily exists for + * historical reasons, future versions of the library may introduce new flags. */ SECP256K1_API secp256k1_context* secp256k1_context_create( unsigned int flags diff --git a/include/secp256k1_preallocated.h b/include/secp256k1_preallocated.h index d2d9014f02881..ed846f75f9de6 100644 --- a/include/secp256k1_preallocated.h +++ b/include/secp256k1_preallocated.h @@ -58,6 +58,8 @@ SECP256K1_API size_t secp256k1_context_preallocated_size( * bytes, as detailed above. * flags: which parts of the context to initialize. * + * See secp256k1_context_create (in secp256k1.h) for further details. + * * See also secp256k1_context_randomize (in secp256k1.h) * and secp256k1_context_preallocated_destroy. */ From 72fedf8a6cff9e26882fa0bc923da0429b6916af Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 5 Dec 2022 11:26:09 +0100 Subject: [PATCH 04/12] docs: Improve docs for static context --- include/secp256k1.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index ce0cae1febc4e..0ed2fdabcba43 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -214,10 +214,13 @@ typedef int (*secp256k1_nonce_function)( #define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06 #define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07 -/** A simple secp256k1 context object with no precomputed tables. These are useful for - * type serialization/parsing functions which require a context object to maintain - * API consistency, but currently do not require expensive precomputations or dynamic - * allocations. +/** A built-in constant secp256k1 context object with static storage duration. + * + * This context object offers *only limited functionality* , i.e., it cannot be used + * for API functions that perform computations involving secret keys, e.g., signing + * and public key generation. If this restriction applies to a specific API function, + * it is mentioned in its documentation. See secp256k1_context_create if you need a + * full context object that supports all functionality offered by the library. */ SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp; @@ -225,7 +228,8 @@ SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp; * * This function uses malloc to allocate memory. It is guaranteed that malloc is * called at most once for every call of this function. If you need to avoid dynamic - * memory allocation entirely, see the functions in secp256k1_preallocated.h. + * memory allocation entirely, see secp256k1_context_no_precomp and the functions in + * secp256k1_preallocated.h. * * Returns: a newly created context object. * In: flags: Always set to SECP256K1_CONTEXT_NONE (see below). From 53796d2b24e813750feae73e85c0a6eee40dc391 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 6 Jul 2022 17:09:31 +0200 Subject: [PATCH 05/12] contexts: Rename static context --- doc/CHANGELOG.md | 1 + include/secp256k1.h | 8 ++++++-- src/secp256k1.c | 11 ++++++----- src/tests.c | 3 +++ 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 632a1b8975793..4c114b2535010 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -11,6 +11,7 @@ Each change falls into one of the following categories: Added, Changed, Deprecat ### Deprecated - Deprecated context flags `SECP256K1_CONTEXT_VERIFY` and `SECP256K1_CONTEXT_SIGN`. Use `SECP256K1_CONTEXT_NONE` instead. + - Renamed `secp256k1_context_no_precomp` to `secp256k1_context_static`. ## [MAJOR.MINOR.PATCH] - YYYY-MM-DD diff --git a/include/secp256k1.h b/include/secp256k1.h index 0ed2fdabcba43..778d6529786c2 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -222,13 +222,17 @@ typedef int (*secp256k1_nonce_function)( * it is mentioned in its documentation. See secp256k1_context_create if you need a * full context object that supports all functionality offered by the library. */ -SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp; +SECP256K1_API extern const secp256k1_context *secp256k1_context_static; + +/** Deprecated alias for secp256k1_context_static. */ +SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp +SECP256K1_DEPRECATED("Use secp256k1_context_static instead"); /** Create a secp256k1 context object (in dynamically allocated memory). * * This function uses malloc to allocate memory. It is guaranteed that malloc is * called at most once for every call of this function. If you need to avoid dynamic - * memory allocation entirely, see secp256k1_context_no_precomp and the functions in + * memory allocation entirely, see secp256k1_context_static and the functions in * secp256k1_preallocated.h. * * Returns: a newly created context object. diff --git a/src/secp256k1.c b/src/secp256k1.c index 05daad2d1cc2b..5a201d98ebe14 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -64,13 +64,14 @@ struct secp256k1_context_struct { int declassify; }; -static const secp256k1_context secp256k1_context_no_precomp_ = { +static const secp256k1_context secp256k1_context_static_ = { { 0 }, { secp256k1_default_illegal_callback_fn, 0 }, { secp256k1_default_error_callback_fn, 0 }, 0 }; -const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_no_precomp_; +const secp256k1_context *secp256k1_context_static = &secp256k1_context_static_; +const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_static_; size_t secp256k1_context_preallocated_size(unsigned int flags) { size_t ret = sizeof(secp256k1_context); @@ -150,7 +151,7 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { } void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) { - ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp); + ARG_CHECK_NO_RETURN(ctx != secp256k1_context_static); if (ctx != NULL) { secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); } @@ -164,7 +165,7 @@ void secp256k1_context_destroy(secp256k1_context* ctx) { } void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { - ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp); + ARG_CHECK_NO_RETURN(ctx != secp256k1_context_static); if (fun == NULL) { fun = secp256k1_default_illegal_callback_fn; } @@ -173,7 +174,7 @@ void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)( } void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { - ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp); + ARG_CHECK_NO_RETURN(ctx != secp256k1_context_static); if (fun == NULL) { fun = secp256k1_default_error_callback_fn; } diff --git a/src/tests.c b/src/tests.c index 6d61dc811e8f4..52497b5d24b0f 100644 --- a/src/tests.c +++ b/src/tests.c @@ -164,6 +164,9 @@ void run_context_tests(int use_prealloc) { secp256k1_scalar msg, key, nonce; secp256k1_scalar sigr, sigs; + /* Check that deprecated secp256k1_context_no_precomp is an alias to secp256k1_context_static. */ + CHECK(secp256k1_context_no_precomp == secp256k1_context_static); + if (use_prealloc) { none_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); From d2c6d48de3c7032fc6d96e8efecb5a933f3c009c Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 18 Jul 2022 16:44:00 +0200 Subject: [PATCH 06/12] tests: Use new name of static context --- src/modules/extrakeys/tests_impl.h | 2 +- src/modules/recovery/tests_impl.h | 2 +- src/modules/schnorrsig/tests_impl.h | 2 +- src/tests.c | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/extrakeys/tests_impl.h b/src/modules/extrakeys/tests_impl.h index c8a99f4466865..6130043bfb90b 100644 --- a/src/modules/extrakeys/tests_impl.h +++ b/src/modules/extrakeys/tests_impl.h @@ -359,7 +359,7 @@ void test_keypair(void) { secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); - secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp); + secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static); secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount); diff --git a/src/modules/recovery/tests_impl.h b/src/modules/recovery/tests_impl.h index abf62f7f3ab69..3791227ae6db7 100644 --- a/src/modules/recovery/tests_impl.h +++ b/src/modules/recovery/tests_impl.h @@ -34,7 +34,7 @@ void test_ecdsa_recovery_api(void) { secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp); + secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static); secp256k1_pubkey pubkey; secp256k1_pubkey recpubkey; secp256k1_ecdsa_signature normal_sig; diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index 25840b8fa701c..2d7907104571e 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -132,7 +132,7 @@ void test_schnorrsig_api(void) { secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp); + secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static); int ecount; secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); diff --git a/src/tests.c b/src/tests.c index 52497b5d24b0f..f6cdde054f71c 100644 --- a/src/tests.c +++ b/src/tests.c @@ -172,7 +172,7 @@ void run_context_tests(int use_prealloc) { sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); vrfy_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); both_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); - sttc_prealloc = malloc(secp256k1_context_preallocated_clone_size(secp256k1_context_no_precomp)); + sttc_prealloc = malloc(secp256k1_context_preallocated_clone_size(secp256k1_context_static)); CHECK(none_prealloc != NULL); CHECK(sign_prealloc != NULL); CHECK(vrfy_prealloc != NULL); @@ -182,13 +182,13 @@ void run_context_tests(int use_prealloc) { sign = secp256k1_context_preallocated_create(sign_prealloc, SECP256K1_CONTEXT_SIGN); vrfy = secp256k1_context_preallocated_create(vrfy_prealloc, SECP256K1_CONTEXT_VERIFY); both = secp256k1_context_preallocated_create(both_prealloc, SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - sttc = secp256k1_context_preallocated_clone(secp256k1_context_no_precomp, sttc_prealloc); + sttc = secp256k1_context_preallocated_clone(secp256k1_context_static, sttc_prealloc); } else { none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - sttc = secp256k1_context_clone(secp256k1_context_no_precomp); + sttc = secp256k1_context_clone(secp256k1_context_static); } memset(&zero_pubkey, 0, sizeof(zero_pubkey)); @@ -5802,7 +5802,7 @@ void run_ec_pubkey_parse_test(void) { ecount = 0; VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 65) == 1); - CHECK(secp256k1_ec_pubkey_parse(secp256k1_context_no_precomp, &pubkey, pubkeyc, 65) == 1); + CHECK(secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, pubkeyc, 65) == 1); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(ecount == 0); VG_UNDEF(&ge, sizeof(ge)); From e383fbfa66d2c7f48c06a4f4810b5e6db945d2c7 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 6 Jul 2022 20:25:00 +0200 Subject: [PATCH 07/12] selftest: Rename internal function to make name available for API --- src/secp256k1.c | 2 +- src/selftest.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/secp256k1.c b/src/secp256k1.c index 5a201d98ebe14..782b3c3c245a6 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -97,7 +97,7 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne size_t prealloc_size; secp256k1_context* ret; - if (!secp256k1_selftest()) { + if (!secp256k1_selftest_passes()) { secp256k1_callback_call(&default_error_callback, "self test failed"); } diff --git a/src/selftest.h b/src/selftest.h index 52f1b8442e712..d083ac952481d 100644 --- a/src/selftest.h +++ b/src/selftest.h @@ -25,7 +25,7 @@ static int secp256k1_selftest_sha256(void) { return secp256k1_memcmp_var(out, output32, 32) == 0; } -static int secp256k1_selftest(void) { +static int secp256k1_selftest_passes(void) { return secp256k1_selftest_sha256(); } From e02d6862bddfc4c18116c22deb86c29380a7bfce Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Fri, 15 Jul 2022 12:48:24 +0200 Subject: [PATCH 08/12] selftest: Expose in public API --- doc/CHANGELOG.md | 3 +++ include/secp256k1.h | 24 +++++++++++++++++++++++- src/secp256k1.c | 10 +++++++--- src/tests.c | 6 ++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 4c114b2535010..1a738a5712f82 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -13,6 +13,9 @@ Each change falls into one of the following categories: Added, Changed, Deprecat - Deprecated context flags `SECP256K1_CONTEXT_VERIFY` and `SECP256K1_CONTEXT_SIGN`. Use `SECP256K1_CONTEXT_NONE` instead. - Renamed `secp256k1_context_no_precomp` to `secp256k1_context_static`. +### Added + - Added `secp256k1_selftest`, to be used in conjunction with `secp256k1_context_static`. + ## [MAJOR.MINOR.PATCH] - YYYY-MM-DD ### Added/Changed/Deprecated/Removed/Fixed/Security diff --git a/include/secp256k1.h b/include/secp256k1.h index 778d6529786c2..7b48e565f686d 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -214,13 +214,16 @@ typedef int (*secp256k1_nonce_function)( #define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06 #define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07 -/** A built-in constant secp256k1 context object with static storage duration. +/** A built-in constant secp256k1 context object with static storage duration, to be + * used in conjunction with secp256k1_selftest. * * This context object offers *only limited functionality* , i.e., it cannot be used * for API functions that perform computations involving secret keys, e.g., signing * and public key generation. If this restriction applies to a specific API function, * it is mentioned in its documentation. See secp256k1_context_create if you need a * full context object that supports all functionality offered by the library. + * + * It is highly recommended to call secp256k1_selftest before using this context. */ SECP256K1_API extern const secp256k1_context *secp256k1_context_static; @@ -228,6 +231,25 @@ SECP256K1_API extern const secp256k1_context *secp256k1_context_static; SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp SECP256K1_DEPRECATED("Use secp256k1_context_static instead"); +/** Perform basic self tests (to be used in conjunction with secp256k1_context_static) + * + * This function performs self tests that detect some serious usage errors and + * similar conditions, e.g., when the library is compiled for the wrong endianness. + * This is a last resort measure to be used in production. The performed tests are + * very rudimentary and are not intended as a replacement for running the test + * binaries. + * + * It is highly recommended to call this before using secp256k1_context_static. + * It is not necessary to call this function before using a context created with + * secp256k1_context_create (or secp256k1_context_preallocated_create), which will + * take care of performing the self tests. + * + * If the tests fail, this function will call the default error handler to abort the + * program (see secp256k1_context_set_error_callback). + */ +SECP256K1_API void secp256k1_selftest(void); + + /** Create a secp256k1 context object (in dynamically allocated memory). * * This function uses malloc to allocate memory. It is guaranteed that malloc is diff --git a/src/secp256k1.c b/src/secp256k1.c index 782b3c3c245a6..41138b570f63c 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -73,6 +73,12 @@ static const secp256k1_context secp256k1_context_static_ = { const secp256k1_context *secp256k1_context_static = &secp256k1_context_static_; const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_static_; +void secp256k1_selftest(void) { + if (!secp256k1_selftest_passes()) { + secp256k1_callback_call(&default_error_callback, "self test failed"); + } +} + size_t secp256k1_context_preallocated_size(unsigned int flags) { size_t ret = sizeof(secp256k1_context); /* A return value of 0 is reserved as an indicator for errors when we call this function internally. */ @@ -97,9 +103,7 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne size_t prealloc_size; secp256k1_context* ret; - if (!secp256k1_selftest_passes()) { - secp256k1_callback_call(&default_error_callback, "self test failed"); - } + secp256k1_selftest(); prealloc_size = secp256k1_context_preallocated_size(flags); if (prealloc_size == 0) { diff --git a/src/tests.c b/src/tests.c index f6cdde054f71c..9080a5f47d1cb 100644 --- a/src/tests.c +++ b/src/tests.c @@ -141,6 +141,11 @@ void random_scalar_order_b32(unsigned char *b32) { secp256k1_scalar_get_b32(b32, &num); } +void run_selftest_tests(void) { + /* Test public API */ + secp256k1_selftest(); +} + void run_context_tests(int use_prealloc) { secp256k1_pubkey pubkey; secp256k1_pubkey zero_pubkey; @@ -7388,6 +7393,7 @@ int main(int argc, char **argv) { secp256k1_testrand_init(argc > 2 ? argv[2] : NULL); /* initialize */ + run_selftest_tests(); run_context_tests(0); run_context_tests(1); run_scratch_tests(); From 06126364ad988771d762923ce71e63e7f5c56951 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 5 Dec 2022 11:23:13 +0100 Subject: [PATCH 09/12] docs: Tidy and improve docs about contexts and randomization --- include/secp256k1.h | 81 ++++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index 7b48e565f686d..112e0360142fc 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -26,11 +26,17 @@ extern "C" { /** Opaque data structure that holds context information * - * The purpose of context structures is to store the randomization data for - * blinding, see secp256k1_context_randomize. - * - * Do not create a new context object for each operation, as construction is - * far slower than all other API calls. + * The primary purpose of context objects is to store randomization data for + * enhanced protection against side-channel leakage. This protection is only + * effective if the context is randomized after its creation. See + * secp256k1_context_create for creation of contexts and + * secp256k1_context_randomize for randomization. + * + * A secondary purpose of context objects is to store pointers to callback + * functions that the library will call when certain error states arise. See + * secp256k1_context_set_error_callback as well as + * secp256k1_context_set_illegal_callback for details. Future library versions + * may use context objects for additional purposes. * * A constructed context can safely be used from multiple threads * simultaneously, but API calls that take a non-const pointer to a context @@ -43,7 +49,7 @@ extern "C" { */ typedef struct secp256k1_context_struct secp256k1_context; -/** Opaque data structure that holds rewriteable "scratch space" +/** Opaque data structure that holds rewritable "scratch space" * * The purpose of this structure is to replace dynamic memory allocations, * because we target architectures where this may not be available. It is @@ -265,6 +271,15 @@ SECP256K1_API void secp256k1_selftest(void); * offered by the library. All other (deprecated) flags will be treated as equivalent * to the SECP256K1_CONTEXT_NONE flag. Though the flags parameter primarily exists for * historical reasons, future versions of the library may introduce new flags. + * + * If the context is intended to be used for API functions that perform computations + * involving secret keys, e.g., signing and public key generation, then it is highly + * recommended to call secp256k1_context_randomize on the context before calling + * those API functions. This will provide enhanced protection against side-channel + * leakage, see secp256k1_context_randomize for details. + * + * Do not create a new context object for each operation, as construction and + * randomization can take non-negligible time. */ SECP256K1_API secp256k1_context* secp256k1_context_create( unsigned int flags @@ -344,7 +359,10 @@ SECP256K1_API void secp256k1_context_set_illegal_callback( ) SECP256K1_ARG_NONNULL(1); /** Set a callback function to be called when an internal consistency check - * fails. The default is crashing. + * fails. + * + * The default callback writes an error message to stderr and calls abort + * to abort the program. * * This can only trigger in case of a hardware failure, miscompilation, * memory corruption, serious bug in the library, or other error would can @@ -800,30 +818,41 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Updates the context randomization to protect against side-channel leakage. - * Returns: 1: randomization successfully updated or nothing to randomize +/** Randomizes the context to provide enhanced protection against side-channel leakage. + * + * Returns: 1: randomization successful (or called on copy of secp256k1_context_static) * 0: error * Args: ctx: pointer to a context object. * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) * - * While secp256k1 code is written to be constant-time no matter what secret - * values are, it's possible that a future compiler may output code which isn't, + * While secp256k1 code is written and tested to be constant-time no matter what + * secret values are, it is possible that a compiler may output code which is not, * and also that the CPU may not emit the same radio frequencies or draw the same - * amount power for all values. - * - * This function provides a seed which is combined into the blinding value: that - * blinding value is added before each multiplication (and removed afterwards) so - * that it does not affect function results, but shields against attacks which - * rely on any input-dependent behaviour. - * - * This function has currently an effect only on contexts initialized for signing - * because randomization is currently used only for signing. However, this is not - * guaranteed and may change in the future. It is safe to call this function on - * contexts not initialized for signing; then it will have no effect and return 1. - * - * You should call this after secp256k1_context_create or - * secp256k1_context_clone (and secp256k1_context_preallocated_create or - * secp256k1_context_clone, resp.), and you may call this repeatedly afterwards. + * amount of power for all values. Randomization of the context shields against + * side-channel observations which aim to exploit secret-dependent behaviour in + * certain computations which involve secret keys. + * + * It is highly recommended to call this function on contexts returned from + * secp256k1_context_create or secp256k1_context_clone (or from the corresponding + * functions in secp256k1_preallocated.h) before using these contexts to call API + * functions that perform computations involving secret keys, e.g., signing and + * public key generation. It is possible to call this function more than once on + * the same context, and doing so before every few computations involving secret + * keys is recommended as a defense-in-depth measure. + * + * Currently, the random seed is mainly used for blinding multiplications of a + * secret scalar with the elliptic curve base point. Multiplications of this + * kind are performed by exactly those API functions which are documented to + * require a context that is not the secp256k1_context_static. As a rule of thumb, + * these are all functions which take a secret key (or a keypair) as an input. + * A notable exception to that rule is the ECDH module, which relies on a different + * kind of elliptic curve point multiplication and thus does not benefit from + * enhanced protection against side-channel leakage currently. + * + * It is safe call this function on a copy of secp256k1_context_static in writable + * memory (e.g., obtained via secp256k1_context_clone). In that case, this + * function is guaranteed to return 1, but the call will have no effect because + * the static context (or a copy thereof) is not meant to be randomized. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( secp256k1_context* ctx, From e7d0185c901dfd6986476ba85aa03f5cfa0951f9 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Fri, 25 Nov 2022 21:39:12 +0100 Subject: [PATCH 10/12] docs: Get rid of "initialized for signing" terminology --- contrib/lax_der_privatekey_parsing.h | 3 +-- include/secp256k1.h | 4 ++-- include/secp256k1_extrakeys.h | 2 +- include/secp256k1_recovery.h | 2 +- include/secp256k1_schnorrsig.h | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/contrib/lax_der_privatekey_parsing.h b/contrib/lax_der_privatekey_parsing.h index 1a8ad8ae0c3b0..3749e418fe3e7 100644 --- a/contrib/lax_der_privatekey_parsing.h +++ b/contrib/lax_der_privatekey_parsing.h @@ -43,8 +43,7 @@ extern "C" { /** Export a private key in DER format. * * Returns: 1 if the private key was valid. - * Args: ctx: pointer to a context object, initialized for signing (cannot - * be NULL) + * Args: ctx: pointer to a context object (not secp256k1_context_static). * Out: privkey: pointer to an array for storing the private key in BER. * Should have space for 279 bytes, and cannot be NULL. * privkeylen: Pointer to an int where the length of the private key in diff --git a/include/secp256k1.h b/include/secp256k1.h index 112e0360142fc..185f0bed318f6 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -636,7 +636,7 @@ SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_def * * Returns: 1: signature created * 0: the nonce generation function failed, or the secret key was invalid. - * Args: ctx: pointer to a context object, initialized for signing. + * Args: ctx: pointer to a context object (not secp256k1_context_static). * Out: sig: pointer to an array where the signature will be placed. * In: msghash32: the 32-byte message hash being signed. * seckey: pointer to a 32-byte secret key. @@ -680,7 +680,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( * * Returns: 1: secret was valid, public key stores. * 0: secret was invalid, try again. - * Args: ctx: pointer to a context object, initialized for signing. + * Args: ctx: pointer to a context object (not secp256k1_context_static). * Out: pubkey: pointer to the created public key. * In: seckey: pointer to a 32-byte secret key. */ diff --git a/include/secp256k1_extrakeys.h b/include/secp256k1_extrakeys.h index 151e8c27848f6..3591bc0012ca0 100644 --- a/include/secp256k1_extrakeys.h +++ b/include/secp256k1_extrakeys.h @@ -159,7 +159,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_ * * Returns: 1: secret was valid, keypair is ready to use * 0: secret was invalid, try again with a different secret - * Args: ctx: pointer to a context object, initialized for signing. + * Args: ctx: pointer to a context object (not secp256k1_context_static). * Out: keypair: pointer to the created keypair. * In: seckey: pointer to a 32-byte secret key. */ diff --git a/include/secp256k1_recovery.h b/include/secp256k1_recovery.h index d14f4fe691eaa..824c604025d2f 100644 --- a/include/secp256k1_recovery.h +++ b/include/secp256k1_recovery.h @@ -72,7 +72,7 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( * * Returns: 1: signature created * 0: the nonce generation function failed, or the secret key was invalid. - * Args: ctx: pointer to a context object, initialized for signing. + * Args: ctx: pointer to a context object (not secp256k1_context_static). * Out: sig: pointer to an array where the signature will be placed. * In: msghash32: the 32-byte message hash being signed. * seckey: pointer to a 32-byte secret key. diff --git a/include/secp256k1_schnorrsig.h b/include/secp256k1_schnorrsig.h index 41532868c119f..e579e1b1d834b 100644 --- a/include/secp256k1_schnorrsig.h +++ b/include/secp256k1_schnorrsig.h @@ -106,7 +106,7 @@ typedef struct { * signatures from being valid in multiple contexts by accident. * * Returns 1 on success, 0 on failure. - * Args: ctx: pointer to a context object, initialized for signing. + * Args: ctx: pointer to a context object (not secp256k1_context_static). * Out: sig64: pointer to a 64-byte array to store the serialized signature. * In: msg32: the 32-byte message being signed. * keypair: pointer to an initialized keypair. From 7289b51d31bf091330f1bcae397fba8b2b2d54ab Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 23 Nov 2022 17:26:41 +0100 Subject: [PATCH 11/12] docs: Use doxygen style if and only if comment is user-facing and improve phrasing slightly. --- include/secp256k1.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index 185f0bed318f6..826ab75850c5e 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -7,7 +7,7 @@ extern "C" { #include -/* Unless explicitly stated all pointer arguments must not be NULL. +/** Unless explicitly stated all pointer arguments must not be NULL. * * The following rules specify the order of arguments in API calls: * @@ -134,7 +134,7 @@ typedef int (*secp256k1_nonce_function)( # define SECP256K1_INLINE inline # endif -/** When this header is used at build-time the SECP256K1_BUILD define needs to be set +/* When this header is used at build-time the SECP256K1_BUILD define needs to be set * to correctly setup export attributes and nullness checks. This is normally done * by secp256k1.c but to guard against this header being included before secp256k1.c * has had a chance to set the define (e.g. via test harnesses that just includes @@ -163,9 +163,9 @@ typedef int (*secp256k1_nonce_function)( # endif #endif -/**Warning attributes - * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out - * some paranoid null checks. */ +/* Warning attributes + * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out + * some paranoid null checks. */ # if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) # define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) # else @@ -177,7 +177,7 @@ typedef int (*secp256k1_nonce_function)( # define SECP256K1_ARG_NONNULL(_x) # endif -/** Attribute for marking functions, types, and variables as deprecated */ +/* Attribute for marking functions, types, and variables as deprecated */ #if !defined(SECP256K1_BUILD) && defined(__has_attribute) # if __has_attribute(__deprecated__) # define SECP256K1_DEPRECATED(_msg) __attribute__ ((__deprecated__(_msg))) @@ -188,11 +188,11 @@ typedef int (*secp256k1_nonce_function)( # define SECP256K1_DEPRECATED(_msg) #endif -/** All flags' lower 8 bits indicate what they're for. Do not use directly. */ +/* All flags' lower 8 bits indicate what they're for. Do not use directly. */ #define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1) #define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0) #define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1) -/** The higher bits contain the actual data. Do not use directly. */ +/* The higher bits contain the actual data. Do not use directly. */ #define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8) #define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) #define SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY (1 << 10) From 4386a2306c2b8cf9ad3040d8010e4295f6f01490 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Fri, 25 Nov 2022 22:32:11 +0100 Subject: [PATCH 12/12] examples: Switch to NONE contexts --- examples/ecdh.c | 8 ++------ examples/ecdsa.c | 8 ++------ examples/schnorr.c | 8 ++------ 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/examples/ecdh.c b/examples/ecdh.c index d7e8add361338..027d52fd5fec3 100644 --- a/examples/ecdh.c +++ b/examples/ecdh.c @@ -30,12 +30,8 @@ int main(void) { secp256k1_pubkey pubkey1; secp256k1_pubkey pubkey2; - /* The specification in secp256k1.h states that `secp256k1_ec_pubkey_create` - * needs a context object initialized for signing, which is why we create - * a context with the SECP256K1_CONTEXT_SIGN flag. - * (The docs for `secp256k1_ecdh` don't require any special context, just - * some initialized context) */ - secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + /* Before we can call actual API functions, we need to create a "context". */ + secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); if (!fill_random(randomize, sizeof(randomize))) { printf("Failed to generate randomness\n"); return 1; diff --git a/examples/ecdsa.c b/examples/ecdsa.c index 434c856ba0ff2..7e4f1b13ac86d 100644 --- a/examples/ecdsa.c +++ b/examples/ecdsa.c @@ -38,12 +38,8 @@ int main(void) { int return_val; secp256k1_pubkey pubkey; secp256k1_ecdsa_signature sig; - /* The specification in secp256k1.h states that `secp256k1_ec_pubkey_create` needs - * a context object initialized for signing and `secp256k1_ecdsa_verify` needs - * a context initialized for verification, which is why we create a context - * for both signing and verification with the SECP256K1_CONTEXT_SIGN and - * SECP256K1_CONTEXT_VERIFY flags. */ - secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + /* Before we can call actual API functions, we need to create a "context". */ + secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); if (!fill_random(randomize, sizeof(randomize))) { printf("Failed to generate randomness\n"); return 1; diff --git a/examples/schnorr.c b/examples/schnorr.c index 82eb07d5d7f00..207c45c42226e 100644 --- a/examples/schnorr.c +++ b/examples/schnorr.c @@ -30,12 +30,8 @@ int main(void) { int return_val; secp256k1_xonly_pubkey pubkey; secp256k1_keypair keypair; - /* The specification in secp256k1_extrakeys.h states that `secp256k1_keypair_create` - * needs a context object initialized for signing. And in secp256k1_schnorrsig.h - * they state that `secp256k1_schnorrsig_verify` needs a context initialized for - * verification, which is why we create a context for both signing and verification - * with the SECP256K1_CONTEXT_SIGN and SECP256K1_CONTEXT_VERIFY flags. */ - secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + /* Before we can call actual API functions, we need to create a "context". */ + secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); if (!fill_random(randomize, sizeof(randomize))) { printf("Failed to generate randomness\n"); return 1;