Skip to content

Commit 4a986e3

Browse files
committed
keystore: reduce SC operations in the seed check
verify_seed() after storing a seed currently re-stretches the password, which needs 5 securechip events. We can skip that because we still have access to the stretched password. If the check succeeds, but there was an error involving the password or secure chip (e.g. the stretching result was corrupted the first time), the consequence is that the user won't be able to unlock, but the seed itself on the MCU, on the backup and retained (encrypted) in seed is unaffected. That trade-off is good, because a failure there (securechip returns no error but actually had a corruption) should be exceedingly rare. This effort is part of mitigating Optiga's throttling mechanism that kicks in after 133 events - users can run into this by repeatedly resetting/restoring).
1 parent 031f463 commit 4a986e3

File tree

4 files changed

+19
-11
lines changed

4 files changed

+19
-11
lines changed

src/keystore.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -208,20 +208,28 @@ static keystore_error_t _get_and_decrypt_seed(
208208
}
209209

210210
static bool _verify_seed(
211-
const char* password,
211+
const uint8_t* encryption_key,
212212
const uint8_t* expected_seed,
213213
size_t expected_seed_len)
214214
{
215-
uint8_t decrypted_seed[KEYSTORE_MAX_SEED_LENGTH] = {0};
216-
size_t seed_len;
217-
UTIL_CLEANUP_32(decrypted_seed);
218-
if (_get_and_decrypt_seed(password, decrypted_seed, &seed_len, NULL) != KEYSTORE_OK) {
215+
uint8_t encrypted_seed_and_hmac[96];
216+
UTIL_CLEANUP_32(encrypted_seed_and_hmac);
217+
uint8_t encrypted_len;
218+
if (!memory_get_encrypted_seed_and_hmac(encrypted_seed_and_hmac, &encrypted_len)) {
219+
return false;
220+
}
221+
222+
size_t decrypted_len = encrypted_len - 48;
223+
uint8_t decrypted[decrypted_len];
224+
bool password_correct = cipher_aes_hmac_decrypt(
225+
encrypted_seed_and_hmac, encrypted_len, decrypted, &decrypted_len, encryption_key);
226+
if (!password_correct) {
219227
return false;
220228
}
221-
if (expected_seed_len != seed_len) {
229+
if (expected_seed_len != decrypted_len) {
222230
return false;
223231
}
224-
if (!MEMEQ(expected_seed, decrypted_seed, seed_len)) {
232+
if (!MEMEQ(expected_seed, decrypted, expected_seed_len)) {
225233
return false;
226234
}
227235
return true;
@@ -356,7 +364,7 @@ keystore_error_t keystore_encrypt_and_store_seed(
356364
if (!memory_set_encrypted_seed_and_hmac(encrypted_seed, encrypted_seed_len_u8)) {
357365
return KEYSTORE_ERR_MEMORY;
358366
}
359-
if (!_verify_seed(password, seed, seed_length)) {
367+
if (!_verify_seed(secret, seed, seed_length)) {
360368
if (!memory_reset_hww()) {
361369
return KEYSTORE_ERR_MEMORY;
362370
}

src/rust/bitbox02-rust/src/hww/api/restore.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ mod tests {
200200
)),
201201
Ok(Response::Success(pb::Success {}))
202202
);
203-
assert_eq!(bitbox02::securechip::fake_event_counter(), 13);
203+
assert_eq!(bitbox02::securechip::fake_event_counter(), 8);
204204
drop(mock_hal); // to remove mutable borrow of counter
205205
assert_eq!(counter, 2);
206206
assert!(!keystore::is_locked());

src/rust/bitbox02-rust/src/hww/api/set_password.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ mod tests {
8080
)),
8181
Ok(Response::Success(pb::Success {}))
8282
);
83-
assert_eq!(bitbox02::securechip::fake_event_counter(), 14);
83+
assert_eq!(bitbox02::securechip::fake_event_counter(), 9);
8484
drop(mock_hal); // to remove mutable borrow of counter
8585
assert_eq!(counter, 2);
8686
assert!(!keystore::is_locked());

src/rust/bitbox02-rust/src/keystore.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ mod tests {
457457

458458
bitbox02::securechip::fake_event_counter_reset();
459459
assert!(keystore::encrypt_and_store_seed(seed, "foo").is_ok());
460-
assert_eq!(bitbox02::securechip::fake_event_counter(), 12);
460+
assert_eq!(bitbox02::securechip::fake_event_counter(), 7);
461461

462462
assert!(keystore::is_locked());
463463

0 commit comments

Comments
 (0)