pass rust secp256k1 context to keystore_secp256k1_schnorr_sign
What changed, and why it matters
This commit is a small internal cleanup: it changes a Bitcoin signing function so that the caller provides the cryptographic context, instead of the function fetching its own. There is no visible bug fix or security patch in the diff itself, and no security relevance is stated by the vendor.
No immediate action required. Treat as routine refactor. If reviewing the broader series, verify that all previous `wally_get_secp_context()` call sites are replaced consistently and that the provided Rust context has the same capabilities (signing/verification flags) as the previous one.
Security signals we found
No security-relevant keywords in commit title or message
No CVE, advisory, or bug reference present
Change is a dependency-injection refactor of secp256k1 context usage
No bounds-check, memory-safety, or cryptographic-constant changes visible
No new validation or error-handling logic added
Evidence from the diff
The patch removes calls to wally_get_secp_context() inside keystore_secp256k1_schnorr_sign and _schnorr_keypair, instead requiring callers to pass a secp256k1_context* (from Rust via SECP256K1/Secp256k1<All>). It updates the C header, the C implementation, the Rust FFI wrapper, the Rust call site in signtx.rs, and the Rust unit tests. The change is part of a series (‘Step-by-step removal of wally_get_secp_context()’) and appears to be architectural dependency injection rather than a vulnerability remediation.
Changed components
src/keystore.csrc/keystore.hsrc/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rssrc/rust/bitbox02/src/keystore.rsInspect captured patch +11 / −5
diff --git a/src/keystore.c b/src/keystore.c
index cefb3f9..dee1e0d 100644
--- a/src/keystore.c
+++ b/src/keystore.c
@@ -580,6 +580,7 @@ bool keystore_get_ed25519_seed(uint8_t* seed_out)
}
static bool _schnorr_keypair(
+ const secp256k1_context* ctx,
const uint32_t* keypath,
size_t keypath_len,
const uint8_t* tweak,
@@ -596,7 +597,6 @@ static bool _schnorr_keypair(
return false;
}
- const secp256k1_context* ctx = wally_get_secp_context();
if (!secp256k1_keypair_create(ctx, keypair_out, private_key)) {
return false;
}
@@ -617,6 +617,7 @@ static void _cleanup_keypair(secp256k1_keypair* keypair)
}
bool keystore_secp256k1_schnorr_sign(
+ const secp256k1_context* ctx,
const uint32_t* keypath,
size_t keypath_len,
const uint8_t* msg32,
@@ -625,10 +626,9 @@ bool keystore_secp256k1_schnorr_sign(
{
secp256k1_keypair __attribute__((__cleanup__(_cleanup_keypair))) keypair = {0};
secp256k1_xonly_pubkey pubkey = {0};
- if (!_schnorr_keypair(keypath, keypath_len, tweak, &keypair, &pubkey)) {
+ if (!_schnorr_keypair(ctx, keypath, keypath_len, tweak, &keypair, &pubkey)) {
return false;
}
- const secp256k1_context* ctx = wally_get_secp_context();
uint8_t aux_rand[32] = {0};
random_32_bytes(aux_rand);
if (secp256k1_schnorrsig_sign32(ctx, sig64_out, msg32, &keypair, aux_rand) != 1) {
diff --git a/src/keystore.h b/src/keystore.h
index a0bbe24..ebbfbbe 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -200,6 +200,7 @@ USE_RESULT bool keystore_get_ed25519_seed(uint8_t* seed_out);
/**
* Sign a message that verifies against the pubkey tweaked using BIP-86.
*
+ * @param[in] ctx secp256k1 context
* @param[in] keypath derivation keypath
* @param[in] keypath_len number of elements in keypath
* @param[in] msg32 32 byte message to sign
@@ -208,6 +209,7 @@ USE_RESULT bool keystore_get_ed25519_seed(uint8_t* seed_out);
* @param[out] sig64_out resulting 64 byte signature
*/
USE_RESULT bool keystore_secp256k1_schnorr_sign(
+ const secp256k1_context* ctx,
const uint32_t* keypath,
size_t keypath_len,
const uint8_t* msg32,
diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
index 77599b1..a28edba 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
@@ -1170,6 +1170,7 @@ async fn _process(
next_response.next.has_signature = true;
next_response.next.signature = bitbox02::keystore::secp256k1_schnorr_sign(
+ SECP256K1,
&tx_input.keypath,
&sighash,
if let TaprootSpendInfo::KeySpend(tweak_hash) = &spend_info {
diff --git a/src/rust/bitbox02/src/keystore.rs b/src/rust/bitbox02/src/keystore.rs
index c383fcf..1bb086c 100644
--- a/src/rust/bitbox02/src/keystore.rs
+++ b/src/rust/bitbox02/src/keystore.rs
@@ -237,6 +237,7 @@ pub fn get_u2f_seed() -> Result<zeroize::Zeroizing<Vec<u8>>, ()> {
}
pub fn secp256k1_schnorr_sign(
+ secp: &Secp256k1<All>,
keypath: &[u32],
msg: &[u8; 32],
tweak: Option<&[u8; 32]>,
@@ -245,6 +246,7 @@ pub fn secp256k1_schnorr_sign(
match unsafe {
bitbox02_sys::keystore_secp256k1_schnorr_sign(
+ secp.ctx().as_ptr().cast(),
keypath.as_ptr(),
keypath.len() as _,
msg.as_ptr(),
@@ -320,8 +322,8 @@ mod tests {
// Test without tweak
crate::random::fake_reset();
- let sig = secp256k1_schnorr_sign(&keypath, &msg, None).unwrap();
let secp = secp256k1::Secp256k1::new();
+ let sig = secp256k1_schnorr_sign(&secp, &keypath, &msg, None).unwrap();
assert!(secp
.verify_schnorr(
&secp256k1::schnorr::Signature::from_slice(&sig).unwrap(),
@@ -339,7 +341,8 @@ mod tests {
secp256k1::Scalar::from_be_bytes(tweak.try_into().unwrap()).unwrap()
};
let (tweaked_pubkey, _) = expected_pubkey.add_tweak(&secp, &tweak).unwrap();
- let sig = secp256k1_schnorr_sign(&keypath, &msg, Some(&tweak.to_be_bytes())).unwrap();
+ let sig =
+ secp256k1_schnorr_sign(&secp, &keypath, &msg, Some(&tweak.to_be_bytes())).unwrap();
assert!(secp
.verify_schnorr(
&secp256k1::schnorr::Signature::from_slice(&sig).unwrap(),
Why this scored 17/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.