1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-18 12:28:09 +00:00

fix(storage): Check for overflow in counter increment.

This commit is contained in:
Andrew Kozlik 2021-03-11 14:00:51 +01:00 committed by Andrew Kozlik
parent 2836bfc64c
commit 4c2e4bcb65
5 changed files with 40 additions and 7 deletions

View File

@ -1363,9 +1363,17 @@ secbool storage_next_counter(const uint16_t key, uint32_t *count) {
}
*count = val_stored[0] + 1 + 32 * (i - 1);
if (*count < val_stored[0]) {
// Value overflow.
return secfalse;
}
if (i < len_words) {
*count += hamming_weight(~val_stored[i]);
if (*count < val_stored[0]) {
// Value overflow.
return secfalse;
}
return norcow_update_word(key, sizeof(uint32_t) * i, val_stored[i] >> 1);
} else {
return storage_set_counter(key, *count);

View File

@ -70,17 +70,17 @@ class Storage:
if sectrue != self.lib.storage_set(c.c_uint16(key), val, c.c_uint16(len(val))):
raise RuntimeError("Failed to set value in storage.")
def set_counter(self, key: int, count: int) -> bool:
return sectrue == self.lib.storage_set_counter(
def set_counter(self, key: int, count: int) -> None:
if count > 0xFFFF_FFFF or sectrue != self.lib.storage_set_counter(
c.c_uint16(key), c.c_uint32(count)
)
):
raise RuntimeError("Failed to set value in storage.")
def next_counter(self, key: int) -> int:
count = c.c_uint32()
if sectrue == self.lib.storage_next_counter(c.c_uint16(key), c.byref(count)):
return count.value
else:
return None
if sectrue != self.lib.storage_next_counter(c.c_uint16(key), c.byref(count)):
raise RuntimeError("Failed to set value in storage.")
return count.value
def delete(self, key: int) -> bool:
return sectrue == self.lib.storage_delete(c.c_uint16(key))

View File

@ -1,3 +1,6 @@
# ----- General ----- #
UINT32_MAX = 0xFFFF_FFFF
# ----- PIN and encryption related ----- #
# App ID where PIN log is stored.

View File

@ -149,6 +149,10 @@ class Storage:
app = key >> 8
if not consts.is_app_public(app):
raise RuntimeError("Counter can be set only for public items")
if val > consts.UINT32_MAX:
raise RuntimeError("Failed to set value in storage.")
counter = val.to_bytes(4, sys.byteorder) + bytearray(
b"\xFF" * consts.COUNTER_TAIL_SIZE
)
@ -167,6 +171,8 @@ class Storage:
tail = helpers.to_int_by_words(current[4:])
tail_count = "{0:064b}".format(tail).count("0")
increased_count = base + tail_count + 1
if increased_count > consts.UINT32_MAX:
raise RuntimeError("Failed to set value in storage.")
if tail_count == consts.COUNTER_MAX_TAIL:
self.set_counter(key, increased_count)

View File

@ -1,5 +1,7 @@
import pytest
from python.src import consts
from . import common
# Strings for testing ChaCha20 encryption.
@ -183,3 +185,17 @@ def test_counter():
for s in (sc, sp):
assert i == s.next_counter(0xC001)
assert common.memory_equals(sc, sp)
for s in (sc, sp):
with pytest.raises(RuntimeError):
s.set_counter(0xC001, consts.UINT32_MAX + 1)
start = consts.UINT32_MAX - 100
s.set_counter(0xC001, start)
for i in range(start, consts.UINT32_MAX):
assert i + 1 == s.next_counter(0xC001)
with pytest.raises(RuntimeError):
s.next_counter(0xC001)
assert common.memory_equals(sc, sp)