Skip to content

Commit c52aaca

Browse files
committed
memory: Check if hww reset was in progress during init
If the device is powered off after erasing but before initializing has finalized it is bricked since a noise key is required. Set a flag in chunk 7 that isn't being erased before reset and clear that flag when reset is done. During boot if that flag still is set, rerun the reset.
1 parent ddd9b65 commit c52aaca

File tree

2 files changed

+66
-5
lines changed

2 files changed

+66
-5
lines changed

src/memory/memory.c

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ typedef union {
134134
// Hash of bootloader used in the attestation sighash.
135135
// If not set, the actual bootloader area is hashed.
136136
secbool_u8 attestation_bootloader_hash_set;
137-
uint8_t reserved[3];
137+
secbool_u8 reset_hww;
138+
uint8_t reserved[2];
138139
uint8_t attestation_bootloader_hash[32];
139140
} fields;
140141
uint8_t bytes[CHUNK_SIZE];
@@ -304,6 +305,13 @@ bool memory_setup(const memory_interface_functions_t* ifs)
304305
}
305306
_interface_functions = ifs;
306307

308+
if (memory_get_reset_hww()) {
309+
if (!memory_reset_hww()) {
310+
return false;
311+
}
312+
}
313+
314+
// Factory setup
307315
chunk_0_t chunk = {0};
308316
CLEANUP_CHUNK(chunk);
309317
_read_chunk(CHUNK_0_PERMANENT, chunk_bytes);
@@ -363,6 +371,10 @@ bool memory_cleanup_smarteeprom(void)
363371

364372
bool memory_reset_hww(void)
365373
{
374+
if (!memory_set_reset_hww()) {
375+
return false;
376+
}
377+
366378
// Erase all app data chunks expect the first and the last one, which is permanent.
367379
for (uint32_t chunk = CHUNK_1; chunk < (FLASH_APPDATA_LEN / CHUNK_SIZE) - 1; chunk++) {
368380
if (!_write_chunk(chunk, NULL)) {
@@ -371,7 +383,6 @@ bool memory_reset_hww(void)
371383
}
372384

373385
// Initialize hww memory
374-
375386
chunk_1_t chunk = {0};
376387
CLEANUP_CHUNK(chunk);
377388
_read_chunk(CHUNK_1, chunk_bytes);
@@ -382,7 +393,9 @@ bool memory_reset_hww(void)
382393
// Set a new noise static private key.
383394
rust_noise_generate_static_private_key(rust_util_bytes_mut(
384395
chunk.fields.noise_static_private_key, sizeof(chunk.fields.noise_static_private_key)));
385-
bool res = _write_chunk(CHUNK_1, chunk.bytes);
396+
if (!_write_chunk(CHUNK_1, chunk.bytes)) {
397+
return false;
398+
}
386399

387400
// Reset bond-db and reinitialize IRK and identity address
388401
if (memory_get_platform() == MEMORY_PLATFORM_BITBOX02_PLUS) {
@@ -405,10 +418,16 @@ bool memory_reset_hww(void)
405418
chunk_shared.fields.ble_identity_address[0] |= 0xc;
406419

407420
memset(&chunk_shared.fields.ble_bond_db, 0xff, sizeof(chunk_shared.fields.ble_bond_db));
408-
res |= _write_to_address(FLASH_SHARED_DATA_START, 0, chunk_shared.bytes);
421+
if (!_write_to_address(FLASH_SHARED_DATA_START, 0, chunk_shared.bytes)) {
422+
return false;
423+
}
409424
}
410425

411-
return res;
426+
if (!memory_clear_reset_hww()) {
427+
return false;
428+
}
429+
430+
return true;
412431
}
413432

414433
static bool _is_bitmask_flag_set(uint8_t flag)
@@ -443,6 +462,32 @@ bool memory_set_initialized(void)
443462
return _write_chunk(CHUNK_1, chunk.bytes);
444463
}
445464

465+
bool memory_set_reset_hww(void)
466+
{
467+
chunk_7_t chunk = {0};
468+
CLEANUP_CHUNK(chunk);
469+
_read_chunk(CHUNK_7_PERMANENT, chunk_bytes);
470+
chunk.fields.reset_hww = sectrue_u8;
471+
return _write_chunk(CHUNK_7_PERMANENT, chunk.bytes);
472+
}
473+
474+
bool memory_clear_reset_hww(void)
475+
{
476+
chunk_7_t chunk = {0};
477+
CLEANUP_CHUNK(chunk);
478+
_read_chunk(CHUNK_7_PERMANENT, chunk_bytes);
479+
chunk.fields.reset_hww = secfalse_u8;
480+
return _write_chunk(CHUNK_7_PERMANENT, chunk.bytes);
481+
}
482+
483+
bool memory_get_reset_hww(void)
484+
{
485+
chunk_7_t chunk = {0};
486+
CLEANUP_CHUNK(chunk);
487+
_read_chunk(CHUNK_7_PERMANENT, chunk_bytes);
488+
return chunk.fields.reset_hww == sectrue_u8;
489+
}
490+
446491
bool memory_is_mnemonic_passphrase_enabled(void)
447492
{
448493
return _is_bitmask_flag_set(BITMASK_ENABLE_MNEMONIC_PASSPHRASE);

src/memory/memory.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,22 @@ USE_RESULT bool memory_is_initialized(void);
106106
*/
107107
USE_RESULT bool memory_set_initialized(void);
108108

109+
/**
110+
* Sets the "reset hww" flag to indicate that reset is in progress. Returns false if it fails to
111+
* write to flash.
112+
*/
113+
USE_RESULT bool memory_set_reset_hww(void);
114+
115+
/**
116+
* Clears the "reset hww" flag. Returns false if it fails to write to flash.
117+
*/
118+
USE_RESULT bool memory_clear_reset_hww(void);
119+
120+
/**
121+
* Get the "reset hww" flag.
122+
*/
123+
USE_RESULT bool memory_get_reset_hww(void);
124+
109125
/**
110126
* Returns true if the bip39 passphrase feature is enabled.
111127
*/

0 commit comments

Comments
 (0)