diff --git a/.gitmodules b/.gitmodules
index 3412a6b589..31b25b3738 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -31,3 +31,6 @@
[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
diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest
index 98891babb8..d245a544c8 100644
--- a/core/SConscript.prodtest
+++ b/core/SConscript.prodtest
@@ -9,7 +9,7 @@ PRODUCTION = ARGUMENTS.get('PRODUCTION', '0') == '1'
BOOTLOADER_DEVEL = ARGUMENTS.get('BOOTLOADER_DEVEL', '0') == '1'
HW_REVISION = ARGUMENTS.get('HW_REVISION', None)
-FEATURES_WANTED = ["input", "sbu", "sd_card", "rgb_led", "usb", "consumption_mask", "optiga", "haptic", "ble"]
+FEATURES_WANTED = ["input", "sbu", "sd_card", "rgb_led", "usb", "consumption_mask", "optiga", "haptic", "ble", "tropic"]
CCFLAGS_MOD = ''
CPPPATH_MOD = []
@@ -118,6 +118,7 @@ SOURCE_PRODTEST = [
'embed/projects/prodtest/cmd/prodtest_sdcard.c',
'embed/projects/prodtest/cmd/prodtest_sbu.c',
'embed/projects/prodtest/cmd/prodtest_touch.c',
+ 'embed/projects/prodtest/cmd/prodtest_tropic.c',
'embed/projects/prodtest/cmd/prodtest_wpc.c',
]
diff --git a/core/embed/projects/prodtest/README.md b/core/embed/projects/prodtest/README.md
index e8458a85e7..42072a385e 100644
--- a/core/embed/projects/prodtest/README.md
+++ b/core/embed/projects/prodtest/README.md
@@ -660,6 +660,36 @@ powerctl-hibernate
OK
```
+### tropic-get-riscv-fw-version
+
+Reads the version of the RISC-V firmware. The command returns `OK` followed by the version.
+
+Example:
+```
+tropic-get-riscv-fw-version
+OK 00020100
+```
+
+### tropic-get-spect-fw-version
+
+Reads the version of the SPECT firmware. The command returns `OK` followed by the version.
+
+Example:
+```
+tropic-get-spect-fw-version
+OK 00000300
+```
+
+### tropic-get-chip-id
+
+Reads the Tropic chip ID. The command returns `OK` followed by the chip ID.
+
+Example:
+```
+tropic-get-chip-id
+OK 00000001000000000000000000000000000000000000000000000000000000000000000001000000054400000000FFFFFFFFFFFF01F00F000544545354303103001300000B54524F50494330312D4553FFFFFFFF000100000000FFFF000100000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13000300
+```
+
### wpc-init
Reinitializes the wireless power receiver driver, restoring it to its default state.
diff --git a/core/embed/projects/prodtest/cmd/prodtest_tropic.c b/core/embed/projects/prodtest/cmd/prodtest_tropic.c
new file mode 100644
index 0000000000..3acd8ddf08
--- /dev/null
+++ b/core/embed/projects/prodtest/cmd/prodtest_tropic.c
@@ -0,0 +1,98 @@
+/*
+ * 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 USE_TROPIC
+
+#include
+
+#include
+#include
+
+static void prodtest_tropic_get_riscv_fw_version(cli_t* cli) {
+ if (cli_arg_count(cli) > 0) {
+ cli_error_arg_count(cli);
+ return;
+ }
+
+ uint8_t version[LT_L2_GET_INFO_RISCV_FW_SIZE];
+ if (!tropic_get_riscv_fw_version(version, sizeof(version))) {
+ cli_error(cli, CLI_ERROR, "Unable to get RISCV FW version");
+ }
+
+ // Respond with an OK message and version
+ cli_ok_hexdata(cli, &version, sizeof(version));
+}
+
+static void prodtest_tropic_get_spect_fw_version(cli_t* cli) {
+ if (cli_arg_count(cli) > 0) {
+ cli_error_arg_count(cli);
+ return;
+ }
+
+ uint8_t version[LT_L2_GET_INFO_SPECT_FW_SIZE];
+ if (!tropic_get_spect_fw_version(version, sizeof(version))) {
+ cli_error(cli, CLI_ERROR, "Unable to get SPECT FW version");
+ }
+
+ // Respond with an OK message and version
+ cli_ok_hexdata(cli, &version, sizeof(version));
+}
+
+static void prodtest_tropic_get_chip_id(cli_t* cli) {
+ if (cli_arg_count(cli) > 0) {
+ cli_error_arg_count(cli);
+ return;
+ }
+
+ uint8_t chip_id[LT_L2_GET_INFO_CHIP_ID_SIZE];
+ if (!tropic_get_chip_id(chip_id, sizeof(chip_id))) {
+ cli_error(cli, CLI_ERROR, "Unable to get CHIP ID");
+ }
+
+ // Respond with an OK message and chip ID
+ cli_ok_hexdata(cli, &chip_id, sizeof(chip_id));
+}
+
+// clang-format off
+
+PRODTEST_CLI_CMD(
+ .name = "tropic-get-riscv-fw-version",
+ .func = prodtest_tropic_get_riscv_fw_version,
+ .info = "Get RISCV FW version",
+ .args = ""
+);
+
+PRODTEST_CLI_CMD(
+ .name = "tropic-get-spect-fw-version",
+ .func = prodtest_tropic_get_spect_fw_version,
+ .info = "Get SPECT FW version",
+ .args = ""
+);
+
+PRODTEST_CLI_CMD(
+ .name = "tropic-get-chip-id",
+ .func = prodtest_tropic_get_chip_id,
+ .info = "Get Tropic CHIP ID",
+ .args = ""
+);
+
+
+
+
+#endif
diff --git a/core/embed/projects/prodtest/main.c b/core/embed/projects/prodtest/main.c
index 10dffcc807..cbf4af7ec6 100644
--- a/core/embed/projects/prodtest/main.c
+++ b/core/embed/projects/prodtest/main.c
@@ -52,6 +52,10 @@
#include "cmd/prodtest_optiga.h"
#endif
+#ifdef USE_TROPIC
+#include
+#endif
+
#ifdef USE_HAPTIC
#include
#endif
@@ -192,6 +196,9 @@ static void drivers_init(void) {
#ifdef USE_RGB_LED
rgb_led_init();
#endif
+#ifdef USE_TROPIC
+ tropic_init();
+#endif
#ifdef USE_BLE
unit_properties_init();
ble_init();
diff --git a/core/embed/sec/tropic/inc/sec/tropic.h b/core/embed/sec/tropic/inc/sec/tropic.h
new file mode 100644
index 0000000000..685e8e0087
--- /dev/null
+++ b/core/embed/sec/tropic/inc/sec/tropic.h
@@ -0,0 +1,34 @@
+/*
+ * 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 .
+ */
+
+#pragma once
+
+#include
+
+#include
+
+bool tropic_init(void);
+
+void tropic_deinit(void);
+
+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);
diff --git a/core/embed/sec/tropic/stm32/tropic01.c b/core/embed/sec/tropic/stm32/tropic01.c
new file mode 100644
index 0000000000..c19de5b704
--- /dev/null
+++ b/core/embed/sec/tropic/stm32/tropic01.c
@@ -0,0 +1,280 @@
+/*
+ * 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
+#include
+
+#define TROPIC01_PWR_PORT GPIOB
+#define TROPIC01_PWR_PIN GPIO_PIN_11
+#define TROPIC01_PWR_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+
+#define TROPIC01_INT_PORT GPIOB
+#define TROPIC01_INT_PIN GPIO_PIN_11
+#define TROPIC01_INT_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+
+#define TROPIC01_SPI_SCK_PORT GPIOB
+#define TROPIC01_SPI_SCK_PIN GPIO_PIN_13
+#define TROPIC01_SPI_SCK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define TROPIC01_SPI_MISO_PORT GPIOB
+#define TROPIC01_SPI_MISO_PIN GPIO_PIN_14
+#define TROPIC01_SPI_MISO_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define TROPIC01_SPI_MOSI_PORT GPIOB
+#define TROPIC01_SPI_MOSI_PIN GPIO_PIN_15
+#define TROPIC01_SPI_MOSI_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define TROPIC01_SPI_NSS_PORT GPIOI
+#define TROPIC01_SPI_NSS_PIN GPIO_PIN_0
+#define TROPIC01_SPI_NSS_EN __HAL_RCC_GPIOI_CLK_ENABLE
+
+typedef struct {
+ bool initialized;
+ SPI_HandleTypeDef spi;
+ lt_handle_t handle;
+} tropic01_driver_t;
+
+static tropic01_driver_t g_tropic01_driver = {.initialized = false};
+
+void tropic01_reset(void) {
+ HAL_GPIO_WritePin(TROPIC01_PWR_PORT, TROPIC01_PWR_PIN, GPIO_PIN_SET);
+ systick_delay_ms(10);
+ HAL_GPIO_WritePin(TROPIC01_PWR_PORT, TROPIC01_PWR_PIN, GPIO_PIN_RESET);
+ systick_delay_ms(10);
+}
+
+bool tropic_init(void) {
+ tropic01_driver_t *drv = &g_tropic01_driver;
+
+ if (drv->initialized) {
+ return true;
+ }
+
+ GPIO_InitTypeDef GPIO_InitStructure = {0};
+
+ TROPIC01_INT_CLK_EN();
+ GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStructure.Alternate = 0;
+ GPIO_InitStructure.Pin = TROPIC01_INT_PIN;
+ HAL_GPIO_Init(TROPIC01_INT_PORT, &GPIO_InitStructure);
+ HAL_GPIO_WritePin(TROPIC01_INT_PORT, TROPIC01_INT_PIN, GPIO_PIN_RESET);
+
+ TROPIC01_PWR_CLK_EN();
+ GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStructure.Alternate = 0;
+ GPIO_InitStructure.Pin = TROPIC01_PWR_PIN;
+ HAL_GPIO_Init(TROPIC01_PWR_PORT, &GPIO_InitStructure);
+ HAL_GPIO_WritePin(TROPIC01_PWR_PORT, TROPIC01_PWR_PIN, GPIO_PIN_RESET);
+
+ TROPIC01_SPI_NSS_EN();
+ GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStructure.Alternate = 0;
+ GPIO_InitStructure.Pin = TROPIC01_SPI_NSS_PIN;
+ HAL_GPIO_Init(TROPIC01_SPI_NSS_PORT, &GPIO_InitStructure);
+ HAL_GPIO_WritePin(TROPIC01_SPI_NSS_PORT, TROPIC01_SPI_NSS_PIN, GPIO_PIN_SET);
+
+ systick_delay_ms(10);
+
+ // spi pins
+ TROPIC01_SPI_SCK_EN();
+ TROPIC01_SPI_MISO_EN();
+ TROPIC01_SPI_MOSI_EN();
+ GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStructure.Alternate = GPIO_AF5_SPI2;
+ GPIO_InitStructure.Pin = TROPIC01_SPI_SCK_PIN;
+ HAL_GPIO_Init(TROPIC01_SPI_SCK_PORT, &GPIO_InitStructure);
+
+ GPIO_InitStructure.Pin = TROPIC01_SPI_SCK_PIN;
+ HAL_GPIO_Init(TROPIC01_SPI_SCK_PORT, &GPIO_InitStructure);
+ GPIO_InitStructure.Pin = TROPIC01_SPI_MISO_PIN;
+ HAL_GPIO_Init(TROPIC01_SPI_MISO_PORT, &GPIO_InitStructure);
+ GPIO_InitStructure.Pin = TROPIC01_SPI_MOSI_PIN;
+ HAL_GPIO_Init(TROPIC01_SPI_MOSI_PORT, &GPIO_InitStructure);
+
+ __HAL_RCC_SPI2_CLK_ENABLE();
+ __HAL_RCC_SPI2_FORCE_RESET();
+ __HAL_RCC_SPI2_RELEASE_RESET();
+
+ drv->spi.Instance = SPI2;
+ drv->spi.Init.Mode = SPI_MODE_MASTER;
+ drv->spi.Init.Direction = SPI_DIRECTION_2LINES;
+ drv->spi.Init.DataSize = SPI_DATASIZE_8BIT;
+ drv->spi.Init.CLKPolarity = SPI_POLARITY_LOW;
+ drv->spi.Init.CLKPhase = SPI_PHASE_1EDGE;
+ drv->spi.Init.NSS = SPI_NSS_HARD_OUTPUT;
+ drv->spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
+ drv->spi.Init.FirstBit = SPI_FIRSTBIT_MSB;
+ drv->spi.Init.TIMode = SPI_TIMODE_DISABLE;
+ drv->spi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ drv->spi.Init.CRCPolynomial = 0;
+
+ 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);
+
+ HAL_SPI_DeInit(&drv->spi);
+ __HAL_RCC_SPI2_FORCE_RESET();
+ __HAL_RCC_SPI2_RELEASE_RESET();
+ __HAL_RCC_SPI2_CLK_DISABLE();
+
+ HAL_GPIO_DeInit(TROPIC01_INT_PORT, TROPIC01_INT_PIN);
+ HAL_GPIO_DeInit(TROPIC01_PWR_PORT, TROPIC01_PWR_PIN);
+ HAL_GPIO_DeInit(TROPIC01_SPI_NSS_PORT, TROPIC01_SPI_NSS_PIN);
+ HAL_GPIO_DeInit(TROPIC01_SPI_SCK_PORT, TROPIC01_SPI_SCK_PIN);
+ HAL_GPIO_DeInit(TROPIC01_SPI_MISO_PORT, TROPIC01_SPI_MISO_PIN);
+ HAL_GPIO_DeInit(TROPIC01_SPI_MOSI_PORT, TROPIC01_SPI_MOSI_PIN);
+
+ memset(drv, 0, sizeof(*drv));
+}
+
+lt_ret_t lt_port_init(lt_handle_t *h) {
+ UNUSED(h);
+ // no action, as we initialize separately
+ return LT_OK;
+}
+
+lt_ret_t lt_port_deinit(lt_handle_t *h) {
+ UNUSED(h);
+ // no action, as we deinitialize separately
+ return LT_OK;
+}
+
+lt_ret_t lt_port_spi_csn_low(lt_handle_t *h) {
+ UNUSED(h);
+
+ HAL_GPIO_WritePin(TROPIC01_SPI_NSS_PORT, TROPIC01_SPI_NSS_PIN,
+ GPIO_PIN_RESET);
+
+ return LT_OK;
+}
+
+lt_ret_t lt_port_spi_csn_high(lt_handle_t *h) {
+ UNUSED(h);
+
+ HAL_GPIO_WritePin(TROPIC01_SPI_NSS_PORT, TROPIC01_SPI_NSS_PIN, GPIO_PIN_SET);
+
+ return LT_OK;
+}
+
+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;
+
+ if (offset + tx_len > LT_L1_LEN_MAX) {
+ return LT_L1_DATA_LEN_ERROR;
+ }
+ int ret = HAL_SPI_TransmitReceive(&drv->spi, h->l2_buff + offset,
+ h->l2_buff + offset, tx_len, timeout);
+ if (ret != HAL_OK) {
+ return LT_FAIL;
+ }
+
+ return LT_OK;
+}
+
+lt_ret_t lt_port_delay(lt_handle_t *h, uint32_t ms) {
+ UNUSED(h);
+
+ systick_delay_ms(ms);
+
+ return LT_OK;
+}
+
+lt_ret_t lt_port_random_bytes(uint32_t *buff, uint16_t len) {
+ while (len > 0) {
+ uint32_t random = rng_get();
+ *buff = random;
+ buff++;
+ 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;
+}
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revA.py b/core/site_scons/models/T3W1/trezor_t3w1_revA.py
index 48e7da96f5..4ad20e5cad 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revA.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revA.py
@@ -102,6 +102,35 @@ def configure(
features_available.append("optiga")
defines += [("USE_OPTIGA", "1")]
+ if "tropic" in features_wanted:
+ sources += ["embed/sec/tropic/stm32/tropic01.c"]
+ sources += ["vendor/libtropic/src/libtropic.c"]
+ sources += ["vendor/libtropic/src/lt_crc16.c"]
+ sources += ["vendor/libtropic/src/lt_l1_port_wrap.c"]
+ sources += ["vendor/libtropic/src/lt_l1.c"]
+ sources += ["vendor/libtropic/src/lt_l2.c"]
+ sources += ["vendor/libtropic/src/lt_l2_frame_check.c"]
+ sources += ["vendor/libtropic/src/lt_l3.c"]
+ sources += ["vendor/libtropic/src/lt_hkdf.c"]
+ sources += ["vendor/libtropic/src/lt_random.c"]
+ sources += [
+ "vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_aesgcm.c"
+ ]
+ sources += [
+ "vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_ed25519.c"
+ ]
+ sources += [
+ "vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_sha256.c"
+ ]
+ sources += [
+ "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_TROPIC", "1")]
+ defines += [("USE_TREZOR_CRYPTO", "1")]
+
if "sbu" in features_wanted:
sources += ["embed/io/sbu/stm32/sbu.c"]
paths += ["embed/io/sbu/inc"]
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revA0.py b/core/site_scons/models/T3W1/trezor_t3w1_revA0.py
index 6330fa3243..d622843aa4 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revA0.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revA0.py
@@ -101,6 +101,35 @@ def configure(
features_available.append("optiga")
defines += [("USE_OPTIGA", "1")]
+ if "tropic" in features_wanted:
+ sources += ["embed/sec/tropic/stm32/tropic01.c"]
+ sources += ["vendor/libtropic/src/libtropic.c"]
+ sources += ["vendor/libtropic/src/lt_crc16.c"]
+ sources += ["vendor/libtropic/src/lt_l1_port_wrap.c"]
+ sources += ["vendor/libtropic/src/lt_l1.c"]
+ sources += ["vendor/libtropic/src/lt_l2.c"]
+ sources += ["vendor/libtropic/src/lt_l2_frame_check.c"]
+ sources += ["vendor/libtropic/src/lt_l3.c"]
+ sources += ["vendor/libtropic/src/lt_hkdf.c"]
+ sources += ["vendor/libtropic/src/lt_random.c"]
+ sources += [
+ "vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_aesgcm.c"
+ ]
+ sources += [
+ "vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_ed25519.c"
+ ]
+ sources += [
+ "vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_sha256.c"
+ ]
+ sources += [
+ "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_TROPIC", "1")]
+ defines += [("USE_TREZOR_CRYPTO", "1")]
+
if "sbu" in features_wanted:
sources += ["embed/io/sbu/stm32/sbu.c"]
paths += ["embed/io/sbu/inc"]
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revB.py b/core/site_scons/models/T3W1/trezor_t3w1_revB.py
index 46f4033575..672352b94e 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revB.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revB.py
@@ -102,6 +102,35 @@ def configure(
features_available.append("optiga")
defines += [("USE_OPTIGA", "1")]
+ if "tropic" in features_wanted:
+ sources += ["embed/sec/tropic/stm32/tropic01.c"]
+ sources += ["vendor/libtropic/src/libtropic.c"]
+ sources += ["vendor/libtropic/src/lt_crc16.c"]
+ sources += ["vendor/libtropic/src/lt_l1_port_wrap.c"]
+ sources += ["vendor/libtropic/src/lt_l1.c"]
+ sources += ["vendor/libtropic/src/lt_l2.c"]
+ sources += ["vendor/libtropic/src/lt_l2_frame_check.c"]
+ sources += ["vendor/libtropic/src/lt_l3.c"]
+ sources += ["vendor/libtropic/src/lt_hkdf.c"]
+ sources += ["vendor/libtropic/src/lt_random.c"]
+ sources += [
+ "vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_aesgcm.c"
+ ]
+ sources += [
+ "vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_ed25519.c"
+ ]
+ sources += [
+ "vendor/libtropic/hal/crypto/trezor_crypto/lt_crypto_trezor_sha256.c"
+ ]
+ sources += [
+ "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_TROPIC", "1")]
+ defines += [("USE_TREZOR_CRYPTO", "1")]
+
if "sbu" in features_wanted:
sources += ["embed/io/sbu/stm32/sbu.c"]
paths += ["embed/io/sbu/inc"]
diff --git a/core/vendor/libtropic b/core/vendor/libtropic
new file mode 120000
index 0000000000..18958f10fc
--- /dev/null
+++ b/core/vendor/libtropic
@@ -0,0 +1 @@
+../../vendor/libtropic/
\ No newline at end of file
diff --git a/vendor/libtropic b/vendor/libtropic
new file mode 160000
index 0000000000..e9ba707e33
--- /dev/null
+++ b/vendor/libtropic
@@ -0,0 +1 @@
+Subproject commit e9ba707e3323abefc2f67e5bed75a51adf2164d8