rust: pass Rust secp256k1 context instead of using wally's context
What changed, and why it matters
This commit is a small internal cleanup in the BitBox02 hardware wallet firmware. It changes how the code passes the cryptographic context (specifically for secp256k1 elliptic-curve operations) from using a shared context provided by an older library (libwally) to using a Rust-managed context. The functions themselves and the underlying cryptographic operations remain the same. There is no direct evidence in the commit that this fixes an exploitable security vulnerability.
Treat as a routine refactoring commit. Review that the new Rust secp256k1 context is initialized with appropriate capabilities (e.g., signing/verification flags) and that its lifetime exceeds all C calls. No immediate security response is indicated by the diff alone.
Security signals we found
Refactoring of cryptographic context management
Removal of dependency on `wally_get_secp_context()`
Use of raw pointer casts (`secp.ctx().as_ptr().cast()`) when crossing the Rust/C boundary
Touches anti-exfiltration host-commitment and DLEQ prove/verify functions
Evidence from the diff
The patch removes the use of wally_get_secp_context() in Rust secp256k1 wrappers and instead requires callers to pass a bitcoin::secp256k1::Secp256k1<All> context, whose internal pointer is forwarded to C functions (secp256k1_ecdsa_anti_exfil_host_commit, bitbox_secp256k1_dleq_prove, bitbox_secp256k1_dleq_verify). The build.rs allowlist drops wally_get_secp_context. Call sites in signtx.rs tests and streaming-silent-payments are updated. This is a refactoring step toward decoupling Rust code from libwally’s secp256k1 context lifetime and ownership model.
Changed components
src/rust/bitbox02/src/secp256k1.rssrc/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs (tests only)src/rust/streaming-silent-payments/src/lib.rssrc/rust/bitbox02-sys/build.rsInspect captured patch +20 / −9
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 8a7a2ab..a59b570 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
@@ -2641,7 +2641,8 @@ mod tests {
// tested in test_keystore_antiklepto.c. That the host nonce was included in the sig is
// tested by the siganture fixture test below.x
let host_nonce_commitment = pb::AntiKleptoHostNonceCommitment {
- commitment: bitbox02::secp256k1::ecdsa_anti_exfil_host_commit(host_nonce).unwrap(),
+ commitment: bitbox02::secp256k1::ecdsa_anti_exfil_host_commit(SECP256K1, host_nonce)
+ .unwrap(),
};
transaction.borrow_mut().inputs[1].host_nonce = Some(host_nonce.to_vec());
transaction.borrow_mut().inputs[1]
diff --git a/src/rust/bitbox02-sys/build.rs b/src/rust/bitbox02-sys/build.rs
index d416bec..c2f4185 100644
--- a/src/rust/bitbox02-sys/build.rs
+++ b/src/rust/bitbox02-sys/build.rs
@@ -158,7 +158,6 @@ const ALLOWLIST_FNS: &[&str] = &[
"ui_screen_stack_push",
"util_format_datetime",
"wally_free_string",
- "wally_get_secp_context",
"communication_mode_ble_enabled",
];
diff --git a/src/rust/bitbox02/src/secp256k1.rs b/src/rust/bitbox02/src/secp256k1.rs
index f17a711..50b4443 100644
--- a/src/rust/bitbox02/src/secp256k1.rs
+++ b/src/rust/bitbox02/src/secp256k1.rs
@@ -14,13 +14,15 @@
use bitcoin::secp256k1::ffi::CPtr;
+use bitcoin::secp256k1::{All, Secp256k1};
+
use alloc::vec::Vec;
-pub fn ecdsa_anti_exfil_host_commit(rand32: &[u8]) -> Result<Vec<u8>, ()> {
+pub fn ecdsa_anti_exfil_host_commit(secp: &Secp256k1<All>, rand32: &[u8]) -> Result<Vec<u8>, ()> {
let mut out = [0u8; 32];
match unsafe {
bitbox02_sys::secp256k1_ecdsa_anti_exfil_host_commit(
- bitbox02_sys::wally_get_secp_context(),
+ secp.ctx().as_ptr().cast(),
out.as_mut_ptr(),
rand32.as_ptr(),
)
@@ -31,6 +33,7 @@ pub fn ecdsa_anti_exfil_host_commit(rand32: &[u8]) -> Result<Vec<u8>, ()> {
}
pub fn dleq_prove(
+ secp: &Secp256k1<All>,
sk: &[u8; 32],
gen2: &bitcoin::secp256k1::PublicKey,
p1: &bitcoin::secp256k1::PublicKey,
@@ -40,7 +43,7 @@ pub fn dleq_prove(
let mut e = [0u8; 32];
let result = unsafe {
bitbox02_sys::bitbox_secp256k1_dleq_prove(
- bitbox02_sys::wally_get_secp_context(),
+ secp.ctx().as_ptr().cast(),
s.as_mut_ptr(),
e.as_mut_ptr(),
sk.as_ptr(),
@@ -59,6 +62,7 @@ pub fn dleq_prove(
}
pub fn dleq_verify(
+ secp: &Secp256k1<All>,
proof: [u8; 64],
gen2: &bitcoin::secp256k1::PublicKey,
p1: &bitcoin::secp256k1::PublicKey,
@@ -66,7 +70,7 @@ pub fn dleq_verify(
) -> Result<(), ()> {
let result = unsafe {
bitbox02_sys::bitbox_secp256k1_dleq_verify(
- bitbox02_sys::wally_get_secp_context(),
+ secp.ctx().as_ptr().cast(),
proof[..32].as_ptr(),
proof[32..].as_ptr(),
p1.as_c_ptr() as _,
@@ -99,7 +103,7 @@ mod tests {
let other_pubkey = other_base;
let other_pubkey = other_pubkey.mul_tweak(&secp, &seckey.into()).unwrap();
- let proof = dleq_prove(seckey_bytes, &other_base, &pubkey, &other_pubkey).unwrap();
+ let proof = dleq_prove(&secp, seckey_bytes, &other_base, &pubkey, &other_pubkey).unwrap();
// Check against fixture so potential upstream changes in the DLEQ implementation get
// caught. Incompatible changes can break BitBox client libraries that rely on this
// specific DLEQ implementation.
@@ -108,6 +112,7 @@ mod tests {
"6c885f825f6ce7565bc6d0bfda90506b11e2682dfe943f5a85badf1c8a96edc5f5e03f5ee2c58bf979646fbada920f9f1c5bd92805fb5b01534b42d26a550f79",
);
dleq_verify(
+ &secp,
proof.try_into().unwrap(),
&other_base,
&pubkey,
diff --git a/src/rust/streaming-silent-payments/src/lib.rs b/src/rust/streaming-silent-payments/src/lib.rs
index 9242d3d..574bcd5 100644
--- a/src/rust/streaming-silent-payments/src/lib.rs
+++ b/src/rust/streaming-silent-payments/src/lib.rs
@@ -141,10 +141,16 @@ fn create_dleq_proof(
.mul_tweak(secp, &Scalar::from(*a_sum))
.map_err(|_| ())?;
- let proof =
- bitbox02::secp256k1::dleq_prove(a_sum.as_ref(), scan_pubkey, a_sum_pubkey, &c_pubkey)?;
+ let proof = bitbox02::secp256k1::dleq_prove(
+ secp,
+ a_sum.as_ref(),
+ scan_pubkey,
+ a_sum_pubkey,
+ &c_pubkey,
+ )?;
// Sanity check.
bitbox02::secp256k1::dleq_verify(
+ secp,
proof.as_slice().try_into().unwrap(),
scan_pubkey,
a_sum_pubkey,
Why this scored 16/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.