1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-25 16:08:32 +00:00

WIP - get_device_id and random bytes in rust

This commit is contained in:
grdddj 2022-03-17 21:44:00 +01:00
parent 715ed53bcf
commit a15930dd4a
9 changed files with 87 additions and 28 deletions

View File

@ -29,6 +29,7 @@ static void _librust_qstrs(void) {
MP_QSTR_set_rotation; MP_QSTR_set_rotation;
MP_QSTR_get_label; MP_QSTR_get_label;
MP_QSTR_set_label; MP_QSTR_set_label;
MP_QSTR_get_device_id;
MP_QSTR_get_mnemonic_secret; MP_QSTR_get_mnemonic_secret;
MP_QSTR_set_mnemonic_secret; MP_QSTR_set_mnemonic_secret;
MP_QSTR_is_passphrase_enabled; MP_QSTR_is_passphrase_enabled;

View File

@ -7,12 +7,12 @@ use crate::{
obj::Obj, obj::Obj,
qstr::Qstr, qstr::Qstr,
}, },
trezorhal::secbool, trezorhal::{random, secbool},
util, util,
}; };
use cstr_core::cstr; use cstr_core::cstr;
use heapless::Vec; use heapless::{String, Vec};
use core::{ use core::{
convert::{TryFrom, TryInto}, convert::{TryFrom, TryInto},
@ -196,6 +196,26 @@ extern "C" fn storagedevice_set_label(label: Obj) -> Obj {
unsafe { util::try_or_raise(block) } unsafe { util::try_or_raise(block) }
} }
extern "C" fn storagedevice_get_device_id() -> Obj {
let block = || {
let key = _get_appkey(DEVICE_ID, true);
let device_id = &storagedevice_storage_get(key) as &[u8];
// TODO: is there some easier way?
// TODO: replace unwrap() with "?"
if device_id.is_empty() {
let new_device_id = &random::get_random_bytes(12) as &[u8];
let hex_id = _hexlify_bytes(new_device_id);
let device_id_bytes = hex_id.as_str().as_bytes();
storagedevice_storage_set(key, device_id_bytes.as_ptr(), device_id_bytes.len() as u16);
hex_id.as_str().try_into()
} else {
str::from_utf8(device_id).unwrap().try_into()
}
};
unsafe { util::try_or_raise(block) }
}
extern "C" fn storagedevice_get_mnemonic_secret() -> Obj { extern "C" fn storagedevice_get_mnemonic_secret() -> Obj {
let block = || { let block = || {
let key = _get_appkey(_MNEMONIC_SECRET, false); let key = _get_appkey(_MNEMONIC_SECRET, false);
@ -548,13 +568,7 @@ pub fn storagedevice_storage_get(key: u16) -> Vec<u8, MAX_LEN> {
// Would mean having Option<XXX> as the return type // Would mean having Option<XXX> as the return type
let result = &buf[..len as usize]; let result = &buf[..len as usize];
// TODO: can we somehow convert it more easily? result.iter().cloned().collect()
let mut vector_result = Vec::<u8, MAX_LEN>::new();
for byte in result {
vector_result.push(*byte).unwrap();
}
vector_result
} }
// TODO: is it worth having a special function to not allocate so much in all // TODO: is it worth having a special function to not allocate so much in all
@ -693,6 +707,23 @@ fn _normalize_autolock_delay(delay_ms: u32) -> u32 {
} }
} }
// TODO: could be put elsewhere to be available for all modules
pub fn _hexlify_bytes(bytes: &[u8]) -> String<64> {
let mut buf = String::<64>::from("");
for byte in bytes {
fn hex_from_digit(num: u8) -> char {
if num < 10 {
(b'0' + num) as char
} else {
(b'A' + num - 10) as char
}
}
buf.push(hex_from_digit(byte / 16)).unwrap();
buf.push(hex_from_digit(byte % 16)).unwrap();
}
buf
}
#[no_mangle] #[no_mangle]
pub static mp_module_trezorstoragedevice: Module = obj_module! { pub static mp_module_trezorstoragedevice: Module = obj_module! {
Qstr::MP_QSTR___name_storage__ => Qstr::MP_QSTR_trezorstoragedevice.to_obj(), Qstr::MP_QSTR___name_storage__ => Qstr::MP_QSTR_trezorstoragedevice.to_obj(),
@ -734,6 +765,10 @@ pub static mp_module_trezorstoragedevice: Module = obj_module! {
/// """Set label.""" /// """Set label."""
Qstr::MP_QSTR_set_label => obj_fn_1!(storagedevice_set_label).as_obj(), Qstr::MP_QSTR_set_label => obj_fn_1!(storagedevice_set_label).as_obj(),
/// def get_device_id() -> str:
/// """Get device ID."""
Qstr::MP_QSTR_get_device_id => obj_fn_0!(storagedevice_get_device_id).as_obj(),
/// def get_mnemonic_secret() -> bytes: /// def get_mnemonic_secret() -> bytes:
/// """Get mnemonic secret.""" /// """Get mnemonic secret."""
Qstr::MP_QSTR_get_mnemonic_secret => obj_fn_0!(storagedevice_get_mnemonic_secret).as_obj(), Qstr::MP_QSTR_get_mnemonic_secret => obj_fn_0!(storagedevice_get_mnemonic_secret).as_obj(),
@ -917,4 +952,11 @@ mod tests {
let result = _normalize_autolock_delay(1_000_000); let result = _normalize_autolock_delay(1_000_000);
assert_eq!(result, 1_000_000); assert_eq!(result, 1_000_000);
} }
#[test]
fn hexlify_bytes() {
let bytes: &[u8; 6] = &[52, 241, 6, 151, 173, 74];
let result = _hexlify_bytes(bytes);
assert_eq!(result, String::<64>::from("34F10697AD4A"));
}
} }

View File

@ -1,8 +1,14 @@
use heapless::Vec;
extern "C" { extern "C" {
// trezor-crypto/rand.h // trezor-crypto/rand.h
fn random_uniform(n: u32) -> u32; fn random_uniform(n: u32) -> u32;
fn random_buffer(buf: *const u8, len: u16);
} }
// TODO: what is the sensible max size not to allocate too much every time?
const MAX_LEN: usize = u8::MAX as usize;
pub fn uniform(n: u32) -> u32 { pub fn uniform(n: u32) -> u32 {
unsafe { random_uniform(n) } unsafe { random_uniform(n) }
} }
@ -15,6 +21,10 @@ pub fn shuffle<T>(slice: &mut [T]) {
} }
} }
// TODO: create random_bytes() pub fn get_random_bytes(len: u8) -> Vec<u8, MAX_LEN> {
// from trezorcrypto import random let mut buf: [u8; MAX_LEN] = [0; MAX_LEN];
// random_buffer unsafe { random_buffer(&mut buf as *mut _, len as u16) };
let result = &buf[..len as usize];
result.iter().cloned().collect()
}

View File

@ -43,6 +43,11 @@ def set_label(label: str) -> bool:
"""Set label.""" """Set label."""
# rust/src/storagedevice/storage_device.rs
def get_device_id() -> str:
"""Get device ID."""
# rust/src/storagedevice/storage_device.rs # rust/src/storagedevice/storage_device.rs
def get_mnemonic_secret() -> bytes: def get_mnemonic_secret() -> bytes:
"""Get mnemonic secret.""" """Get mnemonic secret."""

View File

@ -42,7 +42,7 @@ def get_features() -> Features:
patch_version=utils.VERSION_PATCH, patch_version=utils.VERSION_PATCH,
revision=utils.SCM_REVISION, revision=utils.SCM_REVISION,
model=utils.MODEL, model=utils.MODEL,
device_id=storage.device.get_device_id(), device_id=storagedevice.get_device_id(),
label=storagedevice.get_label(), label=storagedevice.get_label(),
pin_protection=config.has_pin(), pin_protection=config.has_pin(),
unlocked=config.is_unlocked(), unlocked=config.is_unlocked(),

View File

@ -45,9 +45,9 @@ with unimport_manager:
del boot del boot
# start the USB # start the USB
import storage.device from trezor import storagedevice
usb.bus.open(storage.device.get_device_id()) usb.bus.open(storagedevice.get_device_id())
# run the endless loop # run the endless loop
while True: while True:

View File

@ -27,7 +27,7 @@ def reset() -> None:
""" """
Wipes storage but keeps the device id unchanged. Wipes storage but keeps the device id unchanged.
""" """
device_id = device.get_device_id() device_id = storagedevice.get_device_id()
wipe() wipe()
common.set(common.APP_DEVICE, device.DEVICE_ID, device_id.encode(), public=True) common.set(common.APP_DEVICE, device.DEVICE_ID, device_id.encode(), public=True)

View File

@ -1,10 +1,12 @@
from micropython import const from micropython import const
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from ubinascii import hexlify
import storage.cache import storage.cache
from storage import common from storage import common
# from ubinascii import hexlify
# TODO: try ... from trezorstoragedevice import * # TODO: try ... from trezorstoragedevice import *
@ -82,18 +84,18 @@ SD_SALT_AUTH_KEY_LEN_BYTES = const(16)
# return common.get_bool(_NAMESPACE, INITIALIZED, public=True) # return common.get_bool(_NAMESPACE, INITIALIZED, public=True)
def _new_device_id() -> str: # def _new_device_id() -> str:
from trezorcrypto import random # avoid pulling in trezor.crypto # from trezorcrypto import random # avoid pulling in trezor.crypto
return hexlify(random.bytes(12)).decode().upper() # return hexlify(random.bytes(12)).decode().upper()
def get_device_id() -> str: # def get_device_id() -> str:
dev_id = common.get(_NAMESPACE, DEVICE_ID, public=True) # dev_id = common.get(_NAMESPACE, DEVICE_ID, public=True)
if not dev_id: # if not dev_id:
dev_id = _new_device_id().encode() # dev_id = _new_device_id().encode()
common.set(_NAMESPACE, DEVICE_ID, dev_id, public=True) # common.set(_NAMESPACE, DEVICE_ID, dev_id, public=True)
return dev_id.decode() # return dev_id.decode()
# def get_rotation() -> int: # def get_rotation() -> int:

View File

@ -1,7 +1,6 @@
from micropython import const from micropython import const
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import storage.device
from trezor import io, storagedevice from trezor import io, storagedevice
from trezor.sdcard import with_filesystem from trezor.sdcard import with_filesystem
from trezor.utils import consteq from trezor.utils import consteq
@ -32,7 +31,7 @@ def compute_auth_tag(salt: bytes, auth_key: bytes) -> bytes:
def _get_device_dir() -> str: def _get_device_dir() -> str:
return f"/trezor/device_{storage.device.get_device_id().lower()}" return f"/trezor/device_{storagedevice.get_device_id().lower()}"
def _get_salt_path(new: bool = False) -> str: def _get_salt_path(new: bool = False) -> str: