From 21c7cef19c442d93fccf2f6eaaa4fe2a49bab1d0 Mon Sep 17 00:00:00 2001 From: Marko Bencun Date: Sun, 30 Jul 2023 00:28:21 +0200 Subject: [PATCH] use the magic in the schnorrsig extraparams struct for versioning This ensures compatibility in that it makes sure that the `secp256k1_schnorrsig_sign_custom()` works for users using an older version of the headers but linking against a newer version of the library. --- include/secp256k1_schnorrsig.h | 29 +++++++++++++++++++++++++---- src/modules/schnorrsig/main_impl.h | 16 ++++++++++++---- src/modules/schnorrsig/tests_impl.h | 6 ++++++ 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/include/secp256k1_schnorrsig.h b/include/secp256k1_schnorrsig.h index b8e7226ea8..49e560755b 100644 --- a/include/secp256k1_schnorrsig.h +++ b/include/secp256k1_schnorrsig.h @@ -122,6 +122,15 @@ typedef int (*secp256k1_nonce_function_hardened)( */ SECP256K1_API const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340; +/** First version of the extraparams struct. See `secp256k1_schnorrsig_extraparams` for the + latest version and its documentation. + */ +typedef struct { + unsigned char magic[4]; + secp256k1_nonce_function_hardened noncefp; + void *ndata; +} secp256k1_schnorrsig_extraparams_v0; + /** Data structure that contains additional arguments for schnorrsig_sign_custom. * * A schnorrsig_extraparams structure object can be initialized correctly by @@ -150,16 +159,28 @@ typedef struct { void *ndata; secp256k1_schnorrsig_s2c_opening* s2c_opening; const unsigned char* s2c_data32; -} secp256k1_schnorrsig_extraparams; +} secp256k1_schnorrsig_extraparams_v1; + +typedef secp256k1_schnorrsig_extraparams_v1 secp256k1_schnorrsig_extraparams; + +#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V0 { 0xda, 0x6f, 0xb3, 0x8c } +#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V1 { 0x05, 0x96, 0x5b, 0x5c } +#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V1 + +#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT_V0 {\ + SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V0,\ + NULL,\ + NULL\ +} -#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC { 0xda, 0x6f, 0xb3, 0x8c } -#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT {\ - SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC,\ +#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT_V1 {\ + SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V1,\ NULL,\ NULL,\ NULL,\ NULL\ } +#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT_V1 /** Create a Schnorr signature. * diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 43534cd0d2..ac19082c0e 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -104,7 +104,8 @@ static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 * * by using the correct tagged hash function. */ static const unsigned char bip340_algo[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; -static const unsigned char schnorrsig_extraparams_magic[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC; +static const unsigned char schnorrsig_extraparams_magic_v0[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V0; +static const unsigned char schnorrsig_extraparams_magic_v1[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V1; 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) { secp256k1_sha256 sha; @@ -309,12 +310,19 @@ int secp256k1_schnorrsig_sign_custom(const secp256k1_context* ctx, unsigned char if (extraparams != NULL) { ARG_CHECK(secp256k1_memcmp_var(extraparams->magic, - schnorrsig_extraparams_magic, + schnorrsig_extraparams_magic_v0, + sizeof(extraparams->magic)) == 0 || + secp256k1_memcmp_var(extraparams->magic, + schnorrsig_extraparams_magic_v1, sizeof(extraparams->magic)) == 0); noncefp = extraparams->noncefp; ndata = extraparams->ndata; - s2c_opening = extraparams->s2c_opening; - s2c_data32 = extraparams->s2c_data32; + if (secp256k1_memcmp_var(extraparams->magic, + schnorrsig_extraparams_magic_v1, + sizeof(extraparams->magic)) == 0) { + s2c_opening = extraparams->s2c_opening; + s2c_data32 = extraparams->s2c_data32; + } } return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg, msglen, keypair, noncefp, ndata, s2c_opening, s2c_data32); } diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index 04050b4c35..39e5ff47b8 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -832,6 +832,7 @@ void test_schnorrsig_sign(void) { unsigned char sig[64]; unsigned char sig2[64]; unsigned char zeros64[64] = { 0 }; + secp256k1_schnorrsig_extraparams_v0 extraparams_v0 = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT_V0; secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; unsigned char aux_rand[32]; @@ -868,6 +869,11 @@ void test_schnorrsig_sign(void) { CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 1); CHECK(secp256k1_schnorrsig_sign32(CTX, sig2, msg, &keypair, extraparams.ndata) == 1); CHECK(secp256k1_memcmp_var(sig, sig2, sizeof(sig)) == 0); + + /* Test extraparams v0 to simulate users using old headers linking against a new version of the library */ + memset(sig, 1, sizeof(sig)); + CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, (secp256k1_schnorrsig_extraparams*)&extraparams_v0) == 1); + CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk)); } #define N_SIGS 3