1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-02-21 12:02:19 +00:00

feat(core/prodtest): add tropic01 HAL integration and basic production tests

[no changelog]
This commit is contained in:
tychovrahe 2025-02-14 17:55:09 +01:00
parent 2ca8d093c6
commit 52c6123171
12 changed files with 543 additions and 1 deletions

3
.gitmodules vendored
View File

@ -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

View File

@ -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',
]

View File

@ -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.

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifdef USE_TROPIC
#include <trezor_rtl.h>
#include <rtl/cli.h>
#include <sec/tropic.h>
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

View File

@ -52,6 +52,10 @@
#include "cmd/prodtest_optiga.h"
#endif
#ifdef USE_TROPIC
#include <sec/tropic.h>
#endif
#ifdef USE_HAPTIC
#include <io/haptic.h>
#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();

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <trezor_types.h>
#include <libtropic.h>
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);

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <trezor_bsp.h>
#include <trezor_rtl.h>
#include <libtropic.h>
#include <sec/rng.h>
#include <sec/tropic.h>
#include <sys/systick.h>
#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;
}

View File

@ -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"]

View File

@ -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"]

View File

@ -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"]

1
core/vendor/libtropic vendored Symbolic link
View File

@ -0,0 +1 @@
../../vendor/libtropic/

1
vendor/libtropic vendored Submodule

@ -0,0 +1 @@
Subproject commit e9ba707e3323abefc2f67e5bed75a51adf2164d8