mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-04 22:02:34 +00:00
feat(core): support quad-word only flash
[no changelog]
This commit is contained in:
parent
238e3fd7c1
commit
43d132acfa
191
storage/norcow.c
191
storage/norcow.c
@ -28,8 +28,6 @@
|
||||
// NRCW = 4e524357
|
||||
#define NORCOW_MAGIC_V0 ((uint32_t)0x5743524e)
|
||||
|
||||
#define NORCOW_WORD_SIZE (sizeof(uint32_t))
|
||||
#define NORCOW_PREFIX_LEN NORCOW_WORD_SIZE
|
||||
#define NORCOW_MAGIC_LEN NORCOW_WORD_SIZE
|
||||
#define NORCOW_VERSION_LEN NORCOW_WORD_SIZE
|
||||
|
||||
@ -39,10 +37,26 @@
|
||||
// The key value which is used to indicate that the entry has been deleted.
|
||||
#define NORCOW_KEY_DELETED (0x0000)
|
||||
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
#define NORCOW_WORD_SIZE (sizeof(uint32_t))
|
||||
#define NORCOW_PREFIX_LEN (NORCOW_WORD_SIZE)
|
||||
#define NORCOW_KEY_LEN 2
|
||||
#define NORCOW_LEN_LEN 2
|
||||
#define ALIGN(X) ((X) = ((X) + 3) & ~3)
|
||||
// The offset from the beginning of the sector where stored items start.
|
||||
#define NORCOW_STORAGE_START \
|
||||
(NORCOW_HEADER_LEN + NORCOW_MAGIC_LEN + NORCOW_VERSION_LEN)
|
||||
|
||||
#else
|
||||
#define NORCOW_WORD_SIZE (4 * sizeof(uint32_t))
|
||||
#define NORCOW_PREFIX_LEN (2 * NORCOW_WORD_SIZE)
|
||||
#define NORCOW_KEY_LEN 16
|
||||
#define NORCOW_LEN_LEN 16
|
||||
#define ALIGN(X) ((X) = ((X) + 0xF) & ~0xF)
|
||||
// The offset from the beginning of the sector where stored items start.
|
||||
#define NORCOW_STORAGE_START (NORCOW_HEADER_LEN + NORCOW_WORD_SIZE)
|
||||
#endif
|
||||
|
||||
// The index of the active reading sector and writing sector. These should be
|
||||
// equal except when storage version upgrade or compaction is in progress.
|
||||
static uint8_t norcow_active_sector = 0;
|
||||
@ -66,7 +80,8 @@ static const void *norcow_ptr(uint8_t sector, uint32_t offset, uint32_t size) {
|
||||
/*
|
||||
* Writes data to given sector, starting from offset
|
||||
*/
|
||||
static secbool norcow_write(uint8_t sector, uint32_t offset, uint32_t prefix,
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
static secbool norcow_write(uint8_t sector, uint32_t offset, uint16_t key,
|
||||
const uint8_t *data, uint16_t len) {
|
||||
if (sector >= NORCOW_SECTOR_COUNT) {
|
||||
return secfalse;
|
||||
@ -76,6 +91,8 @@ static secbool norcow_write(uint8_t sector, uint32_t offset, uint32_t prefix,
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
uint32_t prefix = ((uint32_t)len << 16) | key;
|
||||
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
|
||||
// write prefix
|
||||
@ -100,6 +117,62 @@ static secbool norcow_write(uint8_t sector, uint32_t offset, uint32_t prefix,
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return sectrue;
|
||||
}
|
||||
#else
|
||||
static secbool norcow_write(uint8_t sector, uint32_t offset, uint16_t key,
|
||||
const uint8_t *data, uint16_t len) {
|
||||
if (sector >= NORCOW_SECTOR_COUNT) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
uint16_t len_adjusted = ((len) + 0xF) & ~0xF;
|
||||
|
||||
if (offset + NORCOW_PREFIX_LEN + len_adjusted > NORCOW_SECTOR_SIZE) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
|
||||
uint32_t d[4];
|
||||
d[0] = key;
|
||||
d[1] = 0xFFFFFFFF;
|
||||
d[2] = 0xFFFFFFFF;
|
||||
d[3] = 0xFFFFFFFF;
|
||||
// write key
|
||||
ensure(flash_area_write_quadword(&STORAGE_AREAS[sector], offset, d), NULL);
|
||||
offset += NORCOW_WORD_SIZE;
|
||||
|
||||
d[0] = len;
|
||||
// write len
|
||||
ensure(flash_area_write_quadword(&STORAGE_AREAS[sector], offset, d), NULL);
|
||||
offset += NORCOW_WORD_SIZE;
|
||||
|
||||
if (data != NULL) {
|
||||
// write data
|
||||
for (uint16_t i = 0; i < len / NORCOW_WORD_SIZE;
|
||||
i++, offset += NORCOW_WORD_SIZE) {
|
||||
memcpy(d, data + i * NORCOW_WORD_SIZE, NORCOW_WORD_SIZE);
|
||||
ensure(flash_area_write_quadword(&STORAGE_AREAS[sector], offset, d),
|
||||
NULL);
|
||||
}
|
||||
|
||||
memset(d, 0, sizeof(d));
|
||||
// pad with zeroes
|
||||
for (uint16_t i = 0; i < len % NORCOW_WORD_SIZE; i++) {
|
||||
((uint8_t *)d)[i] = data[i + len - len % NORCOW_WORD_SIZE];
|
||||
}
|
||||
|
||||
if (len % NORCOW_WORD_SIZE != 0) {
|
||||
ensure(flash_area_write_quadword(&STORAGE_AREAS[sector], offset, d),
|
||||
NULL);
|
||||
}
|
||||
} else {
|
||||
offset += len;
|
||||
}
|
||||
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return sectrue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Erases sector (and sets a magic)
|
||||
@ -126,16 +199,36 @@ static void erase_sector(uint8_t sector, secbool set_magic) {
|
||||
#endif
|
||||
|
||||
if (sectrue == set_magic) {
|
||||
ensure(norcow_write(sector, NORCOW_HEADER_LEN, NORCOW_MAGIC, NULL, 0),
|
||||
"set magic failed");
|
||||
ensure(norcow_write(sector, NORCOW_HEADER_LEN + NORCOW_MAGIC_LEN,
|
||||
~NORCOW_VERSION, NULL, 0),
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
|
||||
ensure(flash_area_write_word(&STORAGE_AREAS[sector], NORCOW_HEADER_LEN,
|
||||
NORCOW_MAGIC),
|
||||
NULL);
|
||||
ensure(flash_area_write_word(&STORAGE_AREAS[sector],
|
||||
NORCOW_HEADER_LEN + NORCOW_MAGIC_LEN,
|
||||
~NORCOW_VERSION),
|
||||
"set version failed");
|
||||
ensure(flash_lock_write(), NULL);
|
||||
#else
|
||||
uint32_t d[4];
|
||||
d[0] = NORCOW_MAGIC;
|
||||
d[1] = ~NORCOW_VERSION;
|
||||
d[2] = 0xFFFFFFFF;
|
||||
d[3] = 0xFFFFFFFF;
|
||||
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
|
||||
ensure(
|
||||
flash_area_write_quadword(&STORAGE_AREAS[sector], NORCOW_HEADER_LEN, d),
|
||||
"set magic and version failed");
|
||||
|
||||
ensure(flash_lock_write(), NULL);
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#define ALIGN4(X) (X) = ((X) + 3) & ~3
|
||||
|
||||
/*
|
||||
* Reads one item starting from offset
|
||||
*/
|
||||
@ -145,7 +238,7 @@ static secbool read_item(uint8_t sector, uint32_t offset, uint16_t *key,
|
||||
|
||||
const void *k = norcow_ptr(sector, *pos, 2);
|
||||
if (k == NULL) return secfalse;
|
||||
*pos += 2;
|
||||
*pos += NORCOW_KEY_LEN;
|
||||
memcpy(key, k, sizeof(uint16_t));
|
||||
if (*key == NORCOW_KEY_FREE) {
|
||||
return secfalse;
|
||||
@ -153,13 +246,13 @@ static secbool read_item(uint8_t sector, uint32_t offset, uint16_t *key,
|
||||
|
||||
const void *l = norcow_ptr(sector, *pos, 2);
|
||||
if (l == NULL) return secfalse;
|
||||
*pos += 2;
|
||||
*pos += NORCOW_LEN_LEN;
|
||||
memcpy(len, l, sizeof(uint16_t));
|
||||
|
||||
*val = norcow_ptr(sector, *pos, *len);
|
||||
if (*val == NULL) return secfalse;
|
||||
*pos += *len;
|
||||
ALIGN4(*pos);
|
||||
ALIGN(*pos);
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
@ -168,10 +261,9 @@ static secbool read_item(uint8_t sector, uint32_t offset, uint16_t *key,
|
||||
*/
|
||||
static secbool write_item(uint8_t sector, uint32_t offset, uint16_t key,
|
||||
const void *val, uint16_t len, uint32_t *pos) {
|
||||
uint32_t prefix = ((uint32_t)len << 16) | key;
|
||||
*pos = offset + NORCOW_PREFIX_LEN + len;
|
||||
ALIGN4(*pos);
|
||||
return norcow_write(sector, offset, prefix, val, len);
|
||||
ALIGN(*pos);
|
||||
return norcow_write(sector, offset, key, val, len);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -417,6 +509,7 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len,
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
const flash_area_t *area = &STORAGE_AREAS[norcow_write_sector];
|
||||
secbool ret = secfalse;
|
||||
const void *ptr = NULL;
|
||||
uint16_t len_old = 0;
|
||||
@ -428,19 +521,20 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len,
|
||||
offset =
|
||||
(const uint8_t *)ptr -
|
||||
(const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE);
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
if (val != NULL && len_old == len) {
|
||||
ret = sectrue;
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
if (sectrue !=
|
||||
flash_area_write_byte(&STORAGE_AREAS[norcow_write_sector],
|
||||
offset + i, ((const uint8_t *)val)[i])) {
|
||||
if (sectrue != flash_area_write_byte(area, offset + i,
|
||||
((const uint8_t *)val)[i])) {
|
||||
ret = secfalse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ensure(flash_lock_write(), NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// If the update was not possible then write the entry as a new item.
|
||||
@ -449,18 +543,26 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len,
|
||||
if (sectrue == *found) {
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
// Update the prefix to indicate that the old item has been deleted.
|
||||
uint32_t prefix = (uint32_t)len_old << 16;
|
||||
ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector],
|
||||
offset - NORCOW_PREFIX_LEN, prefix),
|
||||
ensure(flash_area_write_word(area, offset - NORCOW_PREFIX_LEN, prefix),
|
||||
NULL);
|
||||
#else
|
||||
// Update the key to indicate that the old item has been deleted.
|
||||
uint32_t d[4] = {0};
|
||||
ensure(flash_area_write_quadword(area, offset - NORCOW_PREFIX_LEN, d),
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
// Delete the old item data.
|
||||
uint32_t end = offset + len_old;
|
||||
while (offset < end) {
|
||||
ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector],
|
||||
offset, 0x00000000),
|
||||
NULL);
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
ensure(flash_area_write_word(area, offset, 0x00000000), NULL);
|
||||
#else
|
||||
ensure(flash_area_write_quadword(area, offset, d), NULL);
|
||||
#endif
|
||||
offset += NORCOW_WORD_SIZE;
|
||||
}
|
||||
|
||||
@ -490,6 +592,7 @@ secbool norcow_delete(uint16_t key) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
const flash_area_t *area = &STORAGE_AREAS[norcow_write_sector];
|
||||
const void *ptr = NULL;
|
||||
uint16_t len = 0;
|
||||
if (sectrue != find_item(norcow_write_sector, key, &ptr, &len)) {
|
||||
@ -502,18 +605,24 @@ secbool norcow_delete(uint16_t key) {
|
||||
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
// Update the prefix to indicate that the item has been deleted.
|
||||
uint32_t prefix = (uint32_t)len << 16;
|
||||
ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector],
|
||||
offset - NORCOW_PREFIX_LEN, prefix),
|
||||
NULL);
|
||||
ensure(flash_area_write_word(area, offset - NORCOW_PREFIX_LEN, prefix), NULL);
|
||||
#else
|
||||
// Update the key to indicate that the old item has been deleted.
|
||||
uint32_t d[4] = {0};
|
||||
ensure(flash_area_write_quadword(area, offset - NORCOW_PREFIX_LEN, d), NULL);
|
||||
#endif
|
||||
|
||||
// Delete the item data.
|
||||
uint32_t end = offset + len;
|
||||
while (offset < end) {
|
||||
ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector], offset,
|
||||
0x00000000),
|
||||
NULL);
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
ensure(flash_area_write_word(area, offset, 0x00000000), NULL);
|
||||
#else
|
||||
ensure(flash_area_write_quadword(area, offset, d), NULL);
|
||||
#endif
|
||||
offset += NORCOW_WORD_SIZE;
|
||||
}
|
||||
|
||||
@ -522,6 +631,7 @@ secbool norcow_delete(uint16_t key) {
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
/*
|
||||
* Update a word in flash at the given pointer. The pointer must point
|
||||
* into the NORCOW area.
|
||||
@ -546,6 +656,7 @@ secbool norcow_update_word(uint16_t key, uint16_t offset, uint32_t value) {
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return sectrue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Update the value of the given key starting at the given offset.
|
||||
@ -564,12 +675,28 @@ secbool norcow_update_bytes(const uint16_t key, const uint16_t offset,
|
||||
(const uint8_t *)ptr -
|
||||
(const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE) +
|
||||
offset;
|
||||
const flash_area_t *area = &STORAGE_AREAS[norcow_write_sector];
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
for (uint16_t i = 0; i < len; i++, sector_offset++) {
|
||||
ensure(flash_area_write_byte(&STORAGE_AREAS[norcow_write_sector],
|
||||
sector_offset, data[i]),
|
||||
NULL);
|
||||
ensure(flash_area_write_byte(area, sector_offset, data[i]), NULL);
|
||||
}
|
||||
#else
|
||||
uint32_t d[4];
|
||||
for (uint16_t i = 0; i < len / 16; i++) {
|
||||
memcpy(d, data + i * 16, 16);
|
||||
ensure(flash_area_write_quadword(area, sector_offset, d), NULL);
|
||||
sector_offset += 16;
|
||||
}
|
||||
memset(d, 0, 16);
|
||||
// pad with zeroes
|
||||
for (uint16_t i = 0; i < len % 16; i++) {
|
||||
((uint8_t *)d)[i] = data[i + len - len % 16];
|
||||
}
|
||||
if (len % 16 != 0) {
|
||||
ensure(flash_area_write_quadword(area, sector_offset, d), NULL);
|
||||
}
|
||||
#endif
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return sectrue;
|
||||
}
|
||||
|
@ -65,11 +65,13 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len,
|
||||
*/
|
||||
secbool norcow_delete(uint16_t key);
|
||||
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
/*
|
||||
* Update a word in flash in the given key at the given offset.
|
||||
* Note that you can only change bits from 1 to 0.
|
||||
*/
|
||||
secbool norcow_update_word(uint16_t key, uint16_t offset, uint32_t value);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Update the value of the given key starting at the given offset.
|
||||
|
@ -126,6 +126,12 @@ const uint32_t V0_PIN_EMPTY = 1;
|
||||
// The length of the ChaCha20 IV (aka nonce) in bytes as per RFC 7539.
|
||||
#define CHACHA20_IV_SIZE 12
|
||||
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
#define CHACHA20_IV_PADDING 0
|
||||
#else
|
||||
#define CHACHA20_IV_PADDING 4
|
||||
#endif
|
||||
|
||||
// The length of the ChaCha20 block in bytes.
|
||||
#define CHACHA20_BLOCK_SIZE 64
|
||||
|
||||
@ -145,7 +151,11 @@ const uint8_t WIPE_CODE_EMPTY[] = {0, 0, 0, 0};
|
||||
#define V2_WIPE_CODE_EMPTY 0
|
||||
|
||||
// The length of the counter tail in words.
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
#define COUNTER_TAIL_WORDS 2
|
||||
#else
|
||||
#define COUNTER_TAIL_WORDS 0
|
||||
#endif
|
||||
|
||||
// Values used in the guard key integrity check.
|
||||
#define GUARD_KEY_MODULUS 6311
|
||||
@ -404,19 +414,22 @@ static secbool set_wipe_code(const uint8_t *wipe_code, size_t wipe_code_len) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
uint32_t data[(MAX_WIPE_CODE_LEN + WIPE_CODE_SALT_SIZE + WIPE_CODE_TAG_SIZE) /
|
||||
sizeof(uint32_t)] = {0};
|
||||
|
||||
memcpy((uint8_t *)data, wipe_code, wipe_code_len);
|
||||
memcpy((uint8_t *)data + wipe_code_len, salt_and_tag,
|
||||
WIPE_CODE_SALT_SIZE + WIPE_CODE_TAG_SIZE);
|
||||
|
||||
// Write wipe code into the preallocated entry.
|
||||
if (sectrue !=
|
||||
norcow_update_bytes(WIPE_CODE_DATA_KEY, 0, wipe_code, wipe_code_len)) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
// Write salt and tag into the preallocated entry.
|
||||
if (sectrue !=
|
||||
norcow_update_bytes(WIPE_CODE_DATA_KEY, wipe_code_len, salt_and_tag,
|
||||
WIPE_CODE_SALT_SIZE + WIPE_CODE_TAG_SIZE)) {
|
||||
if (sectrue != norcow_update_bytes(WIPE_CODE_DATA_KEY, 0, (uint8_t *)data,
|
||||
wipe_code_len + WIPE_CODE_SALT_SIZE +
|
||||
WIPE_CODE_TAG_SIZE)) {
|
||||
memzero(data, sizeof(data));
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
memzero(data, sizeof(data));
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
@ -710,6 +723,12 @@ static secbool pin_fails_reset(void) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
#ifndef FLASH_BYTE_ACCESS
|
||||
uint32_t new_logs[GUARD_KEY_WORDS + 2 * PIN_LOG_WORDS];
|
||||
secbool edited = secfalse;
|
||||
memcpy(new_logs, logs, len);
|
||||
#endif
|
||||
|
||||
uint32_t guard_mask = 0;
|
||||
uint32_t guard = 0;
|
||||
wait_random();
|
||||
@ -723,16 +742,35 @@ static secbool pin_fails_reset(void) {
|
||||
const uint32_t *entry_log = success_log + PIN_LOG_WORDS;
|
||||
for (size_t i = 0; i < PIN_LOG_WORDS; ++i) {
|
||||
if (entry_log[i] == unused) {
|
||||
#ifndef FLASH_BYTE_ACCESS
|
||||
if (edited == sectrue) {
|
||||
return norcow_set(PIN_LOGS_KEY, new_logs, sizeof(new_logs));
|
||||
}
|
||||
#endif
|
||||
return sectrue;
|
||||
}
|
||||
if (success_log[i] != guard) {
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
if (sectrue != norcow_update_word(
|
||||
PIN_LOGS_KEY, sizeof(uint32_t) * (i + GUARD_KEY_WORDS),
|
||||
entry_log[i])) {
|
||||
return secfalse;
|
||||
}
|
||||
#else
|
||||
if (new_logs[(i + GUARD_KEY_WORDS)] != entry_log[i]) {
|
||||
edited = sectrue;
|
||||
new_logs[(i + GUARD_KEY_WORDS)] = entry_log[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifndef FLASH_BYTE_ACCESS
|
||||
if (edited == sectrue) {
|
||||
if (sectrue != norcow_set(PIN_LOGS_KEY, new_logs, sizeof(new_logs))) {
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return pin_logs_init(0);
|
||||
}
|
||||
|
||||
@ -751,6 +789,11 @@ secbool storage_pin_fails_increase(void) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
#ifndef FLASH_BYTE_ACCESS
|
||||
uint32_t new_logs[GUARD_KEY_WORDS + 2 * PIN_LOG_WORDS];
|
||||
memcpy(new_logs, logs, len);
|
||||
#endif
|
||||
|
||||
uint32_t guard_mask = 0;
|
||||
uint32_t guard = 0;
|
||||
wait_random();
|
||||
@ -775,6 +818,7 @@ secbool storage_pin_fails_increase(void) {
|
||||
word = (word >> 2) | (word >> 1);
|
||||
|
||||
wait_random();
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
if (sectrue !=
|
||||
norcow_update_word(
|
||||
PIN_LOGS_KEY,
|
||||
@ -783,6 +827,14 @@ secbool storage_pin_fails_increase(void) {
|
||||
handle_fault("PIN logs update");
|
||||
return secfalse;
|
||||
}
|
||||
#else
|
||||
new_logs[(i + GUARD_KEY_WORDS + PIN_LOG_WORDS)] =
|
||||
(word & ~guard_mask) | guard;
|
||||
if (sectrue != norcow_set(PIN_LOGS_KEY, new_logs, sizeof(new_logs))) {
|
||||
handle_fault("PIN logs update");
|
||||
return secfalse;
|
||||
}
|
||||
#endif
|
||||
return sectrue;
|
||||
}
|
||||
}
|
||||
@ -1145,11 +1197,11 @@ static secbool storage_get_encrypted(const uint16_t key, void *val_dest,
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
if (*len < CHACHA20_IV_SIZE + POLY1305_TAG_SIZE) {
|
||||
if (*len < CHACHA20_IV_SIZE + CHACHA20_IV_PADDING + POLY1305_TAG_SIZE) {
|
||||
handle_fault("ciphertext length check");
|
||||
return secfalse;
|
||||
}
|
||||
*len -= CHACHA20_IV_SIZE + POLY1305_TAG_SIZE;
|
||||
*len -= CHACHA20_IV_SIZE + CHACHA20_IV_PADDING + POLY1305_TAG_SIZE;
|
||||
|
||||
if (val_dest == NULL) {
|
||||
return sectrue;
|
||||
@ -1160,9 +1212,10 @@ static secbool storage_get_encrypted(const uint16_t key, void *val_dest,
|
||||
}
|
||||
|
||||
const uint8_t *iv = (const uint8_t *)val_stored;
|
||||
const uint8_t *tag_stored = (const uint8_t *)val_stored + CHACHA20_IV_SIZE;
|
||||
const uint8_t *ciphertext =
|
||||
(const uint8_t *)val_stored + CHACHA20_IV_SIZE + POLY1305_TAG_SIZE;
|
||||
const uint8_t *tag_stored =
|
||||
(const uint8_t *)val_stored + CHACHA20_IV_SIZE + CHACHA20_IV_PADDING;
|
||||
const uint8_t *ciphertext = (const uint8_t *)val_stored + CHACHA20_IV_SIZE +
|
||||
CHACHA20_IV_PADDING + POLY1305_TAG_SIZE;
|
||||
uint8_t tag_computed[POLY1305_TAG_SIZE] = {0};
|
||||
chacha20poly1305_ctx ctx = {0};
|
||||
rfc7539_init(&ctx, cached_dek, iv);
|
||||
@ -1229,24 +1282,27 @@ secbool storage_get(const uint16_t key, void *val_dest, const uint16_t max_len,
|
||||
*/
|
||||
static secbool storage_set_encrypted(const uint16_t key, const void *val,
|
||||
const uint16_t len) {
|
||||
if (len > UINT16_MAX - CHACHA20_IV_SIZE - POLY1305_TAG_SIZE) {
|
||||
if (len >
|
||||
UINT16_MAX - CHACHA20_IV_SIZE - CHACHA20_IV_PADDING - POLY1305_TAG_SIZE) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
// Preallocate space on the flash storage.
|
||||
if (sectrue !=
|
||||
auth_set(key, NULL, CHACHA20_IV_SIZE + POLY1305_TAG_SIZE + len)) {
|
||||
if (sectrue != auth_set(key, NULL,
|
||||
CHACHA20_IV_SIZE + CHACHA20_IV_PADDING +
|
||||
POLY1305_TAG_SIZE + len)) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
// Write the IV to the flash.
|
||||
uint8_t buffer[CHACHA20_BLOCK_SIZE] = {0};
|
||||
uint8_t buffer[CHACHA20_BLOCK_SIZE + CHACHA20_IV_PADDING] = {0};
|
||||
random_buffer(buffer, CHACHA20_IV_SIZE);
|
||||
uint16_t offset = 0;
|
||||
if (sectrue != norcow_update_bytes(key, offset, buffer, CHACHA20_IV_SIZE)) {
|
||||
if (sectrue != norcow_update_bytes(key, offset, buffer,
|
||||
CHACHA20_IV_SIZE + CHACHA20_IV_PADDING)) {
|
||||
return secfalse;
|
||||
}
|
||||
offset += CHACHA20_IV_SIZE + POLY1305_TAG_SIZE;
|
||||
offset += CHACHA20_IV_SIZE + CHACHA20_IV_PADDING + POLY1305_TAG_SIZE;
|
||||
|
||||
// Encrypt all blocks except for the last one.
|
||||
chacha20poly1305_ctx ctx = {0};
|
||||
@ -1270,7 +1326,8 @@ static secbool storage_set_encrypted(const uint16_t key, const void *val,
|
||||
secbool ret = norcow_update_bytes(key, offset, buffer, len - i);
|
||||
if (sectrue == ret) {
|
||||
rfc7539_finish(&ctx, sizeof(key), len, buffer);
|
||||
ret = norcow_update_bytes(key, CHACHA20_IV_SIZE, buffer, POLY1305_TAG_SIZE);
|
||||
ret = norcow_update_bytes(key, CHACHA20_IV_SIZE + CHACHA20_IV_PADDING,
|
||||
buffer, POLY1305_TAG_SIZE);
|
||||
}
|
||||
memzero(&ctx, sizeof(ctx));
|
||||
memzero(buffer, sizeof(buffer));
|
||||
@ -1372,7 +1429,11 @@ secbool storage_next_counter(const uint16_t key, uint32_t *count) {
|
||||
// Value overflow.
|
||||
return secfalse;
|
||||
}
|
||||
#ifdef FLASH_BYTE_ACCESS
|
||||
return norcow_update_word(key, sizeof(uint32_t) * i, val_stored[i] >> 1);
|
||||
#else
|
||||
return storage_set_counter(key, *count);
|
||||
#endif
|
||||
} else {
|
||||
return storage_set_counter(key, *count);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user