refactor(core): split secret, make it optional, add compile flags based on presence
What changed, and why it matters
This commit reorganizes how Trezor firmware handles secret keys and the 'secret' subsystem. It splits key-handling code into a new optional component (secret_keys), adds compile-time flags (USE_SECRET and USE_SECRET_KEYS) so different device models can include or exclude these features, and updates the build configuration for every supported model. The change is a structural refactor, not a direct security fix, but it touches sensitive code paths that protect device secrets and storage encryption.
Treat this as a high-risk refactor requiring careful review and regression testing. Verify that every model configuration still enables USE_SECRET and USE_SECRET_KEYS where the previous common code unconditionally included them, ensuring no production device loses secret-handling functionality. Specifically confirm that the boardloader's erase_storage(NULL) fallback correctly and securely wipes storage when USE_SECRET is absent, and that removing secret_safety_erase() does not weaken anti-exfiltration behavior. Run full build and test matrix across all models, and review downstream callers of secret_key APIs for missing guards.
Security signals we found
Refactor of secret and secret_keys subsystems with new compile-time feature flags
Conditional compilation of secret_init(), secret_safety_erase(), secret_prepare_fw(), and secret_key_delegated_identity__verified()
Direct storage erase fallback in boardloader when USE_SECRET is disabled
Build-system changes affecting all supported hardware models and emulators
No changelog entry and no explicit security disclosure in commit message
Evidence from the diff
The commit refactors the firmware’s secret-management layer. Previously, secret.c and secret_keys.c lived under core/embed/sec/secret/ and were compiled for all models. Now they are separated: secret remains under core/embed/sec/secret/ and secret_keys moves to core/embed/sec/secret_keys/. Both are made optional via USE_SECRET and USE_SECRET_KEYS defines. All board/emulator model configuration files (D001/D002, T2B1/T2T1/T3B1/T3T1/T3W1) are updated to explicitly add the include paths, source files, and defines. Code that calls secret_ or secret_key_ APIs is wrapped in #ifdef USE_SECRET or #ifdef USE_SECRET_KEYS guards. A notable functional change is in boardloader/main.c: when USE_SECRET is not defined, the boardloader now calls erase_storage(NULL) directly instead of secret_safety_erase() to wipe storage on a fault path.
Changed components
core/embed/projects/boardloader/main.ccore/embed/projects/bootloader/main.ccore/embed/projects/kernel/main.ccore/embed/projects/prodtest/cmd/prodtest_secrets.ccore/embed/projects/secmon/main.ccore/embed/projects/unix/main_main.ccore/embed/sec/secret_keys (new directory)core/embed/sec/secret (retained, split)core/embed/sys/smcall and syscall dispatch/stub/verifier filescore/embed/upymod/modtrezorutils/modtrezorutils.ccore/site_scons/models for D001/D002/T2B1/T2T1/T3B1/T3T1/T3W1Inspect captured patch +848 / −664
diff --git a/core/embed/projects/boardloader/main.c b/core/embed/projects/boardloader/main.c
index 606f589f..11a2cebb 100644
--- a/core/embed/projects/boardloader/main.c
+++ b/core/embed/projects/boardloader/main.c
@@ -24,9 +24,9 @@
#include <io/rsod.h>
#include <sec/board_capabilities.h>
#include <sec/option_bytes.h>
-#include <sec/secret.h>
#include <sys/bootutils.h>
#include <sys/flash.h>
+#include <sys/flash_utils.h>
#include <sys/reset_flags.h>
#include <sys/rng.h>
#include <sys/system.h>
@@ -55,6 +55,10 @@
#include <sec/tamper.h>
#endif
+#ifdef USE_SECRET
+#include <sec/secret.h>
+#endif
+
#include "bld_version.h"
#include "version.h"
@@ -72,7 +76,9 @@ static void drivers_init(void) {
#ifdef USE_TAMPER
tamper_init();
#endif
+#ifdef USE_SECRET
secret_init();
+#endif
#ifdef USE_HASH_PROCESSOR
hash_processor_init();
#endif
@@ -308,8 +314,13 @@ int main(void) {
// This may indicate a first boot after manufacturing,
// or a potential hardware fault or exploit attempt.
- // Make storage data inaccessible.
+#ifdef USE_SECRET
+ // if secret is used, it is responsible for making storage data inaccessible
secret_safety_erase();
+#else
+ // Otherwise, erase storage here directly
+ ensure(erase_storage(NULL), NULL);
+#endif
// Display an error message on the screen and reset the device.
return 0;
diff --git a/core/embed/projects/bootloader/main.c b/core/embed/projects/bootloader/main.c
index 0ce196fa..a81c981e 100644
--- a/core/embed/projects/bootloader/main.c
+++ b/core/embed/projects/bootloader/main.c
@@ -28,7 +28,6 @@
#include <sec/image.h>
#include <sec/random_delays.h>
#include <sec/rsod_special.h>
-#include <sec/secret.h>
#include <sec/unit_properties.h>
#include <sys/bootargs.h>
#include <sys/bootutils.h>
@@ -83,6 +82,9 @@
#ifdef USE_NRF
#include <io/nrf.h>
#endif
+#ifdef USE_SECRET
+#include <sec/secret.h>
+#endif
#ifdef USE_BLE
#include "wire/wire_iface_ble.h"
@@ -148,6 +150,10 @@ static void display_touch_init(secbool manufacturing_mode,
static secbool boot_sequence(void) {
secbool stay_in_bootloader = secfalse;
+#ifdef USE_SECRET
+ secret_init();
+#endif
+
#ifdef USE_BACKUP_RAM
backup_ram_init();
#endif
@@ -419,6 +425,7 @@ void real_jump_to_firmware(void) {
ensure_secmon_min_version(secmon_hdr->monotonic);
#endif
+#ifdef USE_SECRET
secbool provisioning_access =
((vhdr.vtrust & (VTRUST_ALLOW_PROVISIONING | VTRUST_SECRET_MASK)) ==
(VTRUST_SECRET_ALLOW | VTRUST_ALLOW_PROVISIONING)) *
@@ -428,6 +435,7 @@ void real_jump_to_firmware(void) {
((vhdr.vtrust & VTRUST_SECRET_MASK) == VTRUST_SECRET_ALLOW) * sectrue;
secret_prepare_fw(secret_run_access, provisioning_access);
+#endif
// if all warnings are disabled in VTRUST flags then skip the procedure
if ((vhdr.vtrust & VTRUST_NO_WARNING) != VTRUST_NO_WARNING) {
diff --git a/core/embed/projects/kernel/main.c b/core/embed/projects/kernel/main.c
index 3a5532bb..4e9b8215 100644
--- a/core/embed/projects/kernel/main.c
+++ b/core/embed/projects/kernel/main.c
@@ -27,7 +27,6 @@
#include <sec/boot_image.h>
#include <sec/option_bytes.h>
#include <sec/random_delays.h>
-#include <sec/secret.h>
#include <sec/secure_aes.h>
#include <sec/unit_properties.h>
#include <sys/bootutils.h>
@@ -63,6 +62,10 @@
#include <sec/hash_processor.h>
#endif
+#ifdef USE_SECRET
+#include <sec/secret.h>
+#endif
+
#ifdef USE_OPTIGA
#include <sec/optiga_init.h>
#endif
@@ -116,6 +119,7 @@ void drivers_init() {
#ifdef SECURE_MODE
parse_boardloader_capabilities();
unit_properties_init();
+
#ifdef USE_STORAGE_HWKEY
secure_aes_init();
#endif
diff --git a/core/embed/projects/prodtest/cmd/prodtest_otp_variant.c b/core/embed/projects/prodtest/cmd/prodtest_otp_variant.c
index d43e15d3..32a3f7fd 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_otp_variant.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_otp_variant.c
@@ -23,7 +23,6 @@
#include <rtl/cli.h>
#include <rtl/printf.h>
-#include <sec/secret.h>
#include <sys/flash_otp.h>
#include <stdlib.h>
@@ -33,6 +32,10 @@
#include "prodtest_tropic.h"
#endif
+#ifdef USE_SECRET
+#include <sec/secret.h>
+#endif
+
static void prodtest_otp_variant_read(cli_t* cli) {
if (cli_arg_count(cli) > 0) {
cli_error_arg_count(cli);
diff --git a/core/embed/projects/prodtest/cmd/prodtest_secrets.c b/core/embed/projects/prodtest/cmd/prodtest_secrets.c
index 9e964005..6b2c20a4 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_secrets.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_secrets.c
@@ -17,6 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifdef USE_SECRET
+
#include <trezor_model.h>
#include <string.h>
@@ -388,3 +390,6 @@ PRODTEST_CLI_CMD(
.args = ""
);
#endif
+
+#endif
+#endif
diff --git a/core/embed/projects/secmon/main.c b/core/embed/projects/secmon/main.c
index 009535ce..6bca93bc 100644
--- a/core/embed/projects/secmon/main.c
+++ b/core/embed/projects/secmon/main.c
@@ -52,6 +52,10 @@
#include <sec/hash_processor.h>
#endif
+#ifdef USE_SECRET
+#include <sec/secret.h>
+#endif
+
// Configure and enable power for USB peripheral
// (need to be called in secure mode since PWR and RCC peripheras are
// not accessible from non-secure mode)
diff --git a/core/embed/projects/unix/main_main.c b/core/embed/projects/unix/main_main.c
index 69019313..f4ec3c6d 100644
--- a/core/embed/projects/unix/main_main.c
+++ b/core/embed/projects/unix/main_main.c
@@ -22,7 +22,6 @@
#include <io/display.h>
#include <io/rsod.h>
#include <io/usb_config.h>
-#include <sec/secret.h>
#include <sec/unit_properties.h>
#include <sys/applet.h>
#include <sys/bootutils.h>
@@ -58,6 +57,10 @@
#include "zkp_context.h"
#endif
+#ifdef USE_SECRET
+#include <sec/secret.h>
+#endif
+
#include <SDL.h>
#ifdef USE_TROPIC
@@ -160,7 +163,7 @@ static void kernel_loop(applet_t *coreapp) {
int main(int argc, char **argv) {
system_init(&rsod_panic_handler);
-#ifdef LOCKABLE_BOOTLOADER
+#if defined(USE_SECRET) && defined(LOCKABLE_BOOTLOADER)
secret_lock_bootloader();
#endif
diff --git a/core/embed/sec/secret/inc/sec/secret_keys.h b/core/embed/sec/secret/inc/sec/secret_keys.h
deleted file mode 100644
index 83c44c33..00000000
--- a/core/embed/sec/secret/inc/sec/secret_keys.h
+++ /dev/null
@@ -1,99 +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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <trezor_types.h>
-
-#include <ecdsa.h>
-
-secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]);
-
-#ifdef SECURE_MODE
-
-#ifdef SECRET_MASTER_KEY_SLOT_SIZE
-
-#define SECRET_KEY_MASKING
-
-#include <../vendor/mldsa-native/mldsa/params.h>
-
-secbool secret_key_mcu_device_auth(uint8_t dest[MLDSA_SEEDBYTES]);
-
-#endif // SECRET_MASTER_KEY_SLOT_SIZE
-
-#ifdef USE_OPTIGA
-
-#define OPTIGA_PAIRING_SECRET_SIZE 32
-secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]);
-secbool secret_key_optiga_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]);
-
-#endif // USE_OPTIGA
-
-#ifdef USE_TROPIC
-
-#include <ed25519-donna/ed25519.h>
-
-secbool secret_key_tropic_public(curve25519_key dest);
-
-secbool secret_key_tropic_pairing_unprivileged(curve25519_key dest);
-secbool secret_key_tropic_pairing_privileged(curve25519_key dest);
-secbool secret_key_tropic_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]);
-
-#endif // USE_TROPIC
-
-#ifdef USE_NRF_AUTH
-
-#define NRF_PAIRING_SECRET_SIZE 32
-secbool secret_key_nrf_pairing(uint8_t dest[NRF_PAIRING_SECRET_SIZE]);
-
-#endif
-
-#define SECRET_KEY_STORAGE_SALT_SIZE 32
-
-secbool secret_key_storage_salt(uint16_t fw_type,
- uint8_t dest[SECRET_KEY_STORAGE_SALT_SIZE]);
-
-#define SECRET_KEY_MASTER_KEY_SIZE 32
-
-typedef struct {
- size_t size;
- uint8_t bytes[SECRET_KEY_MASTER_KEY_SIZE];
-} secret_key_master_key_t;
-
-/**
- * Retrieves the generated buffer with the master key.
- *
- * If master key has not yet been generated for the device,
- * it is generated now.
- *
- * This key is used to derive additional credential keys (e.g. Evolu).
- *
- * @param master_key structure filled with the generated data.
- */
-secbool secret_key_master_key_get(secret_key_master_key_t* master_key);
-
-#endif // SECURE_MODE
-
-#ifdef KERNEL_MODE
-#ifdef USE_NRF_AUTH
-secbool secret_validate_nrf_pairing(const uint8_t* message, size_t msg_len,
- const uint8_t* mac, size_t mac_len);
-
-#endif
-#endif
diff --git a/core/embed/sec/secret/secret_keys_common.c b/core/embed/sec/secret/secret_keys_common.c
deleted file mode 100644
index 79e4ccde..00000000
--- a/core/embed/sec/secret/secret_keys_common.c
+++ /dev/null
@@ -1,116 +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 <http://www.gnu.org/licenses/>.
- */
-
-#ifdef SECURE_MODE
-
-#include <sec/secret.h>
-#include <sec/secret_keys.h>
-#include <trezor_model.h>
-#include <trezor_rtl.h>
-
-#include "../storage/storage_salt.h"
-#include "hmac.h"
-#include "memzero.h"
-#include "nist256p1.h"
-#include "secret_keys_common.h"
-
-static void diversify_and_derive(uint16_t index, uint16_t subindex,
- const uint8_t master_key[SHA256_DIGEST_LENGTH],
- uint8_t master_key_length,
- uint8_t dest[SHA256_DIGEST_LENGTH]) {
- // The diversifier consists of:
- // - the key derivation index (2 bytes big-endian), which identifies the
- // purpose of the key,
- // - the subindex (2 bytes big-endian), which is incremented until the derived
- // key meets required criteria, and
- // - the block index (1 byte), which can be used to produce outputs that are
- // longer than 32 bytes.
- uint8_t diversifier[] = {index >> 8, index & 0xff, subindex >> 8,
- subindex & 0xff, 0};
-
- hmac_sha256(master_key, master_key_length, diversifier, sizeof(diversifier),
- dest);
-}
-
-secbool secret_key_derive_sym(uint8_t slot, uint16_t index, uint16_t subindex,
- uint8_t dest[SHA256_DIGEST_LENGTH]) {
- secbool ret = sectrue;
-
- secret_key_master_key_t master_key = {.bytes = {0},
- .size = SECRET_KEY_MASTER_KEY_SIZE};
-
-#ifdef SECRET_PRIVILEGED_MASTER_KEY_SLOT
- ret = secret_key_get(slot, master_key.bytes, master_key.size);
-#else // SECRET_PRIVILEGED_MASTER_KEY_SLOT
- if (slot != UNUSED_KEY_SLOT) {
- ret = secfalse;
- goto cleanup;
- }
- ret = secret_key_master_key_get(&master_key);
-#endif // SECRET_PRIVILEGED_MASTER_KEY_SLOT
-
- if (ret != sectrue) {
- goto cleanup;
- }
-
- diversify_and_derive(index, subindex, master_key.bytes, master_key.size,
- dest);
-
-cleanup:
- memzero(master_key.bytes, master_key.size);
- return ret;
-}
-
-secbool secret_key_derive_nist256p1(uint8_t slot, uint16_t index,
- uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
- // `slot` argument is not used unless SECRET_PRIVILEGED_MASTER_KEY_SLOT is
- // defined
-
- _Static_assert(ECDSA_PRIVATE_KEY_SIZE == SHA256_DIGEST_LENGTH, "");
-
- secbool ret = sectrue;
- bignum256 s = {0};
- for (uint16_t i = 0; i < 10000; i++) {
- ret = secret_key_derive_sym(slot, index, i, dest);
- if (ret != sectrue) {
- goto cleanup;
- }
-
- bn_read_be(dest, &s);
- if (!bn_is_zero(&s) && bn_is_less(&s, &nist256p1.order)) {
- // Valid private key, we are done.
- ret = sectrue;
- goto cleanup;
- }
-
- // Invalid private key, we generate the next key in line.
- }
-
- // Loop exhausted all attempts without producing a valid private key.
- ret = secfalse;
-
-cleanup:
- memzero(&s, sizeof(s));
- if (ret != sectrue) {
- memzero(dest, ECDSA_PRIVATE_KEY_SIZE);
- }
- return ret;
-}
-
-#endif // SECURE_MODE
diff --git a/core/embed/sec/secret/secret_keys_common.h b/core/embed/sec/secret/secret_keys_common.h
deleted file mode 100644
index 5c8540c8..00000000
--- a/core/embed/sec/secret/secret_keys_common.h
+++ /dev/null
@@ -1,51 +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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <trezor_types.h>
-
-#ifdef SECURE_MODE
-
-#include <trezor_model.h>
-#include <trezor_rtl.h>
-
-// Key derivation indices
-#define KEY_INDEX_MCU_DEVICE_AUTH 0
-#define KEY_INDEX_OPTIGA_PAIRING 1
-#define KEY_INDEX_OPTIGA_MASKING 2
-#define KEY_INDEX_TROPIC_PAIRING_UNPRIVILEGED 3
-#define KEY_INDEX_TROPIC_PAIRING_PRIVILEGED 4
-#define KEY_INDEX_TROPIC_MASKING 5
-#define KEY_INDEX_NRF_PAIRING 6
-#define KEY_INDEX_STORAGE_SALT 7
-#define KEY_INDEX_DELEGATED_IDENTITY 8
-
-#ifndef SECRET_PRIVILEGED_MASTER_KEY_SLOT
-#define UNUSED_KEY_SLOT 0
-// This is a dummy value used instead of SECRET_PRIVILEGED_MASTER_KEY_SLOT
-#endif // SECRET_PRIVILEGED_MASTER_KEY_SLOT
-
-secbool secret_key_derive_sym(uint8_t slot, uint16_t index, uint16_t subindex,
- uint8_t dest[SHA256_DIGEST_LENGTH]);
-
-secbool secret_key_derive_nist256p1(uint8_t slot, uint16_t index,
- uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]);
-
-#endif // SECURE_MODE
diff --git a/core/embed/sec/secret/stm32f4/secret_keys.c b/core/embed/sec/secret/stm32f4/secret_keys.c
deleted file mode 100644
index 53b75ff0..00000000
--- a/core/embed/sec/secret/stm32f4/secret_keys.c
+++ /dev/null
@@ -1,69 +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 <http://www.gnu.org/licenses/>.
- */
-
-#ifdef SECURE_MODE
-
-#include <trezor_bsp.h>
-#include <trezor_model.h>
-#include <trezor_rtl.h>
-
-#include <sec/secret.h>
-#include <sec/secret_keys.h>
-#include "../secret_keys_common.h"
-
-#include <sec/rng_strong.h>
-#include <sys/flash_otp.h>
-#include <sys/mpu.h>
-#include "memzero.h"
-
-#ifdef USE_OPTIGA
-
-secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]) {
- return secret_key_get(SECRET_OPTIGA_SLOT, dest, OPTIGA_PAIRING_SECRET_SIZE);
-}
-
-#endif // USE_OPTIGA
-
-secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
- secret_key_derive_nist256p1(UNUSED_KEY_SLOT, KEY_INDEX_DELEGATED_IDENTITY,
- dest);
- return sectrue;
-}
-
-secbool secret_key_master_key_get(secret_key_master_key_t* master_key) {
- if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_MASTER_KEY)) {
- uint8_t rnd_bytes[SECRET_KEY_MASTER_KEY_SIZE];
- if (!rng_fill_buffer_strong(rnd_bytes, SECRET_KEY_MASTER_KEY_SIZE)) {
- memzero(rnd_bytes, sizeof(rnd_bytes));
- return secfalse;
- }
- ensure(flash_otp_write(FLASH_OTP_BLOCK_MASTER_KEY, 0, rnd_bytes,
- SECRET_KEY_MASTER_KEY_SIZE),
- NULL);
- ensure(flash_otp_lock(FLASH_OTP_BLOCK_MASTER_KEY), NULL);
- }
- ensure(flash_otp_read(FLASH_OTP_BLOCK_MASTER_KEY, 0, &master_key->bytes[0],
- SECRET_KEY_MASTER_KEY_SIZE),
- NULL);
-
- master_key->size = SECRET_KEY_MASTER_KEY_SIZE;
- return sectrue;
-}
-
-#endif // SECURE_MODE
diff --git a/core/embed/sec/secret/stm32u5/secret_keys.c b/core/embed/sec/secret/stm32u5/secret_keys.c
deleted file mode 100644
index b34a4b1c..00000000
--- a/core/embed/sec/secret/stm32u5/secret_keys.c
+++ /dev/null
@@ -1,196 +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 <http://www.gnu.org/licenses/>.
- */
-
-#ifdef SECURE_MODE
-
-#include <trezor_bsp.h>
-#include <trezor_model.h>
-#include <trezor_rtl.h>
-
-#include <sec/secret.h>
-#include <sec/secret_keys.h>
-#include "../secret_keys_common.h"
-#include "hmac.h"
-#include "memzero.h"
-
-#ifdef SECRET_PRIVILEGED_MASTER_KEY_SLOT
-
-secbool secret_key_mcu_device_auth(uint8_t dest[MLDSA_SEEDBYTES]) {
- _Static_assert(MLDSA_SEEDBYTES == SHA256_DIGEST_LENGTH);
- return secret_key_derive_sym(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
- KEY_INDEX_MCU_DEVICE_AUTH, 0, dest);
-}
-
-#ifdef USE_OPTIGA
-secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]) {
- _Static_assert(OPTIGA_PAIRING_SECRET_SIZE == SHA256_DIGEST_LENGTH);
- return secret_key_derive_sym(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
- KEY_INDEX_OPTIGA_PAIRING, 0, dest);
-}
-
-secbool secret_key_optiga_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
- return secret_key_derive_nist256p1(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
- KEY_INDEX_OPTIGA_MASKING, dest);
-}
-
-#endif // USE_OPTIGA
-
-secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
- return secret_key_derive_nist256p1(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
- KEY_INDEX_DELEGATED_IDENTITY, dest);
-}
-
-#ifdef USE_TROPIC
-static secbool secret_key_derive_curve25519(uint8_t slot, uint16_t index,
- curve25519_key dest) {
- _Static_assert(sizeof(curve25519_key) == SHA256_DIGEST_LENGTH);
-
- secbool ret = secret_key_derive_sym(slot, index, 0, dest);
- dest[0] &= 248;
- dest[31] &= 127;
- dest[31] |= 64;
- return ret;
-}
-
-secbool secret_key_tropic_public(curve25519_key dest) {
- return secret_key_get(SECRET_TROPIC_TROPIC_PUBKEY_SLOT, dest,
- sizeof(curve25519_key));
-}
-
-secbool secret_key_tropic_pairing_unprivileged(curve25519_key dest) {
- return secret_key_derive_curve25519(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
- KEY_INDEX_TROPIC_PAIRING_UNPRIVILEGED,
- dest);
-}
-
-secbool secret_key_tropic_pairing_privileged(curve25519_key dest) {
- return secret_key_derive_curve25519(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
- KEY_INDEX_TROPIC_PAIRING_PRIVILEGED,
- dest);
-}
-
-secbool secret_key_tropic_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
- return secret_key_derive_nist256p1(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
- KEY_INDEX_TROPIC_MASKING, dest);
-}
-
-#endif // USE_TROPIC
-
-#ifdef USE_NRF_AUTH
-
-static secbool secequal(const void* ptr1, const void* ptr2, size_t n) {
- const uint8_t* p1 = ptr1;
- const uint8_t* p2 = ptr2;
- uint8_t diff = 0;
- size_t i = 0;
- for (i = 0; i < n; ++i) {
- diff |= *p1 ^ *p2;
- ++p1;
- ++p2;
- }
- return diff ? secfalse : sectrue;
-}
-
-secbool secret_key_nrf_pairing(uint8_t dest[NRF_PAIRING_SECRET_SIZE]) {
- _Static_assert(NRF_PAIRING_SECRET_SIZE == SHA256_DIGEST_LENGTH);
-
- if (secfalse != secret_is_locked()) {
- return secfalse;
- }
-
- return secret_key_derive_sym(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
- KEY_INDEX_NRF_PAIRING, 0, dest);
-}
-
-secbool secret_validate_nrf_pairing(const uint8_t* message, size_t msg_len,
- const uint8_t* mac, size_t mac_len) {
- secbool result = secfalse;
-
- uint8_t key[NRF_PAIRING_SECRET_SIZE] = {0};
-
- if (sectrue != secret_key_derive_sym(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
- KEY_INDEX_NRF_PAIRING, 0, key)) {
- return secfalse;
- }
-
- if (mac_len != SHA256_DIGEST_LENGTH) {
- goto cleanup;
- }
-
- uint8_t dest[SHA256_DIGEST_LENGTH] = {0};
-
- hmac_sha256(key, sizeof(key), message, msg_len, dest);
-
- if (secequal(dest, mac, SHA256_DIGEST_LENGTH) == sectrue) {
- result = sectrue;
- }
-
-cleanup:
- memzero(dest, sizeof(dest));
- memzero(key, sizeof(key));
- return result;
-}
-
-#endif // USE_NRF_AUTH
-
-secbool secret_key_storage_salt(uint16_t fw_type,
- uint8_t dest[SECRET_KEY_STORAGE_SALT_SIZE]) {
- _Static_assert(SECRET_KEY_STORAGE_SALT_SIZE == SHA256_DIGEST_LENGTH);
- return secret_key_derive_sym(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
- KEY_INDEX_STORAGE_SALT, fw_type, dest);
-}
-
-#else // SECRET_PRIVILEGED_MASTER_KEY_SLOT
-#include <sec/rng_strong.h>
-#include <sys/flash_otp.h>
-#include <sys/mpu.h>
-
-#ifdef USE_OPTIGA
-secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]) {
- return secret_key_get(SECRET_OPTIGA_SLOT, dest, OPTIGA_PAIRING_SECRET_SIZE);
-}
-#endif // USE_OPTIGA
-
-secbool secret_key_master_key_get(secret_key_master_key_t* master_key) {
- if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_MASTER_KEY)) {
- uint8_t rnd_bytes[SECRET_KEY_MASTER_KEY_SIZE];
- if (!rng_fill_buffer_strong(rnd_bytes, SECRET_KEY_MASTER_KEY_SIZE)) {
- memzero(rnd_bytes, sizeof(rnd_bytes));
- return secfalse;
- }
- ensure(flash_otp_write(FLASH_OTP_BLOCK_MASTER_KEY, 0, rnd_bytes,
- SECRET_KEY_MASTER_KEY_SIZE),
- NULL);
- }
- ensure(flash_otp_read(FLASH_OTP_BLOCK_MASTER_KEY, 0, &master_key->bytes[0],
- SECRET_KEY_MASTER_KEY_SIZE),
- NULL);
-
- master_key->size = SECRET_KEY_MASTER_KEY_SIZE;
- return sectrue;
-}
-
-secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
- return secret_key_derive_nist256p1(UNUSED_KEY_SLOT,
- KEY_INDEX_DELEGATED_IDENTITY, dest);
-}
-
-#endif // SECRET_PRIVILEGED_MASTER_KEY_SLOT
-
-#endif // SECURE_MODE
diff --git a/core/embed/sec/secret/unix/secret_keys.c b/core/embed/sec/secret/unix/secret_keys.c
deleted file mode 100644
index 86ceaacb..00000000
--- a/core/embed/sec/secret/unix/secret_keys.c
+++ /dev/null
@@ -1,92 +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 <http://www.gnu.org/licenses/>.
- */
-
-#ifdef SECURE_MODE
-
-#include <trezor_bsp.h>
-#include <trezor_model.h>
-#include <trezor_rtl.h>
-
-#include <sec/secret.h>
-#include <sec/secret_keys.h>
-#include "../secret_keys_common.h"
-
-#ifdef USE_TROPIC
-
-static uint8_t SECRET_TROPIC_PAIRING_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};
-
-static uint8_t SECRET_TROPIC_PUBKEY_BYTES[] = {
- 0x31, 0xE9, 0x0A, 0xF1, 0x50, 0x45, 0x10, 0xEE, 0x4E, 0xFD, 0x79,
- 0x13, 0x33, 0x41, 0x48, 0x15, 0x89, 0xA2, 0x89, 0x5C, 0xC5, 0xFB,
- 0xB1, 0x3E, 0xD5, 0x71, 0x1C, 0x1E, 0x9B, 0x81, 0x98, 0x72};
-
-_Static_assert(sizeof(SECRET_TROPIC_PAIRING_BYTES) == sizeof(curve25519_key),
- "Invalid size of Tropic pairing key");
-
-_Static_assert(sizeof(SECRET_TROPIC_PUBKEY_BYTES) == sizeof(curve25519_key),
- "Invalid size of Tropic public key");
-
-secbool secret_key_mcu_device_auth(uint8_t dest[MLDSA_SEEDBYTES]) {
- _Static_assert(MLDSA_SEEDBYTES == SHA256_DIGEST_LENGTH);
- memset(dest, 3, SHA256_DIGEST_LENGTH);
- return sectrue;
-}
-
-secbool secret_key_tropic_public(curve25519_key dest) {
- memcpy(dest, SECRET_TROPIC_PUBKEY_BYTES, sizeof(curve25519_key));
- return sectrue;
-}
-
-secbool secret_key_tropic_pairing_unprivileged(curve25519_key dest) {
- memset(dest, 2, sizeof(curve25519_key));
- return sectrue;
-}
-
-secbool secret_key_tropic_pairing_privileged(curve25519_key dest) {
- memcpy(dest, SECRET_TROPIC_PAIRING_BYTES, sizeof(curve25519_key));
- return sectrue;
-}
-
-secbool secret_key_tropic_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
- memset(dest, 1, ECDSA_PRIVATE_KEY_SIZE);
- return sectrue;
-}
-
-#endif // USE_TROPIC
-
-secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
-#ifdef SECRET_UNPRIVILEGED_MASTER_KEY_SLOT
- static uint8_t key_slot = SECRET_UNPRIVILEGED_MASTER_KEY_SLOT;
-#else
- static uint8_t key_slot = UNUSED_KEY_SLOT;
-#endif
- return secret_key_derive_nist256p1(key_slot, KEY_INDEX_DELEGATED_IDENTITY,
- dest);
-}
-
-secbool secret_key_master_key_get(secret_key_master_key_t* master_key) {
- memset(master_key->bytes, 0, SECRET_KEY_MASTER_KEY_SIZE);
- master_key->size = SECRET_KEY_MASTER_KEY_SIZE;
- return sectrue;
-}
-
-#endif // SECURE_MODE
diff --git a/core/embed/sec/secret_keys/inc/sec/secret_keys.h b/core/embed/sec/secret_keys/inc/sec/secret_keys.h
new file mode 100644
index 00000000..83c44c33
--- /dev/null
+++ b/core/embed/sec/secret_keys/inc/sec/secret_keys.h
@@ -0,0 +1,99 @@
+/*
+ * 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 <ecdsa.h>
+
+secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]);
+
+#ifdef SECURE_MODE
+
+#ifdef SECRET_MASTER_KEY_SLOT_SIZE
+
+#define SECRET_KEY_MASKING
+
+#include <../vendor/mldsa-native/mldsa/params.h>
+
+secbool secret_key_mcu_device_auth(uint8_t dest[MLDSA_SEEDBYTES]);
+
+#endif // SECRET_MASTER_KEY_SLOT_SIZE
+
+#ifdef USE_OPTIGA
+
+#define OPTIGA_PAIRING_SECRET_SIZE 32
+secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]);
+secbool secret_key_optiga_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]);
+
+#endif // USE_OPTIGA
+
+#ifdef USE_TROPIC
+
+#include <ed25519-donna/ed25519.h>
+
+secbool secret_key_tropic_public(curve25519_key dest);
+
+secbool secret_key_tropic_pairing_unprivileged(curve25519_key dest);
+secbool secret_key_tropic_pairing_privileged(curve25519_key dest);
+secbool secret_key_tropic_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]);
+
+#endif // USE_TROPIC
+
+#ifdef USE_NRF_AUTH
+
+#define NRF_PAIRING_SECRET_SIZE 32
+secbool secret_key_nrf_pairing(uint8_t dest[NRF_PAIRING_SECRET_SIZE]);
+
+#endif
+
+#define SECRET_KEY_STORAGE_SALT_SIZE 32
+
+secbool secret_key_storage_salt(uint16_t fw_type,
+ uint8_t dest[SECRET_KEY_STORAGE_SALT_SIZE]);
+
+#define SECRET_KEY_MASTER_KEY_SIZE 32
+
+typedef struct {
+ size_t size;
+ uint8_t bytes[SECRET_KEY_MASTER_KEY_SIZE];
+} secret_key_master_key_t;
+
+/**
+ * Retrieves the generated buffer with the master key.
+ *
+ * If master key has not yet been generated for the device,
+ * it is generated now.
+ *
+ * This key is used to derive additional credential keys (e.g. Evolu).
+ *
+ * @param master_key structure filled with the generated data.
+ */
+secbool secret_key_master_key_get(secret_key_master_key_t* master_key);
+
+#endif // SECURE_MODE
+
+#ifdef KERNEL_MODE
+#ifdef USE_NRF_AUTH
+secbool secret_validate_nrf_pairing(const uint8_t* message, size_t msg_len,
+ const uint8_t* mac, size_t mac_len);
+
+#endif
+#endif
diff --git a/core/embed/sec/secret_keys/secret_keys_common.c b/core/embed/sec/secret_keys/secret_keys_common.c
new file mode 100644
index 00000000..0bdec212
--- /dev/null
+++ b/core/embed/sec/secret_keys/secret_keys_common.c
@@ -0,0 +1,120 @@
+/*
+ * 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 SECURE_MODE
+
+#include <trezor_model.h>
+#include <trezor_rtl.h>
+
+#include <sec/secret_keys.h>
+
+#ifdef SECRET_PRIVILEGED_MASTER_KEY_SLOT
+#include <sec/secret.h>
+#endif
+
+#include "../storage/storage_salt.h"
+#include "hmac.h"
+#include "memzero.h"
+#include "nist256p1.h"
+#include "secret_keys_common.h"
+
+static void diversify_and_derive(uint16_t index, uint16_t subindex,
+ const uint8_t master_key[SHA256_DIGEST_LENGTH],
+ uint8_t master_key_length,
+ uint8_t dest[SHA256_DIGEST_LENGTH]) {
+ // The diversifier consists of:
+ // - the key derivation index (2 bytes big-endian), which identifies the
+ // purpose of the key,
+ // - the subindex (2 bytes big-endian), which is incremented until the derived
+ // key meets required criteria, and
+ // - the block index (1 byte), which can be used to produce outputs that are
+ // longer than 32 bytes.
+ uint8_t diversifier[] = {index >> 8, index & 0xff, subindex >> 8,
+ subindex & 0xff, 0};
+
+ hmac_sha256(master_key, master_key_length, diversifier, sizeof(diversifier),
+ dest);
+}
+
+secbool secret_key_derive_sym(uint8_t slot, uint16_t index, uint16_t subindex,
+ uint8_t dest[SHA256_DIGEST_LENGTH]) {
+ secbool ret = sectrue;
+
+ secret_key_master_key_t master_key = {.bytes = {0},
+ .size = SECRET_KEY_MASTER_KEY_SIZE};
+
+#ifdef SECRET_PRIVILEGED_MASTER_KEY_SLOT
+ ret = secret_key_get(slot, master_key.bytes, master_key.size);
+#else // SECRET_PRIVILEGED_MASTER_KEY_SLOT
+ if (slot != UNUSED_KEY_SLOT) {
+ ret = secfalse;
+ goto cleanup;
+ }
+ ret = secret_key_master_key_get(&master_key);
+#endif // SECRET_PRIVILEGED_MASTER_KEY_SLOT
+
+ if (ret != sectrue) {
+ goto cleanup;
+ }
+
+ diversify_and_derive(index, subindex, master_key.bytes, master_key.size,
+ dest);
+
+cleanup:
+ memzero(master_key.bytes, master_key.size);
+ return ret;
+}
+
+secbool secret_key_derive_nist256p1(uint8_t slot, uint16_t index,
+ uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
+ // `slot` argument is not used unless SECRET_PRIVILEGED_MASTER_KEY_SLOT is
+ // defined
+
+ _Static_assert(ECDSA_PRIVATE_KEY_SIZE == SHA256_DIGEST_LENGTH, "");
+
+ secbool ret = sectrue;
+ bignum256 s = {0};
+ for (uint16_t i = 0; i < 10000; i++) {
+ ret = secret_key_derive_sym(slot, index, i, dest);
+ if (ret != sectrue) {
+ goto cleanup;
+ }
+
+ bn_read_be(dest, &s);
+ if (!bn_is_zero(&s) && bn_is_less(&s, &nist256p1.order)) {
+ // Valid private key, we are done.
+ ret = sectrue;
+ goto cleanup;
+ }
+
+ // Invalid private key, we generate the next key in line.
+ }
+
+ // Loop exhausted all attempts without producing a valid private key.
+ ret = secfalse;
+
+cleanup:
+ memzero(&s, sizeof(s));
+ if (ret != sectrue) {
+ memzero(dest, ECDSA_PRIVATE_KEY_SIZE);
+ }
+ return ret;
+}
+
+#endif // SECURE_MODE
diff --git a/core/embed/sec/secret_keys/secret_keys_common.h b/core/embed/sec/secret_keys/secret_keys_common.h
new file mode 100644
index 00000000..5c8540c8
--- /dev/null
+++ b/core/embed/sec/secret_keys/secret_keys_common.h
@@ -0,0 +1,51 @@
+/*
+ * 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>
+
+#ifdef SECURE_MODE
+
+#include <trezor_model.h>
+#include <trezor_rtl.h>
+
+// Key derivation indices
+#define KEY_INDEX_MCU_DEVICE_AUTH 0
+#define KEY_INDEX_OPTIGA_PAIRING 1
+#define KEY_INDEX_OPTIGA_MASKING 2
+#define KEY_INDEX_TROPIC_PAIRING_UNPRIVILEGED 3
+#define KEY_INDEX_TROPIC_PAIRING_PRIVILEGED 4
+#define KEY_INDEX_TROPIC_MASKING 5
+#define KEY_INDEX_NRF_PAIRING 6
+#define KEY_INDEX_STORAGE_SALT 7
+#define KEY_INDEX_DELEGATED_IDENTITY 8
+
+#ifndef SECRET_PRIVILEGED_MASTER_KEY_SLOT
+#define UNUSED_KEY_SLOT 0
+// This is a dummy value used instead of SECRET_PRIVILEGED_MASTER_KEY_SLOT
+#endif // SECRET_PRIVILEGED_MASTER_KEY_SLOT
+
+secbool secret_key_derive_sym(uint8_t slot, uint16_t index, uint16_t subindex,
+ uint8_t dest[SHA256_DIGEST_LENGTH]);
+
+secbool secret_key_derive_nist256p1(uint8_t slot, uint16_t index,
+ uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]);
+
+#endif // SECURE_MODE
diff --git a/core/embed/sec/secret_keys/stm32f4/secret_keys.c b/core/embed/sec/secret_keys/stm32f4/secret_keys.c
new file mode 100644
index 00000000..ccd99a24
--- /dev/null
+++ b/core/embed/sec/secret_keys/stm32f4/secret_keys.c
@@ -0,0 +1,68 @@
+/*
+ * 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 SECURE_MODE
+
+#include <trezor_bsp.h>
+#include <trezor_model.h>
+#include <trezor_rtl.h>
+
+#include <sec/secret_keys.h>
+#include "../secret_keys_common.h"
+
+#include <sec/rng_strong.h>
+#include <sys/flash_otp.h>
+#include "memzero.h"
+
+#ifdef USE_OPTIGA
+#include <sec/secret.h>
+
+secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]) {
+ return secret_key_get(SECRET_OPTIGA_SLOT, dest, OPTIGA_PAIRING_SECRET_SIZE);
+}
+
+#endif // USE_OPTIGA
+
+secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
+ secret_key_derive_nist256p1(UNUSED_KEY_SLOT, KEY_INDEX_DELEGATED_IDENTITY,
+ dest);
+ return sectrue;
+}
+
+secbool secret_key_master_key_get(secret_key_master_key_t* master_key) {
+ if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_MASTER_KEY)) {
+ uint8_t rnd_bytes[SECRET_KEY_MASTER_KEY_SIZE];
+ if (!rng_fill_buffer_strong(rnd_bytes, SECRET_KEY_MASTER_KEY_SIZE)) {
+ memzero(rnd_bytes, sizeof(rnd_bytes));
+ return secfalse;
+ }
+ ensure(flash_otp_write(FLASH_OTP_BLOCK_MASTER_KEY, 0, rnd_bytes,
+ SECRET_KEY_MASTER_KEY_SIZE),
+ NULL);
+ ensure(flash_otp_lock(FLASH_OTP_BLOCK_MASTER_KEY), NULL);
+ }
+ ensure(flash_otp_read(FLASH_OTP_BLOCK_MASTER_KEY, 0, &master_key->bytes[0],
+ SECRET_KEY_MASTER_KEY_SIZE),
+ NULL);
+
+ master_key->size = SECRET_KEY_MASTER_KEY_SIZE;
+ return sectrue;
+}
+
+#endif // SECURE_MODE
diff --git a/core/embed/sec/secret_keys/stm32u5/secret_keys.c b/core/embed/sec/secret_keys/stm32u5/secret_keys.c
new file mode 100644
index 00000000..c68e338d
--- /dev/null
+++ b/core/embed/sec/secret_keys/stm32u5/secret_keys.c
@@ -0,0 +1,201 @@
+/*
+ * 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 SECURE_MODE
+
+#include <trezor_bsp.h>
+#include <trezor_model.h>
+#include <trezor_rtl.h>
+
+#include <sec/secret_keys.h>
+
+#include "../secret_keys_common.h"
+#include "hmac.h"
+#include "memzero.h"
+
+#if defined(USE_TROPIC) || defined(USE_NRF_AUTH) || \
+ (!SECRET_PRIVILEGED_MASTER_KEY_SLOT && defined(USE_OPTIGA))
+#include <sec/secret.h>
+#endif
+
+#ifdef SECRET_PRIVILEGED_MASTER_KEY_SLOT
+
+secbool secret_key_mcu_device_auth(uint8_t dest[MLDSA_SEEDBYTES]) {
+ _Static_assert(MLDSA_SEEDBYTES == SHA256_DIGEST_LENGTH);
+ return secret_key_derive_sym(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
+ KEY_INDEX_MCU_DEVICE_AUTH, 0, dest);
+}
+
+#ifdef USE_OPTIGA
+secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]) {
+ _Static_assert(OPTIGA_PAIRING_SECRET_SIZE == SHA256_DIGEST_LENGTH);
+ return secret_key_derive_sym(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
+ KEY_INDEX_OPTIGA_PAIRING, 0, dest);
+}
+
+secbool secret_key_optiga_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
+ return secret_key_derive_nist256p1(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
+ KEY_INDEX_OPTIGA_MASKING, dest);
+}
+
+#endif // USE_OPTIGA
+
+secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
+ return secret_key_derive_nist256p1(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
+ KEY_INDEX_DELEGATED_IDENTITY, dest);
+}
+
+#ifdef USE_TROPIC
+static secbool secret_key_derive_curve25519(uint8_t slot, uint16_t index,
+ curve25519_key dest) {
+ _Static_assert(sizeof(curve25519_key) == SHA256_DIGEST_LENGTH);
+
+ secbool ret = secret_key_derive_sym(slot, index, 0, dest);
+ dest[0] &= 248;
+ dest[31] &= 127;
+ dest[31] |= 64;
+ return ret;
+}
+
+secbool secret_key_tropic_public(curve25519_key dest) {
+ return secret_key_get(SECRET_TROPIC_TROPIC_PUBKEY_SLOT, dest,
+ sizeof(curve25519_key));
+}
+
+secbool secret_key_tropic_pairing_unprivileged(curve25519_key dest) {
+ return secret_key_derive_curve25519(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
+ KEY_INDEX_TROPIC_PAIRING_UNPRIVILEGED,
+ dest);
+}
+
+secbool secret_key_tropic_pairing_privileged(curve25519_key dest) {
+ return secret_key_derive_curve25519(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
+ KEY_INDEX_TROPIC_PAIRING_PRIVILEGED,
+ dest);
+}
+
+secbool secret_key_tropic_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
+ return secret_key_derive_nist256p1(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
+ KEY_INDEX_TROPIC_MASKING, dest);
+}
+
+#endif // USE_TROPIC
+
+#ifdef USE_NRF_AUTH
+
+static secbool secequal(const void* ptr1, const void* ptr2, size_t n) {
+ const uint8_t* p1 = ptr1;
+ const uint8_t* p2 = ptr2;
+ uint8_t diff = 0;
+ size_t i = 0;
+ for (i = 0; i < n; ++i) {
+ diff |= *p1 ^ *p2;
+ ++p1;
+ ++p2;
+ }
+ return diff ? secfalse : sectrue;
+}
+
+secbool secret_key_nrf_pairing(uint8_t dest[NRF_PAIRING_SECRET_SIZE]) {
+ _Static_assert(NRF_PAIRING_SECRET_SIZE == SHA256_DIGEST_LENGTH);
+
+ if (secfalse != secret_is_locked()) {
+ return secfalse;
+ }
+
+ return secret_key_derive_sym(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
+ KEY_INDEX_NRF_PAIRING, 0, dest);
+}
+
+secbool secret_validate_nrf_pairing(const uint8_t* message, size_t msg_len,
+ const uint8_t* mac, size_t mac_len) {
+ secbool result = secfalse;
+
+ uint8_t key[NRF_PAIRING_SECRET_SIZE] = {0};
+
+ if (sectrue != secret_key_derive_sym(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
+ KEY_INDEX_NRF_PAIRING, 0, key)) {
+ return secfalse;
+ }
+
+ if (mac_len != SHA256_DIGEST_LENGTH) {
+ goto cleanup;
+ }
+
+ uint8_t dest[SHA256_DIGEST_LENGTH] = {0};
+
+ hmac_sha256(key, sizeof(key), message, msg_len, dest);
+
+ if (secequal(dest, mac, SHA256_DIGEST_LENGTH) == sectrue) {
+ result = sectrue;
+ }
+
+cleanup:
+ memzero(dest, sizeof(dest));
+ memzero(key, sizeof(key));
+ return result;
+}
+
+#endif // USE_NRF_AUTH
+
+secbool secret_key_storage_salt(uint16_t fw_type,
+ uint8_t dest[SECRET_KEY_STORAGE_SALT_SIZE]) {
+ _Static_assert(SECRET_KEY_STORAGE_SALT_SIZE == SHA256_DIGEST_LENGTH);
+ return secret_key_derive_sym(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
+ KEY_INDEX_STORAGE_SALT, fw_type, dest);
+}
+
+#else // SECRET_PRIVILEGED_MASTER_KEY_SLOT
+#include <sec/rng_strong.h>
+#include <sys/flash_otp.h>
+#include <sys/mpu.h>
+
+#ifdef USE_OPTIGA
+secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]) {
+ return secret_key_get(SECRET_OPTIGA_SLOT, dest, OPTIGA_PAIRING_SECRET_SIZE);
+}
+#endif // USE_OPTIGA
+
+secbool secret_key_master_key_get(secret_key_master_key_t* master_key) {
+ if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_MASTER_KEY)) {
+ uint8_t rnd_bytes[SECRET_KEY_MASTER_KEY_SIZE];
+ if (!rng_fill_buffer_strong(rnd_bytes, SECRET_KEY_MASTER_KEY_SIZE)) {
+ memzero(rnd_bytes, sizeof(rnd_bytes));
+ return secfalse;
+ }
+ ensure(flash_otp_write(FLASH_OTP_BLOCK_MASTER_KEY, 0, rnd_bytes,
+ SECRET_KEY_MASTER_KEY_SIZE),
+ NULL);
+ }
+ ensure(flash_otp_read(FLASH_OTP_BLOCK_MASTER_KEY, 0, &master_key->bytes[0],
+ SECRET_KEY_MASTER_KEY_SIZE),
+ NULL);
+
+ master_key->size = SECRET_KEY_MASTER_KEY_SIZE;
+ return sectrue;
+}
+
+secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
+ return secret_key_derive_nist256p1(UNUSED_KEY_SLOT,
+ KEY_INDEX_DELEGATED_IDENTITY, dest);
+}
+
+#endif // SECRET_PRIVILEGED_MASTER_KEY_SLOT
+
+#endif // SECURE_MODE
diff --git a/core/embed/sec/secret_keys/unix/secret_keys.c b/core/embed/sec/secret_keys/unix/secret_keys.c
new file mode 100644
index 00000000..1cbeb97c
--- /dev/null
+++ b/core/embed/sec/secret_keys/unix/secret_keys.c
@@ -0,0 +1,91 @@
+/*
+ * 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 SECURE_MODE
+
+#include <trezor_bsp.h>
+#include <trezor_model.h>
+#include <trezor_rtl.h>
+
+#include <sec/secret_keys.h>
+#include "../secret_keys_common.h"
+
+#ifdef USE_TROPIC
+
+static uint8_t SECRET_TROPIC_PAIRING_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};
+
+static uint8_t SECRET_TROPIC_PUBKEY_BYTES[] = {
+ 0x31, 0xE9, 0x0A, 0xF1, 0x50, 0x45, 0x10, 0xEE, 0x4E, 0xFD, 0x79,
+ 0x13, 0x33, 0x41, 0x48, 0x15, 0x89, 0xA2, 0x89, 0x5C, 0xC5, 0xFB,
+ 0xB1, 0x3E, 0xD5, 0x71, 0x1C, 0x1E, 0x9B, 0x81, 0x98, 0x72};
+
+_Static_assert(sizeof(SECRET_TROPIC_PAIRING_BYTES) == sizeof(curve25519_key),
+ "Invalid size of Tropic pairing key");
+
+_Static_assert(sizeof(SECRET_TROPIC_PUBKEY_BYTES) == sizeof(curve25519_key),
+ "Invalid size of Tropic public key");
+
+secbool secret_key_mcu_device_auth(uint8_t dest[MLDSA_SEEDBYTES]) {
+ _Static_assert(MLDSA_SEEDBYTES == SHA256_DIGEST_LENGTH);
+ memset(dest, 3, SHA256_DIGEST_LENGTH);
+ return sectrue;
+}
+
+secbool secret_key_tropic_public(curve25519_key dest) {
+ memcpy(dest, SECRET_TROPIC_PUBKEY_BYTES, sizeof(curve25519_key));
+ return sectrue;
+}
+
+secbool secret_key_tropic_pairing_unprivileged(curve25519_key dest) {
+ memset(dest, 2, sizeof(curve25519_key));
+ return sectrue;
+}
+
+secbool secret_key_tropic_pairing_privileged(curve25519_key dest) {
+ memcpy(dest, SECRET_TROPIC_PAIRING_BYTES, sizeof(curve25519_key));
+ return sectrue;
+}
+
+secbool secret_key_tropic_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
+ memset(dest, 1, ECDSA_PRIVATE_KEY_SIZE);
+ return sectrue;
+}
+
+#endif // USE_TROPIC
+
+secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
+#ifdef SECRET_UNPRIVILEGED_MASTER_KEY_SLOT
+ static uint8_t key_slot = SECRET_UNPRIVILEGED_MASTER_KEY_SLOT;
+#else
+ static uint8_t key_slot = UNUSED_KEY_SLOT;
+#endif
+ return secret_key_derive_nist256p1(key_slot, KEY_INDEX_DELEGATED_IDENTITY,
+ dest);
+}
+
+secbool secret_key_master_key_get(secret_key_master_key_t* master_key) {
+ memset(master_key->bytes, 0, SECRET_KEY_MASTER_KEY_SIZE);
+ master_key->size = SECRET_KEY_MASTER_KEY_SIZE;
+ return sectrue;
+}
+
+#endif // SECURE_MODE
diff --git a/core/embed/sys/smcall/stm32/smcall_dispatch.c b/core/embed/sys/smcall/stm32/smcall_dispatch.c
index 43a744c1..f875cf61 100644
--- a/core/embed/sys/smcall/stm32/smcall_dispatch.c
+++ b/core/embed/sys/smcall/stm32/smcall_dispatch.c
@@ -25,14 +25,20 @@
#include <sec/fwutils.h>
#include <sec/random_delays.h>
#include <sec/rng_strong.h>
-#include <sec/secret.h>
-#include <sec/secret_keys.h>
#include <sec/unit_properties.h>
#include <sys/bootargs.h>
#include <sys/bootutils.h>
#include <sys/irq.h>
#include <sys/system.h>
+#ifdef USE_SECRET
+#include <sec/secret.h>
+#endif
+
+#ifdef USE_SECRET_KEYS
+#include <sec/secret_keys.h>
+#endif
+
#ifdef USE_BACKUP_RAM
#include <sec/backup_ram.h>
#endif
@@ -136,11 +142,13 @@ __attribute((no_stack_protector)) void smcall_handler(uint32_t *args,
device_sn_size);
} break;
+#ifdef USE_SECRET
#ifdef LOCKABLE_BOOTLOADER
case SMCALL_SECRET_BOOTLOADER_LOCKED: {
args[0] = secret_bootloader_locked();
} break;
#endif
+#endif
#ifdef USE_NRF_AUTH
case SMCALL_SECRET_VALIDATE_NRF_PAIRING: {
@@ -212,10 +220,12 @@ __attribute((no_stack_protector)) void smcall_handler(uint32_t *args,
#endif
#endif // USE_OPTIGA
+#ifdef USE_SECRET_KEYS
case SMCALL_SECRET_KEYS_GET_DELEGATED_IDENTITY_KEY: {
uint8_t *dest = (uint8_t *)args[0];
args[0] = secret_key_delegated_identity__verified(dest);
} break;
+#endif
case SMCALL_STORAGE_SETUP: {
PIN_UI_WAIT_CALLBACK callback = (PIN_UI_WAIT_CALLBACK)args[0];
diff --git a/core/embed/sys/smcall/stm32/smcall_stubs.c b/core/embed/sys/smcall/stm32/smcall_stubs.c
index 0f087356..f814913f 100644
--- a/core/embed/sys/smcall/stm32/smcall_stubs.c
+++ b/core/embed/sys/smcall/stm32/smcall_stubs.c
@@ -146,6 +146,7 @@ bool unit_properties_get_sn(uint8_t *device_sn, size_t max_device_sn_size,
// secret.h
// =============================================================================
+#ifdef USE_SECRET
#ifdef LOCKABLE_BOOTLOADER
#include <sec/secret.h>
@@ -155,6 +156,7 @@ secbool secret_bootloader_locked(void) {
}
#endif // LOCKABLE_BOOTLOADER
+#endif
// =============================================================================
// random_delays.h
@@ -216,6 +218,7 @@ void optiga_set_sec_max(void) { smcall_invoke0(SMCALL_OPTIGA_SET_SEC_MAX); }
// secret_keys.h
// =============================================================================
+#ifdef USE_SECRET_KEYS
#include <sec/secret_keys.h>
secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
@@ -223,6 +226,8 @@ secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
SMCALL_SECRET_KEYS_GET_DELEGATED_IDENTITY_KEY);
}
+#endif
+
// =============================================================================
// storage.h
// =============================================================================
diff --git a/core/embed/sys/smcall/stm32/smcall_verifiers.c b/core/embed/sys/smcall/stm32/smcall_verifiers.c
index 459ee15b..7574de46 100644
--- a/core/embed/sys/smcall/stm32/smcall_verifiers.c
+++ b/core/embed/sys/smcall/stm32/smcall_verifiers.c
@@ -217,6 +217,8 @@ access_violation:
// ---------------------------------------------------------------------
+#ifdef USE_SECRET_KEYS
+
#include <sec/secret_keys.h>
secbool secret_key_delegated_identity__verified(
@@ -231,6 +233,7 @@ access_violation:
apptask_access_violation();
return secfalse;
}
+#endif
// ---------------------------------------------------------------------
diff --git a/core/embed/sys/smcall/stm32/smcall_verifiers.h b/core/embed/sys/smcall/stm32/smcall_verifiers.h
index 0f685a4d..87a75c2a 100644
--- a/core/embed/sys/smcall/stm32/smcall_verifiers.h
+++ b/core/embed/sys/smcall/stm32/smcall_verifiers.h
@@ -73,11 +73,13 @@ bool __wur optiga_read_sec__verified(uint8_t *sec);
// ---------------------------------------------------------------------
+#ifdef USE_SECRET_KEYS
#include <sec/secret_keys.h>
secbool secret_key_delegated_identity__verified(
uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]);
+#endif
// ---------------------------------------------------------------------
#include <sec/storage.h>
diff --git a/core/embed/sys/syscall/stm32/syscall_dispatch.c b/core/embed/sys/syscall/stm32/syscall_dispatch.c
index f0cd39ab..9f2ed3ec 100644
--- a/core/embed/sys/syscall/stm32/syscall_dispatch.c
+++ b/core/embed/sys/syscall/stm32/syscall_dispatch.c
@@ -30,8 +30,6 @@
#include <io/usb.h>
#include <sec/fwutils.h>
#include <sec/rng_strong.h>
-#include <sec/secret.h>
-#include <sec/secret_keys.h>
#include <sec/unit_properties.h>
#include <sys/bootutils.h>
#include <sys/irq.h>
@@ -40,6 +38,10 @@
#include <sys/system.h>
#include <sys/systick.h>
+#ifdef USE_SECRET
+#include <sec/secret.h>
+#endif
+
#ifdef USE_BLE
#include <io/ble.h>
#endif
@@ -377,11 +379,13 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
device_sn_size);
} break;
+#ifdef USE_SECRET
#ifdef LOCKABLE_BOOTLOADER
case SYSCALL_SECRET_BOOTLOADER_LOCKED: {
args[0] = secret_bootloader_locked();
} break;
#endif
+#endif
#ifdef USE_BUTTON
case SYSCALL_BUTTON_GET_EVENT: {
@@ -496,10 +500,12 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
#endif
#endif // USE_OPTIGA
+#ifdef USE_SECRET_KEYS
case SYSCALL_SECRET_KEYS_GET_DELEGATED_IDENTITY_KEY: {
uint8_t *dest = (uint8_t *)args[0];
args[0] = secret_key_delegated_identity__verified(dest);
} break;
+#endif
#ifdef USE_TELEMETRY
case SYSCALL_TELEMETRY_GET: {
diff --git a/core/embed/sys/syscall/stm32/syscall_stubs.c b/core/embed/sys/syscall/stm32/syscall_stubs.c
index a6cccbf2..7d704039 100644
--- a/core/embed/sys/syscall/stm32/syscall_stubs.c
+++ b/core/embed/sys/syscall/stm32/syscall_stubs.c
@@ -344,13 +344,28 @@ bool unit_properties_get_sn(uint8_t *device_sn, size_t max_device_sn_size,
// =============================================================================
// secret.h
// =============================================================================
-
+#ifdef USE_SECRET
#ifdef LOCKABLE_BOOTLOADER
#include <sec/secret.h>
secbool secret_bootloader_locked(void) {
return (secbool)syscall_invoke0(SYSCALL_SECRET_BOOTLOADER_LOCKED);
}
+#endif
+#endif
+
+// =============================================================================
+// secret_keys.h
+// =============================================================================
+
+#ifdef USE_SECRET_KEYS
+#include <sec/secret_keys.h>
+
+secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
+ return (secbool)syscall_invoke1(
+ (uint32_t)dest, SYSCALL_SECRET_KEYS_GET_DELEGATED_IDENTITY_KEY);
+}
+
#endif
// =============================================================================
@@ -486,17 +501,6 @@ void optiga_set_sec_max(void) { syscall_invoke0(SYSCALL_OPTIGA_SET_SEC_MAX); }
#endif // USE_OPTIGA
-// =============================================================================
-// secret_keys.h
-// =============================================================================
-
-#include <sec/secret_keys.h>
-
-secbool secret_key_delegated_identity(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
- return (secbool)syscall_invoke1(
- (uint32_t)dest, SYSCALL_SECRET_KEYS_GET_DELEGATED_IDENTITY_KEY);
-}
-
// =============================================================================
// telemetry.h
// =============================================================================
diff --git a/core/embed/sys/syscall/stm32/syscall_verifiers.c b/core/embed/sys/syscall/stm32/syscall_verifiers.c
index 0a25a347..ebc76bd0 100644
--- a/core/embed/sys/syscall/stm32/syscall_verifiers.c
+++ b/core/embed/sys/syscall/stm32/syscall_verifiers.c
@@ -581,6 +581,7 @@ access_violation:
// ---------------------------------------------------------------------
+#ifdef USE_SECRET_KEYS
#include <sec/secret_keys.h>
secbool secret_key_delegated_identity__verified(
@@ -595,6 +596,7 @@ access_violation:
apptask_access_violation();
return secfalse;
}
+#endif
// ---------------------------------------------------------------------
diff --git a/core/embed/sys/syscall/stm32/syscall_verifiers.h b/core/embed/sys/syscall/stm32/syscall_verifiers.h
index bb829927..dfd8b1fa 100644
--- a/core/embed/sys/syscall/stm32/syscall_verifiers.h
+++ b/core/embed/sys/syscall/stm32/syscall_verifiers.h
@@ -162,10 +162,12 @@ bool __wur optiga_read_sec__verified(uint8_t *sec);
#endif // USE_OPTIGA
// ---------------------------------------------------------------------
+#ifdef USE_SECRET_KEYS
#include <sec/secret_keys.h>
secbool secret_key_delegated_identity__verified(
uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]);
+#endif
// ---------------------------------------------------------------------
#ifdef USE_TELEMETRY
diff --git a/core/embed/upymod/modtrezorutils/modtrezorutils.c b/core/embed/upymod/modtrezorutils/modtrezorutils.c
index 1a0d4fe8..67c2a323 100644
--- a/core/embed/upymod/modtrezorutils/modtrezorutils.c
+++ b/core/embed/upymod/modtrezorutils/modtrezorutils.c
@@ -40,12 +40,19 @@
#include <io/notify.h>
#include <rtl/scm_revision.h>
#include <sec/fwutils.h>
-#include <sec/secret_keys.h>
#include <sec/unit_properties.h>
#include <sys/bootutils.h>
#include "blake2s.h"
#include "memzero.h"
+#ifdef USE_SECRET
+#include <sec/secret.h>
+#endif
+
+#ifdef USE_SECRET_KEYS
+#include <sec/secret_keys.h>
+#endif
+
#ifdef USE_TELEMETRY
#include <sec/telemetry.h>
#endif
@@ -57,10 +64,6 @@
#include <io/nrf.h>
#endif
-#if !defined(TREZOR_EMULATOR)
-#include <sec/secret.h>
-#endif
-
#if !PYOPT && LOG_STACK_USAGE
#include <sys/stack_utils.h>
#endif
@@ -664,7 +667,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorutils_check_firmware_header_obj,
/// the feature is not supported.
/// """
STATIC mp_obj_t mod_trezorutils_bootloader_locked() {
-#if LOCKABLE_BOOTLOADER
+#if LOCKABLE_BOOTLOADER && defined USE_SECRET
#ifdef TREZOR_EMULATOR
return mp_const_true;
#else
diff --git a/core/site_scons/models/D001/discovery.py b/core/site_scons/models/D001/discovery.py
index 140be80c..813948dd 100644
--- a/core/site_scons/models/D001/discovery.py
+++ b/core/site_scons/models/D001/discovery.py
@@ -40,6 +40,11 @@ def configure(
("USE_HSE", "1"),
]
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/stm32f4/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "display" in features_wanted:
sources += [
"embed/io/display/stm32f429i-disc1/display_driver.c",
diff --git a/core/site_scons/models/D002/discovery2.py b/core/site_scons/models/D002/discovery2.py
index 6a405aea..34f16ef8 100644
--- a/core/site_scons/models/D002/discovery2.py
+++ b/core/site_scons/models/D002/discovery2.py
@@ -53,6 +53,15 @@ def configure(
("USE_SECMON_VERIFICATION", "1"),
]
+ paths += ["embed/sec/secret/inc"]
+ sources += ["embed/sec/secret/stm32u5/secret.c"]
+ defines += [("USE_SECRET", "1")]
+
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/stm32u5/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "boot_ucb" in features_wanted:
sources += ["embed/sec/image/boot_header.c"]
sources += ["embed/sec/image/boot_ucb.c"]
diff --git a/core/site_scons/models/T2B1/emulator.py b/core/site_scons/models/T2B1/emulator.py
index 9087f0ed..37980b37 100644
--- a/core/site_scons/models/T2B1/emulator.py
+++ b/core/site_scons/models/T2B1/emulator.py
@@ -42,6 +42,15 @@ def configure(
("LOCKABLE_BOOTLOADER", "1"),
]
+ paths += ["embed/sec/secret/inc"]
+ sources += ["embed/sec/secret/unix/secret.c"]
+ defines += [("USE_SECRET", "1")]
+
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/unix/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "sbu" in features_wanted:
sources += ["embed/io/sbu/unix/sbu.c"]
paths += ["embed/io/sbu/inc"]
diff --git a/core/site_scons/models/T2B1/trezor_r_v10.py b/core/site_scons/models/T2B1/trezor_r_v10.py
index 01d946bf..d64b4b48 100644
--- a/core/site_scons/models/T2B1/trezor_r_v10.py
+++ b/core/site_scons/models/T2B1/trezor_r_v10.py
@@ -49,6 +49,15 @@ def configure(
("USE_HSE", "1"),
]
+ paths += ["embed/sec/secret/inc"]
+ sources += ["embed/sec/secret/stm32f4/secret.c"]
+ defines += [("USE_SECRET", "1")]
+
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/stm32f4/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "display" in features_wanted:
sources += ["embed/io/display/vg-2864/display_driver.c"]
paths += ["embed/io/display/inc"]
diff --git a/core/site_scons/models/T2T1/emulator.py b/core/site_scons/models/T2T1/emulator.py
index 3b2a6f67..0aebb6e3 100644
--- a/core/site_scons/models/T2T1/emulator.py
+++ b/core/site_scons/models/T2T1/emulator.py
@@ -40,6 +40,11 @@ def configure(
("FLASH_BLOCK_WORDS", "1"),
]
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/unix/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "sd_card" in features_wanted:
features_available.append("sd_card")
sources += [
diff --git a/core/site_scons/models/T2T1/trezor_t.py b/core/site_scons/models/T2T1/trezor_t.py
index 6ec1311b..c2166c42 100644
--- a/core/site_scons/models/T2T1/trezor_t.py
+++ b/core/site_scons/models/T2T1/trezor_t.py
@@ -48,6 +48,11 @@ def configure(
("USE_HSE", "1"),
]
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/stm32f4/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "display" in features_wanted:
sources += ["embed/io/display/st-7789/display_nofb.c"]
sources += ["embed/io/display/st-7789/display_driver.c"]
diff --git a/core/site_scons/models/T3B1/emulator.py b/core/site_scons/models/T3B1/emulator.py
index 20161095..0cba6e6f 100644
--- a/core/site_scons/models/T3B1/emulator.py
+++ b/core/site_scons/models/T3B1/emulator.py
@@ -42,6 +42,15 @@ def configure(
("FLASH_BLOCK_WORDS", "1"),
]
+ paths += ["embed/sec/secret/inc"]
+ sources += ["embed/sec/secret/unix/secret.c"]
+ defines += [("USE_SECRET", "1")]
+
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/unix/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "sbu" in features_wanted:
sources += ["embed/io/sbu/unix/sbu.c"]
paths += ["embed/io/sbu/inc"]
diff --git a/core/site_scons/models/T3B1/trezor_t3b1_revB.py b/core/site_scons/models/T3B1/trezor_t3b1_revB.py
index 72b3984a..8fed9260 100644
--- a/core/site_scons/models/T3B1/trezor_t3b1_revB.py
+++ b/core/site_scons/models/T3B1/trezor_t3b1_revB.py
@@ -49,6 +49,15 @@ def configure(
("HW_REVISION", str(hw_revision)),
]
+ paths += ["embed/sec/secret/inc"]
+ sources += ["embed/sec/secret/stm32u5/secret.c"]
+ defines += [("USE_SECRET", "1")]
+
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/stm32u5/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "display" in features_wanted:
sources += ["embed/io/display/vg-2864/display_driver.c"]
paths += ["embed/io/display/inc"]
diff --git a/core/site_scons/models/T3T1/emulator.py b/core/site_scons/models/T3T1/emulator.py
index 7b398366..80677182 100644
--- a/core/site_scons/models/T3T1/emulator.py
+++ b/core/site_scons/models/T3T1/emulator.py
@@ -44,6 +44,15 @@ def configure(
("FLASH_BLOCK_WORDS", "1"),
]
+ paths += ["embed/sec/secret/inc"]
+ sources += ["embed/sec/secret/unix/secret.c"]
+ defines += [("USE_SECRET", "1")]
+
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/unix/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "sd_card" in features_wanted:
features_available.append("sd_card")
sources += [
diff --git a/core/site_scons/models/T3T1/trezor_t3t1_revE.py b/core/site_scons/models/T3T1/trezor_t3t1_revE.py
index 509bd778..005b5d01 100644
--- a/core/site_scons/models/T3T1/trezor_t3t1_revE.py
+++ b/core/site_scons/models/T3T1/trezor_t3t1_revE.py
@@ -51,6 +51,15 @@ def configure(
("HW_REVISION", str(hw_revision)),
]
+ paths += ["embed/sec/secret/inc"]
+ sources += ["embed/sec/secret/stm32u5/secret.c"]
+ defines += [("USE_SECRET", "1")]
+
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/stm32u5/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "display" in features_wanted:
sources += ["embed/io/display/st-7789/display_fb.c"]
sources += ["embed/io/display/st-7789/display_driver.c"]
diff --git a/core/site_scons/models/T3W1/emulator.py b/core/site_scons/models/T3W1/emulator.py
index e7d2ade0..624945e0 100644
--- a/core/site_scons/models/T3W1/emulator.py
+++ b/core/site_scons/models/T3W1/emulator.py
@@ -46,6 +46,15 @@ def configure(
("FLASH_BLOCK_WORDS", "1"),
]
+ paths += ["embed/sec/secret/inc"]
+ sources += ["embed/sec/secret/unix/secret.c"]
+ defines += [("USE_SECRET", "1")]
+
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/unix/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "sbu" in features_wanted:
sources += ["embed/io/sbu/unix/sbu.c"]
paths += ["embed/io/sbu/inc"]
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revA.py b/core/site_scons/models/T3W1/trezor_t3w1_revA.py
index 0a966dfc..d388554d 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revA.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revA.py
@@ -61,6 +61,15 @@ def configure(
("TERMINAL_Y_PADDING", "12"),
]
+ paths += ["embed/sec/secret/inc"]
+ sources += ["embed/sec/secret/stm32u5/secret.c"]
+ defines += [("USE_SECRET", "1")]
+
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/stm32u5/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "boot_ucb" in features_wanted:
sources += ["embed/sec/image/boot_header.c"]
sources += ["embed/sec/image/boot_ucb.c"]
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revB.py b/core/site_scons/models/T3W1/trezor_t3w1_revB.py
index fa88fca9..29645c82 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revB.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revB.py
@@ -61,6 +61,15 @@ def configure(
("TERMINAL_Y_PADDING", "12"),
]
+ paths += ["embed/sec/secret/inc"]
+ sources += ["embed/sec/secret/stm32u5/secret.c"]
+ defines += [("USE_SECRET", "1")]
+
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/stm32u5/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "boot_ucb" in features_wanted:
sources += ["embed/sec/image/boot_header.c"]
sources += ["embed/sec/image/boot_ucb.c"]
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revC.py b/core/site_scons/models/T3W1/trezor_t3w1_revC.py
index 19300f55..b0338dd6 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revC.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revC.py
@@ -61,6 +61,15 @@ def configure(
("TERMINAL_Y_PADDING", "12"),
]
+ paths += ["embed/sec/secret/inc"]
+ sources += ["embed/sec/secret/stm32u5/secret.c"]
+ defines += [("USE_SECRET", "1")]
+
+ paths += ["embed/sec/secret_keys/inc"]
+ sources += ["embed/sec/secret_keys/stm32u5/secret_keys.c"]
+ sources += ["embed/sec/secret_keys/secret_keys_common.c"]
+ defines += [("USE_SECRET_KEYS", "1")]
+
if "boot_ucb" in features_wanted:
sources += ["embed/sec/image/boot_header.c"]
sources += ["embed/sec/image/boot_ucb.c"]
diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py
index 6cccd60e..f9302934 100644
--- a/core/site_scons/models/stm32f4_common.py
+++ b/core/site_scons/models/stm32f4_common.py
@@ -29,7 +29,6 @@ def stm32f4_common_files(env, features_wanted, defines, sources, paths):
"embed/sys/pvd/inc",
"embed/sys/rng/inc",
"embed/sec/board_capabilities/inc",
- "embed/sec/secret/inc",
"embed/sec/unit_properties/inc",
"embed/sys/flash/inc",
"embed/sys/stack/inc",
@@ -74,9 +73,6 @@ def stm32f4_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/option_bytes/stm32f4/option_bytes.c",
"embed/sec/random_delays/stm32/random_delays.c",
"embed/sec/rng/rng_strong.c",
- "embed/sec/secret/stm32f4/secret.c",
- "embed/sec/secret/stm32f4/secret_keys.c",
- "embed/sec/secret/secret_keys_common.c",
"embed/sec/storage/stm32f4/storage_salt.c",
"embed/sec/time_estimate/stm32/time_estimate.c",
"embed/sec/unit_properties/stm32/unit_properties.c",
diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py
index 98011103..be5fd103 100644
--- a/core/site_scons/models/stm32u5_common.py
+++ b/core/site_scons/models/stm32u5_common.py
@@ -20,7 +20,6 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/option_bytes/inc",
"embed/sec/random_delays/inc",
"embed/sec/rng/inc",
- "embed/sec/secret/inc",
"embed/sec/secure_aes/inc",
"embed/sec/tamper/inc",
"embed/sec/time_estimate/inc",
@@ -97,9 +96,6 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/option_bytes/stm32u5/option_bytes.c",
"embed/sec/random_delays/stm32/random_delays.c",
"embed/sec/rng/rng_strong.c",
- "embed/sec/secret/stm32u5/secret.c",
- "embed/sec/secret/stm32u5/secret_keys.c",
- "embed/sec/secret/secret_keys_common.c",
"embed/sec/secure_aes/stm32u5/secure_aes.c",
"embed/sec/secure_aes/stm32u5/secure_aes_unpriv.c",
"embed/sec/storage/stm32u5/storage_salt.c",
diff --git a/core/site_scons/models/unix_common.py b/core/site_scons/models/unix_common.py
index 362641d4..43acbc4c 100644
--- a/core/site_scons/models/unix_common.py
+++ b/core/site_scons/models/unix_common.py
@@ -20,7 +20,6 @@ def unix_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/board_capabilities/inc",
"embed/sec/rng/inc",
"embed/sec/monoctr/inc",
- "embed/sec/secret/inc",
"embed/sec/unit_properties/inc",
"embed/sys/cpuid/inc",
"embed/sys/flash/inc",
@@ -39,9 +38,6 @@ def unix_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/board_capabilities/unix/board_capabilities.c",
"embed/sec/fwutils/fwutils.c",
"embed/sec/random_delays/unix/random_delays.c",
- "embed/sec/secret/unix/secret.c",
- "embed/sec/secret/unix/secret_keys.c",
- "embed/sec/secret/secret_keys_common.c",
"embed/sec/storage/unix/storage_salt.c",
"embed/sec/monoctr/unix/monoctr.c",
"embed/sec/rng/rng_strong.c",
Why this scored 34/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.