1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-10 08:38:07 +00:00

refactor(core): make secret api more versatile, secret layout model dependent

[no changelog]
This commit is contained in:
tychovrahe 2025-06-02 21:40:34 +02:00 committed by TychoVrahe
parent 2a6189c3ae
commit e53cddf65e
28 changed files with 982 additions and 481 deletions

View File

@ -21,6 +21,7 @@
#include <rtl/sizedefs.h> #include <rtl/sizedefs.h>
#include "bootloaders/bootloader_hashes.h" #include "bootloaders/bootloader_hashes.h"
#include "secret_layout.h"
#define MODEL_NAME "D002" #define MODEL_NAME "D002"
#define MODEL_FULL_NAME "Trezor DIY 2" #define MODEL_FULL_NAME "Trezor DIY 2"

View File

@ -0,0 +1,36 @@
/*
* 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
#define SECRET_NUM_KEY_SLOTS 0
// first page: static
#define SECRET_HEADER_OFFSET 0x00
#define SECRET_HEADER_LEN 0x10
#define SECRET_MONOTONIC_COUNTER_0_OFFSET 0x10
#define SECRET_MONOTONIC_COUNTER_0_LEN 0x400
#define SECRET_MONOTONIC_COUNTER_1_OFFSET (0x410)
#define SECRET_MONOTONIC_COUNTER_1_LEN 0x400
// second page: refreshed on wallet wipe
#define SECRET_BHK_OFFSET 0x2000
#define SECRET_BHK_LEN 0x20

View File

@ -20,6 +20,7 @@
#pragma once #pragma once
#include "bootloaders/bootloader_hashes.h" #include "bootloaders/bootloader_hashes.h"
#include "secret_layout.h"
#define MODEL_NAME "Safe 3" #define MODEL_NAME "Safe 3"
#define MODEL_FULL_NAME "Trezor Safe 3" #define MODEL_FULL_NAME "Trezor Safe 3"

View File

@ -0,0 +1,31 @@
/*
* 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
#define SECRET_NUM_KEY_SLOTS 1
// first page: static
#define SECRET_HEADER_OFFSET 0x00
#define SECRET_HEADER_LEN 0x10
#define SECRET_KEY_SLOT_0_OFFSET 0x10
#define SECRET_KEY_SLOT_0_LEN 0x20
#define SECRET_OPTIGA_SLOT 0

View File

@ -20,6 +20,7 @@
#pragma once #pragma once
#include "bootloaders/bootloader_hashes.h" #include "bootloaders/bootloader_hashes.h"
#include "secret_layout.h"
#include <rtl/sizedefs.h> #include <rtl/sizedefs.h>

View File

@ -0,0 +1,41 @@
/*
* 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
#define SECRET_NUM_KEY_SLOTS 1
// first page: static
#define SECRET_HEADER_OFFSET 0x00
#define SECRET_HEADER_LEN 0x10
#define SECRET_KEY_SLOT_0_OFFSET 0x10
#define SECRET_KEY_SLOT_0_LEN 0x20
#define SECRET_MONOTONIC_COUNTER_0_OFFSET 0x30
#define SECRET_MONOTONIC_COUNTER_0_LEN 0x400
#define SECRET_MONOTONIC_COUNTER_1_OFFSET (0x430)
#define SECRET_MONOTONIC_COUNTER_1_LEN 0x400
// second page: refreshed on wallet wipe
#define SECRET_BHK_OFFSET 0x2000
#define SECRET_BHK_LEN 0x20
#define SECRET_OPTIGA_SLOT 0

View File

@ -20,6 +20,7 @@
#pragma once #pragma once
#include "bootloaders/bootloader_hashes.h" #include "bootloaders/bootloader_hashes.h"
#include "secret_layout.h"
#include <rtl/sizedefs.h> #include <rtl/sizedefs.h>

View File

@ -0,0 +1,41 @@
/*
* 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
#define SECRET_NUM_KEY_SLOTS 1
// first page: static
#define SECRET_HEADER_OFFSET 0x00
#define SECRET_HEADER_LEN 0x10
#define SECRET_KEY_SLOT_0_OFFSET 0x10
#define SECRET_KEY_SLOT_0_LEN 0x20
#define SECRET_MONOTONIC_COUNTER_0_OFFSET 0x30
#define SECRET_MONOTONIC_COUNTER_0_LEN 0x400
#define SECRET_MONOTONIC_COUNTER_1_OFFSET (0x430)
#define SECRET_MONOTONIC_COUNTER_1_LEN 0x400
// second page: refreshed on wallet wipe
#define SECRET_BHK_OFFSET 0x2000
#define SECRET_BHK_LEN 0x20
#define SECRET_OPTIGA_SLOT 0

View File

@ -21,6 +21,7 @@
#pragma once #pragma once
#include <rtl/sizedefs.h> #include <rtl/sizedefs.h>
#include "secret_layout.h"
#include "bootloaders/bootloader_hashes.h" #include "bootloaders/bootloader_hashes.h"

View File

@ -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
#define SECRET_NUM_KEY_SLOTS 3
// first page: static
#define SECRET_HEADER_OFFSET 0x00
#define SECRET_HEADER_LEN 0x10
#define SECRET_KEY_SLOT_0_OFFSET 0x10
#define SECRET_KEY_SLOT_0_LEN 0x20
#define SECRET_MONOTONIC_COUNTER_0_OFFSET 0x30
#define SECRET_MONOTONIC_COUNTER_0_LEN 0x400
#define SECRET_MONOTONIC_COUNTER_1_OFFSET (0x430)
#define SECRET_MONOTONIC_COUNTER_1_LEN 0x400
#define SECRET_KEY_SLOT_1_OFFSET 0x830
#define SECRET_KEY_SLOT_1_LEN 0x20
#define SECRET_KEY_SLOT_2_OFFSET 0x850
#define SECRET_KEY_SLOT_2_LEN 0x20
#define SECRET_KEY_SLOT_2_PUBLIC 1
// second page: refreshed on wallet wipe
#define SECRET_BHK_OFFSET 0x2000
#define SECRET_BHK_LEN 0x20
// slot assignments
#define SECRET_OPTIGA_SLOT 0
#define SECRET_TROPIC_TREZOR_PRIVKEY_SLOT 1
#define SECRET_TROPIC_TROPIC_PUBKEY_SLOT 2

View File

@ -155,8 +155,7 @@ int main(int argc, char **argv) {
} break; } break;
#ifdef LOCKABLE_BOOTLOADER #ifdef LOCKABLE_BOOTLOADER
case 'l': case 'l':
// write bootloader-lock secret secret_lock_bootloader();
secret_write_header();
break; break;
#endif #endif
default: default:

View File

@ -19,6 +19,7 @@
#ifdef USE_OPTIGA #ifdef USE_OPTIGA
#include <trezor_model.h>
#include <trezor_rtl.h> #include <trezor_rtl.h>
#include <rtl/cli.h> #include <rtl/cli.h>
@ -164,10 +165,10 @@ static bool set_metadata(cli_t* cli, uint16_t oid,
} }
void pair_optiga(cli_t* cli) { void pair_optiga(cli_t* cli) {
uint8_t secret[SECRET_KEY_LEN] = {0}; uint8_t secret[32] = {0};
if (secret_optiga_get(secret) != sectrue) { if (secret_key_get(SECRET_OPTIGA_SLOT, secret, sizeof(secret)) != sectrue) {
if (secret_optiga_writable() != sectrue) { if (secret_key_writable(SECRET_OPTIGA_SLOT) != sectrue) {
// optiga pairing secret is unwritable, so fail // optiga pairing secret is unwritable, so fail
optiga_pairing_state = OPTIGA_PAIRING_ERR_WRITE_FLASH; optiga_pairing_state = OPTIGA_PAIRING_ERR_WRITE_FLASH;
return; return;
@ -203,14 +204,14 @@ void pair_optiga(cli_t* cli) {
} }
// Store the pairing secret in the flash memory. // Store the pairing secret in the flash memory.
if (sectrue != secret_optiga_set(secret)) { if (sectrue != secret_key_set(SECRET_OPTIGA_SLOT, secret, sizeof(secret))) {
optiga_pairing_state = OPTIGA_PAIRING_ERR_WRITE_FLASH; optiga_pairing_state = OPTIGA_PAIRING_ERR_WRITE_FLASH;
return; return;
} }
// Reload the pairing secret from the flash memory. // Reload the pairing secret from the flash memory.
memzero(secret, sizeof(secret)); memzero(secret, sizeof(secret));
if (sectrue != secret_optiga_get(secret)) { if (sectrue != secret_key_get(SECRET_OPTIGA_SLOT, secret, sizeof(secret))) {
optiga_pairing_state = OPTIGA_PAIRING_ERR_READ_FLASH; optiga_pairing_state = OPTIGA_PAIRING_ERR_READ_FLASH;
return; return;
} }

View File

@ -1,16 +1,16 @@
#include <trezor_model.h> #include <trezor_model.h>
#include <trezor_rtl.h> #include <trezor_rtl.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <SDL.h> #include <SDL.h>
#include <io/display.h> #include <io/display.h>
#include <sec/secret.h>
#include <util/flash.h> #include <util/flash.h>
#include <util/flash_otp.h> #include <util/flash_otp.h>
#include <stdlib.h>
int prodtest_main(void); int prodtest_main(void);
void usage(void) { void usage(void) {
@ -54,6 +54,10 @@ int main(int argc, char **argv) {
flash_init(); flash_init();
flash_otp_init(); flash_otp_init();
#ifdef LOCKABLE_BOOTLOADER
secret_lock_bootloader();
#endif
int opt; int opt;
while ((opt = getopt(argc, argv, "h")) != -1) { while ((opt = getopt(argc, argv, "h")) != -1) {
switch (opt) { switch (opt) {

View File

@ -37,6 +37,7 @@
#include <unistd.h> #include <unistd.h>
#include <io/display.h> #include <io/display.h>
#include <sec/secret.h>
#include <sys/system.h> #include <sys/system.h>
#include <sys/systimer.h> #include <sys/systimer.h>
#include <util/flash.h> #include <util/flash.h>
@ -57,7 +58,6 @@
#endif #endif
#ifdef USE_TROPIC #ifdef USE_TROPIC
#include <sec/secret.h>
#include <sec/tropic.h> #include <sec/tropic.h>
#endif #endif
@ -528,6 +528,10 @@ MP_NOINLINE int main_(int argc, char **argv) {
pre_process_options(argc, argv); pre_process_options(argc, argv);
#ifdef LOCKABLE_BOOTLOADER
secret_lock_bootloader();
#endif
system_init(&rsod_panic_handler); system_init(&rsod_panic_handler);
drivers_init(); drivers_init();

View File

@ -29,14 +29,25 @@
static int32_t get_offset(monoctr_type_t type) { static int32_t get_offset(monoctr_type_t type) {
switch (type) { switch (type) {
case MONOCTR_BOOTLOADER_VERSION: case MONOCTR_BOOTLOADER_VERSION:
return SECRET_MONOTONIC_COUNTER_OFFSET; return SECRET_MONOTONIC_COUNTER_0_OFFSET;
case MONOCTR_FIRMWARE_VERSION: case MONOCTR_FIRMWARE_VERSION:
return SECRET_MONOTONIC_COUNTER2_OFFSET; return SECRET_MONOTONIC_COUNTER_1_OFFSET;
default: default:
return -1; return -1;
} }
} }
static size_t get_length(monoctr_type_t type) {
switch (type) {
case MONOCTR_BOOTLOADER_VERSION:
return SECRET_MONOTONIC_COUNTER_0_LEN;
case MONOCTR_FIRMWARE_VERSION:
return SECRET_MONOTONIC_COUNTER_1_LEN;
default:
return 0;
}
}
secbool monoctr_write(monoctr_type_t type, uint8_t value) { secbool monoctr_write(monoctr_type_t type, uint8_t value) {
if (value > MONOCTR_MAX_VALUE) { if (value > MONOCTR_MAX_VALUE) {
return secfalse; return secfalse;
@ -72,13 +83,14 @@ secbool monoctr_write(monoctr_type_t type, uint8_t value) {
secbool monoctr_read(monoctr_type_t type, uint8_t *value) { secbool monoctr_read(monoctr_type_t type, uint8_t *value) {
int32_t offset = get_offset(type); int32_t offset = get_offset(type);
size_t length = get_length(type);
if (offset < 0) { if (offset < 0) {
return secfalse; return secfalse;
} }
const uint8_t *counter_addr = flash_area_get_address( const uint8_t *counter_addr =
&SECRET_AREA, offset, SECRET_MONOTONIC_COUNTER_LEN); flash_area_get_address(&SECRET_AREA, offset, length);
if (counter_addr == NULL) { if (counter_addr == NULL) {
return secfalse; return secfalse;
@ -90,7 +102,7 @@ secbool monoctr_read(monoctr_type_t type, uint8_t *value) {
int i = 0; int i = 0;
for (i = 0; i < SECRET_MONOTONIC_COUNTER_LEN / 16; i++) { for (i = 0; i < length / 16; i++) {
secbool not_cleared = sectrue; secbool not_cleared = sectrue;
for (int j = 0; j < 16; j++) { for (int j = 0; j < 16; j++) {
if (counter_addr[i * 16 + j] != 0xFF) { if (counter_addr[i * 16 + j] != 0xFF) {
@ -106,7 +118,7 @@ secbool monoctr_read(monoctr_type_t type, uint8_t *value) {
} }
} }
for (; i < SECRET_MONOTONIC_COUNTER_LEN / 16; i++) { for (; i < length / 16; i++) {
secbool not_cleared = sectrue; secbool not_cleared = sectrue;
for (int j = 0; j < 16; j++) { for (int j = 0; j < 16; j++) {
if (counter_addr[i * 16 + j] != 0xFF) { if (counter_addr[i * 16 + j] != 0xFF) {

View File

@ -24,7 +24,7 @@
#include <sec/optiga.h> #include <sec/optiga.h>
#include <sec/optiga_commands.h> #include <sec/optiga_commands.h>
#include <sec/optiga_transport.h> #include <sec/optiga_transport.h>
#include <sec/secret.h> #include <sec/secret_keys.h>
#include <sys/systick.h> #include <sys/systick.h>
#include "memzero.h" #include "memzero.h"
@ -57,8 +57,8 @@ void optiga_init_and_configure(void) {
optiga_init(); optiga_init();
uint8_t secret[SECRET_KEY_LEN] = {0}; uint8_t secret[OPTIGA_PAIRING_SECRET_SIZE] = {0};
secbool secret_ok = secret_optiga_get(secret); secbool secret_ok = secret_key_optiga_pairing(secret);
if (sectrue == secret_ok) { if (sectrue == secret_ok) {
// If the shielded connection cannot be established, reset Optiga and // If the shielded connection cannot be established, reset Optiga and

View File

@ -23,105 +23,112 @@
#ifdef SECURE_MODE #ifdef SECURE_MODE
#define SECRET_KEY_LEN 32 /**
* @brief Writes data to the secret storage.
// first page: static *
#define SECRET_HEADER_MAGIC "TRZS" * @param data Pointer to the data to write.
#define SECRET_HEADER_LEN 16 * @param offset Offset in the storage to begin writing.
#define SECRET_OPTIGA_KEY_OFFSET 16 * @param len Number of bytes to write.
*/
#define SECRET_MONOTONIC_COUNTER_OFFSET 48
#define SECRET_MONOTONIC_COUNTER_LEN 1024
#define SECRET_MONOTONIC_COUNTER2_OFFSET (SECRET_MONOTONIC_COUNTER_LEN + 48)
#define SECRET_TROPIC_TRZ_PRIVKEY_OFFSET \
(SECRET_MONOTONIC_COUNTER_LEN + SECRET_MONOTONIC_COUNTER2_OFFSET)
#define SECRET_TROPIC_TRO_PUBKEY_OFFSET \
(SECRET_TROPIC_TRZ_PRIVKEY_OFFSET + SECRET_KEY_LEN)
// second page: refreshed on wallet wipe
#define SECRET_BHK_OFFSET (1024 * 8)
// Writes data to the secret storage
void secret_write(const uint8_t* data, uint32_t offset, uint32_t len); void secret_write(const uint8_t* data, uint32_t offset, uint32_t len);
// Reads data from the secret storage /**
* @brief Reads data from the secret storage.
*
* @param data Pointer to buffer where read data will be stored.
* @param offset Offset in the storage to begin reading.
* @param len Number of bytes to read.
* @return secbool sectrue on successful read, secfalse otherwise.
*/
secbool secret_read(uint8_t* data, uint32_t offset, uint32_t len); secbool secret_read(uint8_t* data, uint32_t offset, uint32_t len);
// Checks if the secret storage has been wiped /**
secbool secret_wiped(void); * @brief Writes a key to the secret storage.
*
* Encrypts the secret if encryption is available on the platform.
*
* @param slot Index of the key slot.
* @param key Pointer to the key data.
* @param len Length of the key in bytes.
* @return secbool sectrue if the key was written successfully, secfalse
* otherwise.
*/
secbool secret_key_set(uint8_t slot, const uint8_t* key, size_t len);
// Verifies that the secret storage has the correct header /**
secbool secret_verify_header(void); * @brief Reads a secret key from the storage.
*
* Decrypts the secret if encryption is available on the platform.
*
* @param slot Index of the key slot.
* @param dest Pointer to destination buffer for the key.
* @param len Length of the dest buffer.
* @return secbool secrue if the key was read successfully, secfalse otherwise.
*/
secbool secret_key_get(uint8_t slot, uint8_t* dest, size_t len);
// Erases the entire secret storage /**
void secret_erase(void); * @brief Checks if a secret key slot is writable.
*
* @param slot Index of the key slot.
* @return secbool sectrue if the key slot can be written, secfalse otherwise.
*/
secbool secret_key_writable(uint8_t slot);
// Writes the secret header to the secret storage /**
void secret_write_header(void); * @brief Regenerates the BHK and writes it to the secret storage.
*/
#ifdef USE_OPTIGA
// OPTIGA KEYS
// Writes optiga pairing secret to the secret storage
// Encrypts the secret if encryption is available on the platform
// Returns true if the secret was written successfully
secbool secret_optiga_set(const uint8_t secret[SECRET_KEY_LEN]);
// Reads optiga pairing secret
// Decrypts the secret if encryption is available on the platform
// Returns true if the secret was read successfully
// Reading can fail if optiga is not paired, the pairing secret was not
// provisioned to the firmware (by calling secret_optiga_backup), or the secret
// was made unavailable by calling secret_optiga_hide
secbool secret_optiga_get(uint8_t dest[SECRET_KEY_LEN]);
// Checks if the optiga pairing secret is present in the secret storage
secbool secret_optiga_present(void);
// Checks if the optiga pairing secret can be written to the secret storage
secbool secret_optiga_writable(void);
#endif
#ifdef USE_TROPIC
// TROPIC KEYS
secbool secret_tropic_get_trezor_privkey(uint8_t dest[SECRET_KEY_LEN]);
secbool secret_tropic_get_tropic_pubkey(uint8_t dest[SECRET_KEY_LEN]);
secbool secret_tropic_set(const uint8_t privkey[SECRET_KEY_LEN],
const uint8_t pubkey[SECRET_KEY_LEN]);
secbool secret_tropic_present(void);
secbool secret_tropic_writable(void);
#endif
// Regenerates the BHK and writes it to the secret storage
void secret_bhk_regenerate(void); void secret_bhk_regenerate(void);
// Prepares the secret storage for running the firmware /**
// Provisions secrets/keys to the firmware, depending on the trust level * @brief Prepares the secret storage for running the firmware.
// Disables access to the secret storage until next reset, if possible *
// This function is called by the bootloader before starting the firmware * Provisions secrets and keys to the firmware depending on the trust level.
* Disables access to the secret storage until next reset, if possible.
* This function is called by the bootloader before starting the firmware.
*
* @param allow_run_with_secret Allow firmware to run with secret access.
* @param allow_provisioning_access Allow provisioning access to secrets.
*/
void secret_prepare_fw(secbool allow_run_with_secret, void secret_prepare_fw(secbool allow_run_with_secret,
secbool allow_provisioning_access); secbool allow_provisioning_access);
// Prepares the secret storage for running the boardloader and next stages /**
// Ensures that secret storage access is enabled * @brief Initializes the secret storage for running the boardloader and next
// This function is called by the boardloader * stages.
*
* Ensures that secret storage access is enabled.
* This function is called by the boardloader.
*/
void secret_init(void); void secret_init(void);
#ifdef LOCKABLE_BOOTLOADER #ifdef LOCKABLE_BOOTLOADER
// Unlocks the bootloader, all neccessary keys are erased
/**
* @brief Unlocks the bootloader and erases all necessary keys.
*/
void secret_unlock_bootloader(void); void secret_unlock_bootloader(void);
#ifdef TREZOR_EMULATOR
/**
* @brief Locks the bootloader (emulator only).
*/
void secret_lock_bootloader(void);
#endif
#endif #endif
#endif // SECURE_MODE #endif // SECURE_MODE
#ifdef LOCKABLE_BOOTLOADER #ifdef LOCKABLE_BOOTLOADER
// Checks if bootloader is locked, that is the secret storage contains optiga
// pairing secret on platforms where access to the secret storage cannot be /**
// restricted for unofficial firmware * @brief Checks if the bootloader is locked.
*
* On platforms where secret storage access cannot be restricted for unofficial
* firmware, a locked bootloader indicates presence of a non-public key.
*
* @return secbool sectrue if bootloader is locked, secfalse otherwise.
*/
secbool secret_bootloader_locked(void); secbool secret_bootloader_locked(void);
#endif #endif

View File

@ -0,0 +1,42 @@
/*
* 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
#ifdef USE_OPTIGA
#define OPTIGA_PAIRING_SECRET_SIZE 32
secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]);
#endif
#ifdef USE_TROPIC
#include <ed25519-donna/ed25519.h>
secbool secret_key_tropic_public(curve25519_key dest);
secbool secret_key_tropic_pairing(curve25519_key dest);
#endif
#endif

View File

@ -26,12 +26,23 @@
#ifdef KERNEL_MODE #ifdef KERNEL_MODE
#ifdef SECRET_NUM_KEY_SLOTS
#define SECRET_HEADER_MAGIC "TRZS"
#define SECRET_HEADER_MAGIC_LEN (sizeof(SECRET_HEADER_MAGIC) - 1)
#define SECRET_NUM_MAX_SLOTS 1
_Static_assert(SECRET_NUM_MAX_SLOTS >= SECRET_NUM_KEY_SLOTS,
"Exceeded max slots");
_Static_assert(SECRET_KEY_SLOT_0_LEN == 32, "Invalid key slot length");
static secbool bootloader_locked_set = secfalse; static secbool bootloader_locked_set = secfalse;
static secbool bootloader_locked = secfalse; static secbool bootloader_locked = secfalse;
secbool secret_verify_header(void) { secbool secret_verify_header(void) {
uint8_t* addr = (uint8_t*)flash_area_get_address(&SECRET_AREA, 0, uint8_t* addr = (uint8_t*)flash_area_get_address(
sizeof(SECRET_HEADER_MAGIC)); &SECRET_AREA, SECRET_HEADER_OFFSET, SECRET_HEADER_LEN);
if (addr == NULL) { if (addr == NULL) {
return secfalse; return secfalse;
@ -40,7 +51,7 @@ secbool secret_verify_header(void) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
bootloader_locked = bootloader_locked =
memcmp(addr, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0 memcmp(addr, SECRET_HEADER_MAGIC, SECRET_HEADER_MAGIC_LEN) == 0
? sectrue ? sectrue
: secfalse; : secfalse;
@ -65,8 +76,8 @@ void secret_unlock_bootloader(void) { secret_erase(); }
void secret_write_header(void) { void secret_write_header(void) {
uint8_t header[SECRET_HEADER_LEN] = {0}; uint8_t header[SECRET_HEADER_LEN] = {0};
memcpy(header, SECRET_HEADER_MAGIC, 4); memcpy(header, SECRET_HEADER_MAGIC, SECRET_HEADER_MAGIC_LEN);
secret_write(header, 0, SECRET_HEADER_LEN); secret_write(header, SECRET_HEADER_OFFSET, SECRET_HEADER_LEN);
} }
void secret_write(const uint8_t* data, uint32_t offset, uint32_t len) { void secret_write(const uint8_t* data, uint32_t offset, uint32_t len) {
@ -98,7 +109,7 @@ secbool secret_read(uint8_t* data, uint32_t offset, uint32_t len) {
return sectrue; return sectrue;
} }
secbool secret_wiped(void) { static secbool secret_wiped(void) {
uint32_t size = flash_area_get_size(&SECRET_AREA); uint32_t size = flash_area_get_size(&SECRET_AREA);
secbool wiped = sectrue; secbool wiped = sectrue;
@ -127,22 +138,54 @@ void secret_erase(void) {
mpu_restore(mpu_mode); mpu_restore(mpu_mode);
} }
secbool secret_optiga_set(const uint8_t secret[SECRET_KEY_LEN]) { secbool secret_key_set(uint8_t slot, const uint8_t* key, size_t len) {
if (slot >= SECRET_NUM_KEY_SLOTS) {
return secfalse;
}
if (len != SECRET_KEY_SLOT_0_LEN) {
return secfalse;
}
uint32_t offset = SECRET_KEY_SLOT_0_OFFSET;
secret_erase(); secret_erase();
secret_write_header(); secret_write_header();
secret_write(secret, SECRET_OPTIGA_KEY_OFFSET, SECRET_KEY_LEN); secret_write(key, offset, len);
return sectrue; return sectrue;
} }
secbool secret_optiga_get(uint8_t dest[SECRET_KEY_LEN]) { secbool secret_key_get(uint8_t slot, uint8_t* dest, size_t len) {
return secret_read(dest, SECRET_OPTIGA_KEY_OFFSET, SECRET_KEY_LEN); if (slot >= SECRET_NUM_KEY_SLOTS) {
return secfalse;
}
if (len != SECRET_KEY_SLOT_0_LEN) {
return secfalse;
}
uint32_t offset = SECRET_KEY_SLOT_0_OFFSET;
return secret_read(dest, offset, len);
} }
secbool secret_optiga_present(void) { static secbool secret_key_present(uint8_t slot) {
if (slot >= SECRET_NUM_KEY_SLOTS) {
return secfalse;
}
return (sectrue != secret_wiped()) * sectrue; return (sectrue != secret_wiped()) * sectrue;
} }
secbool secret_optiga_writable(void) { return secret_wiped(); } secbool secret_key_writable(uint8_t slot) {
if (slot >= SECRET_NUM_KEY_SLOTS) {
return secfalse;
}
return secret_wiped();
}
#endif
void secret_prepare_fw(secbool allow_run_with_secret, void secret_prepare_fw(secbool allow_run_with_secret,
secbool allow_provisioning_access) { secbool allow_provisioning_access) {

View File

@ -0,0 +1,35 @@
/*
* 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>
#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
#endif

View File

@ -32,14 +32,75 @@
#ifdef SECURE_MODE #ifdef SECURE_MODE
#define REG_BHK_OFFSET 0 #define SECRET_HEADER_MAGIC "TRZS"
#define REG_OPTIGA_KEY_OFFSET 8 #define SECRET_HEADER_MAGIC_LEN (sizeof(SECRET_HEADER_MAGIC) - 1)
#define REG_TROPIC_TRZ_PRIVKEY_OFFSET 16
#define REG_TROPIC_TRO_PUBKEY_OFFSET 24
secbool secret_verify_header(void) { #define SECRET_BHK_REG_OFFSET 0
#define SECRET_NUM_MAX_SLOTS 3
#ifndef SECRET_KEY_SLOT_0_OFFSET
#define SECRET_KEY_SLOT_0_OFFSET 0
#define SECRET_KEY_SLOT_0_LEN 0
#endif
#ifndef SECRET_KEY_SLOT_1_OFFSET
#define SECRET_KEY_SLOT_1_OFFSET 0
#define SECRET_KEY_SLOT_1_LEN 0
#endif
#ifndef SECRET_KEY_SLOT_2_OFFSET
#define SECRET_KEY_SLOT_2_OFFSET 0
#define SECRET_KEY_SLOT_2_LEN 0
#endif
#define SECRET_KEY_MAX_LEN (24 * sizeof(uint32_t))
_Static_assert(SECRET_NUM_MAX_SLOTS >= SECRET_NUM_KEY_SLOTS);
_Static_assert(SECRET_KEY_SLOT_0_LEN + SECRET_KEY_SLOT_1_LEN +
SECRET_KEY_SLOT_2_LEN <=
SECRET_KEY_MAX_LEN,
"secret key slots too large");
_Static_assert(SECRET_KEY_SLOT_0_LEN % 16 == 0,
"secret key length must be multiple of 16 bytes");
_Static_assert(SECRET_KEY_SLOT_1_LEN % 16 == 0,
"secret key length must be multiple of 16 bytes");
_Static_assert(SECRET_KEY_SLOT_2_LEN % 16 == 0,
"secret key length must be multiple of 16 bytes");
static uint32_t secret_slot_offsets[SECRET_NUM_MAX_SLOTS] = {
SECRET_KEY_SLOT_0_OFFSET,
SECRET_KEY_SLOT_1_OFFSET,
SECRET_KEY_SLOT_2_OFFSET,
};
static uint32_t secret_slot_lengths[SECRET_NUM_MAX_SLOTS] = {
SECRET_KEY_SLOT_0_LEN,
SECRET_KEY_SLOT_1_LEN,
SECRET_KEY_SLOT_2_LEN,
};
static secbool secret_slot_public[SECRET_NUM_MAX_SLOTS] = {
#ifdef SECRET_KEY_SLOT_0_PUBLIC
sectrue,
#else
secfalse,
#endif
#ifdef SECRET_KEY_SLOT_1_PUBLIC
sectrue,
#else
secfalse,
#endif
#ifdef SECRET_KEY_SLOT_2_PUBLIC
sectrue,
#else
secfalse,
#endif
};
static secbool secret_verify_header(void) {
uint8_t *addr = (uint8_t *)flash_area_get_address( uint8_t *addr = (uint8_t *)flash_area_get_address(
&SECRET_AREA, 0, sizeof(SECRET_HEADER_MAGIC)); &SECRET_AREA, SECRET_HEADER_OFFSET, SECRET_HEADER_LEN);
if (addr == NULL) { if (addr == NULL) {
return secfalse; return secfalse;
@ -48,7 +109,7 @@ secbool secret_verify_header(void) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
secbool header_present = secbool header_present =
memcmp(addr, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0 memcmp(addr, SECRET_HEADER_MAGIC, SECRET_HEADER_MAGIC_LEN) == 0
? sectrue ? sectrue
: secfalse; : secfalse;
@ -57,6 +118,18 @@ secbool secret_verify_header(void) {
return header_present; return header_present;
} }
static void secret_erase(void) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase");
mpu_restore(mpu_mode);
}
static void secret_write_header(void) {
uint8_t header[SECRET_HEADER_LEN] = {0};
memcpy(header, SECRET_HEADER_MAGIC, SECRET_HEADER_MAGIC_LEN);
secret_write(header, SECRET_HEADER_OFFSET, SECRET_HEADER_LEN);
}
static secbool secret_ensure_initialized(void) { static secbool secret_ensure_initialized(void) {
if (sectrue != secret_verify_header()) { if (sectrue != secret_verify_header()) {
ensure(erase_storage(NULL), "erase storage failed"); ensure(erase_storage(NULL), "erase storage failed");
@ -67,12 +140,6 @@ static secbool secret_ensure_initialized(void) {
return sectrue; return sectrue;
} }
void secret_write_header(void) {
uint8_t header[SECRET_HEADER_LEN] = {0};
memcpy(header, SECRET_HEADER_MAGIC, 4);
secret_write(header, 0, SECRET_HEADER_LEN);
}
void secret_write(const uint8_t *data, uint32_t offset, uint32_t len) { void secret_write(const uint8_t *data, uint32_t offset, uint32_t len) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
ensure(flash_unlock_write(), "secret write"); ensure(flash_unlock_write(), "secret write");
@ -119,9 +186,41 @@ static secbool secret_bhk_locked(void) {
sectrue; sectrue;
} }
static secbool secret_key_present(uint32_t offset) { static secbool secret_is_slot_valid(uint8_t slot) {
return ((slot < SECRET_NUM_KEY_SLOTS) && (secret_slot_offsets[slot] != 0)) *
sectrue;
}
static uint32_t secret_get_slot_offset(uint8_t slot) {
if (slot >= SECRET_NUM_KEY_SLOTS) {
return 0;
}
return secret_slot_offsets[slot];
}
static uint32_t secret_get_slot_len(uint8_t slot) {
if (slot >= SECRET_NUM_KEY_SLOTS) {
return 0;
}
return secret_slot_lengths[slot];
}
static size_t secret_get_reg_offset(uint8_t slot) {
// SECRET_BHK_LEN is in bytes; each reg is 32 bits = 4 bytes
size_t cumulative = SECRET_BHK_LEN / sizeof(uint32_t);
for (uint8_t i = 0; i < slot; i++) {
if (sectrue == secret_is_slot_valid(i)) {
cumulative += (secret_slot_lengths[i] / sizeof(uint32_t));
}
}
return cumulative;
}
static secbool secret_record_present(uint32_t offset, uint32_t len) {
uint8_t *secret = uint8_t *secret =
(uint8_t *)flash_area_get_address(&SECRET_AREA, offset, SECRET_KEY_LEN); (uint8_t *)flash_area_get_address(&SECRET_AREA, offset, len);
if (secret == NULL) { if (secret == NULL) {
return secfalse; return secfalse;
@ -131,7 +230,7 @@ static secbool secret_key_present(uint32_t offset) {
int secret_empty_bytes = 0; int secret_empty_bytes = 0;
for (int i = 0; i < SECRET_KEY_LEN; i++) { for (int i = 0; i < len; i++) {
// 0xFF being the default value of the flash memory (before any write) // 0xFF being the default value of the flash memory (before any write)
// 0x00 being the value of the flash memory after manual erase // 0x00 being the value of the flash memory after manual erase
if (secret[i] == 0xFF || secret[i] == 0x00) { if (secret[i] == 0xFF || secret[i] == 0x00) {
@ -141,12 +240,30 @@ static secbool secret_key_present(uint32_t offset) {
mpu_restore(mpu_mode); mpu_restore(mpu_mode);
return sectrue * (secret_empty_bytes != SECRET_KEY_LEN); return sectrue * (secret_empty_bytes != len);
} }
__attribute__((unused)) static secbool secret_key_writable(uint32_t offset) { static secbool secret_key_present(uint8_t slot) {
if (sectrue != secret_is_slot_valid(slot)) {
return secfalse;
}
uint32_t offset = secret_get_slot_offset(slot);
uint32_t len = secret_get_slot_len(slot);
return secret_record_present(offset, len);
}
secbool secret_key_writable(uint8_t slot) {
if (sectrue != secret_is_slot_valid(slot)) {
return secfalse;
}
uint32_t offset = secret_get_slot_offset(slot);
uint32_t len = secret_get_slot_len(slot);
const uint8_t *const secret = const uint8_t *const secret =
(uint8_t *)flash_area_get_address(&SECRET_AREA, offset, SECRET_KEY_LEN); (uint8_t *)flash_area_get_address(&SECRET_AREA, offset, len);
if (secret == NULL) { if (secret == NULL) {
return secfalse; return secfalse;
@ -156,7 +273,7 @@ __attribute__((unused)) static secbool secret_key_writable(uint32_t offset) {
int secret_empty_bytes = 0; int secret_empty_bytes = 0;
for (int i = 0; i < SECRET_KEY_LEN; i++) { for (int i = 0; i < len; i++) {
// 0xFF being the default value of the flash memory (before any write) // 0xFF being the default value of the flash memory (before any write)
// 0x00 being the value of the flash memory after manual erase // 0x00 being the value of the flash memory after manual erase
if (secret[i] == 0xFF) { if (secret[i] == 0xFF) {
@ -166,24 +283,27 @@ __attribute__((unused)) static secbool secret_key_writable(uint32_t offset) {
mpu_restore(mpu_mode); mpu_restore(mpu_mode);
return sectrue * (secret_empty_bytes == SECRET_KEY_LEN); return sectrue * (secret_empty_bytes == len);
} }
__attribute__((unused)) static void secret_key_cache(uint8_t reg_offset, static void secret_key_cache(uint8_t slot) {
uint32_t key_offset) { uint32_t offset = secret_get_slot_offset(slot);
uint32_t secret[SECRET_KEY_LEN / sizeof(uint32_t)] = {0}; uint32_t len = secret_get_slot_len(slot);
size_t reg_offset = secret_get_reg_offset(slot);
secbool ok = secret_read((uint8_t *)secret, key_offset, SECRET_KEY_LEN); uint32_t secret[SECRET_KEY_MAX_LEN] = {0};
secbool ok = secret_read((uint8_t *)secret, offset, len);
volatile uint32_t *reg = &TAMP->BKP0R; volatile uint32_t *reg = &TAMP->BKP0R;
reg += reg_offset; reg += reg_offset;
if (sectrue == ok) { if (sectrue == ok) {
for (int i = 0; i < (SECRET_KEY_LEN / sizeof(uint32_t)); i++) { for (int i = 0; i < (len / sizeof(uint32_t)); i++) {
*reg = ((uint32_t *)secret)[i]; *reg = secret[i];
reg++; reg++;
} }
} else { } else {
for (int i = 0; i < (SECRET_KEY_LEN / sizeof(uint32_t)); i++) { for (int i = 0; i < (len / sizeof(uint32_t)); i++) {
*reg = 0; *reg = 0;
reg++; reg++;
} }
@ -191,28 +311,46 @@ __attribute__((unused)) static void secret_key_cache(uint8_t reg_offset,
memzero(secret, sizeof(secret)); memzero(secret, sizeof(secret));
} }
__attribute__((unused)) static secbool secret_key_set( secbool secret_key_set(uint8_t slot, const uint8_t *key, size_t len) {
const uint8_t secret[SECRET_KEY_LEN], uint8_t reg_offset, if (sectrue != secret_is_slot_valid(slot)) {
uint32_t key_offset) {
uint8_t secret_enc[SECRET_KEY_LEN] = {0};
if (sectrue != secure_aes_ecb_encrypt_hw(secret, sizeof(secret_enc),
secret_enc,
SECURE_AES_KEY_DHUK_SP)) {
return secfalse; return secfalse;
} }
secret_write(secret_enc, key_offset, SECRET_KEY_LEN);
uint32_t offset = secret_get_slot_offset(slot);
uint32_t slot_len = secret_get_slot_len(slot);
if (slot_len != len) {
return secfalse;
}
uint8_t secret_enc[SECRET_KEY_MAX_LEN] = {0};
if (sectrue !=
secure_aes_ecb_encrypt_hw(key, len, secret_enc, SECURE_AES_KEY_DHUK_SP)) {
return secfalse;
}
secret_write(secret_enc, offset, len);
memzero(secret_enc, sizeof(secret_enc)); memzero(secret_enc, sizeof(secret_enc));
secret_key_cache(reg_offset, key_offset); secret_key_cache(slot);
return sectrue; return sectrue;
} }
__attribute__((unused)) static secbool secret_key_get( secbool secret_key_get(uint8_t slot, uint8_t *dest, size_t len) {
uint8_t dest[SECRET_KEY_LEN], uint8_t reg_offset) { if (sectrue != secret_is_slot_valid(slot)) {
uint32_t secret[SECRET_KEY_LEN / sizeof(uint32_t)] = {0}; return secfalse;
}
uint32_t slot_len = secret_get_slot_len(slot);
size_t reg_offset = secret_get_reg_offset(slot);
if (slot_len != len) {
return secfalse;
}
uint32_t secret[SECRET_KEY_MAX_LEN] = {0};
bool all_zero = true; bool all_zero = true;
volatile uint32_t *reg = &TAMP->BKP0R; volatile uint32_t *reg = &TAMP->BKP0R;
for (int i = 0; i < (SECRET_KEY_LEN / sizeof(uint32_t)); i++) { for (int i = 0; i < (len / sizeof(uint32_t)); i++) {
secret[i] = reg[i + reg_offset]; secret[i] = reg[i + reg_offset];
if (secret[i] != 0) { if (secret[i] != 0) {
@ -224,21 +362,33 @@ __attribute__((unused)) static secbool secret_key_get(
return secfalse; return secfalse;
} }
secbool res = secure_aes_ecb_decrypt_hw((uint8_t *)secret, SECRET_KEY_LEN, secbool res = secure_aes_ecb_decrypt_hw((uint8_t *)secret, len, dest,
dest, SECURE_AES_KEY_DHUK_SP); SECURE_AES_KEY_DHUK_SP);
memzero(secret, sizeof(secret)); memzero(secret, sizeof(secret));
return res; return res;
} }
// Deletes the secret from the register // Deletes the secret from the register
__attribute__((unused)) static void secret_key_uncache(uint8_t reg_offset) { __attribute__((unused)) static void secret_key_uncache(uint8_t slot) {
size_t reg_offset = secret_get_reg_offset(slot);
uint32_t slot_len = secret_get_slot_len(slot);
volatile uint32_t *reg = &TAMP->BKP0R; volatile uint32_t *reg = &TAMP->BKP0R;
for (int i = 0; i < 8; i++) { for (int i = 0; i < slot_len / sizeof(uint32_t); i++) {
reg[i + reg_offset] = 0; reg[i + reg_offset] = 0;
} }
} }
static void secret_key_erase(uint8_t slot) {
uint8_t value[SECRET_KEY_MAX_LEN] = {0};
uint32_t offset = secret_get_slot_offset(slot);
uint32_t slot_len = secret_get_slot_len(slot);
secret_write(value, offset, slot_len);
}
// Provision the secret BHK from the secret storage to the BHK register // Provision the secret BHK from the secret storage to the BHK register
// which makes the BHK usable for encryption by the firmware, without having // which makes the BHK usable for encryption by the firmware, without having
// read access to it. // read access to it.
@ -247,23 +397,23 @@ static void secret_bhk_load(void) {
reboot_device(); reboot_device();
} }
uint32_t secret[SECRET_KEY_LEN / sizeof(uint32_t)] = {0}; uint32_t secret[SECRET_BHK_LEN / sizeof(uint32_t)] = {0};
if (sectrue != secret_key_present(SECRET_BHK_OFFSET)) { if (sectrue != secret_record_present(SECRET_BHK_OFFSET, SECRET_BHK_LEN)) {
secret_bhk_regenerate(); secret_bhk_regenerate();
} }
secbool ok = secbool ok =
secret_read((uint8_t *)secret, SECRET_BHK_OFFSET, SECRET_KEY_LEN); secret_read((uint8_t *)secret, SECRET_BHK_OFFSET, SECRET_BHK_LEN);
volatile uint32_t *reg1 = &TAMP->BKP0R; volatile uint32_t *reg1 = &TAMP->BKP0R;
if (sectrue == ok) { if (sectrue == ok) {
for (int i = 0; i < (SECRET_KEY_LEN / sizeof(uint32_t)); i++) { for (int i = 0; i < (SECRET_BHK_LEN / sizeof(uint32_t)); i++) {
*reg1 = ((uint32_t *)secret)[i]; *reg1 = ((uint32_t *)secret)[i];
reg1++; reg1++;
} }
} else { } else {
for (int i = 0; i < (SECRET_KEY_LEN / sizeof(uint32_t)); i++) { for (int i = 0; i < (SECRET_BHK_LEN / sizeof(uint32_t)); i++) {
*reg1 = 0; *reg1 = 0;
reg1++; reg1++;
} }
@ -293,199 +443,88 @@ void secret_bhk_regenerate(void) {
ensure(flash_lock_write(), "Failed regenerating BHK"); ensure(flash_lock_write(), "Failed regenerating BHK");
} }
#ifdef USE_OPTIGA static void secret_keys_uncache(void) {
// Checks that the optiga pairing secret is present in the secret storage. for (uint8_t i = 0; i < SECRET_NUM_KEY_SLOTS; i++) {
// This functions only works when software has access to the secret storage, if (sectrue == secret_is_slot_valid(i)) {
// i.e. in bootloader. Access to secret storage is restricted by calling secret_key_uncache(i);
// secret_hide. }
secbool secret_optiga_present(void) {
return secret_key_present(SECRET_OPTIGA_KEY_OFFSET);
}
secbool secret_optiga_writable(void) {
return secret_key_writable(SECRET_OPTIGA_KEY_OFFSET);
}
secbool secret_optiga_set(const uint8_t secret[SECRET_KEY_LEN]) {
return secret_key_set(secret, REG_OPTIGA_KEY_OFFSET,
SECRET_OPTIGA_KEY_OFFSET);
}
secbool secret_optiga_get(uint8_t dest[SECRET_KEY_LEN]) {
return secret_key_get(dest, REG_OPTIGA_KEY_OFFSET);
}
// Backs up the optiga pairing secret from the secret storage to the backup
// register
static void secret_optiga_cache(void) {
if (sectrue == secret_optiga_present()) {
secret_key_cache(REG_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_OFFSET);
} }
} }
// Deletes the optiga pairing secret from the register static void secret_keys_cache(void) {
static void secret_optiga_uncache(void) { secret_key_uncache(8); } for (uint8_t i = 0; i < SECRET_NUM_KEY_SLOTS; i++) {
if (sectrue == secret_is_slot_valid(i) &&
static void secret_optiga_erase(void) { sectrue == secret_key_present(i)) {
uint8_t value[SECRET_KEY_LEN] = {0}; secret_key_cache(i);
secret_write(value, SECRET_OPTIGA_KEY_OFFSET, SECRET_KEY_LEN); }
}
#endif
#ifdef USE_TROPIC
secbool secret_tropic_get_trezor_privkey(uint8_t dest[SECRET_KEY_LEN]) {
return secret_key_get(dest, REG_TROPIC_TRZ_PRIVKEY_OFFSET);
}
secbool secret_tropic_get_tropic_pubkey(uint8_t dest[SECRET_KEY_LEN]) {
return secret_key_get(dest, REG_TROPIC_TRO_PUBKEY_OFFSET);
}
secbool secret_tropic_set(const uint8_t privkey[SECRET_KEY_LEN],
const uint8_t pubkey[SECRET_KEY_LEN]) {
secbool res1 = secret_key_set(privkey, REG_TROPIC_TRZ_PRIVKEY_OFFSET,
SECRET_TROPIC_TRZ_PRIVKEY_OFFSET);
if (sectrue != res1) {
return secfalse;
}
secbool res2 = secret_key_set(pubkey, REG_TROPIC_TRO_PUBKEY_OFFSET,
SECRET_TROPIC_TRO_PUBKEY_OFFSET);
return res2;
}
secbool secret_tropic_present(void) {
secbool res1 = secret_key_present(SECRET_TROPIC_TRZ_PRIVKEY_OFFSET);
secbool res2 = secret_key_present(SECRET_TROPIC_TRO_PUBKEY_OFFSET);
return secbool_and(res1, res2);
}
secbool secret_tropic_present_any(void) {
secbool res1 = secret_key_present(SECRET_TROPIC_TRZ_PRIVKEY_OFFSET);
secbool res2 = secret_key_present(SECRET_TROPIC_TRO_PUBKEY_OFFSET);
return secbool_or(res1, res2);
}
secbool secret_tropic_writable(void) {
secbool res1 = secret_key_writable(SECRET_TROPIC_TRZ_PRIVKEY_OFFSET);
secbool res2 = secret_key_writable(SECRET_TROPIC_TRO_PUBKEY_OFFSET);
return secbool_or(res1, res2);
}
static void secret_tropic_erase(void) {
uint8_t value[SECRET_KEY_LEN] = {0};
secret_write(value, SECRET_TROPIC_TRZ_PRIVKEY_OFFSET, SECRET_KEY_LEN);
secret_write(value, SECRET_TROPIC_TRO_PUBKEY_OFFSET, SECRET_KEY_LEN);
}
// Backs up the tropic pairing secret from the secret storage to the backup
// register
static void secret_tropic_cache(void) {
if (sectrue == secret_tropic_present()) {
secret_key_cache(REG_TROPIC_TRZ_PRIVKEY_OFFSET,
SECRET_TROPIC_TRZ_PRIVKEY_OFFSET);
secret_key_cache(REG_TROPIC_TRO_PUBKEY_OFFSET,
SECRET_TROPIC_TRO_PUBKEY_OFFSET);
} }
} }
// Deletes the tropic pairing secret from the register static void secret_keys_cache_public(void) {
static void secret_tropic_uncache(void) { for (uint8_t i = 0; i < SECRET_NUM_KEY_SLOTS; i++) {
secret_key_uncache(REG_TROPIC_TRZ_PRIVKEY_OFFSET); if ((sectrue == secret_is_slot_valid(i)) &&
secret_key_uncache(REG_TROPIC_TRO_PUBKEY_OFFSET); (sectrue == secret_key_present(i)) &&
(sectrue == secret_slot_public[i])) {
secret_key_cache(i);
}
}
} }
#endif // return sectrue if all the key slots are valid and contain a key
static secbool secret_keys_present(void) {
secbool result = sectrue;
void secret_erase(void) { for (uint8_t i = 0; i < SECRET_NUM_KEY_SLOTS; i++) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); if (sectrue == secret_is_slot_valid(i)) {
ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase"); result = secbool_and(result, secret_key_present(i));
mpu_restore(mpu_mode); }
}
return result;
} }
static void secret_se_uncache(void) { #if defined BOOTLOADER || defined BOARDLOADER
#ifdef USE_OPTIGA // return sectrue if any non-public key slot is valid and contains a key
secret_optiga_uncache(); static secbool secret_keys_present_any(void) {
#endif secbool result = secfalse;
#ifdef USE_TROPIC
secret_tropic_uncache(); for (uint8_t i = 0; i < SECRET_NUM_KEY_SLOTS; i++) {
#endif if (sectrue == secret_is_slot_valid(i) &&
sectrue != secret_slot_public[i]) {
result = secbool_or(result, secret_key_present(i));
}
}
return result;
} }
static void secret_se_cache(void) {
#ifdef USE_OPTIGA
secret_optiga_cache();
#endif
#ifdef USE_TROPIC
secret_tropic_cache();
#endif
}
static secbool secret_se_present(void) {
#ifdef USE_OPTIGA
secbool res1 = secret_optiga_present();
#else
secbool res1 = sectrue;
#endif #endif
#ifdef USE_TROPIC // return sectrue if at least one key slot is writable
secbool res2 = secret_tropic_present(); static secbool secret_keys_writable(void) {
#else secbool result = secfalse;
secbool res2 = sectrue;
#endif
return secbool_and(res1, res2); for (uint8_t i = 0; i < SECRET_NUM_KEY_SLOTS; i++) {
} if (sectrue == secret_is_slot_valid(i)) {
result = secbool_or(result, secret_key_writable(i));
}
}
__attribute__((unused)) static secbool secret_se_present_any(void) { return result;
#ifdef USE_OPTIGA
secbool res1 = secret_optiga_present();
#else
secbool res1 = secfalse;
#endif
#ifdef USE_TROPIC
secbool res2 = secret_tropic_present_any();
#else
secbool res2 = secfalse;
#endif
return secbool_or(res1, res2);
}
static secbool secret_se_writable(void) {
#ifdef USE_OPTIGA
secbool res1 = secret_optiga_writable();
#else
secbool res1 = secfalse;
#endif
#ifdef USE_TROPIC
secbool res2 = secret_tropic_writable();
#else
secbool res2 = secfalse;
#endif
return secbool_or(res1, res2);
} }
#ifdef LOCKABLE_BOOTLOADER #ifdef LOCKABLE_BOOTLOADER
secbool secret_bootloader_locked(void) { secbool secret_bootloader_locked(void) {
#if defined BOOTLOADER || defined BOARDLOADER #if defined BOOTLOADER || defined BOARDLOADER
return secret_se_present_any(); return secret_keys_present_any();
#else #else
const volatile uint32_t *reg1 = &TAMP->BKP8R; // in firmware, we determine bootloader state by checking if bootloader
for (int i = 0; i < 24; i++) { // has provided any non-public key
if (reg1[i] != 0) { for (int i = 0; i < SECRET_NUM_KEY_SLOTS; i++) {
uint32_t val[SECRET_KEY_MAX_LEN] = {0};
size_t len = secret_get_slot_len(i);
if (secfalse == secret_slot_public[i] &&
sectrue == secret_key_get(i, (uint8_t *)val, len)) {
memzero(val, sizeof(val));
return sectrue; return sectrue;
} }
} }
@ -494,12 +533,12 @@ secbool secret_bootloader_locked(void) {
} }
void secret_unlock_bootloader(void) { void secret_unlock_bootloader(void) {
#ifdef USE_OPTIGA for (uint8_t i = 0; i < SECRET_NUM_KEY_SLOTS; i++) {
secret_optiga_erase(); if (sectrue == secret_is_slot_valid(i) &&
#endif sectrue != secret_slot_public[i]) {
#ifdef USE_TROPIC secret_key_erase(i);
secret_tropic_erase(); }
#endif }
} }
#endif #endif
@ -519,29 +558,35 @@ void secret_prepare_fw(secbool allow_run_with_secret,
* all-cases. * all-cases.
*/ */
secret_bhk_load(); if (sectrue != allow_run_with_secret &&
secret_bhk_lock(); secfalse != secret_bootloader_locked()) {
secret_se_uncache();
secbool se_secret_present = secret_se_present();
secbool se_secret_writable = secret_se_writable();
if (sectrue == allow_provisioning_access && sectrue == se_secret_writable &&
secfalse == se_secret_present) {
// SE Secret is not present and the secret sector is writable.
// This means the U5 chip is unprovisioned.
// Allow trusted firmware (prodtest presumably) to access the secret sector,
// early return here.
return;
}
if (sectrue == allow_run_with_secret && sectrue == se_secret_present) {
// Firmware is trusted, and the SE secret is present, make it available.
secret_se_cache();
}
// Disable access unconditionally.
secret_disable_access();
if (sectrue != allow_run_with_secret && sectrue == se_secret_present) {
// Untrusted firmware, locked bootloader. Show the restricted screen. // Untrusted firmware, locked bootloader. Show the restricted screen.
show_install_restricted_screen(); show_install_restricted_screen();
} }
secret_bhk_load();
secret_bhk_lock();
secret_keys_uncache();
secbool secret_present = secret_keys_present();
secbool secret_writable = secret_keys_writable();
if (sectrue == allow_provisioning_access && sectrue == secret_writable &&
secfalse == secret_present) {
// Secret keys are not present and they are writable.
// This means the U5 chip is unprovisioned.
// Allow trusted firmware (prodtest presumably) to access the secret sector,
// early return here.
secret_keys_cache();
return;
}
if (sectrue == allow_run_with_secret && sectrue == secret_present) {
// Firmware is trusted, and the secret keys are present, make it available.
secret_keys_cache();
} else {
// Make only public keys available.
secret_keys_cache_public();
}
// Disable access unconditionally.
secret_disable_access();
} }
void secret_init(void) { void secret_init(void) {

View File

@ -0,0 +1,47 @@
/*
* 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>
#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
#ifdef USE_TROPIC
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(curve25519_key dest) {
return secret_key_get(SECRET_TROPIC_TREZOR_PRIVKEY_SLOT, dest,
sizeof(curve25519_key));
}
#endif
#endif

View File

@ -17,158 +17,156 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <memzero.h>
#include <trezor_model.h> #include <trezor_model.h>
#include <trezor_rtl.h> #include <trezor_rtl.h>
#include <sec/secret.h> #include <sec/secret.h>
#include <sys/mpu.h>
#include <util/flash.h>
#ifdef KERNEL_MODE #ifdef KERNEL_MODE
static uint8_t SECRET_TROPIC_TREZOR_PRIVKEY_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 secbool bootloader_locked_set = secfalse;
static secbool bootloader_locked = secfalse;
secbool secret_verify_header(void) {
uint8_t* addr = (uint8_t*)flash_area_get_address(&SECRET_AREA, 0,
sizeof(SECRET_HEADER_MAGIC));
if (addr == NULL) {
return secfalse;
}
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
bootloader_locked =
memcmp(addr, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0
? sectrue
: secfalse;
mpu_restore(mpu_mode);
bootloader_locked_set = sectrue;
return bootloader_locked;
}
#ifdef LOCKABLE_BOOTLOADER #ifdef LOCKABLE_BOOTLOADER
secbool secret_bootloader_locked(void) { static secbool bootloader_locked = secfalse;
if (bootloader_locked_set != sectrue) {
// Set bootloader_locked.
secret_verify_header();
}
return bootloader_locked;
}
void secret_unlock_bootloader(void) { secret_erase(); }
#endif #endif
void secret_write_header(void) { #ifndef SECRET_NUM_KEY_SLOTS
uint8_t header[SECRET_HEADER_LEN] = {0}; #define SECRET_NUM_KEY_SLOTS 0
memcpy(header, SECRET_HEADER_MAGIC, 4); #endif
secret_write(header, 0, SECRET_HEADER_LEN);
}
void secret_write(const uint8_t* data, uint32_t offset, uint32_t len) { #ifdef SECRET_KEY_SLOT_0_LEN
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); static uint8_t secret_key_slot0[SECRET_KEY_SLOT_0_LEN] = {0};
ensure(flash_unlock_write(), "secret write"); #endif
for (int i = 0; i < len; i++) { #ifdef SECRET_KEY_SLOT_1_LEN
ensure(flash_area_write_byte(&SECRET_AREA, offset + i, data[i]), static uint8_t secret_key_slot1[SECRET_KEY_SLOT_1_LEN] = {0};
"secret write"); #endif
} #ifdef SECRET_KEY_SLOT_2_LEN
ensure(flash_lock_write(), "secret write"); static uint8_t secret_key_slot2[SECRET_KEY_SLOT_2_LEN] = {0};
mpu_restore(mpu_mode); #endif
}
secbool secret_read(uint8_t* data, uint32_t offset, uint32_t len) { size_t secret_get_slot_len(uint8_t slot) {
if (sectrue != secret_verify_header()) { switch (slot) {
return secfalse; #ifdef SECRET_KEY_SLOT_0_LEN
} case 0:
return SECRET_KEY_SLOT_0_LEN;
uint8_t* addr = (uint8_t*)flash_area_get_address(&SECRET_AREA, offset, len); #endif
#ifdef SECRET_KEY_SLOT_1_LEN
if (addr == NULL) { case 1:
return secfalse; return SECRET_KEY_SLOT_1_LEN;
} #endif
#ifdef SECRET_KEY_SLOT_2_LEN
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); case 2:
memcpy(data, addr, len); return SECRET_KEY_SLOT_2_LEN;
mpu_restore(mpu_mode); #endif
default:
return sectrue;
}
secbool secret_wiped(void) {
uint32_t size = flash_area_get_size(&SECRET_AREA);
secbool wiped = sectrue;
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
for (int i = 0; i < size; i += 4) {
uint32_t* addr = (uint32_t*)flash_area_get_address(&SECRET_AREA, i, 4);
if (addr == NULL) {
wiped = secfalse;
break; break;
}
if (*addr != 0xFFFFFFFF) {
wiped = secfalse;
break;
}
} }
return 0;
}
mpu_restore(mpu_mode); uint8_t* secret_get_slot_ptr(uint8_t slot) {
switch (slot) {
return wiped; #ifdef SECRET_KEY_SLOT_0_LEN
case 0:
return secret_key_slot0;
#endif
#ifdef SECRET_KEY_SLOT_1_LEN
case 1:
return secret_key_slot1;
#endif
#ifdef SECRET_KEY_SLOT_2_LEN
case 2:
return secret_key_slot2;
#endif
default:
break;
}
return NULL;
} }
void secret_erase(void) { void secret_erase(void) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET); for (uint8_t i = 0; i < SECRET_NUM_KEY_SLOTS; i++) {
ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase"); uint8_t* slot_ptr = secret_get_slot_ptr(i);
mpu_restore(mpu_mode); if (slot_ptr != NULL) {
memzero(slot_ptr, secret_get_slot_len(i));
}
}
} }
secbool secret_optiga_set(const uint8_t secret[SECRET_KEY_LEN]) { #ifdef LOCKABLE_BOOTLOADER
secbool secret_bootloader_locked(void) { return bootloader_locked; }
void secret_unlock_bootloader(void) {
secret_erase(); secret_erase();
secret_write_header(); bootloader_locked = secfalse;
secret_write(secret, SECRET_OPTIGA_KEY_OFFSET, SECRET_KEY_LEN); }
void secret_lock_bootloader(void) { bootloader_locked = sectrue; }
#endif
secbool secret_key_set(uint8_t slot, const uint8_t* key, size_t len) {
if (slot >= SECRET_NUM_KEY_SLOTS) {
return secfalse;
}
if (len != secret_get_slot_len(slot)) {
return secfalse;
}
uint8_t* slot_ptr = secret_get_slot_ptr(slot);
if (slot_ptr == NULL) {
return secfalse;
}
memcpy(slot_ptr, key, len);
return sectrue; return sectrue;
} }
secbool secret_optiga_get(uint8_t dest[SECRET_KEY_LEN]) { secbool secret_key_get(uint8_t slot, uint8_t* dest, size_t len) {
return secret_read(dest, SECRET_OPTIGA_KEY_OFFSET, SECRET_KEY_LEN); if (slot >= SECRET_NUM_KEY_SLOTS) {
} return secfalse;
}
secbool secret_optiga_present(void) { if (len != secret_get_slot_len(slot)) {
return (sectrue != secret_wiped()) * sectrue; return secfalse;
} }
secbool secret_optiga_writable(void) { return secret_wiped(); } uint8_t* slot_ptr = secret_get_slot_ptr(slot);
if (slot_ptr == NULL) {
return secfalse;
}
secbool secret_tropic_get_trezor_privkey(uint8_t dest[SECRET_KEY_LEN]) { memcpy(dest, slot_ptr, len);
memcpy(dest, &SECRET_TROPIC_TREZOR_PRIVKEY_BYTES, SECRET_KEY_LEN);
return sectrue; return sectrue;
} }
secbool secret_tropic_get_tropic_pubkey(uint8_t dest[SECRET_KEY_LEN]) { static secbool secret_key_present(uint8_t slot) {
memcpy(dest, &SECRET_TROPIC_PUBKEY_BYTES, SECRET_KEY_LEN); if (slot >= SECRET_NUM_KEY_SLOTS) {
return sectrue; return secfalse;
}
uint8_t* slot_ptr = secret_get_slot_ptr(slot);
if (slot_ptr == NULL) {
return secfalse;
}
for (size_t i = 0; i < secret_get_slot_len(slot); i++) {
if (slot_ptr[i] != 0) {
return sectrue;
}
}
return secfalse;
}
secbool secret_key_writable(uint8_t slot) {
return secret_key_present(slot) == secfalse;
} }
void secret_prepare_fw(secbool allow_run_with_secret, void secret_prepare_fw(secbool allow_run_with_secret,
secbool allow_provisioning_access) { secbool allow_provisioning_access) {
(void)allow_provisioning_access; (void)allow_provisioning_access;
#ifdef LOCKABLE_BOOTLOADER #ifdef LOCKABLE_BOOTLOADER
if (sectrue != allow_run_with_secret && sectrue != secret_wiped()) { if (sectrue != allow_run_with_secret && sectrue != bootloader_locked) {
// This function does not return // This function does not return
show_install_restricted_screen(); show_install_restricted_screen();
} }

View File

@ -0,0 +1,58 @@
/*
* 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>
#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_tropic_public(curve25519_key dest) {
memcpy(dest, SECRET_TROPIC_PUBKEY_BYTES, sizeof(curve25519_key));
return sectrue;
}
secbool secret_key_tropic_pairing(curve25519_key dest) {
memcpy(dest, SECRET_TROPIC_PAIRING_BYTES, sizeof(curve25519_key));
return sectrue;
}
#endif
#endif

View File

@ -22,7 +22,7 @@
#include <trezor_rtl.h> #include <trezor_rtl.h>
#include <trezor_types.h> #include <trezor_types.h>
#include <sec/secret.h> #include <sec/secret_keys.h>
#include <sec/tropic.h> #include <sec/tropic.h>
#include <libtropic.h> #include <libtropic.h>
@ -48,8 +48,8 @@ bool tropic_init(void) {
return true; return true;
} }
uint8_t tropic_secret_tropic_pubkey[SECRET_KEY_LEN] = {0}; curve25519_key tropic_secret_tropic_pubkey = {0};
uint8_t tropic_secret_trezor_privkey[SECRET_KEY_LEN] = {0}; curve25519_key tropic_secret_trezor_privkey = {0};
if (!tropic_hal_init()) { if (!tropic_hal_init()) {
goto cleanup; goto cleanup;
@ -60,13 +60,11 @@ bool tropic_init(void) {
goto cleanup; goto cleanup;
} }
secbool pubkey_ok = secbool pubkey_ok = secret_key_tropic_public(tropic_secret_tropic_pubkey);
secret_tropic_get_tropic_pubkey(tropic_secret_tropic_pubkey); secbool privkey_ok = secret_key_tropic_pairing(tropic_secret_trezor_privkey);
secbool privkey_ok =
secret_tropic_get_trezor_privkey(tropic_secret_trezor_privkey);
if (pubkey_ok == sectrue && privkey_ok == sectrue) { if (pubkey_ok == sectrue && privkey_ok == sectrue) {
uint8_t trezor_pubkey[SECRET_KEY_LEN] = {0}; uint8_t trezor_pubkey[32] = {0};
curve25519_scalarmult_basepoint(trezor_pubkey, curve25519_scalarmult_basepoint(trezor_pubkey,
tropic_secret_trezor_privkey); tropic_secret_trezor_privkey);

View File

@ -69,6 +69,7 @@ def stm32f4_common_files(env, defines, sources, paths):
"embed/sec/random_delays/stm32/random_delays.c", "embed/sec/random_delays/stm32/random_delays.c",
"embed/sec/rng/stm32/rng.c", "embed/sec/rng/stm32/rng.c",
"embed/sec/secret/stm32f4/secret.c", "embed/sec/secret/stm32f4/secret.c",
"embed/sec/secret/stm32f4/secret_keys.c",
"embed/sec/time_estimate/stm32/time_estimate.c", "embed/sec/time_estimate/stm32/time_estimate.c",
"embed/sys/dbg/stm32/dbg_printf.c", "embed/sys/dbg/stm32/dbg_printf.c",
"embed/sys/irq/stm32/irq.c", "embed/sys/irq/stm32/irq.c",

View File

@ -88,6 +88,7 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/random_delays/stm32/random_delays.c", "embed/sec/random_delays/stm32/random_delays.c",
"embed/sec/rng/stm32/rng.c", "embed/sec/rng/stm32/rng.c",
"embed/sec/secret/stm32u5/secret.c", "embed/sec/secret/stm32u5/secret.c",
"embed/sec/secret/stm32u5/secret_keys.c",
"embed/sec/secure_aes/stm32u5/secure_aes.c", "embed/sec/secure_aes/stm32u5/secure_aes.c",
"embed/sec/secure_aes/stm32u5/secure_aes_unpriv.c", "embed/sec/secure_aes/stm32u5/secure_aes_unpriv.c",
"embed/sec/time_estimate/stm32/time_estimate.c", "embed/sec/time_estimate/stm32/time_estimate.c",

View File

@ -36,6 +36,7 @@ def unix_common_files(env, defines, sources, paths):
"embed/sec/entropy/unix/entropy.c", "embed/sec/entropy/unix/entropy.c",
"embed/sec/random_delays/unix/random_delays.c", "embed/sec/random_delays/unix/random_delays.c",
"embed/sec/secret/unix/secret.c", "embed/sec/secret/unix/secret.c",
"embed/sec/secret/unix/secret_keys.c",
"embed/sec/monoctr/unix/monoctr.c", "embed/sec/monoctr/unix/monoctr.c",
"embed/sec/rng/unix/rng.c", "embed/sec/rng/unix/rng.c",
"embed/sec/time_estimate/unix/time_estimate.c", "embed/sec/time_estimate/unix/time_estimate.c",