Skip to content

Commit ae18fce

Browse files
committed
Merge branch 'reduce-sc-ops'
2 parents a6f1c2e + cb3ddce commit ae18fce

File tree

9 files changed

+82
-68
lines changed

9 files changed

+82
-68
lines changed

src/keystore.c

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -528,19 +528,11 @@ bool keystore_get_bip39_word(uint16_t idx, char** word_out)
528528
}
529529

530530
bool keystore_secp256k1_nonce_commit(
531-
const uint32_t* keypath,
532-
size_t keypath_len,
531+
const uint8_t* private_key,
533532
const uint8_t* msg32,
534533
const uint8_t* host_commitment,
535534
uint8_t* signer_commitment_out)
536535
{
537-
uint8_t private_key[32] = {0};
538-
UTIL_CLEANUP_32(private_key);
539-
if (!rust_secp256k1_get_private_key(
540-
keypath, keypath_len, rust_util_bytes_mut(private_key, sizeof(private_key)))) {
541-
return false;
542-
}
543-
544536
const secp256k1_context* ctx = wally_get_secp_context();
545537
secp256k1_ecdsa_s2c_opening signer_commitment;
546538
if (!secp256k1_ecdsa_anti_exfil_signer_commit(
@@ -555,23 +547,12 @@ bool keystore_secp256k1_nonce_commit(
555547
}
556548

557549
bool keystore_secp256k1_sign(
558-
const uint32_t* keypath,
559-
size_t keypath_len,
550+
const uint8_t* private_key,
560551
const uint8_t* msg32,
561552
const uint8_t* host_nonce32,
562553
uint8_t* sig_compact_out,
563554
int* recid_out)
564555
{
565-
if (keystore_is_locked()) {
566-
return false;
567-
}
568-
uint8_t private_key[32] = {0};
569-
UTIL_CLEANUP_32(private_key);
570-
if (!rust_secp256k1_get_private_key(
571-
keypath, keypath_len, rust_util_bytes_mut(private_key, sizeof(private_key)))) {
572-
return false;
573-
}
574-
575556
const secp256k1_context* ctx = wally_get_secp_context();
576557
secp256k1_ecdsa_signature secp256k1_sig = {0};
577558
if (!secp256k1_anti_exfil_sign(

src/keystore.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -157,24 +157,22 @@ USE_RESULT bool keystore_get_bip39_word(uint16_t idx, char** word_out);
157157
* Get a commitment to the original nonce before tweaking it with the host nonce. This is part of
158158
* the ECDSA Anti-Klepto Protocol. For more details, check the docs of
159159
* `secp256k1_ecdsa_anti_exfil_signer_commit`.
160-
* @param[in] keypath derivation keypath
161-
* @param[in] keypath_len size of keypath buffer
160+
* @param[in] private_key 32 byte private key
162161
* @param[in] msg32 32 byte message which will be signed by `keystore_secp256k1_sign`.
163162
* @param[in] host_commitment must be `sha256(sha256(tag)||shas256(tag)||host_nonce)` where
164163
* host_nonce is passed to `keystore_secp256k1_sign()`. See
165164
* `secp256k1_ecdsa_anti_exfil_host_commit()`.
166165
* @param[out] client_commitment_out EC_PUBLIC_KEY_LEN bytes compressed signer nonce pubkey.
167166
*/
168167
USE_RESULT bool keystore_secp256k1_nonce_commit(
169-
const uint32_t* keypath,
170-
size_t keypath_len,
168+
const uint8_t* private_key,
171169
const uint8_t* msg32,
172170
const uint8_t* host_commitment,
173171
uint8_t* client_commitment_out);
174172

175173
// clang-format off
176174
/**
177-
* Sign message with private key at the given keypath. Keystore must be unlocked.
175+
* Sign message with private key using the given private key.
178176
*
179177
* Details about `host_nonce32`, the host nonce contribution.
180178
* Instead of using plain rfc6979 to generate the nonce in this signature, the following formula is used:
@@ -187,8 +185,7 @@ USE_RESULT bool keystore_secp256k1_nonce_commit(
187185
* This is part of the ECSDA Anti-Klepto protocol, preventing this function to leak any secrets via
188186
* the signatures (see the ecdsa-s2c module in secp256k1-zpk for more details).
189187
*
190-
* @param[in] keypath derivation keypath
191-
* @param[in] keypath_len size of keypath buffer
188+
* @param[in] private_key 32 byte private key
192189
* @param[in] msg32 32 byte message to sign
193190
* @param[in] host_nonce32 32 byte nonce contribution. Cannot be NULL.
194191
* Intended to be a contribution by the host. If there is none available, use 32 zero bytes.
@@ -199,8 +196,7 @@ USE_RESULT bool keystore_secp256k1_nonce_commit(
199196
*/
200197
// clang-format on
201198
USE_RESULT bool keystore_secp256k1_sign(
202-
const uint32_t* keypath,
203-
size_t keypath_len,
199+
const uint8_t* private_key,
204200
const uint8_t* msg32,
205201
const uint8_t* host_nonce32,
206202
uint8_t* sig_compact_out,

src/rust/bitbox02-rust/src/hww/api/bitcoin/signmsg.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@ pub async fn process(
9898
// Engage in the anti-klepto protocol if the host sends a host nonce commitment.
9999
Some(pb::AntiKleptoHostNonceCommitment { ref commitment }) => {
100100
let signer_commitment = keystore::secp256k1_nonce_commit(
101-
keypath,
101+
crate::keystore::secp256k1_get_private_key(keypath)?
102+
.as_slice()
103+
.try_into()
104+
.unwrap(),
102105
&sighash,
103106
commitment
104107
.as_slice()
@@ -114,8 +117,14 @@ pub async fn process(
114117
None => [0; 32],
115118
};
116119

117-
let sign_result = bitbox02::keystore::secp256k1_sign(keypath, &sighash, &host_nonce)?;
118-
120+
let sign_result = bitbox02::keystore::secp256k1_sign(
121+
crate::keystore::secp256k1_get_private_key(keypath)?
122+
.as_slice()
123+
.try_into()
124+
.unwrap(),
125+
&sighash,
126+
&host_nonce,
127+
)?;
119128
let mut signature: Vec<u8> = sign_result.signature.to_vec();
120129
signature.push(sign_result.recid);
121130

src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,11 +1203,12 @@ async fn _process(
12031203
sighash_flags: SIGHASH_ALL,
12041204
});
12051205

1206+
let private_key = crate::keystore::secp256k1_get_private_key(&tx_input.keypath)?;
12061207
// Engage in the Anti-Klepto protocol if the host sends a host nonce commitment.
12071208
let host_nonce: [u8; 32] = match tx_input.host_nonce_commitment {
12081209
Some(pb::AntiKleptoHostNonceCommitment { ref commitment }) => {
12091210
let signer_commitment = bitbox02::keystore::secp256k1_nonce_commit(
1210-
&tx_input.keypath,
1211+
private_key.as_slice().try_into().unwrap(),
12111212
&sighash,
12121213
commitment
12131214
.as_slice()
@@ -1230,8 +1231,12 @@ async fn _process(
12301231
None => [0; 32],
12311232
};
12321233

1233-
let sign_result =
1234-
bitbox02::keystore::secp256k1_sign(&tx_input.keypath, &sighash, &host_nonce)?;
1234+
let sign_result = bitbox02::keystore::secp256k1_sign(
1235+
private_key.as_slice().try_into().unwrap(),
1236+
&sighash,
1237+
&host_nonce,
1238+
)?;
1239+
drop(private_key);
12351240
next_response.next.has_signature = true;
12361241
next_response.next.signature = sign_result.signature.to_vec();
12371242
}

src/rust/bitbox02-rust/src/hww/api/ethereum/sign.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,10 @@ pub async fn _process(
389389
// Engage in the anti-klepto protocol if the host sends a host nonce commitment.
390390
Some(pb::AntiKleptoHostNonceCommitment { ref commitment }) => {
391391
let signer_commitment = keystore::secp256k1_nonce_commit(
392-
request.keypath(),
392+
&crate::keystore::secp256k1_get_private_key(request.keypath())?
393+
.as_slice()
394+
.try_into()
395+
.unwrap(),
393396
&hash,
394397
commitment
395398
.as_slice()
@@ -404,8 +407,14 @@ pub async fn _process(
404407
// Return signature directly without the anti-klepto protocol, for backwards compatibility.
405408
None => [0; 32],
406409
};
407-
let sign_result = keystore::secp256k1_sign(request.keypath(), &hash, &host_nonce)?;
408-
410+
let sign_result = keystore::secp256k1_sign(
411+
&crate::keystore::secp256k1_get_private_key(request.keypath())?
412+
.as_slice()
413+
.try_into()
414+
.unwrap(),
415+
&hash,
416+
&host_nonce,
417+
)?;
409418
let mut signature: Vec<u8> = sign_result.signature.to_vec();
410419
signature.push(sign_result.recid);
411420

src/rust/bitbox02-rust/src/hww/api/ethereum/sign_typed_msg.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,10 @@ pub async fn process(
563563
let host_nonce = match request.host_nonce_commitment {
564564
Some(pb::AntiKleptoHostNonceCommitment { ref commitment }) => {
565565
let signer_commitment = keystore::secp256k1_nonce_commit(
566-
&request.keypath,
566+
crate::keystore::secp256k1_get_private_key(&request.keypath)?
567+
.as_slice()
568+
.try_into()
569+
.unwrap(),
567570
&sighash,
568571
commitment
569572
.as_slice()
@@ -578,8 +581,14 @@ pub async fn process(
578581
_ => return Err(Error::InvalidInput),
579582
};
580583

581-
let sign_result = bitbox02::keystore::secp256k1_sign(&request.keypath, &sighash, &host_nonce)?;
582-
584+
let sign_result = bitbox02::keystore::secp256k1_sign(
585+
crate::keystore::secp256k1_get_private_key(&request.keypath)?
586+
.as_slice()
587+
.try_into()
588+
.unwrap(),
589+
&sighash,
590+
&host_nonce,
591+
)?;
583592
let mut signature: Vec<u8> = sign_result.signature.to_vec();
584593
signature.push(sign_result.recid);
585594

src/rust/bitbox02-rust/src/hww/api/ethereum/signmsg.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ pub async fn process(
6767
// Engage in the anti-klepto protocol if the host sends a host nonce commitment.
6868
Some(pb::AntiKleptoHostNonceCommitment { ref commitment }) => {
6969
let signer_commitment = keystore::secp256k1_nonce_commit(
70-
&request.keypath,
70+
crate::keystore::secp256k1_get_private_key(&request.keypath)?
71+
.as_slice()
72+
.try_into()
73+
.unwrap(),
7174
&sighash,
7275
commitment
7376
.as_slice()
@@ -83,8 +86,14 @@ pub async fn process(
8386
None => [0; 32],
8487
};
8588

86-
let sign_result = bitbox02::keystore::secp256k1_sign(&request.keypath, &sighash, &host_nonce)?;
87-
89+
let sign_result = bitbox02::keystore::secp256k1_sign(
90+
crate::keystore::secp256k1_get_private_key(&request.keypath)?
91+
.as_slice()
92+
.try_into()
93+
.unwrap(),
94+
&sighash,
95+
&host_nonce,
96+
)?;
8897
let mut signature: Vec<u8> = sign_result.signature.to_vec();
8998
signature.push(sign_result.recid);
9099

src/rust/bitbox02/src/keystore.rs

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -218,16 +218,15 @@ pub struct SignResult {
218218
}
219219

220220
pub fn secp256k1_sign(
221-
keypath: &[u32],
221+
private_key: &[u8; 32],
222222
msg: &[u8; 32],
223223
host_nonce: &[u8; 32],
224224
) -> Result<SignResult, ()> {
225225
let mut signature = [0u8; 64];
226226
let mut recid: util::c_types::c_int = 0;
227227
match unsafe {
228228
bitbox02_sys::keystore_secp256k1_sign(
229-
keypath.as_ptr(),
230-
keypath.len() as _,
229+
private_key.as_ptr(),
231230
msg.as_ptr(),
232231
host_nonce.as_ptr(),
233232
signature.as_mut_ptr(),
@@ -243,15 +242,14 @@ pub fn secp256k1_sign(
243242
}
244243

245244
pub fn secp256k1_nonce_commit(
246-
keypath: &[u32],
245+
private_key: &[u8; 32],
247246
msg: &[u8; 32],
248247
host_commitment: &[u8; 32],
249248
) -> Result<[u8; EC_PUBLIC_KEY_LEN], ()> {
250249
let mut signer_commitment = [0u8; EC_PUBLIC_KEY_LEN];
251250
match unsafe {
252251
bitbox02_sys::keystore_secp256k1_nonce_commit(
253-
keypath.as_ptr(),
254-
keypath.len() as _,
252+
private_key.as_ptr(),
255253
msg.as_ptr(),
256254
host_commitment.as_ptr(),
257255
signer_commitment.as_mut_ptr(),
@@ -338,21 +336,19 @@ mod tests {
338336
use super::*;
339337
use bitcoin::secp256k1;
340338

341-
use crate::testing::{mock_memory, mock_unlocked, mock_unlocked_using_mnemonic};
339+
use crate::testing::{mock_memory, mock_unlocked_using_mnemonic};
342340
use util::bip32::HARDENED;
343341

344342
#[test]
345343
fn test_secp256k1_sign() {
346-
lock();
347-
let keypath = [44 + HARDENED, 0 + HARDENED, 0 + HARDENED, 0, 5];
344+
let private_key =
345+
hex::decode("a2d8cf543c60d65162b5a06f0cef9760c883f8aa09f31236859faa85d0b74c7c")
346+
.unwrap();
348347
let msg = [0x88u8; 32];
349348
let host_nonce = [0x56u8; 32];
350349

351-
// Fails because keystore is locked.
352-
assert!(secp256k1_sign(&keypath, &msg, &host_nonce).is_err());
353-
354-
mock_unlocked();
355-
let sign_result = secp256k1_sign(&keypath, &msg, &host_nonce).unwrap();
350+
let sign_result =
351+
secp256k1_sign(&private_key.try_into().unwrap(), &msg, &host_nonce).unwrap();
356352
// Verify signature against expected pubkey.
357353

358354
let secp = secp256k1::Secp256k1::new();
@@ -426,16 +422,15 @@ mod tests {
426422

427423
#[test]
428424
fn test_secp256k1_nonce_commit() {
429-
lock();
430-
let keypath = [44 + HARDENED, 0 + HARDENED, 0 + HARDENED, 0, 5];
425+
let private_key =
426+
hex::decode("a2d8cf543c60d65162b5a06f0cef9760c883f8aa09f31236859faa85d0b74c7c")
427+
.unwrap();
431428
let msg = [0x88u8; 32];
432429
let host_commitment = [0xabu8; 32];
433430

434-
// Fails because keystore is locked.
435-
assert!(secp256k1_nonce_commit(&keypath, &msg, &host_commitment).is_err());
436-
437-
mock_unlocked();
438-
let client_commitment = secp256k1_nonce_commit(&keypath, &msg, &host_commitment).unwrap();
431+
let client_commitment =
432+
secp256k1_nonce_commit(&private_key.try_into().unwrap(), &msg, &host_commitment)
433+
.unwrap();
439434
assert_eq!(
440435
hex::encode(client_commitment),
441436
"0381e4136251c87f2947b735159c6dd644a7b58d35b437e20c878e5129f1320e5e",

test/unit-test/test_keystore_antiklepto.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,11 @@ static void _test_keystore_antiklepto(void** state)
9393

9494
// Commit - protocol step 2.
9595
assert_true(keystore_secp256k1_nonce_commit(
96-
keypath, 5, msg, host_nonce_commitment, signer_commitment));
96+
xprv_derived.priv_key + 1, msg, host_nonce_commitment, signer_commitment));
9797
// Protocol step 3: host_nonce sent from host to signer to be used in step 4
9898
// Sign - protocol step 4.
99-
assert_true(keystore_secp256k1_sign(keypath, 5, msg, host_nonce, sig, &recid));
99+
assert_true(
100+
keystore_secp256k1_sign(xprv_derived.priv_key + 1, msg, host_nonce, sig, &recid));
100101

101102
// Protocol step 5: host verification.
102103
secp256k1_ecdsa_signature parsed_signature;

0 commit comments

Comments
 (0)