1
0
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:
andrew 2019-02-08 20:24:55 +01:00
parent 18fa999974
commit 5c2765740d
2 changed files with 60 additions and 1 deletions

View File

@ -105,6 +105,9 @@
// The length of the ChaCha20 block in bytes. // The length of the ChaCha20 block in bytes.
#define CHACHA20_BLOCK_SIZE 64 #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. // Values used in the guard key integrity check.
#define GUARD_KEY_MODULUS 6311 #define GUARD_KEY_MODULUS 6311
#define GUARD_KEY_REMAINDER 15 #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; 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; secbool ret = secfalse;
if ((app & FLAG_PUBLIC) != 0) { if ((app & FLAG_PUBLIC) != 0) {
const void *val_stored = NULL; const void *val_stored = NULL;
@ -967,6 +970,60 @@ secbool storage_delete(const uint16_t key)
return ret; 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) secbool storage_has_pin(void)
{ {
if (sectrue != initialized) { if (sectrue != initialized) {

View File

@ -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_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_set(const uint16_t key, const void *val, uint16_t len);
secbool storage_delete(const uint16_t key); 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 #endif