1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-24 15:38:22 +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_get_label;
MP_QSTR_set_label;
MP_QSTR_get_device_id;
MP_QSTR_get_mnemonic_secret;
MP_QSTR_set_mnemonic_secret;
MP_QSTR_is_passphrase_enabled;

View File

@ -7,12 +7,12 @@ use crate::{
obj::Obj,
qstr::Qstr,
},
trezorhal::secbool,
trezorhal::{random, secbool},
util,
};
use cstr_core::cstr;
use heapless::Vec;
use heapless::{String, Vec};
use core::{
convert::{TryFrom, TryInto},
@ -196,6 +196,26 @@ extern "C" fn storagedevice_set_label(label: Obj) -> Obj {
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 {
let block = || {
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
let result = &buf[..len as usize];
// TODO: can we somehow convert it more easily?
let mut vector_result = Vec::<u8, MAX_LEN>::new();
for byte in result {
vector_result.push(*byte).unwrap();
}
vector_result
result.iter().cloned().collect()
}
// 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]
pub static mp_module_trezorstoragedevice: Module = obj_module! {
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."""
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:
/// """Get mnemonic secret."""
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);
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" {
// trezor-crypto/rand.h
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 {
unsafe { random_uniform(n) }
}
@ -15,6 +21,10 @@ pub fn shuffle<T>(slice: &mut [T]) {
}
}
// TODO: create random_bytes()
// from trezorcrypto import random
// random_buffer
pub fn get_random_bytes(len: u8) -> Vec<u8, MAX_LEN> {
let mut buf: [u8; MAX_LEN] = [0; MAX_LEN];
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."""
# rust/src/storagedevice/storage_device.rs
def get_device_id() -> str:
"""Get device ID."""
# rust/src/storagedevice/storage_device.rs
def get_mnemonic_secret() -> bytes:
"""Get mnemonic secret."""

View File

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

View File

@ -45,9 +45,9 @@ with unimport_manager:
del boot
# 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
while True:

View File

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

View File

@ -1,10 +1,12 @@
from micropython import const
from typing import TYPE_CHECKING
from ubinascii import hexlify
import storage.cache
from storage import common
# from ubinascii import hexlify
# 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)
def _new_device_id() -> str:
from trezorcrypto import random # avoid pulling in trezor.crypto
# def _new_device_id() -> str:
# 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:
dev_id = common.get(_NAMESPACE, DEVICE_ID, public=True)
if not dev_id:
dev_id = _new_device_id().encode()
common.set(_NAMESPACE, DEVICE_ID, dev_id, public=True)
return dev_id.decode()
# def get_device_id() -> str:
# dev_id = common.get(_NAMESPACE, DEVICE_ID, public=True)
# if not dev_id:
# dev_id = _new_device_id().encode()
# common.set(_NAMESPACE, DEVICE_ID, dev_id, public=True)
# return dev_id.decode()
# def get_rotation() -> int:

View File

@ -1,7 +1,6 @@
from micropython import const
from typing import TYPE_CHECKING
import storage.device
from trezor import io, storagedevice
from trezor.sdcard import with_filesystem
from trezor.utils import consteq
@ -32,7 +31,7 @@ def compute_auth_tag(salt: bytes, auth_key: bytes) -> bytes:
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: