nonce: terminate RFC6979 loop at UINT_MAX
What changed, and why it matters
This commit fixes an infinite-loop bug in the RFC6979 nonce generation code used for creating cryptographic signatures. If a caller asked for attempt number UINT_MAX (the maximum value of an unsigned integer), the old loop would generate that nonce but then keep going forever because the loop counter would wrap around to zero and never exceed the target. The fix generates the nonce first, then checks whether the requested attempt has been reached and exits. This is a reliability/correctness bug in a critical cryptographic path, though it requires a caller to deliberately request UINT_MAX to trigger.
Apply the patch. Review callers to confirm UINT_MAX is not passed in normal operation, and consider adding a test case for the UINT_MAX nonce attempt boundary. No immediate incident response is indicated unless custom callers pass UINT_MAX.
Security signals we found
Infinite loop in cryptographic nonce generation when counter is UINT_MAX
Loop index wraparound causing non-termination
RFC6979 nonce function behavior mismatch with public API contract
Potential denial-of-service via API parameter
Evidence from the diff
In nonce_function_rfc6979_impl in src/secp256k1.c, the loop for (i = 0; i <= counter; i++) generates HMAC-SHA256-based nonce candidates. When counter == UINT_MAX, the condition i <= counter is true for every i in unsigned int range; after i reaches UINT_MAX and increments, it wraps to 0, causing an infinite loop. The patch changes the loop to for (i = 0; ; i++), generates the candidate, and breaks when i == counter. This preserves the correct nonce for every unsigned int attempt, including UINT_MAX, and prevents wraparound. The bug is a denial-of-service/infinite loop in nonce generation, not a key-leak or signature-forgery vulnerability.
Changed components
src/secp256k1.cnonce_function_rfc6979_implRFC6979 HMAC-SHA256 nonce generationInspect captured patch +2 / −1
diff --git a/src/secp256k1.c b/src/secp256k1.c
index b216872..07160cc 100644
--- a/src/secp256k1.c
+++ b/src/secp256k1.c
@@ -521,8 +521,9 @@ static int nonce_function_rfc6979_impl(const secp256k1_hash_ctx *hash_ctx, unsig
buffer_append(keydata, &offset, algo16, 16);
}
secp256k1_rfc6979_hmac_sha256_initialize(hash_ctx, &rng, keydata, offset);
- for (i = 0; i <= counter; i++) {
+ for (i = 0; ; i++) {
secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, nonce32, 32);
+ if (i == counter) break;
}
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
Why this scored 37/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.