mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-23 23:08:14 +00:00
storage: Add STORAGE_UPGRADED_KEY to protect against fake storage upgrade attacks.
This commit is contained in:
parent
a168d661cf
commit
1deebf1065
@ -53,6 +53,9 @@
|
||||
// Norcow storage key of the wipe code data.
|
||||
#define WIPE_CODE_DATA_KEY ((APP_STORAGE << 8) | 0x06)
|
||||
|
||||
// Norcow storage key of the storage upgrade flag.
|
||||
#define STORAGE_UPGRADED_KEY ((APP_STORAGE << 8) | 0x07)
|
||||
|
||||
// The PIN value corresponding to an empty PIN.
|
||||
#define PIN_EMPTY 1
|
||||
|
||||
@ -150,6 +153,8 @@ static uint8_t hardware_salt[HARDWARE_SALT_SIZE] = {0};
|
||||
static uint32_t norcow_active_version = 0;
|
||||
static const uint8_t TRUE_BYTE = 0x01;
|
||||
static const uint8_t FALSE_BYTE = 0x00;
|
||||
static const uint32_t TRUE_WORD = 0xC35A69A5;
|
||||
static const uint32_t FALSE_WORD = 0x3CA5965A;
|
||||
|
||||
static void __handle_fault(const char *msg, const char *file, int line,
|
||||
const char *func);
|
||||
@ -621,6 +626,8 @@ static void init_wiped_storage(void) {
|
||||
ensure(auth_init(), "set_storage_auth_tag failed");
|
||||
ensure(storage_set_encrypted(VERSION_KEY, &version, sizeof(version)),
|
||||
"set_storage_version failed");
|
||||
ensure(norcow_set(STORAGE_UPGRADED_KEY, &FALSE_WORD, sizeof(FALSE_WORD)),
|
||||
"set_storage_not_upgraded failed");
|
||||
ensure(pin_logs_init(0), "init_pin_logs failed");
|
||||
ensure(set_wipe_code(WIPE_CODE_EMPTY), "set_wipe_code failed");
|
||||
|
||||
@ -854,12 +861,36 @@ secbool check_storage_version(void) {
|
||||
handle_fault("storage version check");
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
const void *storage_upgraded = NULL;
|
||||
if (sectrue != norcow_get(STORAGE_UPGRADED_KEY, &storage_upgraded, &len) ||
|
||||
len != sizeof(TRUE_WORD)) {
|
||||
handle_fault("storage version check");
|
||||
return secfalse;
|
||||
}
|
||||
if (version > norcow_active_version) {
|
||||
// Attack: Storage was downgraded.
|
||||
storage_wipe();
|
||||
handle_fault("storage version check");
|
||||
return secfalse;
|
||||
} else if (version < norcow_active_version) {
|
||||
// Storage was upgraded.
|
||||
if (*(const uint32_t *)storage_upgraded != TRUE_WORD) {
|
||||
// Attack: The upgrade process was bypassed.
|
||||
storage_wipe();
|
||||
handle_fault("storage version check");
|
||||
return secfalse;
|
||||
}
|
||||
norcow_set(STORAGE_UPGRADED_KEY, &FALSE_WORD, sizeof(FALSE_WORD));
|
||||
storage_set_encrypted(VERSION_KEY, &norcow_active_version,
|
||||
sizeof(norcow_active_version));
|
||||
} else {
|
||||
// Standard operation. The storage was neither upgraded nor downgraded.
|
||||
if (*(const uint32_t *)storage_upgraded != FALSE_WORD) {
|
||||
// Attack: The upgrade process was launched when it shouldn't have been.
|
||||
storage_wipe();
|
||||
handle_fault("storage version check");
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
return sectrue;
|
||||
}
|
||||
@ -900,7 +931,6 @@ static secbool decrypt_dek(const uint8_t *kek, const uint8_t *keiv) {
|
||||
memcpy(cached_keys, keys, sizeof(keys));
|
||||
memzero(keys, sizeof(keys));
|
||||
memzero(tag, sizeof(tag));
|
||||
|
||||
// Check that the authenticated version number matches the norcow version.
|
||||
// NOTE: This also initializes the authentication_sum by calling
|
||||
// storage_get_encrypted() which calls auth_get().
|
||||
@ -1464,6 +1494,11 @@ static secbool storage_upgrade(void) {
|
||||
}
|
||||
}
|
||||
|
||||
if (sectrue !=
|
||||
norcow_set(STORAGE_UPGRADED_KEY, &TRUE_WORD, sizeof(TRUE_WORD))) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
norcow_active_version = NORCOW_VERSION;
|
||||
return norcow_upgrade_finish();
|
||||
}
|
||||
|
@ -18,6 +18,9 @@ SAT_KEY = (PIN_APP_ID << 8) | 0x05
|
||||
# Norcow storage key of the wipe code data.
|
||||
WIPE_CODE_DATA_KEY = (PIN_APP_ID << 8) | 0x06
|
||||
|
||||
# Norcow storage key of the storage upgrade flag.
|
||||
STORAGE_UPGRADED_KEY = (PIN_APP_ID << 8) | 0x07
|
||||
|
||||
# The PIN value corresponding to an empty PIN.
|
||||
PIN_EMPTY = 1
|
||||
|
||||
@ -102,6 +105,8 @@ WORD_SIZE = 4
|
||||
# Boolean values are stored as a simple 0/1 int.
|
||||
TRUE_BYTE = b"\x01"
|
||||
FALSE_BYTE = b"\x00"
|
||||
TRUE_WORD = b"\xA5\x69\x5A\xC3"
|
||||
FALSE_WORD = b"\x5A\x96\xA5\x3C"
|
||||
|
||||
# ----- Crypto ----- #
|
||||
|
||||
|
@ -39,6 +39,7 @@ class Storage:
|
||||
|
||||
self.nc.set(consts.SAT_KEY, crypto.init_hmacs(self.sak))
|
||||
self._set_encrypt(consts.VERSION_KEY, b"\x02\x00\x00\x00")
|
||||
self.nc.set(consts.STORAGE_UPGRADED_KEY, consts.FALSE_WORD)
|
||||
self.pin_log.init()
|
||||
self._set_wipe_code(consts.WIPE_CODE_EMPTY)
|
||||
self._set_pin(consts.PIN_EMPTY)
|
||||
|
Loading…
Reference in New Issue
Block a user