Merge bitcoin-core/secp256k1#1893: test: cover schnorrsig_sign_custom in constant-time tests
What changed, and why it matters
This commit only adds new test code to check that a specific Schnorr signing function behaves in a constant-time manner under Valgrind. It does not change any production cryptographic code, so it cannot introduce or fix a security vulnerability in the library itself. It is a test-coverage improvement.
No security action required; treat as routine test improvement. Reviewers may verify the new tests pass under Valgrind as described.
Security signals we found
Only test file src/ctime_tests.c changed
No production cryptographic code modified
Adds constant-time (CHECKMEM/Valgrind) coverage for schnorrsig_sign_custom
PR description explicitly disclaims production vulnerability
Evidence from the diff
The change is confined to src/ctime_tests.c. It adds CHECKMEM/Valgrind constant-time test coverage for secp256k1_schnorrsig_sign_custom with NULL extraparams, non-NULL extraparams.ndata using the default nonce function, and a custom nonce callback. No production code paths are modified. The PR description explicitly states this is a coverage improvement and does not claim a production vulnerability.
Changed components
src/ctime_tests.cInspect captured patch +41 / −0
### src/ctime_tests.c
@@ -49,6 +49,12 @@
# pragma GCC diagnostic warning "-Wunused-function"
#endif
+#ifdef ENABLE_MODULE_SCHNORRSIG
+static int nonce_function_custom(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 secp256k1_nonce_function_bip340(nonce32, msg, msglen, key32, xonly_pk32, algo, algolen, data);
+}
+#endif
+
static void run_tests(secp256k1_context *ctx, unsigned char *key);
int main(void) {
@@ -99,6 +105,10 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
#ifdef ENABLE_MODULE_EXTRAKEYS
secp256k1_keypair keypair;
#endif
+#ifdef ENABLE_MODULE_SCHNORRSIG
+ secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
+ unsigned char aux_rand[32] = { 0 };
+#endif
#ifdef ENABLE_MODULE_ELLSWIFT
unsigned char ellswift[64];
static const unsigned char prefix[64] = {'t', 'e', 's', 't'};
@@ -214,6 +224,37 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
ret = secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypair, NULL);
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
+
+ SECP256K1_CHECKMEM_UNDEFINE(key, 32);
+ ret = secp256k1_keypair_create(ctx, &keypair, key);
+ SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
+ CHECK(ret == 1);
+ SECP256K1_CHECKMEM_UNDEFINE(&keypair, sizeof(keypair));
+ ret = secp256k1_schnorrsig_sign_custom(ctx, sig, msg, 32, &keypair, NULL);
+ SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
+ CHECK(ret == 1);
+
+ extraparams.noncefp = NULL;
+ extraparams.ndata = aux_rand;
+ SECP256K1_CHECKMEM_UNDEFINE(key, 32);
+ ret = secp256k1_keypair_create(ctx, &keypair, key);
+ SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
+ CHECK(ret == 1);
+ SECP256K1_CHECKMEM_UNDEFINE(&keypair, sizeof(keypair));
+ ret = secp256k1_schnorrsig_sign_custom(ctx, sig, msg, 32, &keypair, &extraparams);
+ SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
+ CHECK(ret == 1);
+
+ extraparams.noncefp = nonce_function_custom;
+ extraparams.ndata = aux_rand;
+ SECP256K1_CHECKMEM_UNDEFINE(key, 32);
+ ret = secp256k1_keypair_create(ctx, &keypair, key);
+ SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
+ CHECK(ret == 1);
+ SECP256K1_CHECKMEM_UNDEFINE(&keypair, sizeof(keypair));
+ ret = secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, &extraparams);
+ SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
+ CHECK(ret == 1);
#endif
#ifdef ENABLE_MODULE_MUSIGWhy this scored 15/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.