mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 22:38:08 +00:00
Add efficient counter implementation.
This commit is contained in:
parent
18fa999974
commit
5c2765740d
59
storage.c
59
storage.c
@ -105,6 +105,9 @@
|
||||
// The length of the ChaCha20 block in bytes.
|
||||
#define CHACHA20_BLOCK_SIZE 64
|
||||
|
||||
// The length of the counter tail in bytes.
|
||||
#define COUNTER_TAIL_LEN 8
|
||||
|
||||
// Values used in the guard key integrity check.
|
||||
#define GUARD_KEY_MODULUS 6311
|
||||
#define GUARD_KEY_REMAINDER 15
|
||||
@ -858,7 +861,7 @@ secbool storage_get(const uint16_t key, void *val_dest, const uint16_t max_len,
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
// If the top bit of APP is set, then the value is not encrypted and can be read from an unlocked device.
|
||||
// If the top bit of APP is set, then the value is not encrypted and can be read from a locked device.
|
||||
secbool ret = secfalse;
|
||||
if ((app & FLAG_PUBLIC) != 0) {
|
||||
const void *val_stored = NULL;
|
||||
@ -967,6 +970,60 @@ secbool storage_delete(const uint16_t key)
|
||||
return ret;
|
||||
}
|
||||
|
||||
secbool storage_set_counter(const uint16_t key, const uint32_t count)
|
||||
{
|
||||
const uint8_t app = key >> 8;
|
||||
if ((app & FLAG_PUBLIC) == 0) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
// The count is stored as a 32-bit integer followed by a tail of "1" bits,
|
||||
// which is used as a tally.
|
||||
uint8_t value[sizeof(count) + COUNTER_TAIL_LEN];
|
||||
memset(value, 0xff, sizeof(value));
|
||||
*((uint32_t*)value) = count;
|
||||
return storage_set(key, value, sizeof(value));
|
||||
}
|
||||
|
||||
secbool storage_next_counter(const uint16_t key, uint32_t *count)
|
||||
{
|
||||
const uint8_t app = key >> 8;
|
||||
// APP == 0 is reserved for PIN related values
|
||||
if (sectrue != initialized || app == APP_STORAGE || (app & FLAG_PUBLIC) == 0) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
if (sectrue != unlocked && (app & FLAGS_WRITE) != FLAGS_WRITE) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
uint16_t len = 0;
|
||||
const uint32_t *val_stored = NULL;
|
||||
if (sectrue != norcow_get(key, (const void**)&val_stored, &len)) {
|
||||
*count = 0;
|
||||
return storage_set_counter(key, 0);
|
||||
}
|
||||
|
||||
if (len < sizeof(uint32_t) || len % sizeof(uint32_t) != 0) {
|
||||
return secfalse;
|
||||
}
|
||||
uint16_t len_words = len / sizeof(uint32_t);
|
||||
|
||||
uint16_t i = 1;
|
||||
while (i < len_words && val_stored[i] == 0) {
|
||||
++i;
|
||||
}
|
||||
|
||||
*count = val_stored[0] + 1 + 32 * (i - 1);
|
||||
|
||||
if (i < len_words) {
|
||||
*count += hamming_weight(~val_stored[i]);
|
||||
return norcow_update_word(key, sizeof(uint32_t) * i, val_stored[i] >> 1);
|
||||
} else {
|
||||
return storage_set_counter(key, *count);
|
||||
}
|
||||
}
|
||||
|
||||
secbool storage_has_pin(void)
|
||||
{
|
||||
if (sectrue != initialized) {
|
||||
|
@ -38,5 +38,7 @@ secbool storage_change_pin(const uint32_t oldpin, const uint32_t newpin);
|
||||
secbool storage_get(const uint16_t key, void *val, const uint16_t max_len, uint16_t *len);
|
||||
secbool storage_set(const uint16_t key, const void *val, uint16_t len);
|
||||
secbool storage_delete(const uint16_t key);
|
||||
secbool storage_set_counter(const uint16_t key, const uint32_t count);
|
||||
secbool storage_next_counter(const uint16_t key, uint32_t *count);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user