From b7b8e77ccba9c3beb22e8ca95dc3e74a0ca0d691 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Mon, 17 Mar 2025 06:42:10 +0100 Subject: [PATCH] feat(core): enable tropic in firmware/kernel on hw [no changelog] --- core/SConscript.firmware | 2 +- core/SConscript.kernel | 28 +-- core/SConscript.prodtest | 32 +++ core/SConscript.unix | 8 +- core/embed/projects/kernel/main.c | 8 + core/embed/projects/unix/main.c | 2 +- core/embed/sec/secret/stm32u5/secret.c | 10 + core/embed/sec/tropic/inc/sec/tropic.h | 13 ++ core/embed/sec/tropic/stm32/tropic01.c | 71 +----- core/embed/sec/tropic/tropic.c | 207 ++++++++++++++++++ .../tropic_transport.h => tropic_internal.h} | 9 +- core/embed/sec/tropic/tropic_transport.c | 53 ----- core/embed/sec/tropic/unix/tropic01.c | 27 +++ .../sys/syscall/stm32/syscall_dispatch.c | 31 +++ .../embed/sys/syscall/stm32/syscall_numbers.h | 5 + core/embed/sys/syscall/stm32/syscall_stubs.c | 25 +++ .../sys/syscall/stm32/syscall_verifiers.c | 52 +++++ .../sys/syscall/stm32/syscall_verifiers.h | 16 ++ .../modtrezorcrypto/modtrezorcrypto-tropic.h | 38 ++-- core/site_scons/models/T3W1/emulator.py | 5 +- .../models/T3W1/trezor_t3w1_revA.py | 1 + .../models/T3W1/trezor_t3w1_revB.py | 1 + .../models/T3W1/trezor_t3w1_revC.py | 1 + 23 files changed, 478 insertions(+), 167 deletions(-) create mode 100644 core/embed/sec/tropic/tropic.c rename core/embed/sec/tropic/{inc/sec/tropic_transport.h => tropic_internal.h} (87%) delete mode 100644 core/embed/sec/tropic/tropic_transport.c create mode 100644 core/embed/sec/tropic/unix/tropic01.c diff --git a/core/SConscript.firmware b/core/SConscript.firmware index 6f199e31bb..dca12971fb 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -45,7 +45,7 @@ FEATURE_FLAGS = { "AES_GCM": BENCHMARK or THP, } -FEATURES_WANTED = ["input", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga", "haptic", "ble"] +FEATURES_WANTED = ["input", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga", "haptic", "ble", "tropic"] if DISABLE_OPTIGA: if PYOPT != '0': raise RuntimeError("DISABLE_OPTIGA requires PYOPT=0") diff --git a/core/SConscript.kernel b/core/SConscript.kernel index 626904922e..ef6b0b6fa7 100644 --- a/core/SConscript.kernel +++ b/core/SConscript.kernel @@ -27,10 +27,10 @@ FEATURE_FLAGS = { "RDI": True, "SECP256K1_ZKP": True, # required for trezor.crypto.curve.bip340 (BIP340/Taproot) "SYSTEM_VIEW": False, - "AES_GCM": False, + "AES_GCM": True, } -FEATURES_WANTED = ["input", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga", "haptic", "ble"] +FEATURES_WANTED = ["input", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga", "haptic", "ble", "tropic"] if DISABLE_OPTIGA: # TODO use PYOPT instead of PRODUCTION, same as in firmware, blocked on #4253 if PRODUCTION: @@ -177,17 +177,6 @@ if FEATURE_FLAGS["SECP256K1_ZKP"]: 'vendor/trezor-crypto/zkp_bip340.c', ] -# AES-GCM -if FEATURE_FLAGS["AES_GCM"]: - CPPDEFINES_MOD += [ - 'USE_AES_GCM', - 'AES_VAR', - ] - SOURCE_MOD_CRYPTO += [ - 'vendor/trezor-crypto/aes/gf128mul.c', - 'vendor/trezor-crypto/aes/aesgcm.c', - ] - SOURCE_MOD += [ 'embed/gfx/bitblt/gfx_bitblt.c', 'embed/gfx/bitblt/gfx_bitblt_rgb565.c', @@ -258,6 +247,19 @@ env = Environment( FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) +FEATURE_FLAGS["AES_GCM"] = FEATURE_FLAGS["AES_GCM"] or "tropic" in FEATURES_AVAILABLE + +# AES-GCM +if FEATURE_FLAGS["AES_GCM"]: + CPPDEFINES_MOD += [ + 'USE_AES_GCM', + 'AES_VAR', + ] + SOURCE_MOD_CRYPTO += [ + 'vendor/trezor-crypto/aes/gf128mul.c', + 'vendor/trezor-crypto/aes/aesgcm.c', + ] + SOURCE_FIRMWARE = [ 'embed/projects/kernel/main.c', ] diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest index a8d20bcc49..6627f780ac 100644 --- a/core/SConscript.prodtest +++ b/core/SConscript.prodtest @@ -10,6 +10,10 @@ BOOTLOADER_DEVEL = ARGUMENTS.get('BOOTLOADER_DEVEL', '0') == '1' HW_REVISION = ARGUMENTS.get('HW_REVISION', None) UI_DEBUG_OVERLAY = ARGUMENTS.get('UI_DEBUG_OVERLAY', '0') == '1' +FEATURE_FLAGS = { + "AES_GCM": True, +} + FEATURES_WANTED = ["input", "sbu", "nfc", "sd_card", "rgb_led", "usb", "consumption_mask", "optiga", "haptic", "tropic", "ble", "hw_revision"] CCFLAGS_MOD = '' @@ -41,22 +45,50 @@ SOURCE_MOD_CRYPTO += [ 'vendor/trezor-crypto/aes/aeskey.c', 'vendor/trezor-crypto/aes/aestab.c', 'vendor/trezor-crypto/bignum.c', + 'vendor/trezor-crypto/blake256.c', + 'vendor/trezor-crypto/blake2b.c', 'vendor/trezor-crypto/buffer.c', 'vendor/trezor-crypto/chacha_drbg.c', 'vendor/trezor-crypto/chacha20poly1305/chacha_merged.c', 'vendor/trezor-crypto/der.c', 'vendor/trezor-crypto/ecdsa.c', + 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-32bit.c', + 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-helpers.c', + 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-scalarmult-base.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-32bit-tables.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-basepoint-table.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-impl-base.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-keccak.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-sha3.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519.c', + 'vendor/trezor-crypto/ed25519-donna/modm-donna-32bit.c', + 'vendor/trezor-crypto/groestl.c', + 'vendor/trezor-crypto/hasher.c', 'vendor/trezor-crypto/hmac.c', 'vendor/trezor-crypto/hmac_drbg.c', 'vendor/trezor-crypto/memzero.c', 'vendor/trezor-crypto/nist256p1.c', 'vendor/trezor-crypto/rand.c', + 'vendor/trezor-crypto/ripemd160.c', 'vendor/trezor-crypto/rfc6979.c', 'vendor/trezor-crypto/secp256k1.c', 'vendor/trezor-crypto/sha2.c', + 'vendor/trezor-crypto/sha3.c', 'vendor/trezor-crypto/tls_prf.c', ] +# AES-GCM +if FEATURE_FLAGS["AES_GCM"]: + CPPDEFINES_MOD += [ + 'USE_AES_GCM', + 'AES_VAR', + ] + SOURCE_MOD_CRYPTO += [ + 'vendor/trezor-crypto/aes/gf128mul.c', + 'vendor/trezor-crypto/aes/aesgcm.c', + ] + + # modtrezorui CPPPATH_MOD += [ 'vendor/micropython/lib/uzlib' diff --git a/core/SConscript.unix b/core/SConscript.unix index 87470fc35c..bb77d3d096 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -51,7 +51,6 @@ SOURCE_MOD = [ 'vendor/micropython/extmod/vfs_posix_file.c', ] SOURCE_MOD_CRYPTO = [] -SOURCE_MOD_TROPIC = [] RUST_UI_FEATURES = [] # modtrezorconfig @@ -255,13 +254,8 @@ 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', @@ -790,7 +784,7 @@ if FROZEN: # obj_program = [] -source_files = SOURCE_MOD + SOURCE_MOD_CRYPTO + SOURCE_MOD_TROPIC + SOURCE_MICROPYTHON + SOURCE_UNIX +source_files = SOURCE_MOD + SOURCE_MOD_CRYPTO + 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"]: diff --git a/core/embed/projects/kernel/main.c b/core/embed/projects/kernel/main.c index 146652b240..46797630e6 100644 --- a/core/embed/projects/kernel/main.c +++ b/core/embed/projects/kernel/main.c @@ -57,6 +57,10 @@ #include #endif +#ifdef USE_TROPIC +#include +#endif + #ifdef USE_POWERCTL #include #endif @@ -167,6 +171,10 @@ void drivers_init() { #ifdef USE_OPTIGA optiga_init_and_configure(); #endif + +#ifdef USE_TROPIC + tropic_init(); +#endif } // defined in linker script diff --git a/core/embed/projects/unix/main.c b/core/embed/projects/unix/main.c index a06e288507..5f99c5a838 100644 --- a/core/embed/projects/unix/main.c +++ b/core/embed/projects/unix/main.c @@ -58,7 +58,7 @@ #ifdef USE_TROPIC #include -#include +#include #endif #include "py/builtin.h" diff --git a/core/embed/sec/secret/stm32u5/secret.c b/core/embed/sec/secret/stm32u5/secret.c index 3392e915ea..1750603b73 100644 --- a/core/embed/sec/secret/stm32u5/secret.c +++ b/core/embed/sec/secret/stm32u5/secret.c @@ -295,6 +295,16 @@ static void secret_optiga_uncache(void) { } #endif +#ifdef USE_TROPIC +secbool secret_tropic_get_trezor_privkey(uint8_t dest[SECRET_TROPIC_KEY_LEN]) { + return secfalse; +} + +secbool secret_tropic_get_tropic_pubkey(uint8_t dest[SECRET_TROPIC_KEY_LEN]) { + return secfalse; +} +#endif + void secret_optiga_erase(void) { uint8_t value[SECRET_OPTIGA_KEY_LEN] = {0}; secret_write(value, SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN); diff --git a/core/embed/sec/tropic/inc/sec/tropic.h b/core/embed/sec/tropic/inc/sec/tropic.h index cb2d332dbe..f0e8404534 100644 --- a/core/embed/sec/tropic/inc/sec/tropic.h +++ b/core/embed/sec/tropic/inc/sec/tropic.h @@ -21,6 +21,8 @@ #include +#ifdef KERNEL_MODE + #define TROPIC_CHIP_ID_SIZE 128 #define TROPIC_RISCV_FW_SIZE 4 #define TROPIC_SPECT_FW_SIZE 4 @@ -34,3 +36,14 @@ bool tropic_get_spect_fw_version(uint8_t* version_buffer, uint16_t max_len); bool tropic_get_riscv_fw_version(uint8_t* version_buffer, uint16_t max_len); bool tropic_get_chip_id(uint8_t* chip_id, uint16_t max_len); + +#endif + +bool tropic_ping(const uint8_t* msg_out, uint8_t* msg_in, uint16_t msg_len); + +bool tropic_get_cert(uint8_t* buf, uint16_t buf_size); + +bool tropic_ecc_key_generate(uint16_t slot_index); + +bool tropic_ecc_sign(uint16_t key_slot_index, const uint8_t* dig, + uint16_t dig_len, uint8_t* sig, uint16_t sig_len); diff --git a/core/embed/sec/tropic/stm32/tropic01.c b/core/embed/sec/tropic/stm32/tropic01.c index c19de5b704..2fd9cadb2c 100644 --- a/core/embed/sec/tropic/stm32/tropic01.c +++ b/core/embed/sec/tropic/stm32/tropic01.c @@ -16,6 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#ifdef KERNEL_MODE #include #include @@ -50,10 +51,9 @@ typedef struct { bool initialized; SPI_HandleTypeDef spi; - lt_handle_t handle; -} tropic01_driver_t; +} tropic01_hal_driver_t; -static tropic01_driver_t g_tropic01_driver = {.initialized = false}; +static tropic01_hal_driver_t g_tropic01_hal_driver = {.initialized = false}; void tropic01_reset(void) { HAL_GPIO_WritePin(TROPIC01_PWR_PORT, TROPIC01_PWR_PIN, GPIO_PIN_SET); @@ -62,8 +62,8 @@ void tropic01_reset(void) { systick_delay_ms(10); } -bool tropic_init(void) { - tropic01_driver_t *drv = &g_tropic01_driver; +bool tropic_hal_init(void) { + tropic01_hal_driver_t *drv = &g_tropic01_hal_driver; if (drv->initialized) { return true; @@ -137,24 +137,13 @@ bool tropic_init(void) { HAL_SPI_Init(&drv->spi); - if (LT_OK != lt_init(&drv->handle)) { - goto cleanup; - } - drv->initialized = true; return true; - -cleanup: - tropic_deinit(); - - return false; } -void tropic_deinit(void) { - tropic01_driver_t *drv = &g_tropic01_driver; - - lt_deinit(&drv->handle); +void tropic_hal_deinit(void) { + tropic01_hal_driver_t *drv = &g_tropic01_hal_driver; HAL_SPI_DeInit(&drv->spi); __HAL_RCC_SPI2_FORCE_RESET(); @@ -202,7 +191,7 @@ lt_ret_t lt_port_spi_csn_high(lt_handle_t *h) { lt_ret_t lt_port_spi_transfer(lt_handle_t *h, uint8_t offset, uint16_t tx_len, uint32_t timeout) { - tropic01_driver_t *drv = &g_tropic01_driver; + tropic01_hal_driver_t *drv = &g_tropic01_hal_driver; if (offset + tx_len > LT_L1_LEN_MAX) { return LT_L1_DATA_LEN_ERROR; @@ -235,46 +224,4 @@ lt_ret_t lt_port_random_bytes(uint32_t *buff, uint16_t len) { return LT_OK; } -bool tropic_get_spect_fw_version(uint8_t *version_buffer, uint16_t max_len) { - tropic01_driver_t *drv = &g_tropic01_driver; - - if (!drv->initialized) { - return false; - } - - if (LT_OK != lt_get_info_spect_fw_ver(&drv->handle, (uint8_t *)version_buffer, - max_len)) { - return false; - } - - return true; -} - -bool tropic_get_riscv_fw_version(uint8_t *version_buffer, uint16_t max_len) { - tropic01_driver_t *drv = &g_tropic01_driver; - - if (!drv->initialized) { - return false; - } - - if (LT_OK != lt_get_info_riscv_fw_ver(&drv->handle, (uint8_t *)version_buffer, - max_len)) { - return false; - } - - return true; -} - -bool tropic_get_chip_id(uint8_t *chip_id, uint16_t max_len) { - tropic01_driver_t *drv = &g_tropic01_driver; - - if (!drv->initialized) { - return false; - } - - if (LT_OK != lt_get_info_chip_id(&drv->handle, (uint8_t *)chip_id, max_len)) { - return false; - } - - return true; -} +#endif diff --git a/core/embed/sec/tropic/tropic.c b/core/embed/sec/tropic/tropic.c new file mode 100644 index 0000000000..25618e42c0 --- /dev/null +++ b/core/embed/sec/tropic/tropic.c @@ -0,0 +1,207 @@ +/* + * 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 . + */ + +#ifdef KERNEL_MODE + +#include +#include + +#include +#include + +#include + +#include "ed25519-donna/ed25519.h" +#include "memzero.h" +#include "tropic_internal.h" + +#define PKEY_INDEX_BYTE PAIRING_KEY_SLOT_INDEX_0 + +typedef struct { + bool initialized; + bool sec_chan_established; + lt_handle_t handle; +} tropic_driver_t; + +static tropic_driver_t g_tropic_driver = {0}; + +bool tropic_init(void) { + tropic_driver_t *drv = &g_tropic_driver; + + if (drv->initialized) { + return true; + } + + uint8_t tropic_secret_tropic_pubkey[SECRET_TROPIC_KEY_LEN] = {0}; + uint8_t tropic_secret_trezor_privkey[SECRET_TROPIC_KEY_LEN] = {0}; + + if (!tropic_hal_init()) { + goto cleanup; + } + + if (lt_init(&drv->handle) != LT_OK) { + tropic_hal_deinit(); + goto cleanup; + } + + secbool pubkey_ok = + secret_tropic_get_tropic_pubkey(tropic_secret_tropic_pubkey); + secbool privkey_ok = + secret_tropic_get_trezor_privkey(tropic_secret_trezor_privkey); + + if (pubkey_ok == sectrue && privkey_ok == sectrue) { + uint8_t trezor_pubkey[SECRET_TROPIC_KEY_LEN] = {0}; + curve25519_scalarmult_basepoint(trezor_pubkey, + tropic_secret_trezor_privkey); + + lt_ret_t ret = lt_session_start( + &drv->handle, tropic_secret_tropic_pubkey, PKEY_INDEX_BYTE, + tropic_secret_trezor_privkey, trezor_pubkey); + + // todo delete the ensure + ensure((ret == LT_OK) * sectrue, "lt_session_start failed"); + drv->sec_chan_established = (ret == LT_OK); + } + + memzero(tropic_secret_trezor_privkey, sizeof(tropic_secret_trezor_privkey)); + memzero(tropic_secret_trezor_privkey, sizeof(tropic_secret_tropic_pubkey)); + + drv->initialized = true; + + return true; + +cleanup: + tropic_deinit(); + return false; +} + +void tropic_deinit(void) { + tropic_driver_t *drv = &g_tropic_driver; + + lt_deinit(&drv->handle); + + tropic_hal_deinit(); + + memset(drv, 0, sizeof(*drv)); +} + +bool tropic_get_spect_fw_version(uint8_t *version_buffer, uint16_t max_len) { + tropic_driver_t *drv = &g_tropic_driver; + + if (!drv->initialized) { + return false; + } + + if (LT_OK != lt_get_info_spect_fw_ver(&drv->handle, (uint8_t *)version_buffer, + max_len)) { + return false; + } + + return true; +} + +bool tropic_get_riscv_fw_version(uint8_t *version_buffer, uint16_t max_len) { + tropic_driver_t *drv = &g_tropic_driver; + + if (!drv->initialized) { + return false; + } + + if (LT_OK != lt_get_info_riscv_fw_ver(&drv->handle, (uint8_t *)version_buffer, + max_len)) { + return false; + } + + return true; +} + +bool tropic_get_chip_id(uint8_t *chip_id, uint16_t max_len) { + tropic_driver_t *drv = &g_tropic_driver; + + if (!drv->initialized) { + return false; + } + + if (LT_OK != lt_get_info_chip_id(&drv->handle, (uint8_t *)chip_id, max_len)) { + return false; + } + + return true; +} + +bool tropic_ping(const uint8_t *msg_out, uint8_t *msg_in, uint16_t msg_len) { + tropic_driver_t *drv = &g_tropic_driver; + + if (!drv->initialized) { + return false; + } + + lt_ret_t res = lt_ping(&drv->handle, msg_out, msg_in, msg_len); + return res == LT_OK; +} + +bool tropic_get_cert(uint8_t *buf, uint16_t buf_size) { + tropic_driver_t *drv = &g_tropic_driver; + + if (!drv->initialized) { + return false; + } + + lt_ret_t res = lt_get_info_cert(&drv->handle, buf, buf_size); + return res == LT_OK; +} + +bool tropic_ecc_key_generate(uint16_t slot_index) { + tropic_driver_t *drv = &g_tropic_driver; + + if (!drv->initialized) { + return false; + } + + if (slot_index > ECC_SLOT_31) { + return false; + } + + lt_ret_t ret = lt_ecc_key_generate(&drv->handle, slot_index, CURVE_ED25519); + return ret == LT_OK; +} + +bool tropic_ecc_sign(uint16_t key_slot_index, const uint8_t *dig, + uint16_t dig_len, uint8_t *sig, uint16_t sig_len) { + tropic_driver_t *drv = &g_tropic_driver; + + if (!drv->initialized) { + return false; + } + + if (key_slot_index > ECC_SLOT_31) { + return false; + } + + lt_ret_t res = lt_ecc_eddsa_sign(&drv->handle, key_slot_index, dig, dig_len, + sig, sig_len); + if (res != LT_OK) { + memzero(sig, sig_len); + return false; + } + + return true; +} + +#endif diff --git a/core/embed/sec/tropic/inc/sec/tropic_transport.h b/core/embed/sec/tropic/tropic_internal.h similarity index 87% rename from core/embed/sec/tropic/inc/sec/tropic_transport.h rename to core/embed/sec/tropic/tropic_internal.h index fa3cb0560e..6a43ce1d21 100644 --- a/core/embed/sec/tropic/inc/sec/tropic_transport.h +++ b/core/embed/sec/tropic/tropic_internal.h @@ -17,9 +17,10 @@ * along with this program. If not, see . */ -#ifndef TREZORHAL_TROPIC_TRANSPORT_H -#define TREZORHAL_TROPIC_TRANSPORT_H +#pragma once -void tropic_init(void); +#include -#endif +bool tropic_hal_init(void); + +void tropic_hal_deinit(void); diff --git a/core/embed/sec/tropic/tropic_transport.c b/core/embed/sec/tropic/tropic_transport.c deleted file mode 100644 index 94747cea21..0000000000 --- a/core/embed/sec/tropic/tropic_transport.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 . - */ - -#include -#include -#include -#include -#include "ed25519-donna/ed25519.h" -#include "libtropic.h" -#include "memzero.h" - -#define PKEY_INDEX_BYTE PAIRING_KEY_SLOT_INDEX_0 - -STATIC lt_handle_t lt_handle = {0}; - -void tropic_init(void) { - uint8_t tropic_secret_tropic_pubkey[SECRET_TROPIC_KEY_LEN] = {0}; - uint8_t tropic_secret_trezor_privkey[SECRET_TROPIC_KEY_LEN] = {0}; - - ensure((lt_init(<_handle) == LT_OK) * sectrue, "lt_init failed"); - - ensure(secret_tropic_get_tropic_pubkey(tropic_secret_tropic_pubkey), - "secret_tropic_get_tropic_pubkey failed"); - ensure(secret_tropic_get_trezor_privkey(tropic_secret_trezor_privkey), - "secret_tropic_get_trezor_privkey failed"); - - uint8_t trezor_pubkey[SECRET_TROPIC_KEY_LEN] = {}; - curve25519_scalarmult_basepoint(trezor_pubkey, tropic_secret_trezor_privkey); - - lt_ret_t ret = LT_FAIL; - ret = - lt_session_start(<_handle, tropic_secret_tropic_pubkey, PKEY_INDEX_BYTE, - tropic_secret_trezor_privkey, trezor_pubkey); - memzero(tropic_secret_trezor_privkey, sizeof(tropic_secret_trezor_privkey)); - - ensure((ret == LT_OK) * sectrue, "lt_session_start failed"); -} diff --git a/core/embed/sec/tropic/unix/tropic01.c b/core/embed/sec/tropic/unix/tropic01.c new file mode 100644 index 0000000000..3e345df054 --- /dev/null +++ b/core/embed/sec/tropic/unix/tropic01.c @@ -0,0 +1,27 @@ +/* + * 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 . + */ +#ifdef KERNEL_MODE + +#include + +bool tropic_hal_init(void) { return true; } + +void tropic_hal_deinit(void) {} + +#endif diff --git a/core/embed/sys/syscall/stm32/syscall_dispatch.c b/core/embed/sys/syscall/stm32/syscall_dispatch.c index 1fbed25511..61e9fb583b 100644 --- a/core/embed/sys/syscall/stm32/syscall_dispatch.c +++ b/core/embed/sys/syscall/stm32/syscall_dispatch.c @@ -825,6 +825,37 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args, } break; #endif // USE_DMA2D +#ifdef USE_TROPIC + case SYSCALL_TROPIC_PING: { + const uint8_t *msg_out = (const uint8_t *)args[0]; + uint8_t *msg_in = (uint8_t *)args[1]; + uint16_t msg_len = (uint16_t)args[2]; + args[0] = tropic_ping__verified(msg_out, msg_in, msg_len); + } break; + + case SYSCALL_TROPIC_GET_CERT: { + uint8_t *buf = (uint8_t *)args[0]; + uint16_t buf_size = (uint16_t)args[1]; + args[0] = tropic_get_cert__verified(buf, buf_size); + } break; + case SYSCALL_TROPIC_ECC_KEY_GENERATE: { + uint16_t slot_index = (uint16_t)args[0]; + args[0] = tropic_ecc_key_generate__verified(slot_index); + + } break; + case SYSCALL_TROPIC_ECC_SIGN: { + uint16_t key_slot_index = (uint16_t)args[0]; + const uint8_t *dig = (const uint8_t *)args[1]; + uint16_t dig_len = (uint16_t)args[2]; + uint8_t *sig = (uint8_t *)args[3]; + uint16_t sig_len = (uint16_t)args[4]; + + args[0] = + tropic_ecc_sign__verified(key_slot_index, dig, dig_len, sig, sig_len); + + } break; +#endif + default: system_exit_fatal("Invalid syscall", __FILE__, __LINE__); break; diff --git a/core/embed/sys/syscall/stm32/syscall_numbers.h b/core/embed/sys/syscall/stm32/syscall_numbers.h index b201521674..fe1f8886f9 100644 --- a/core/embed/sys/syscall/stm32/syscall_numbers.h +++ b/core/embed/sys/syscall/stm32/syscall_numbers.h @@ -169,4 +169,9 @@ typedef enum { SYSCALL_DMA2D_RGBA8888_BLEND_MONO4, SYSCALL_DMA2D_RGBA8888_BLEND_MONO8, + SYSCALL_TROPIC_PING, + SYSCALL_TROPIC_GET_CERT, + SYSCALL_TROPIC_ECC_KEY_GENERATE, + SYSCALL_TROPIC_ECC_SIGN, + } syscall_number_t; diff --git a/core/embed/sys/syscall/stm32/syscall_stubs.c b/core/embed/sys/syscall/stm32/syscall_stubs.c index 8a9ff70241..228e55c19c 100644 --- a/core/embed/sys/syscall/stm32/syscall_stubs.c +++ b/core/embed/sys/syscall/stm32/syscall_stubs.c @@ -783,4 +783,29 @@ bool dma2d_rgba8888_blend_mono8(const gfx_bitblt_t *bb) { #endif // USE_DMA2D +#ifdef USE_TROPIC + +bool tropic_ping(const uint8_t *msg_in, uint8_t *msg_out, uint16_t msg_len) { + return (bool)syscall_invoke3((uint32_t)msg_in, (uint32_t)msg_out, msg_len, + SYSCALL_TROPIC_PING); +} + +bool tropic_get_cert(uint8_t *buf, uint16_t buf_size) { + return (bool)syscall_invoke2((uint32_t)buf, buf_size, + SYSCALL_TROPIC_GET_CERT); +} + +bool tropic_ecc_key_generate(uint16_t slot_index) { + return (bool)syscall_invoke1((uint32_t)slot_index, + SYSCALL_TROPIC_ECC_KEY_GENERATE); +} + +bool tropic_ecc_sign(uint16_t key_slot_index, const uint8_t *dig, + uint16_t dig_len, uint8_t *sig, uint16_t sig_len) { + return (bool)syscall_invoke5((uint32_t)key_slot_index, (uint32_t)dig, dig_len, + (uint32_t)sig, sig_len, SYSCALL_TROPIC_ECC_SIGN); +} + +#endif + #endif // KERNEL_MODE diff --git a/core/embed/sys/syscall/stm32/syscall_verifiers.c b/core/embed/sys/syscall/stm32/syscall_verifiers.c index 031fc97838..84e9b60bbf 100644 --- a/core/embed/sys/syscall/stm32/syscall_verifiers.c +++ b/core/embed/sys/syscall/stm32/syscall_verifiers.c @@ -1072,4 +1072,56 @@ access_violation: #endif +#ifdef USE_TROPIC +#include + +bool tropic_ping__verified(const uint8_t *msg_out, uint8_t *msg_in, + uint16_t msg_len) { + if (!probe_read_access(msg_out, msg_len)) { + goto access_violation; + } + + if (!probe_write_access(msg_in, msg_len)) { + goto access_violation; + } + + return tropic_ping(msg_out, msg_in, msg_len); +access_violation: + apptask_access_violation(); + return false; +} + +bool tropic_get_cert__verified(uint8_t *buf, uint16_t buf_size) { + if (!probe_write_access(buf, buf_size)) { + goto access_violation; + } + + return tropic_get_cert(buf, buf_size); +access_violation: + apptask_access_violation(); + return false; +} + +bool tropic_ecc_key_generate__verified(uint16_t slot_index) { + return tropic_ecc_key_generate(slot_index); +} + +bool tropic_ecc_sign__verified(uint16_t key_slot_index, const uint8_t *dig, + uint16_t dig_len, uint8_t *sig, + uint16_t sig_len) { + if (!probe_read_access(dig, dig_len)) { + goto access_violation; + } + + if (!probe_write_access(sig, sig_len)) { + goto access_violation; + } + + return tropic_ecc_sign(key_slot_index, dig, dig_len, sig, sig_len); +access_violation: + apptask_access_violation(); + return false; +} +#endif + #endif // SYSCALL_DISPATCH diff --git a/core/embed/sys/syscall/stm32/syscall_verifiers.h b/core/embed/sys/syscall/stm32/syscall_verifiers.h index c5cf506739..1b27116b33 100644 --- a/core/embed/sys/syscall/stm32/syscall_verifiers.h +++ b/core/embed/sys/syscall/stm32/syscall_verifiers.h @@ -264,4 +264,20 @@ bool button_get_event__verified(button_event_t *event); #endif +// --------------------------------------------------------------------- +#ifdef USE_TROPIC + +bool tropic_ping__verified(const uint8_t *msg_out, uint8_t *msg_in, + uint16_t msg_len); + +bool tropic_get_cert__verified(uint8_t *buf, uint16_t buf_size); + +bool tropic_ecc_key_generate__verified(uint16_t slot_index); + +bool tropic_ecc_sign__verified(uint16_t key_slot_index, const uint8_t *dig, + uint16_t dig_len, uint8_t *sig, + uint16_t sig_len); + +#endif + #endif // SYSCALL_DISPATCH diff --git a/core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h b/core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h index febdb08cfc..99a3b5a5e2 100644 --- a/core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h +++ b/core/embed/upymod/modtrezorcrypto/modtrezorcrypto-tropic.h @@ -20,10 +20,7 @@ #if USE_TROPIC #include -#include -#include "libtropic.h" - -extern STATIC lt_handle_t lt_handle; +#include /// package: trezorcrypto.tropic @@ -42,16 +39,13 @@ MP_DEFINE_EXCEPTION(TropicError, Exception) /// 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; - mp_buffer_info_t message_b = {0}; mp_get_buffer_raise(message, &message_b, MP_BUFFER_READ); uint8_t msg_in[message_b.len]; - 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."); + bool ret = tropic_ping(message_b.buf, msg_in, message_b.len); + if (!ret) { + mp_raise_msg(&mp_type_TropicError, "tropic_ping failed."); } vstr_t result = {0}; @@ -69,12 +63,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_tropic_ping_obj, /// Return the chip's certificate. /// """ STATIC mp_obj_t mod_trezorcrypto_tropic_get_certificate() { - lt_ret_t ret = LT_FAIL; - uint8_t X509_cert[CERT_SIZE] = {0}; - ret = lt_get_info_cert(<_handle, X509_cert, CERT_SIZE); - if (ret != LT_OK) { - mp_raise_msg(&mp_type_TropicError, "lt_get_info_cert failed."); + bool ret = tropic_get_cert(X509_cert, CERT_SIZE); + if (!ret) { + mp_raise_msg(&mp_type_TropicError, "tropic_get_cert failed."); } vstr_t vstr = {0}; @@ -99,11 +91,9 @@ STATIC mp_obj_t mod_trezorcrypto_tropic_key_generate(mp_obj_t key_index) { mp_raise_ValueError("Invalid index."); } - lt_ret_t ret = LT_FAIL; - - ret = lt_ecc_key_generate(<_handle, idx, CURVE_ED25519); - if (ret != LT_OK) { - mp_raise_msg(&mp_type_TropicError, "lt_ecc_key_generate failed."); + bool ret = tropic_ecc_key_generate(idx); + if (!ret) { + mp_raise_msg(&mp_type_TropicError, "tropic_ecc_key_generate failed."); } return mp_const_none; @@ -131,14 +121,12 @@ STATIC mp_obj_t mod_trezorcrypto_tropic_sign(mp_obj_t key_index, mp_raise_ValueError("Invalid length of digest."); } - lt_ret_t ret = LT_FAIL; - 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) { + bool ret = tropic_ecc_sign(idx, (const uint8_t *)dig.buf, dig.len, + ((uint8_t *)sig.buf), SIG_SIZE); + if (!ret) { vstr_clear(&sig); mp_raise_msg(&mp_type_TropicError, "lt_ecc_eddsa_sign failed."); } diff --git a/core/site_scons/models/T3W1/emulator.py b/core/site_scons/models/T3W1/emulator.py index 0aa1eb5beb..cc5cf28d3c 100644 --- a/core/site_scons/models/T3W1/emulator.py +++ b/core/site_scons/models/T3W1/emulator.py @@ -55,7 +55,8 @@ def configure( if "tropic" in features_wanted: sources += [ "embed/sec/secret/unix/secret.c", - "embed/sec/tropic/tropic_transport.c", + "embed/sec/tropic/tropic.c", + "embed/sec/tropic/unix/tropic01.c", "vendor/libtropic/src/libtropic.c", "vendor/libtropic/src/lt_crc16.c", "vendor/libtropic/src/lt_hkdf.c", @@ -72,6 +73,8 @@ def configure( "vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_x25519.c", ] paths += ["embed/sec/tropic/inc"] + paths += ["vendor/libtropic/include"] + paths += ["vendor/libtropic/src"] defines += ["USE_TREZOR_CRYPTO"] features_available.append("tropic") defines += ["USE_TROPIC=1"] diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revA.py b/core/site_scons/models/T3W1/trezor_t3w1_revA.py index 8f94eca4bb..05bfcc8194 100644 --- a/core/site_scons/models/T3W1/trezor_t3w1_revA.py +++ b/core/site_scons/models/T3W1/trezor_t3w1_revA.py @@ -137,6 +137,7 @@ def configure( defines += [("USE_OPTIGA", "1")] if "tropic" in features_wanted: + sources += ["embed/sec/tropic/tropic.c"] sources += ["embed/sec/tropic/stm32/tropic01.c"] sources += ["vendor/libtropic/src/libtropic.c"] sources += ["vendor/libtropic/src/lt_crc16.c"] diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revB.py b/core/site_scons/models/T3W1/trezor_t3w1_revB.py index 6d81b310fd..79f1d98a03 100644 --- a/core/site_scons/models/T3W1/trezor_t3w1_revB.py +++ b/core/site_scons/models/T3W1/trezor_t3w1_revB.py @@ -137,6 +137,7 @@ def configure( defines += [("USE_OPTIGA", "1")] if "tropic" in features_wanted: + sources += ["embed/sec/tropic/tropic.c"] sources += ["embed/sec/tropic/stm32/tropic01.c"] sources += ["vendor/libtropic/src/libtropic.c"] sources += ["vendor/libtropic/src/lt_crc16.c"] diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revC.py b/core/site_scons/models/T3W1/trezor_t3w1_revC.py index e25a6b0024..b737b8e59e 100644 --- a/core/site_scons/models/T3W1/trezor_t3w1_revC.py +++ b/core/site_scons/models/T3W1/trezor_t3w1_revC.py @@ -137,6 +137,7 @@ def configure( defines += [("USE_OPTIGA", "1")] if "tropic" in features_wanted: + sources += ["embed/sec/tropic/tropic.c"] sources += ["embed/sec/tropic/stm32/tropic01.c"] sources += ["vendor/libtropic/src/libtropic.c"] sources += ["vendor/libtropic/src/lt_crc16.c"]