mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 07:28:10 +00:00
storage: Add external salt parameter to unlock() and change_pin().
This commit is contained in:
parent
69d936a390
commit
4f01003637
@ -67,30 +67,41 @@ STATIC mp_obj_t mod_trezorconfig_init(size_t n_args, const mp_obj_t *args) {
|
|||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_init_obj, 0, 1,
|
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_init_obj, 0, 1,
|
||||||
mod_trezorconfig_init);
|
mod_trezorconfig_init);
|
||||||
|
|
||||||
/// def unlock(pin: int) -> bool:
|
/// def unlock(pin: int, ext_salt: Optional[bytes] = None) -> bool:
|
||||||
/// """
|
/// """
|
||||||
/// Attempts to unlock the storage with given PIN. Returns True on
|
/// Attempts to unlock the storage with the given PIN and external salt.
|
||||||
/// success, False on failure.
|
/// Returns True on success, False on failure.
|
||||||
/// """
|
/// """
|
||||||
STATIC mp_obj_t mod_trezorconfig_unlock(mp_obj_t pin) {
|
STATIC mp_obj_t mod_trezorconfig_unlock(size_t n_args, const mp_obj_t *args) {
|
||||||
uint32_t pin_i = trezor_obj_get_uint(pin);
|
uint32_t pin = trezor_obj_get_uint(args[0]);
|
||||||
if (sectrue != storage_unlock(pin_i)) {
|
const uint8_t *ext_salt = NULL;
|
||||||
|
if (n_args > 1 && args[1] != mp_const_none) {
|
||||||
|
mp_buffer_info_t ext_salt_b;
|
||||||
|
mp_get_buffer_raise(args[1], &ext_salt_b, MP_BUFFER_READ);
|
||||||
|
if (ext_salt_b.len != EXTERNAL_SALT_SIZE)
|
||||||
|
mp_raise_msg(&mp_type_ValueError, "Invalid length of external salt.");
|
||||||
|
ext_salt = ext_salt_b.buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sectrue != storage_unlock(pin, ext_salt)) {
|
||||||
return mp_const_false;
|
return mp_const_false;
|
||||||
}
|
}
|
||||||
return mp_const_true;
|
return mp_const_true;
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorconfig_unlock_obj,
|
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_unlock_obj, 1, 2,
|
||||||
mod_trezorconfig_unlock);
|
mod_trezorconfig_unlock);
|
||||||
|
|
||||||
/// def check_pin(pin: int) -> bool:
|
/// def check_pin(pin: int, ext_salt: Optional[bytes] = None) -> bool:
|
||||||
/// """
|
/// """
|
||||||
/// Check the given PIN. Returns True on success, False on failure.
|
/// Check the given PIN with the given external salt.
|
||||||
|
/// Returns True on success, False on failure.
|
||||||
/// """
|
/// """
|
||||||
STATIC mp_obj_t mod_trezorconfig_check_pin(mp_obj_t pin) {
|
STATIC mp_obj_t mod_trezorconfig_check_pin(size_t n_args,
|
||||||
return mod_trezorconfig_unlock(pin);
|
const mp_obj_t *args) {
|
||||||
|
return mod_trezorconfig_unlock(n_args, args);
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorconfig_check_pin_obj,
|
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_check_pin_obj, 1, 2,
|
||||||
mod_trezorconfig_check_pin);
|
mod_trezorconfig_check_pin);
|
||||||
|
|
||||||
/// def lock() -> None:
|
/// def lock() -> None:
|
||||||
/// """
|
/// """
|
||||||
@ -126,20 +137,43 @@ STATIC mp_obj_t mod_trezorconfig_get_pin_rem(void) {
|
|||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_get_pin_rem_obj,
|
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_get_pin_rem_obj,
|
||||||
mod_trezorconfig_get_pin_rem);
|
mod_trezorconfig_get_pin_rem);
|
||||||
|
|
||||||
/// def change_pin(pin: int, newpin: int) -> bool:
|
/// def change_pin(
|
||||||
|
/// oldpin: int,
|
||||||
|
/// newpin: int,
|
||||||
|
/// old_ext_salt: Optional[bytes] = None,
|
||||||
|
/// new_ext_salt: Optional[bytes] = None,
|
||||||
|
/// ) -> bool:
|
||||||
/// """
|
/// """
|
||||||
/// Change PIN. Returns True on success, False on failure.
|
/// Change PIN and external salt. Returns True on success, False on failure.
|
||||||
/// """
|
/// """
|
||||||
STATIC mp_obj_t mod_trezorconfig_change_pin(mp_obj_t pin, mp_obj_t newpin) {
|
STATIC mp_obj_t mod_trezorconfig_change_pin(size_t n_args,
|
||||||
uint32_t pin_i = trezor_obj_get_uint(pin);
|
const mp_obj_t *args) {
|
||||||
uint32_t newpin_i = trezor_obj_get_uint(newpin);
|
uint32_t oldpin = trezor_obj_get_uint(args[0]);
|
||||||
if (sectrue != storage_change_pin(pin_i, newpin_i)) {
|
uint32_t newpin = trezor_obj_get_uint(args[1]);
|
||||||
|
mp_buffer_info_t ext_salt_b;
|
||||||
|
const uint8_t *old_ext_salt = NULL;
|
||||||
|
if (n_args > 2 && args[2] != mp_const_none) {
|
||||||
|
mp_get_buffer_raise(args[2], &ext_salt_b, MP_BUFFER_READ);
|
||||||
|
if (ext_salt_b.len != EXTERNAL_SALT_SIZE)
|
||||||
|
mp_raise_msg(&mp_type_ValueError, "Invalid length of external salt.");
|
||||||
|
old_ext_salt = ext_salt_b.buf;
|
||||||
|
}
|
||||||
|
const uint8_t *new_ext_salt = NULL;
|
||||||
|
if (n_args > 3 && args[3] != mp_const_none) {
|
||||||
|
mp_get_buffer_raise(args[3], &ext_salt_b, MP_BUFFER_READ);
|
||||||
|
if (ext_salt_b.len != EXTERNAL_SALT_SIZE)
|
||||||
|
mp_raise_msg(&mp_type_ValueError, "Invalid length of external salt.");
|
||||||
|
new_ext_salt = ext_salt_b.buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sectrue !=
|
||||||
|
storage_change_pin(oldpin, newpin, old_ext_salt, new_ext_salt)) {
|
||||||
return mp_const_false;
|
return mp_const_false;
|
||||||
}
|
}
|
||||||
return mp_const_true;
|
return mp_const_true;
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorconfig_change_pin_obj,
|
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_change_pin_obj, 2,
|
||||||
mod_trezorconfig_change_pin);
|
4, mod_trezorconfig_change_pin);
|
||||||
|
|
||||||
/// def get(app: int, key: int, public: bool = False) -> Optional[bytes]:
|
/// def get(app: int, key: int, public: bool = False) -> Optional[bytes]:
|
||||||
/// """
|
/// """
|
||||||
|
@ -12,17 +12,18 @@ def init(
|
|||||||
|
|
||||||
|
|
||||||
# extmod/modtrezorconfig/modtrezorconfig.c
|
# extmod/modtrezorconfig/modtrezorconfig.c
|
||||||
def unlock(pin: int) -> bool:
|
def unlock(pin: int, ext_salt: Optional[bytes] = None) -> bool:
|
||||||
"""
|
"""
|
||||||
Attempts to unlock the storage with given PIN. Returns True on
|
Attempts to unlock the storage with the given PIN and external salt.
|
||||||
success, False on failure.
|
Returns True on success, False on failure.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
# extmod/modtrezorconfig/modtrezorconfig.c
|
# extmod/modtrezorconfig/modtrezorconfig.c
|
||||||
def check_pin(pin: int) -> bool:
|
def check_pin(pin: int, ext_salt: Optional[bytes] = None) -> bool:
|
||||||
"""
|
"""
|
||||||
Check the given PIN. Returns True on success, False on failure.
|
Check the given PIN with the given external salt.
|
||||||
|
Returns True on success, False on failure.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@ -48,9 +49,14 @@ def get_pin_rem() -> int:
|
|||||||
|
|
||||||
|
|
||||||
# extmod/modtrezorconfig/modtrezorconfig.c
|
# extmod/modtrezorconfig/modtrezorconfig.c
|
||||||
def change_pin(pin: int, newpin: int) -> bool:
|
def change_pin(
|
||||||
|
oldpin: int,
|
||||||
|
newpin: int,
|
||||||
|
old_ext_salt: Optional[bytes] = None,
|
||||||
|
new_ext_salt: Optional[bytes] = None,
|
||||||
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Change PIN. Returns True on success, False on failure.
|
Change PIN and external salt. Returns True on success, False on failure.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -316,9 +316,9 @@ static secbool config_upgrade_v10(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
storage_init(NULL, HW_ENTROPY_DATA, HW_ENTROPY_LEN);
|
storage_init(NULL, HW_ENTROPY_DATA, HW_ENTROPY_LEN);
|
||||||
storage_unlock(PIN_EMPTY);
|
storage_unlock(PIN_EMPTY, NULL);
|
||||||
if (config.has_pin) {
|
if (config.has_pin) {
|
||||||
storage_change_pin(PIN_EMPTY, pin_to_int(config.pin));
|
storage_change_pin(PIN_EMPTY, pin_to_int(config.pin), NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (pin_wait != 0) {
|
while (pin_wait != 0) {
|
||||||
@ -386,7 +386,7 @@ void config_init(void) {
|
|||||||
|
|
||||||
// Auto-unlock storage if no PIN is set.
|
// Auto-unlock storage if no PIN is set.
|
||||||
if (storage_is_unlocked() == secfalse && storage_has_pin() == secfalse) {
|
if (storage_is_unlocked() == secfalse && storage_has_pin() == secfalse) {
|
||||||
storage_unlock(PIN_EMPTY);
|
storage_unlock(PIN_EMPTY, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
@ -759,7 +759,7 @@ bool config_containsMnemonic(const char *mnemonic) {
|
|||||||
*/
|
*/
|
||||||
bool config_unlock(const char *pin) {
|
bool config_unlock(const char *pin) {
|
||||||
char oldTiny = usbTiny(1);
|
char oldTiny = usbTiny(1);
|
||||||
secbool ret = storage_unlock(pin_to_int(pin));
|
secbool ret = storage_unlock(pin_to_int(pin), NULL);
|
||||||
usbTiny(oldTiny);
|
usbTiny(oldTiny);
|
||||||
return sectrue == ret;
|
return sectrue == ret;
|
||||||
}
|
}
|
||||||
@ -773,7 +773,8 @@ bool config_changePin(const char *old_pin, const char *new_pin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char oldTiny = usbTiny(1);
|
char oldTiny = usbTiny(1);
|
||||||
secbool ret = storage_change_pin(pin_to_int(old_pin), new_pin_int);
|
secbool ret =
|
||||||
|
storage_change_pin(pin_to_int(old_pin), new_pin_int, NULL, NULL);
|
||||||
usbTiny(oldTiny);
|
usbTiny(oldTiny);
|
||||||
|
|
||||||
#if DEBUG_LINK
|
#if DEBUG_LINK
|
||||||
@ -925,7 +926,7 @@ void config_wipe(void) {
|
|||||||
char oldTiny = usbTiny(1);
|
char oldTiny = usbTiny(1);
|
||||||
storage_wipe();
|
storage_wipe();
|
||||||
if (storage_is_unlocked() != sectrue) {
|
if (storage_is_unlocked() != sectrue) {
|
||||||
storage_unlock(PIN_EMPTY);
|
storage_unlock(PIN_EMPTY, NULL);
|
||||||
}
|
}
|
||||||
usbTiny(oldTiny);
|
usbTiny(oldTiny);
|
||||||
random_buffer((uint8_t *)config_uuid, sizeof(config_uuid));
|
random_buffer((uint8_t *)config_uuid, sizeof(config_uuid));
|
||||||
|
@ -331,15 +331,26 @@ static secbool auth_get(uint16_t key, const void **val, uint16_t *len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void derive_kek(uint32_t pin, const uint8_t *random_salt,
|
static void derive_kek(uint32_t pin, const uint8_t *random_salt,
|
||||||
|
const uint8_t *ext_salt,
|
||||||
uint8_t kek[SHA256_DIGEST_LENGTH],
|
uint8_t kek[SHA256_DIGEST_LENGTH],
|
||||||
uint8_t keiv[SHA256_DIGEST_LENGTH]) {
|
uint8_t keiv[SHA256_DIGEST_LENGTH]) {
|
||||||
#if BYTE_ORDER == BIG_ENDIAN
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
REVERSE32(pin, pin);
|
REVERSE32(pin, pin);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t salt[HARDWARE_SALT_SIZE + RANDOM_SALT_SIZE];
|
uint8_t salt[HARDWARE_SALT_SIZE + RANDOM_SALT_SIZE + EXTERNAL_SALT_SIZE];
|
||||||
memcpy(salt, hardware_salt, HARDWARE_SALT_SIZE);
|
size_t salt_len = 0;
|
||||||
memcpy(salt + HARDWARE_SALT_SIZE, random_salt, RANDOM_SALT_SIZE);
|
|
||||||
|
memcpy(salt + salt_len, hardware_salt, HARDWARE_SALT_SIZE);
|
||||||
|
salt_len += HARDWARE_SALT_SIZE;
|
||||||
|
|
||||||
|
memcpy(salt + salt_len, random_salt, RANDOM_SALT_SIZE);
|
||||||
|
salt_len += RANDOM_SALT_SIZE;
|
||||||
|
|
||||||
|
if (ext_salt != NULL) {
|
||||||
|
memcpy(salt + salt_len, ext_salt, EXTERNAL_SALT_SIZE);
|
||||||
|
salt_len += EXTERNAL_SALT_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t progress = (ui_total - ui_rem) * 1000 / ui_total;
|
uint32_t progress = (ui_total - ui_rem) * 1000 / ui_total;
|
||||||
if (ui_callback && ui_message) {
|
if (ui_callback && ui_message) {
|
||||||
@ -348,7 +359,7 @@ static void derive_kek(uint32_t pin, const uint8_t *random_salt,
|
|||||||
|
|
||||||
PBKDF2_HMAC_SHA256_CTX ctx;
|
PBKDF2_HMAC_SHA256_CTX ctx;
|
||||||
pbkdf2_hmac_sha256_Init(&ctx, (const uint8_t *)&pin, sizeof(pin), salt,
|
pbkdf2_hmac_sha256_Init(&ctx, (const uint8_t *)&pin, sizeof(pin), salt,
|
||||||
sizeof(salt), 1);
|
salt_len, 1);
|
||||||
for (int i = 1; i <= 5; i++) {
|
for (int i = 1; i <= 5; i++) {
|
||||||
pbkdf2_hmac_sha256_Update(&ctx, PIN_ITER_COUNT / 10);
|
pbkdf2_hmac_sha256_Update(&ctx, PIN_ITER_COUNT / 10);
|
||||||
if (ui_callback && ui_message) {
|
if (ui_callback && ui_message) {
|
||||||
@ -360,7 +371,7 @@ static void derive_kek(uint32_t pin, const uint8_t *random_salt,
|
|||||||
pbkdf2_hmac_sha256_Final(&ctx, kek);
|
pbkdf2_hmac_sha256_Final(&ctx, kek);
|
||||||
|
|
||||||
pbkdf2_hmac_sha256_Init(&ctx, (const uint8_t *)&pin, sizeof(pin), salt,
|
pbkdf2_hmac_sha256_Init(&ctx, (const uint8_t *)&pin, sizeof(pin), salt,
|
||||||
sizeof(salt), 2);
|
salt_len, 2);
|
||||||
for (int i = 6; i <= 10; i++) {
|
for (int i = 6; i <= 10; i++) {
|
||||||
pbkdf2_hmac_sha256_Update(&ctx, PIN_ITER_COUNT / 10);
|
pbkdf2_hmac_sha256_Update(&ctx, PIN_ITER_COUNT / 10);
|
||||||
if (ui_callback && ui_message) {
|
if (ui_callback && ui_message) {
|
||||||
@ -377,17 +388,17 @@ static void derive_kek(uint32_t pin, const uint8_t *random_salt,
|
|||||||
memzero(&salt, sizeof(salt));
|
memzero(&salt, sizeof(salt));
|
||||||
}
|
}
|
||||||
|
|
||||||
static secbool set_pin(uint32_t pin) {
|
static secbool set_pin(uint32_t pin, const uint8_t *ext_salt) {
|
||||||
uint8_t buffer[RANDOM_SALT_SIZE + KEYS_SIZE + POLY1305_TAG_SIZE];
|
uint8_t buffer[RANDOM_SALT_SIZE + KEYS_SIZE + POLY1305_TAG_SIZE];
|
||||||
uint8_t *salt = buffer;
|
uint8_t *rand_salt = buffer;
|
||||||
uint8_t *ekeys = buffer + RANDOM_SALT_SIZE;
|
uint8_t *ekeys = buffer + RANDOM_SALT_SIZE;
|
||||||
uint8_t *pvc = buffer + RANDOM_SALT_SIZE + KEYS_SIZE;
|
uint8_t *pvc = buffer + RANDOM_SALT_SIZE + KEYS_SIZE;
|
||||||
|
|
||||||
uint8_t kek[SHA256_DIGEST_LENGTH];
|
uint8_t kek[SHA256_DIGEST_LENGTH];
|
||||||
uint8_t keiv[SHA256_DIGEST_LENGTH];
|
uint8_t keiv[SHA256_DIGEST_LENGTH];
|
||||||
chacha20poly1305_ctx ctx;
|
chacha20poly1305_ctx ctx;
|
||||||
random_buffer(salt, RANDOM_SALT_SIZE);
|
random_buffer(rand_salt, RANDOM_SALT_SIZE);
|
||||||
derive_kek(pin, salt, kek, keiv);
|
derive_kek(pin, rand_salt, ext_salt, kek, keiv);
|
||||||
rfc7539_init(&ctx, kek, keiv);
|
rfc7539_init(&ctx, kek, keiv);
|
||||||
memzero(kek, sizeof(kek));
|
memzero(kek, sizeof(kek));
|
||||||
memzero(keiv, sizeof(keiv));
|
memzero(keiv, sizeof(keiv));
|
||||||
@ -515,7 +526,7 @@ static void init_wiped_storage(void) {
|
|||||||
ui_total = DERIVE_SECS;
|
ui_total = DERIVE_SECS;
|
||||||
ui_rem = ui_total;
|
ui_rem = ui_total;
|
||||||
ui_message = PROCESSING_MSG;
|
ui_message = PROCESSING_MSG;
|
||||||
ensure(set_pin(PIN_EMPTY), "init_pin failed");
|
ensure(set_pin(PIN_EMPTY, NULL), "init_pin failed");
|
||||||
if (unlocked != sectrue) {
|
if (unlocked != sectrue) {
|
||||||
memzero(cached_keys, sizeof(cached_keys));
|
memzero(cached_keys, sizeof(cached_keys));
|
||||||
}
|
}
|
||||||
@ -784,7 +795,7 @@ static secbool decrypt_dek(const uint8_t *kek, const uint8_t *keiv) {
|
|||||||
return sectrue;
|
return sectrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static secbool unlock(uint32_t pin) {
|
static secbool unlock(uint32_t pin, const uint8_t *ext_salt) {
|
||||||
if (sectrue != initialized) {
|
if (sectrue != initialized) {
|
||||||
return secfalse;
|
return secfalse;
|
||||||
}
|
}
|
||||||
@ -827,10 +838,10 @@ static secbool unlock(uint32_t pin) {
|
|||||||
|
|
||||||
// Read the random salt from EDEK_PVC_KEY and use it to derive the KEK and
|
// Read the random salt from EDEK_PVC_KEY and use it to derive the KEK and
|
||||||
// KEIV from the PIN.
|
// KEIV from the PIN.
|
||||||
const void *salt = NULL;
|
const void *rand_salt = NULL;
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
if (sectrue != initialized ||
|
if (sectrue != initialized ||
|
||||||
sectrue != norcow_get(EDEK_PVC_KEY, &salt, &len) ||
|
sectrue != norcow_get(EDEK_PVC_KEY, &rand_salt, &len) ||
|
||||||
len != RANDOM_SALT_SIZE + KEYS_SIZE + PVC_SIZE) {
|
len != RANDOM_SALT_SIZE + KEYS_SIZE + PVC_SIZE) {
|
||||||
memzero(&pin, sizeof(pin));
|
memzero(&pin, sizeof(pin));
|
||||||
handle_fault("no EDEK");
|
handle_fault("no EDEK");
|
||||||
@ -838,7 +849,7 @@ static secbool unlock(uint32_t pin) {
|
|||||||
}
|
}
|
||||||
uint8_t kek[SHA256_DIGEST_LENGTH];
|
uint8_t kek[SHA256_DIGEST_LENGTH];
|
||||||
uint8_t keiv[SHA256_DIGEST_LENGTH];
|
uint8_t keiv[SHA256_DIGEST_LENGTH];
|
||||||
derive_kek(pin, (const uint8_t *)salt, kek, keiv);
|
derive_kek(pin, (const uint8_t *)rand_salt, ext_salt, kek, keiv);
|
||||||
memzero(&pin, sizeof(pin));
|
memzero(&pin, sizeof(pin));
|
||||||
|
|
||||||
// First, we increase PIN fail counter in storage, even before checking the
|
// First, we increase PIN fail counter in storage, even before checking the
|
||||||
@ -875,7 +886,7 @@ static secbool unlock(uint32_t pin) {
|
|||||||
return pin_fails_reset();
|
return pin_fails_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
secbool storage_unlock(uint32_t pin) {
|
secbool storage_unlock(uint32_t pin, const uint8_t *ext_salt) {
|
||||||
ui_total = DERIVE_SECS;
|
ui_total = DERIVE_SECS;
|
||||||
ui_rem = ui_total;
|
ui_rem = ui_total;
|
||||||
if (pin == PIN_EMPTY) {
|
if (pin == PIN_EMPTY) {
|
||||||
@ -887,7 +898,7 @@ secbool storage_unlock(uint32_t pin) {
|
|||||||
} else {
|
} else {
|
||||||
ui_message = VERIFYING_PIN_MSG;
|
ui_message = VERIFYING_PIN_MSG;
|
||||||
}
|
}
|
||||||
return unlock(pin);
|
return unlock(pin, ext_salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1152,7 +1163,9 @@ uint32_t storage_get_pin_rem(void) {
|
|||||||
return PIN_MAX_TRIES - ctr;
|
return PIN_MAX_TRIES - ctr;
|
||||||
}
|
}
|
||||||
|
|
||||||
secbool storage_change_pin(uint32_t oldpin, uint32_t newpin) {
|
secbool storage_change_pin(uint32_t oldpin, uint32_t newpin,
|
||||||
|
const uint8_t *old_ext_salt,
|
||||||
|
const uint8_t *new_ext_salt) {
|
||||||
if (sectrue != initialized) {
|
if (sectrue != initialized) {
|
||||||
return secfalse;
|
return secfalse;
|
||||||
}
|
}
|
||||||
@ -1162,10 +1175,10 @@ secbool storage_change_pin(uint32_t oldpin, uint32_t newpin) {
|
|||||||
ui_message = (oldpin != PIN_EMPTY && newpin == PIN_EMPTY) ? VERIFYING_PIN_MSG
|
ui_message = (oldpin != PIN_EMPTY && newpin == PIN_EMPTY) ? VERIFYING_PIN_MSG
|
||||||
: PROCESSING_MSG;
|
: PROCESSING_MSG;
|
||||||
|
|
||||||
if (sectrue != unlock(oldpin)) {
|
if (sectrue != unlock(oldpin, old_ext_salt)) {
|
||||||
return secfalse;
|
return secfalse;
|
||||||
}
|
}
|
||||||
secbool ret = set_pin(newpin);
|
secbool ret = set_pin(newpin, new_ext_salt);
|
||||||
memzero(&oldpin, sizeof(oldpin));
|
memzero(&oldpin, sizeof(oldpin));
|
||||||
memzero(&newpin, sizeof(newpin));
|
memzero(&newpin, sizeof(newpin));
|
||||||
return ret;
|
return ret;
|
||||||
@ -1268,9 +1281,9 @@ static secbool storage_upgrade(void) {
|
|||||||
ui_rem = ui_total;
|
ui_rem = ui_total;
|
||||||
ui_message = PROCESSING_MSG;
|
ui_message = PROCESSING_MSG;
|
||||||
if (sectrue == norcow_get(V0_PIN_KEY, &val, &len)) {
|
if (sectrue == norcow_get(V0_PIN_KEY, &val, &len)) {
|
||||||
set_pin(*(const uint32_t *)val);
|
set_pin(*(const uint32_t *)val, NULL);
|
||||||
} else {
|
} else {
|
||||||
set_pin(PIN_EMPTY);
|
set_pin(PIN_EMPTY, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert PIN failure counter.
|
// Convert PIN failure counter.
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "secbool.h"
|
#include "secbool.h"
|
||||||
|
|
||||||
|
// The length of the external salt in bytes.
|
||||||
|
#define EXTERNAL_SALT_SIZE 32
|
||||||
|
|
||||||
typedef secbool (*PIN_UI_WAIT_CALLBACK)(uint32_t wait, uint32_t progress,
|
typedef secbool (*PIN_UI_WAIT_CALLBACK)(uint32_t wait, uint32_t progress,
|
||||||
const char *message);
|
const char *message);
|
||||||
|
|
||||||
@ -32,11 +35,13 @@ void storage_init(PIN_UI_WAIT_CALLBACK callback, const uint8_t *salt,
|
|||||||
void storage_wipe(void);
|
void storage_wipe(void);
|
||||||
secbool storage_is_unlocked(void);
|
secbool storage_is_unlocked(void);
|
||||||
void storage_lock(void);
|
void storage_lock(void);
|
||||||
secbool storage_unlock(const uint32_t pin);
|
secbool storage_unlock(const uint32_t pin, const uint8_t *ext_salt);
|
||||||
secbool storage_has_pin(void);
|
secbool storage_has_pin(void);
|
||||||
secbool storage_pin_fails_increase(void);
|
secbool storage_pin_fails_increase(void);
|
||||||
uint32_t storage_get_pin_rem(void);
|
uint32_t storage_get_pin_rem(void);
|
||||||
secbool storage_change_pin(const uint32_t oldpin, const uint32_t newpin);
|
secbool storage_change_pin(const uint32_t oldpin, const uint32_t newpin,
|
||||||
|
const uint8_t *old_ext_salt,
|
||||||
|
const uint8_t *new_ext_salt);
|
||||||
secbool storage_get(const uint16_t key, void *val, const uint16_t max_len,
|
secbool storage_get(const uint16_t key, void *val, const uint16_t max_len,
|
||||||
uint16_t *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);
|
||||||
|
Binary file not shown.
@ -1,6 +1,7 @@
|
|||||||
import ctypes as c
|
import ctypes as c
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
EXTERNAL_SALT_LEN = 32
|
||||||
sectrue = -1431655766 # 0xAAAAAAAAA
|
sectrue = -1431655766 # 0xAAAAAAAAA
|
||||||
fname = os.path.join(os.path.dirname(__file__), "libtrezor-storage.so")
|
fname = os.path.join(os.path.dirname(__file__), "libtrezor-storage.so")
|
||||||
|
|
||||||
@ -20,8 +21,10 @@ class Storage:
|
|||||||
def wipe(self) -> None:
|
def wipe(self) -> None:
|
||||||
self.lib.storage_wipe()
|
self.lib.storage_wipe()
|
||||||
|
|
||||||
def unlock(self, pin: int) -> bool:
|
def unlock(self, pin: int, ext_salt: bytes = None) -> bool:
|
||||||
return sectrue == self.lib.storage_unlock(c.c_uint32(pin))
|
if ext_salt is not None and len(ext_salt) != EXTERNAL_SALT_LEN:
|
||||||
|
raise ValueError
|
||||||
|
return sectrue == self.lib.storage_unlock(c.c_uint32(pin), ext_salt)
|
||||||
|
|
||||||
def lock(self) -> None:
|
def lock(self) -> None:
|
||||||
self.lib.storage_lock()
|
self.lib.storage_lock()
|
||||||
@ -32,9 +35,19 @@ class Storage:
|
|||||||
def get_pin_rem(self) -> int:
|
def get_pin_rem(self) -> int:
|
||||||
return self.lib.storage_get_pin_rem()
|
return self.lib.storage_get_pin_rem()
|
||||||
|
|
||||||
def change_pin(self, oldpin: int, newpin: int) -> bool:
|
def change_pin(
|
||||||
|
self,
|
||||||
|
oldpin: int,
|
||||||
|
newpin: int,
|
||||||
|
old_ext_salt: bytes = None,
|
||||||
|
new_ext_salt: bytes = None,
|
||||||
|
) -> bool:
|
||||||
|
if old_ext_salt is not None and len(old_ext_salt) != EXTERNAL_SALT_LEN:
|
||||||
|
raise ValueError
|
||||||
|
if new_ext_salt is not None and len(new_ext_salt) != EXTERNAL_SALT_LEN:
|
||||||
|
raise ValueError
|
||||||
return sectrue == self.lib.storage_change_pin(
|
return sectrue == self.lib.storage_change_pin(
|
||||||
c.c_uint32(oldpin), c.c_uint32(newpin)
|
c.c_uint32(oldpin), c.c_uint32(newpin), old_ext_salt, new_ext_salt
|
||||||
)
|
)
|
||||||
|
|
||||||
def get(self, key: int) -> bytes:
|
def get(self, key: int) -> bytes:
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user