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:
parent
715ed53bcf
commit
a15930dd4a
@ -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;
|
||||||
|
@ -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"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
|
@ -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."""
|
||||||
|
@ -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(),
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user