mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 04:18:10 +00:00
fix(storage): Check for overflow in counter increment.
This commit is contained in:
parent
2836bfc64c
commit
4c2e4bcb65
@ -1363,9 +1363,17 @@ secbool storage_next_counter(const uint16_t key, uint32_t *count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
*count = val_stored[0] + 1 + 32 * (i - 1);
|
*count = val_stored[0] + 1 + 32 * (i - 1);
|
||||||
|
if (*count < val_stored[0]) {
|
||||||
|
// Value overflow.
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
|
||||||
if (i < len_words) {
|
if (i < len_words) {
|
||||||
*count += hamming_weight(~val_stored[i]);
|
*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);
|
return norcow_update_word(key, sizeof(uint32_t) * i, val_stored[i] >> 1);
|
||||||
} else {
|
} else {
|
||||||
return storage_set_counter(key, *count);
|
return storage_set_counter(key, *count);
|
||||||
|
@ -70,17 +70,17 @@ class Storage:
|
|||||||
if sectrue != self.lib.storage_set(c.c_uint16(key), val, c.c_uint16(len(val))):
|
if sectrue != self.lib.storage_set(c.c_uint16(key), val, c.c_uint16(len(val))):
|
||||||
raise RuntimeError("Failed to set value in storage.")
|
raise RuntimeError("Failed to set value in storage.")
|
||||||
|
|
||||||
def set_counter(self, key: int, count: int) -> bool:
|
def set_counter(self, key: int, count: int) -> None:
|
||||||
return sectrue == self.lib.storage_set_counter(
|
if count > 0xFFFF_FFFF or sectrue != self.lib.storage_set_counter(
|
||||||
c.c_uint16(key), c.c_uint32(count)
|
c.c_uint16(key), c.c_uint32(count)
|
||||||
)
|
):
|
||||||
|
raise RuntimeError("Failed to set value in storage.")
|
||||||
|
|
||||||
def next_counter(self, key: int) -> int:
|
def next_counter(self, key: int) -> int:
|
||||||
count = c.c_uint32()
|
count = c.c_uint32()
|
||||||
if sectrue == self.lib.storage_next_counter(c.c_uint16(key), c.byref(count)):
|
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
|
return count.value
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def delete(self, key: int) -> bool:
|
def delete(self, key: int) -> bool:
|
||||||
return sectrue == self.lib.storage_delete(c.c_uint16(key))
|
return sectrue == self.lib.storage_delete(c.c_uint16(key))
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
# ----- General ----- #
|
||||||
|
UINT32_MAX = 0xFFFF_FFFF
|
||||||
|
|
||||||
# ----- PIN and encryption related ----- #
|
# ----- PIN and encryption related ----- #
|
||||||
|
|
||||||
# App ID where PIN log is stored.
|
# App ID where PIN log is stored.
|
||||||
|
@ -149,6 +149,10 @@ class Storage:
|
|||||||
app = key >> 8
|
app = key >> 8
|
||||||
if not consts.is_app_public(app):
|
if not consts.is_app_public(app):
|
||||||
raise RuntimeError("Counter can be set only for public items")
|
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(
|
counter = val.to_bytes(4, sys.byteorder) + bytearray(
|
||||||
b"\xFF" * consts.COUNTER_TAIL_SIZE
|
b"\xFF" * consts.COUNTER_TAIL_SIZE
|
||||||
)
|
)
|
||||||
@ -167,6 +171,8 @@ class Storage:
|
|||||||
tail = helpers.to_int_by_words(current[4:])
|
tail = helpers.to_int_by_words(current[4:])
|
||||||
tail_count = "{0:064b}".format(tail).count("0")
|
tail_count = "{0:064b}".format(tail).count("0")
|
||||||
increased_count = base + tail_count + 1
|
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:
|
if tail_count == consts.COUNTER_MAX_TAIL:
|
||||||
self.set_counter(key, increased_count)
|
self.set_counter(key, increased_count)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from python.src import consts
|
||||||
|
|
||||||
from . import common
|
from . import common
|
||||||
|
|
||||||
# Strings for testing ChaCha20 encryption.
|
# Strings for testing ChaCha20 encryption.
|
||||||
@ -183,3 +185,17 @@ def test_counter():
|
|||||||
for s in (sc, sp):
|
for s in (sc, sp):
|
||||||
assert i == s.next_counter(0xC001)
|
assert i == s.next_counter(0xC001)
|
||||||
assert common.memory_equals(sc, sp)
|
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user