Skip to content

Commit 1dc5c6e

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 1dc5c6e

File tree

2 files changed

+66
-6
lines changed

2 files changed

+66
-6
lines changed

src/memory/memory.c

Lines changed: 50 additions & 6 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,11 +305,17 @@ bool memory_setup(const memory_interface_functions_t* ifs)
304305
}
305306
_interface_functions = ifs;
306307

308+
// Factory setup
307309
chunk_0_t chunk = {0};
308310
CLEANUP_CHUNK(chunk);
309311
_read_chunk(CHUNK_0_PERMANENT, chunk_bytes);
310312
if (chunk.fields.factory_setup_done == sectrue_u8) {
311-
// already factory installed
313+
// already factory installed, check if there is a failed hww reset
314+
if (memory_get_reset_hww()) {
315+
if (!memory_reset_hww()) {
316+
return false;
317+
}
318+
}
312319
return true;
313320
}
314321
// Perform factory setup.
@@ -363,6 +370,10 @@ bool memory_cleanup_smarteeprom(void)
363370

364371
bool memory_reset_hww(void)
365372
{
373+
if (!memory_set_reset_hww()) {
374+
return false;
375+
}
376+
366377
// Erase all app data chunks expect the first and the last one, which is permanent.
367378
for (uint32_t chunk = CHUNK_1; chunk < (FLASH_APPDATA_LEN / CHUNK_SIZE) - 1; chunk++) {
368379
if (!_write_chunk(chunk, NULL)) {
@@ -371,7 +382,6 @@ bool memory_reset_hww(void)
371382
}
372383

373384
// Initialize hww memory
374-
375385
chunk_1_t chunk = {0};
376386
CLEANUP_CHUNK(chunk);
377387
_read_chunk(CHUNK_1, chunk_bytes);
@@ -382,7 +392,9 @@ bool memory_reset_hww(void)
382392
// Set a new noise static private key.
383393
rust_noise_generate_static_private_key(rust_util_bytes_mut(
384394
chunk.fields.noise_static_private_key, sizeof(chunk.fields.noise_static_private_key)));
385-
bool res = _write_chunk(CHUNK_1, chunk.bytes);
395+
if (!_write_chunk(CHUNK_1, chunk.bytes)) {
396+
return false;
397+
}
386398

387399
// Reset bond-db and reinitialize IRK and identity address
388400
if (memory_get_platform() == MEMORY_PLATFORM_BITBOX02_PLUS) {
@@ -405,10 +417,16 @@ bool memory_reset_hww(void)
405417
chunk_shared.fields.ble_identity_address[0] |= 0xc;
406418

407419
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);
420+
if (!_write_to_address(FLASH_SHARED_DATA_START, 0, chunk_shared.bytes)) {
421+
return false;
422+
}
409423
}
410424

411-
return res;
425+
if (!memory_clear_reset_hww()) {
426+
return false;
427+
}
428+
429+
return true;
412430
}
413431

414432
static bool _is_bitmask_flag_set(uint8_t flag)
@@ -443,6 +461,32 @@ bool memory_set_initialized(void)
443461
return _write_chunk(CHUNK_1, chunk.bytes);
444462
}
445463

464+
bool memory_set_reset_hww(void)
465+
{
466+
chunk_7_t chunk = {0};
467+
CLEANUP_CHUNK(chunk);
468+
_read_chunk(CHUNK_7_PERMANENT, chunk_bytes);
469+
chunk.fields.reset_hww = sectrue_u8;
470+
return _write_chunk(CHUNK_7_PERMANENT, chunk.bytes);
471+
}
472+
473+
bool memory_clear_reset_hww(void)
474+
{
475+
chunk_7_t chunk = {0};
476+
CLEANUP_CHUNK(chunk);
477+
_read_chunk(CHUNK_7_PERMANENT, chunk_bytes);
478+
chunk.fields.reset_hww = secfalse_u8;
479+
return _write_chunk(CHUNK_7_PERMANENT, chunk.bytes);
480+
}
481+
482+
bool memory_get_reset_hww(void)
483+
{
484+
chunk_7_t chunk = {0};
485+
CLEANUP_CHUNK(chunk);
486+
_read_chunk(CHUNK_7_PERMANENT, chunk_bytes);
487+
return chunk.fields.reset_hww == sectrue_u8;
488+
}
489+
446490
bool memory_is_mnemonic_passphrase_enabled(void)
447491
{
448492
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)