mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-04 21:48:17 +00:00
Compare commits
12 Commits
aad4a7d22d
...
8a189b5313
Author | SHA1 | Date | |
---|---|---|---|
|
8a189b5313 | ||
|
ef02c4de5d | ||
|
835f7087c6 | ||
|
331e07b1e0 | ||
|
3bf8f12cd5 | ||
|
14a5770703 | ||
|
21d26d60df | ||
|
9567cca9d0 | ||
|
ff3f1deac1 | ||
|
ce62dc6e2a | ||
|
45891cb799 | ||
|
d316d88c0f |
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,3 +11,4 @@ __pycache__/
|
||||
proto.gv*
|
||||
.DS_Store
|
||||
crypto/tests/libtrezor-crypto.so.dSYM/
|
||||
tropic-model/
|
||||
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -27,7 +27,9 @@
|
||||
[submodule "vendor/cmsis_5"]
|
||||
path = vendor/cmsis_5
|
||||
url = https://github.com/ARM-software/CMSIS_5.git
|
||||
|
||||
[submodule "vendor/stm32u5xx_hal_driver"]
|
||||
path = vendor/stm32u5xx_hal_driver
|
||||
url = https://github.com/trezor/stm32u5xx_hal_driver.git
|
||||
[submodule "vendor/libtropic"]
|
||||
path = vendor/libtropic
|
||||
url = https://github.com/tropicsquare/libtropic.git
|
||||
|
@ -31,6 +31,7 @@ PYOPT ?= 1
|
||||
BITCOIN_ONLY ?= 0
|
||||
BOOTLOADER_QA ?= 0
|
||||
BOOTLOADER_DEVEL ?= 0
|
||||
DISABLE_OPTIGA ?= 0
|
||||
TREZOR_MODEL ?= T
|
||||
TREZOR_MEMPERF ?= 0
|
||||
ADDRESS_SANITIZER ?= 0
|
||||
@ -41,6 +42,8 @@ THP ?= 0
|
||||
BENCHMARK ?= 0
|
||||
TREZOR_EMULATOR_DEBUGGABLE ?= 0
|
||||
QUIET_MODE ?= 0
|
||||
TREZOR_DISABLE_ANIMATION ?= $(if $(filter 0,$(PYOPT)),1,0)
|
||||
STORAGE_INSECURE_TESTING_MODE ?= 0
|
||||
|
||||
# OpenOCD interface default. Alternative: ftdi/olimex-arm-usb-tiny-h
|
||||
OPENOCD_INTERFACE ?= stlink
|
||||
@ -142,7 +145,9 @@ SCONS_VARS = \
|
||||
PRODUCTION="$(PRODUCTION)" \
|
||||
PYOPT="$(PYOPT)" \
|
||||
QUIET_MODE="$(QUIET_MODE)" \
|
||||
STORAGE_INSECURE_TESTING_MODE="$(STORAGE_INSECURE_TESTING_MODE)" \
|
||||
THP="$(THP)" \
|
||||
TREZOR_DISABLE_ANIMATION="$(TREZOR_DISABLE_ANIMATION)" \
|
||||
TREZOR_EMULATOR_ASAN="$(ADDRESS_SANITIZER)" \
|
||||
TREZOR_EMULATOR_DEBUGGABLE=$(TREZOR_EMULATOR_DEBUGGABLE) \
|
||||
TREZOR_MEMPERF="$(TREZOR_MEMPERF)" \
|
||||
|
@ -18,6 +18,14 @@ HW_REVISION = ARGUMENTS.get('HW_REVISION', None)
|
||||
THP = ARGUMENTS.get('THP', '0') == '1' # Trezor-Host Protocol
|
||||
MODEL_IDENTIFIER = models.get_model_identifier(TREZOR_MODEL)
|
||||
BENCHMARK = ARGUMENTS.get('BENCHMARK', '0') == '1'
|
||||
DISABLE_ANIMATION = ARGUMENTS.get('TREZOR_DISABLE_ANIMATION', '0') == '1'
|
||||
|
||||
STORAGE_INSECURE_TESTING_MODE = ARGUMENTS.get('STORAGE_INSECURE_TESTING_MODE', '0') == '1'
|
||||
if STORAGE_INSECURE_TESTING_MODE and PRODUCTION:
|
||||
raise RuntimeError("STORAGE_INSECURE_TESTING_MODE cannot be used in production")
|
||||
if STORAGE_INSECURE_TESTING_MODE:
|
||||
DISABLE_OPTIGA = True
|
||||
PYOPT = "0"
|
||||
|
||||
if BENCHMARK and PYOPT != '0':
|
||||
print("BENCHMARK=1 works only with PYOPT=0.")
|
||||
@ -30,7 +38,9 @@ FEATURE_FLAGS = {
|
||||
}
|
||||
|
||||
FEATURES_WANTED = ["input", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga", "haptic"]
|
||||
if DISABLE_OPTIGA and PYOPT == '0':
|
||||
if DISABLE_OPTIGA:
|
||||
if PYOPT != '0':
|
||||
raise RuntimeError("DISABLE_OPTIGA requires PYOPT=0")
|
||||
FEATURES_WANTED.remove("optiga")
|
||||
|
||||
CCFLAGS_MOD = ''
|
||||
@ -69,6 +79,7 @@ CPPDEFINES_MOD += [
|
||||
('USE_CARDANO', '1' if EVERYTHING else '0'),
|
||||
('USE_NEM', '1' if (EVERYTHING and TREZOR_MODEL == "T") else '0'),
|
||||
('USE_EOS', '1' if (EVERYTHING and TREZOR_MODEL == "T") else '0'),
|
||||
('DISABLE_ANIMATION', '1' if DISABLE_ANIMATION else '0'),
|
||||
]
|
||||
SOURCE_MOD += [
|
||||
'embed/upymod/trezorobj.c',
|
||||
@ -367,6 +378,9 @@ if THP:
|
||||
'vendor/trezor-crypto/elligator2.c',
|
||||
]
|
||||
|
||||
if STORAGE_INSECURE_TESTING_MODE:
|
||||
CPPDEFINES_MOD += ['STORAGE_INSECURE_TESTING_MODE']
|
||||
|
||||
ui.init_ui(TREZOR_MODEL, "firmware", CPPDEFINES_MOD, SOURCE_MOD, RUST_UI_FEATURES)
|
||||
|
||||
SOURCE_QSTR = SOURCE_MOD + SOURCE_MICROPYTHON + SOURCE_MICROPYTHON_SPEED
|
||||
@ -681,6 +695,7 @@ if FROZEN:
|
||||
use_button='button' in FEATURES_AVAILABLE,
|
||||
use_touch='touch' in FEATURES_AVAILABLE,
|
||||
ui_layout=ui.get_ui_layout(TREZOR_MODEL),
|
||||
tropic='tropic' in FEATURES_AVAILABLE,
|
||||
thp=THP,
|
||||
)
|
||||
|
||||
@ -873,6 +888,14 @@ elif 'STM32U5G9xx' in CPPDEFINES_HAL or 'STM32U585xx' in CPPDEFINES_HAL:
|
||||
else:
|
||||
raise Exception("Unknown MCU")
|
||||
|
||||
if STORAGE_INSECURE_TESTING_MODE:
|
||||
INSECURE_TESTING_MODE_STR = """
|
||||
#########################################################
|
||||
# STORAGE_INSECURE_TESTING_MODE enabled, DO NOT USE #
|
||||
#########################################################
|
||||
"""
|
||||
action_bin.append(INSECURE_TESTING_MODE_STR)
|
||||
|
||||
program_bin = env.Command(
|
||||
target='firmware.bin',
|
||||
source=program_elf,
|
||||
|
@ -16,6 +16,13 @@ DISABLE_OPTIGA = ARGUMENTS.get('DISABLE_OPTIGA', '0') == '1'
|
||||
HW_REVISION = ARGUMENTS.get('HW_REVISION', None)
|
||||
THP = ARGUMENTS.get('THP', '0') == '1' # Trezor-Host Protocol
|
||||
|
||||
STORAGE_INSECURE_TESTING_MODE = ARGUMENTS.get('STORAGE_INSECURE_TESTING_MODE', '0') == '1'
|
||||
if STORAGE_INSECURE_TESTING_MODE and PRODUCTION:
|
||||
raise RuntimeError("STORAGE_INSECURE_TESTING_MODE cannot be used in production")
|
||||
if STORAGE_INSECURE_TESTING_MODE:
|
||||
DISABLE_OPTIGA = True
|
||||
PYOPT = "0"
|
||||
|
||||
FEATURE_FLAGS = {
|
||||
"RDI": True,
|
||||
"SECP256K1_ZKP": True, # required for trezor.crypto.curve.bip340 (BIP340/Taproot)
|
||||
@ -24,7 +31,10 @@ FEATURE_FLAGS = {
|
||||
}
|
||||
|
||||
FEATURES_WANTED = ["input", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga", "haptic"]
|
||||
if DISABLE_OPTIGA and PYOPT == '0':
|
||||
if DISABLE_OPTIGA:
|
||||
# TODO use PYOPT instead of PRODUCTION, same as in firmware, blocked on #4253
|
||||
if PRODUCTION:
|
||||
raise RuntimeError("DISABLE_OPTIGA requires non-production build")
|
||||
FEATURES_WANTED.remove("optiga")
|
||||
|
||||
CCFLAGS_MOD = ''
|
||||
@ -235,6 +245,8 @@ if THP:
|
||||
'vendor/trezor-crypto/elligator2.c',
|
||||
]
|
||||
|
||||
if STORAGE_INSECURE_TESTING_MODE:
|
||||
CPPDEFINES_MOD += ['STORAGE_INSECURE_TESTING_MODE']
|
||||
|
||||
env = Environment(
|
||||
ENV=os.environ,
|
||||
@ -411,6 +423,14 @@ action_bin=[
|
||||
'$CP $TARGET ' + BINARY_NAME,
|
||||
]
|
||||
|
||||
if STORAGE_INSECURE_TESTING_MODE:
|
||||
INSECURE_TESTING_MODE_STR = """
|
||||
#########################################################
|
||||
# STORAGE_INSECURE_TESTING_MODE enabled, DO NOT USE #
|
||||
#########################################################
|
||||
"""
|
||||
action_bin.append(INSECURE_TESTING_MODE_STR)
|
||||
|
||||
program_bin = env.Command(
|
||||
target='kernel.bin',
|
||||
source=program_elf,
|
||||
|
@ -21,7 +21,7 @@ if BENCHMARK and PYOPT != '0':
|
||||
print("BENCHMARK=1 works only with PYOPT=0.")
|
||||
exit(1)
|
||||
|
||||
FEATURES_WANTED = ["input", "sd_card", "dma2d", "optiga"]
|
||||
FEATURES_WANTED = ["input", "sd_card", "dma2d", "optiga", "tropic"]
|
||||
|
||||
if not models.has_emulator(TREZOR_MODEL):
|
||||
# skip unix build
|
||||
@ -48,6 +48,7 @@ SOURCE_MOD = [
|
||||
'vendor/micropython/extmod/vfs_posix_file.c',
|
||||
]
|
||||
SOURCE_MOD_CRYPTO = []
|
||||
SOURCE_MOD_TROPIC = []
|
||||
RUST_UI_FEATURES = []
|
||||
|
||||
# modtrezorconfig
|
||||
@ -251,6 +252,14 @@ SOURCE_MOD += [
|
||||
'embed/upymod/modutime.c',
|
||||
]
|
||||
|
||||
SOURCE_MOD_TROPIC += [
|
||||
'vendor/libtropic/src/libtropic.c',
|
||||
]
|
||||
|
||||
CPPDEFINES_MOD += ['USE_TREZOR_CRYPTO']
|
||||
|
||||
CPPPATH_MOD += ['vendor/libtropic/src/', 'vendor/libtropic/include/']
|
||||
|
||||
SOURCE_MICROPYTHON = [
|
||||
'vendor/micropython/extmod/modubinascii.c',
|
||||
'vendor/micropython/extmod/moductypes.c',
|
||||
@ -752,6 +761,7 @@ if FROZEN:
|
||||
bitcoin_only=BITCOIN_ONLY,
|
||||
backlight='backlight' in FEATURES_AVAILABLE,
|
||||
optiga='optiga' in FEATURES_AVAILABLE,
|
||||
tropic='tropic' in FEATURES_AVAILABLE,
|
||||
use_button='button' in FEATURES_AVAILABLE,
|
||||
use_touch='touch' in FEATURES_AVAILABLE,
|
||||
ui_layout=ui.get_ui_layout(TREZOR_MODEL),
|
||||
@ -769,7 +779,7 @@ if FROZEN:
|
||||
#
|
||||
|
||||
obj_program = []
|
||||
source_files = SOURCE_MOD + SOURCE_MOD_CRYPTO + SOURCE_MICROPYTHON + SOURCE_UNIX
|
||||
source_files = SOURCE_MOD + SOURCE_MOD_CRYPTO + SOURCE_MOD_TROPIC + SOURCE_MICROPYTHON + SOURCE_UNIX
|
||||
obj_program.extend(env.Object(source=SOURCE_MOD))
|
||||
obj_program.extend(env.Object(source=SOURCE_MOD_CRYPTO, CCFLAGS='$CCFLAGS -ftrivial-auto-var-init=zero'))
|
||||
if FEATURE_FLAGS["SECP256K1_ZKP"]:
|
||||
|
@ -40,6 +40,7 @@ rgb_led = []
|
||||
backlight = []
|
||||
usb = []
|
||||
optiga = []
|
||||
tropic = []
|
||||
translations = ["crypto"]
|
||||
test = [
|
||||
"backlight",
|
||||
|
234
core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h
Normal file
234
core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if USE_TROPIC
|
||||
|
||||
// Default initial Tropic handshake keys
|
||||
#define PKEY_INDEX_BYTE PAIRING_KEY_SLOT_INDEX_0
|
||||
#define SHiPRIV_BYTES \
|
||||
{0xf0, 0xc4, 0xaa, 0x04, 0x8f, 0x00, 0x13, 0xa0, 0x96, 0x84, 0xdf, \
|
||||
0x05, 0xe8, 0xa2, 0x2e, 0xf7, 0x21, 0x38, 0x98, 0x28, 0x2b, 0xa9, \
|
||||
0x43, 0x12, 0xf3, 0x13, 0xdf, 0x2d, 0xce, 0x8d, 0x41, 0x64};
|
||||
#define SHiPUB_BYTES \
|
||||
{0x84, 0x2f, 0xe3, 0x21, 0xa8, 0x24, 0x74, 0x08, 0x37, 0x37, 0xff, \
|
||||
0x2b, 0x9b, 0x88, 0xa2, 0xaf, 0x42, 0x44, 0x2d, 0xb0, 0xd8, 0xaa, \
|
||||
0xcc, 0x6d, 0xc6, 0x9e, 0x99, 0x53, 0x33, 0x44, 0xb2, 0x46};
|
||||
|
||||
#include "libtropic.h"
|
||||
|
||||
/// package: trezorcrypto.tropic
|
||||
|
||||
/// class TropicError(Exception):
|
||||
/// """Error returned by the Tropic Square chip."""
|
||||
MP_DEFINE_EXCEPTION(TropicError, Exception)
|
||||
|
||||
#define PING_MSG_MAX_LEN 64
|
||||
#define ECC_SLOT_COUNT 32
|
||||
#define SIG_SIZE 64
|
||||
|
||||
STATIC bool lt_handle_initialized = false;
|
||||
STATIC lt_handle_t lt_handle = {0};
|
||||
|
||||
STATIC void tropic_init(lt_handle_t *handle) {
|
||||
lt_ret_t ret = LT_FAIL;
|
||||
|
||||
ret = lt_init(handle);
|
||||
if (ret != LT_OK) {
|
||||
mp_raise_msg(&mp_type_TropicError, "lt_init failed.");
|
||||
}
|
||||
|
||||
uint8_t X509_cert[LT_L2_GET_INFO_REQ_CERT_SIZE] = {0};
|
||||
|
||||
ret = lt_get_info_cert(handle, X509_cert, LT_L2_GET_INFO_REQ_CERT_SIZE);
|
||||
if (ret != LT_OK) {
|
||||
mp_raise_msg(&mp_type_TropicError, "lt_get_info_cert failed.");
|
||||
}
|
||||
|
||||
uint8_t stpub[32] = {0};
|
||||
ret = lt_cert_verify_and_parse(X509_cert, 512, stpub);
|
||||
if (ret != LT_OK) {
|
||||
mp_raise_msg(&mp_type_TropicError, "lt_cert_verify_and_parse failed.");
|
||||
}
|
||||
|
||||
uint8_t pkey_index = PKEY_INDEX_BYTE;
|
||||
uint8_t shipriv[] = SHiPRIV_BYTES;
|
||||
uint8_t shipub[] = SHiPUB_BYTES;
|
||||
|
||||
ret = lt_session_start(handle, stpub, pkey_index, shipriv, shipub);
|
||||
if (ret != LT_OK) {
|
||||
mp_raise_msg(&mp_type_TropicError, "lt_session_start failed.");
|
||||
}
|
||||
}
|
||||
|
||||
/// def ping(message: str) -> str:
|
||||
/// """
|
||||
/// Test the session by pinging the chip.
|
||||
/// """
|
||||
STATIC mp_obj_t mod_trezorcrypto_tropic_ping(mp_obj_t message) {
|
||||
lt_ret_t ret = LT_FAIL;
|
||||
|
||||
if (!lt_handle_initialized) {
|
||||
tropic_init(<_handle);
|
||||
lt_handle_initialized = true;
|
||||
}
|
||||
|
||||
uint8_t msg_in[PING_MSG_MAX_LEN] = {0};
|
||||
|
||||
mp_buffer_info_t message_b = {0};
|
||||
mp_get_buffer_raise(message, &message_b, MP_BUFFER_READ);
|
||||
if (message_b.len > 0) {
|
||||
ret = lt_ping(<_handle, (uint8_t *)message_b.buf, (uint8_t *)msg_in,
|
||||
message_b.len);
|
||||
if (ret != LT_OK) {
|
||||
mp_raise_msg(&mp_type_TropicError, "lt_ping failed.");
|
||||
}
|
||||
} else {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
vstr_t result = {0};
|
||||
vstr_init_len(&result, message_b.len);
|
||||
|
||||
memcpy(result.buf, msg_in, message_b.len);
|
||||
result.len = strlen(result.buf);
|
||||
|
||||
return mp_obj_new_str_from_vstr(&mp_type_str, &result);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_tropic_ping_obj,
|
||||
mod_trezorcrypto_tropic_ping);
|
||||
|
||||
/// def get_certificate() -> bytes:
|
||||
/// """
|
||||
/// Return the chip's certificate.
|
||||
/// """
|
||||
STATIC mp_obj_t mod_trezorcrypto_tropic_get_certificate() {
|
||||
lt_ret_t ret = LT_FAIL;
|
||||
|
||||
if (!lt_handle_initialized) {
|
||||
tropic_init(<_handle);
|
||||
lt_handle_initialized = true;
|
||||
}
|
||||
|
||||
uint8_t X509_cert[512] = {0};
|
||||
ret = lt_get_info_cert(<_handle, X509_cert, 512);
|
||||
if (ret != LT_OK) {
|
||||
mp_raise_msg(&mp_type_TropicError, "lt_get_info_cert failed.");
|
||||
}
|
||||
|
||||
vstr_t vstr = {0};
|
||||
vstr_init_len(&vstr, 512);
|
||||
|
||||
memcpy(vstr.buf, X509_cert, 512);
|
||||
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorcrypto_tropic_get_certificate_obj,
|
||||
mod_trezorcrypto_tropic_get_certificate);
|
||||
|
||||
/// def key_generate(
|
||||
/// key_index: int,
|
||||
/// ) -> None:
|
||||
/// """
|
||||
/// Generate ECC key in the device's ECC key slot.
|
||||
/// """
|
||||
STATIC mp_obj_t mod_trezorcrypto_tropic_key_generate(mp_obj_t key_index) {
|
||||
mp_int_t idx = mp_obj_get_int(key_index);
|
||||
if (idx < 0 || idx >= ECC_SLOT_COUNT) {
|
||||
mp_raise_ValueError("Invalid index.");
|
||||
}
|
||||
|
||||
lt_ret_t ret = LT_FAIL;
|
||||
|
||||
if (!lt_handle_initialized) {
|
||||
tropic_init(<_handle);
|
||||
lt_handle_initialized = true;
|
||||
}
|
||||
|
||||
ret = lt_ecc_key_generate(<_handle, idx, CURVE_ED25519);
|
||||
if (ret != LT_OK) {
|
||||
mp_raise_msg(&mp_type_TropicError, "lt_ecc_key_generate failed.");
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_tropic_key_generate_obj,
|
||||
mod_trezorcrypto_tropic_key_generate);
|
||||
|
||||
|
||||
/// def sign(
|
||||
/// key_index: int,
|
||||
/// digest: bytes,
|
||||
/// ) -> bytes:
|
||||
/// """
|
||||
/// Uses the private key at key_index to produce a signature of the digest.
|
||||
/// """
|
||||
STATIC mp_obj_t mod_trezorcrypto_tropic_sign(mp_obj_t key_index,
|
||||
mp_obj_t digest) {
|
||||
mp_int_t idx = mp_obj_get_int(key_index);
|
||||
if (idx < 0 || idx >= ECC_SLOT_COUNT) {
|
||||
mp_raise_ValueError("Invalid index.");
|
||||
}
|
||||
|
||||
mp_buffer_info_t dig = {0};
|
||||
mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ);
|
||||
if (dig.len != 32) {
|
||||
mp_raise_ValueError("Invalid length of digest.");
|
||||
}
|
||||
|
||||
lt_ret_t ret = LT_FAIL;
|
||||
|
||||
if (!lt_handle_initialized) {
|
||||
tropic_init(<_handle);
|
||||
lt_handle_initialized = true;
|
||||
}
|
||||
|
||||
vstr_t sig = {0};
|
||||
vstr_init_len(&sig, SIG_SIZE);
|
||||
|
||||
ret = lt_ecc_eddsa_sign(<_handle, idx, (const uint8_t *)dig.buf, dig.len,
|
||||
((uint8_t *)sig.buf), SIG_SIZE);
|
||||
if (ret != LT_OK) {
|
||||
vstr_clear(&sig);
|
||||
mp_raise_msg(&mp_type_TropicError, "lt_ecc_eddsa_sign failed.");
|
||||
}
|
||||
|
||||
sig.len = SIG_SIZE;
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &sig);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_tropic_sign_obj,
|
||||
mod_trezorcrypto_tropic_sign);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mod_trezorcrypto_tropic_globals_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_tropic)},
|
||||
{MP_ROM_QSTR(MP_QSTR_ping), MP_ROM_PTR(&mod_trezorcrypto_tropic_ping_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_get_certificate),
|
||||
MP_ROM_PTR(&mod_trezorcrypto_tropic_get_certificate_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_key_generate),
|
||||
MP_ROM_PTR(&mod_trezorcrypto_tropic_key_generate_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_trezorcrypto_tropic_sign_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_TropicError), MP_ROM_PTR(&mp_type_TropicError)}};
|
||||
STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_tropic_globals,
|
||||
mod_trezorcrypto_tropic_globals_table);
|
||||
|
||||
STATIC const mp_obj_module_t mod_trezorcrypto_tropic_module = {
|
||||
.base = {&mp_type_module},
|
||||
.globals = (mp_obj_dict_t *)&mod_trezorcrypto_tropic_globals,
|
||||
};
|
||||
|
||||
#endif
|
@ -69,6 +69,9 @@ static void wrapped_ui_wait_callback(uint32_t current, uint32_t total) {
|
||||
#ifdef USE_OPTIGA
|
||||
#include "modtrezorcrypto-optiga.h"
|
||||
#endif
|
||||
#ifdef USE_TROPIC
|
||||
#include "modtrezorcrypto-tropic.h"
|
||||
#endif
|
||||
#if !BITCOIN_ONLY
|
||||
#include "modtrezorcrypto-cardano.h"
|
||||
#include "modtrezorcrypto-monero.h"
|
||||
@ -135,6 +138,9 @@ STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = {
|
||||
#if USE_OPTIGA
|
||||
{MP_ROM_QSTR(MP_QSTR_optiga), MP_ROM_PTR(&mod_trezorcrypto_optiga_module)},
|
||||
#endif
|
||||
#if USE_TROPIC
|
||||
{MP_ROM_QSTR(MP_QSTR_tropic), MP_ROM_PTR(&mod_trezorcrypto_tropic_module)},
|
||||
#endif
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_trezorcrypto_globals,
|
||||
mp_module_trezorcrypto_globals_table);
|
||||
|
@ -388,6 +388,8 @@ STATIC mp_obj_tuple_t mod_trezorutils_version_obj = {
|
||||
/// """Whether the hardware supports haptic feedback."""
|
||||
/// USE_OPTIGA: bool
|
||||
/// """Whether the hardware supports Optiga secure element."""
|
||||
/// USE_TROPIC: bool
|
||||
/// """Whether the hardware supports Tropic Square secure element."""
|
||||
/// USE_TOUCH: bool
|
||||
/// """Whether the hardware supports touch screen."""
|
||||
/// USE_BUTTON: bool
|
||||
@ -410,6 +412,9 @@ STATIC mp_obj_tuple_t mod_trezorutils_version_obj = {
|
||||
/// """UI layout identifier ("tt" for model T, "tr" for models One and R)."""
|
||||
/// USE_THP: bool
|
||||
/// """Whether the firmware supports Trezor-Host Protocol (version 2)."""
|
||||
/// if __debug__:
|
||||
/// DISABLE_ANIMATION: bool
|
||||
/// """Whether the firmware should disable animations."""
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorutils)},
|
||||
@ -458,6 +463,11 @@ STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = {
|
||||
#else
|
||||
{MP_ROM_QSTR(MP_QSTR_USE_OPTIGA), mp_const_false},
|
||||
#endif
|
||||
#ifdef USE_TROPIC
|
||||
{MP_ROM_QSTR(MP_QSTR_USE_TROPIC), mp_const_true},
|
||||
#else
|
||||
{MP_ROM_QSTR(MP_QSTR_USE_TROPIC), mp_const_false},
|
||||
#endif
|
||||
#ifdef USE_TOUCH
|
||||
{MP_ROM_QSTR(MP_QSTR_USE_TOUCH), mp_const_true},
|
||||
#else
|
||||
@ -502,6 +512,13 @@ STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = {
|
||||
#else
|
||||
#error Unknown layout
|
||||
#endif
|
||||
#if !PYOPT
|
||||
#if DISABLE_ANIMATION
|
||||
{MP_ROM_QSTR(MP_QSTR_DISABLE_ANIMATION), mp_const_true},
|
||||
#else
|
||||
{MP_ROM_QSTR(MP_QSTR_DISABLE_ANIMATION), mp_const_false},
|
||||
#endif // TREZOR_DISABLE_ANIMATION
|
||||
#endif // PYOPT
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_trezorutils_globals,
|
||||
|
@ -112,6 +112,7 @@ def _from_env(name: str) -> bool:
|
||||
@click.option("-G", "--alloc-profiling/--no-alloc-profiling", default=_from_env("TREZOR_MEMPERF"), help="Profile memory allocation (requires special micropython build)")
|
||||
@click.option("-h", "--headless", is_flag=True, help="Headless mode (no display, disables animation)")
|
||||
@click.option("--heap-size", metavar="SIZE", default="20M", help="Configure heap size")
|
||||
@click.option("-m", "--tropic-model", is_flag=True, help="Start the Tropic Square model, needed for running the Tropic tests. Needs to be installed first.")
|
||||
@click.option("--main", help="Path to python main file")
|
||||
@click.option("--mnemonic", "mnemonics", multiple=True, help="Initialize device with given mnemonic. Specify multiple times for Shamir shares.")
|
||||
@click.option("--log-memory/--no-log-memory", default=_from_env("TREZOR_LOG_MEMORY"), help="Print memory usage after workflows")
|
||||
@ -139,6 +140,7 @@ def cli(
|
||||
alloc_profiling: bool,
|
||||
headless: bool,
|
||||
heap_size: str,
|
||||
tropic_model: bool,
|
||||
main: str,
|
||||
mnemonics: list[str],
|
||||
log_memory: bool,
|
||||
@ -177,7 +179,7 @@ def cli(
|
||||
if command and not run_command:
|
||||
raise click.ClickException("Extra arguments found. Did you mean to use -c?")
|
||||
|
||||
if watch and (command or debugger):
|
||||
if watch and (command or debugger or tropic_model):
|
||||
raise click.ClickException("Cannot use -w together with -c or -D")
|
||||
|
||||
if watch and inotify is None:
|
||||
@ -297,6 +299,10 @@ def cli(
|
||||
emulator.client, record_dir, report_func=print
|
||||
)
|
||||
|
||||
if tropic_model:
|
||||
run_command = True
|
||||
command = "./tropic-model.sh"
|
||||
|
||||
if run_command:
|
||||
ret = run_command_with_emulator(emulator, command)
|
||||
elif watch:
|
||||
|
31
core/mocks/generated/trezorcrypto/tropic.pyi
Normal file
31
core/mocks/generated/trezorcrypto/tropic.pyi
Normal file
@ -0,0 +1,31 @@
|
||||
from typing import *
|
||||
|
||||
|
||||
# upymod/modtrezorcrypto/modtrezorcrypto-tropic.h
|
||||
class TropicError(Exception):
|
||||
"""Error returned by the Tropic Square chip."""
|
||||
|
||||
def ping(message: str) -> str:
|
||||
"""
|
||||
Test the session by pinging the chip.
|
||||
"""
|
||||
|
||||
def get_certificate() -> bytes:
|
||||
"""
|
||||
Return the chip's certificate.
|
||||
"""
|
||||
|
||||
def key_generate(
|
||||
key_index: int,
|
||||
) -> None:
|
||||
"""
|
||||
Generate ECC key in the device's ECC key slot.
|
||||
"""
|
||||
|
||||
def sign(
|
||||
key_index: int,
|
||||
digest: bytes,
|
||||
) -> bytes:
|
||||
"""
|
||||
Uses the private key at key_index to produce a signature of the digest.
|
||||
"""
|
@ -130,6 +130,8 @@ USE_HAPTIC: bool
|
||||
"""Whether the hardware supports haptic feedback."""
|
||||
USE_OPTIGA: bool
|
||||
"""Whether the hardware supports Optiga secure element."""
|
||||
USE_TROPIC: bool
|
||||
"""Whether the hardware supports Tropic Square secure element."""
|
||||
USE_TOUCH: bool
|
||||
"""Whether the hardware supports touch screen."""
|
||||
USE_BUTTON: bool
|
||||
@ -152,3 +154,6 @@ UI_LAYOUT: str
|
||||
"""UI layout identifier ("tt" for model T, "tr" for models One and R)."""
|
||||
USE_THP: bool
|
||||
"""Whether the firmware supports Trezor-Host Protocol (version 2)."""
|
||||
if __debug__:
|
||||
DISABLE_ANIMATION: bool
|
||||
"""Whether the firmware should disable animations."""
|
||||
|
@ -55,6 +55,27 @@ def configure(
|
||||
features_available.append("optiga")
|
||||
defines += [("USE_OPTIGA", "1")]
|
||||
|
||||
if "tropic" in features_wanted:
|
||||
sources += [
|
||||
"vendor/libtropic/src/libtropic.c",
|
||||
"vendor/libtropic/src/lt_crc16.c",
|
||||
"vendor/libtropic/src/lt_hkdf.c",
|
||||
"vendor/libtropic/src/lt_l1.c",
|
||||
"vendor/libtropic/src/lt_l1_port_wrap.c",
|
||||
"vendor/libtropic/src/lt_l2.c",
|
||||
"vendor/libtropic/src/lt_l2_frame_check.c",
|
||||
"vendor/libtropic/src/lt_l3.c",
|
||||
"vendor/libtropic/src/lt_random.c",
|
||||
"vendor/libtropic/hal/port/unix/lt_port_unix.c",
|
||||
"vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_aesgcm.c",
|
||||
"vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_ed25519.c",
|
||||
"vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_sha256.c",
|
||||
"vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_x25519.c",
|
||||
]
|
||||
defines += ["USE_TREZOR_CRYPTO"]
|
||||
features_available.append("tropic")
|
||||
defines += ["USE_TROPIC=1"]
|
||||
|
||||
if "input" in features_wanted:
|
||||
sources += ["embed/io/touch/unix/touch.c"]
|
||||
paths += ["embed/io/touch/inc"]
|
||||
|
@ -44,6 +44,7 @@ def generate(env):
|
||||
btc_only = env["bitcoin_only"] == "1"
|
||||
backlight = env["backlight"]
|
||||
optiga = env["optiga"]
|
||||
tropic = env["tropic"]
|
||||
layout_tt = env["ui_layout"] == "UI_LAYOUT_TT"
|
||||
layout_tr = env["ui_layout"] == "UI_LAYOUT_TR"
|
||||
touch = env["use_touch"]
|
||||
@ -55,6 +56,7 @@ def generate(env):
|
||||
rf"-e 's/utils\.BITCOIN_ONLY/{btc_only}/g'",
|
||||
rf"-e 's/utils\.USE_BACKLIGHT/{backlight}/g'",
|
||||
rf"-e 's/utils\.USE_OPTIGA/{optiga}/g'",
|
||||
rf"-e 's/utils\.USE_TROPIC/{tropic}/g'",
|
||||
rf"-e 's/utils\.UI_LAYOUT == \"TT\"/{layout_tt}/g'",
|
||||
rf"-e 's/utils\.UI_LAYOUT == \"TR\"/{layout_tr}/g'",
|
||||
rf"-e 's/utils\.UI_LAYOUT == \"MERCURY\"/{layout_mercury}/g'",
|
||||
|
@ -22,5 +22,8 @@ if not utils.BITCOIN_ONLY:
|
||||
if utils.USE_OPTIGA:
|
||||
from trezorcrypto import optiga # noqa: F401
|
||||
|
||||
if utils.USE_TROPIC:
|
||||
from trezorcrypto import tropic # noqa: F401
|
||||
|
||||
if utils.USE_THP:
|
||||
from trezorcrypto import elligator2 # noqa: F401
|
||||
|
@ -24,7 +24,7 @@ else:
|
||||
|
||||
|
||||
if __debug__:
|
||||
trezorui2.disable_animation(bool(utils.DISABLE_ANIMATION))
|
||||
trezorui2.disable_animation(utils.DISABLE_ANIMATION)
|
||||
|
||||
|
||||
# all rendering is done through a singleton of `Display`
|
||||
|
@ -14,6 +14,7 @@ from trezorutils import ( # noqa: F401
|
||||
USE_BUTTON,
|
||||
USE_HAPTIC,
|
||||
USE_OPTIGA,
|
||||
USE_TROPIC,
|
||||
USE_SD_CARD,
|
||||
USE_THP,
|
||||
USE_TOUCH,
|
||||
@ -33,17 +34,20 @@ from trezorutils import ( # noqa: F401
|
||||
)
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
DISABLE_ANIMATION = 0
|
||||
|
||||
if __debug__:
|
||||
if EMULATOR:
|
||||
import uos
|
||||
|
||||
DISABLE_ANIMATION = int(uos.getenv("TREZOR_DISABLE_ANIMATION") or "0")
|
||||
LOG_MEMORY = int(uos.getenv("TREZOR_LOG_MEMORY") or "0")
|
||||
DISABLE_ANIMATION = uos.getenv("TREZOR_DISABLE_ANIMATION") == "1"
|
||||
LOG_MEMORY = uos.getenv("TREZOR_LOG_MEMORY") == "1"
|
||||
else:
|
||||
from trezorutils import DISABLE_ANIMATION # noqa: F401
|
||||
|
||||
LOG_MEMORY = 0
|
||||
|
||||
else:
|
||||
DISABLE_ANIMATION = False
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Iterator, Protocol, Sequence, TypeVar
|
||||
|
||||
|
27
core/tests/test_trezor.crypto.tropic.py
Normal file
27
core/tests/test_trezor.crypto.tropic.py
Normal file
@ -0,0 +1,27 @@
|
||||
from common import * # isort:skip
|
||||
|
||||
from slip39_vectors import vectors
|
||||
from trezor.crypto import tropic
|
||||
|
||||
|
||||
class TestCryptoTropic(unittest.TestCase):
|
||||
def test_ping(self):
|
||||
self.assertEqual(tropic.ping("HeLlO!"), "HeLlO!")
|
||||
|
||||
def test_get_certificate(self):
|
||||
self.assertEqual(len(tropic.get_certificate()), 512)
|
||||
|
||||
def test_sign(self):
|
||||
try:
|
||||
tropic.sign(0, "ASD")
|
||||
assert False
|
||||
except ValueError as e:
|
||||
self.assertIn("invalid length", str(e).lower())
|
||||
|
||||
tropic.key_generate(0)
|
||||
|
||||
# signing should work now that we have a key
|
||||
self.assertEqual(len(tropic.sign(0, "a" * 32)), 64)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
20
core/tropic-model.sh
Executable file
20
core/tropic-model.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ ! -d "tropic-model" ]; then
|
||||
echo "================================================="
|
||||
echo "Please install the Tropic model to the tropic-model/ directory first, using the steps below!"
|
||||
echo "1. mkdir tropic-model && python3 -mvenv tropic-model/venv && source tropic-model/venv/bin/activate"
|
||||
echo "2. Follow instructions here: https://github.com/tropicsquare/ts-tvl/tree/master?tab=readme-ov-file#installing"
|
||||
echo " (basically, download the tvl-XXX.whl and pip install it under the venv created above - which should be already activated)"
|
||||
echo "3. Get config files for the model from https://github.com/tropicsquare/ts-tvl/tree/master/tvl/server/model_config"
|
||||
echo " i. model_config.yml"
|
||||
echo " ii. tropic01_ese_certificate_1.pem"
|
||||
echo " iii.tropic01_ese_private_key_1.pem"
|
||||
echo " iv. tropic01_ese_public_key_1.pem"
|
||||
echo "================================================="
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd tropic-model
|
||||
source venv/bin/activate
|
||||
model_server tcp -vv -c model_config.yml
|
1
core/vendor/libtropic
vendored
Symbolic link
1
core/vendor/libtropic
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../../vendor/libtropic/
|
@ -165,6 +165,7 @@ CFLAGS += -I../vendor/nanopb -Iprotob -DPB_FIELD_16BIT=1 -DPB_ENCODE_ARRAYS_UNPA
|
||||
CFLAGS += -DSCM_REVISION='"$(shell git rev-parse HEAD | sed 's:\(..\):\\x\1:g')"'
|
||||
CFLAGS += -DUSE_MONERO=0
|
||||
CFLAGS += -DUSE_OPTIGA=0
|
||||
CFLAGS += -DUSE_TROPIC=0
|
||||
ifneq ($(BITCOIN_ONLY),1)
|
||||
CFLAGS += -DUSE_ETHEREUM=1
|
||||
CFLAGS += -DUSE_NEM=1
|
||||
|
@ -284,11 +284,15 @@ void norcow_wipe(void) {
|
||||
// Erase the active sector first, because it contains sensitive data.
|
||||
erase_sector(norcow_active_sector, sectrue);
|
||||
|
||||
#if STORAGE_INSECURE_TESTING_MODE && !PRODUCTION
|
||||
// skip erasing inactive sectors
|
||||
#else
|
||||
for (uint8_t i = 0; i < NORCOW_SECTOR_COUNT; i++) {
|
||||
if (i != norcow_active_sector) {
|
||||
erase_sector(i, secfalse);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
norcow_active_version = NORCOW_VERSION;
|
||||
norcow_write_sector = norcow_active_sector;
|
||||
norcow_free_offset = NORCOW_STORAGE_START;
|
||||
|
@ -86,8 +86,12 @@ const uint32_t V0_PIN_EMPTY = 1;
|
||||
// up constant storage space.
|
||||
#define MAX_WIPE_CODE_LEN 50
|
||||
|
||||
#if STORAGE_INSECURE_TESTING_MODE && !PRODUCTION
|
||||
#define PIN_ITER_COUNT 1
|
||||
#else
|
||||
// The total number of iterations to use in PBKDF2.
|
||||
#define PIN_ITER_COUNT 20000
|
||||
#endif
|
||||
|
||||
// The minimum number of milliseconds between progress updates.
|
||||
#define MIN_PROGRESS_UPDATE_MS 100
|
||||
|
@ -2,3 +2,15 @@
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t hamming_weight(uint32_t value);
|
||||
|
||||
#ifndef STORAGE_INSECURE_TESTING_MODE
|
||||
#define STORAGE_INSECURE_TESTING_MODE 0
|
||||
#endif
|
||||
|
||||
#if STORAGE_INSECURE_TESTING_MODE
|
||||
#if PRODUCTION
|
||||
#error "STORAGE_INSECURE_TESTING_MODE can't be used in production"
|
||||
#else
|
||||
#pragma message("STORAGE IS INSECURE DO NOT USE THIS IN PRODUCTION")
|
||||
#endif
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user