mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 20:38:10 +00:00
refactor(core): simplify secret.h api, hide platform differences
[no changelog]
This commit is contained in:
parent
89c6590e45
commit
1600759457
@ -137,11 +137,11 @@ SOURCE_TREZORHAL = [
|
|||||||
'embed/trezorhal/unix/rng.c',
|
'embed/trezorhal/unix/rng.c',
|
||||||
'embed/trezorhal/unix/usb.c',
|
'embed/trezorhal/unix/usb.c',
|
||||||
'embed/trezorhal/unix/random_delays.c',
|
'embed/trezorhal/unix/random_delays.c',
|
||||||
|
'embed/trezorhal/unix/secret.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
if TREZOR_MODEL in ('R', 'T3T1'):
|
if TREZOR_MODEL in ('R', 'T3T1'):
|
||||||
SOURCE_TREZORHAL += [
|
SOURCE_TREZORHAL += [
|
||||||
'embed/trezorhal/unix/secret.c',
|
|
||||||
'embed/trezorhal/unix/optiga_hal.c',
|
'embed/trezorhal/unix/optiga_hal.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -258,11 +258,6 @@ int main(void) {
|
|||||||
#ifdef STM32U5
|
#ifdef STM32U5
|
||||||
tamper_init();
|
tamper_init();
|
||||||
|
|
||||||
if (sectrue == secret_bhk_locked()) {
|
|
||||||
delete_secrets();
|
|
||||||
NVIC_SystemReset();
|
|
||||||
}
|
|
||||||
|
|
||||||
trustzone_init_boardloader();
|
trustzone_init_boardloader();
|
||||||
|
|
||||||
secret_ensure_initialized();
|
secret_ensure_initialized();
|
||||||
|
@ -257,16 +257,6 @@ void ui_screen_fail(void) { screen_install_fail(); }
|
|||||||
uint32_t ui_screen_unlock_bootloader_confirm(void) {
|
uint32_t ui_screen_unlock_bootloader_confirm(void) {
|
||||||
return screen_unlock_bootloader_confirm();
|
return screen_unlock_bootloader_confirm();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_screen_install_restricted(void) {
|
|
||||||
display_clear();
|
|
||||||
screen_fatal_error_rust(
|
|
||||||
"INSTALL RESTRICTED",
|
|
||||||
"Installation of custom firmware is currently restricted.",
|
|
||||||
"Please visit\ntrezor.io/bootloader");
|
|
||||||
|
|
||||||
display_refresh();
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
void ui_screen_install_restricted(void) { screen_install_fail(); }
|
void ui_screen_install_restricted(void) { screen_install_fail(); }
|
||||||
#endif
|
#endif
|
||||||
|
@ -62,7 +62,6 @@ void ui_screen_wipe_progress(int pos, int len);
|
|||||||
void ui_screen_done(uint8_t restart_seconds, secbool full_redraw);
|
void ui_screen_done(uint8_t restart_seconds, secbool full_redraw);
|
||||||
|
|
||||||
void ui_screen_fail(void);
|
void ui_screen_fail(void);
|
||||||
void ui_screen_install_restricted(void);
|
|
||||||
|
|
||||||
void ui_fadein(void);
|
void ui_fadein(void);
|
||||||
void ui_fadeout(void);
|
void ui_fadeout(void);
|
||||||
|
@ -193,7 +193,7 @@ static usb_result_t bootloader_usb_loop(const vendor_header *const vhdr,
|
|||||||
r = process_msg_FirmwareUpload(USB_IFACE_NUM, msg_size, buf);
|
r = process_msg_FirmwareUpload(USB_IFACE_NUM, msg_size, buf);
|
||||||
if (r < 0 && r != UPLOAD_ERR_USER_ABORT) { // error, but not user abort
|
if (r < 0 && r != UPLOAD_ERR_USER_ABORT) { // error, but not user abort
|
||||||
if (r == UPLOAD_ERR_BOOTLOADER_LOCKED) {
|
if (r == UPLOAD_ERR_BOOTLOADER_LOCKED) {
|
||||||
ui_screen_install_restricted();
|
secret_show_install_restricted_screen();
|
||||||
} else {
|
} else {
|
||||||
ui_screen_fail();
|
ui_screen_fail();
|
||||||
}
|
}
|
||||||
@ -325,33 +325,9 @@ void real_jump_to_firmware(void) {
|
|||||||
&FIRMWARE_AREA),
|
&FIRMWARE_AREA),
|
||||||
"Firmware is corrupted");
|
"Firmware is corrupted");
|
||||||
|
|
||||||
#ifdef STM32U5
|
secret_prepare_fw(
|
||||||
secret_bhk_provision();
|
((vhdr.vtrust & VTRUST_SECRET) == VTRUST_SECRET_ALLOW) * sectrue,
|
||||||
secret_bhk_lock();
|
((vhdr.vtrust & VTRUST_ALL) == VTRUST_ALL) * sectrue);
|
||||||
#ifdef USE_OPTIGA
|
|
||||||
if (sectrue == secret_optiga_present()) {
|
|
||||||
secret_optiga_backup();
|
|
||||||
secret_hide();
|
|
||||||
} else {
|
|
||||||
secret_optiga_hide();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
secret_hide();
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_OPTIGA
|
|
||||||
#ifdef STM32U5
|
|
||||||
if ((vhdr.vtrust & VTRUST_SECRET) != 0) {
|
|
||||||
secret_optiga_hide();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (((vhdr.vtrust & VTRUST_SECRET) != 0) && (sectrue != secret_wiped())) {
|
|
||||||
ui_screen_install_restricted();
|
|
||||||
trezor_shutdown();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// if all VTRUST flags are unset = ultimate trust => skip the procedure
|
// if all VTRUST flags are unset = ultimate trust => skip the procedure
|
||||||
if ((vhdr.vtrust & VTRUST_ALL) != VTRUST_ALL) {
|
if ((vhdr.vtrust & VTRUST_ALL) != VTRUST_ALL) {
|
||||||
|
@ -638,7 +638,8 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined USE_OPTIGA && !defined STM32U5
|
#if defined USE_OPTIGA && !defined STM32U5
|
||||||
if (sectrue != secret_wiped() && ((vhdr.vtrust & VTRUST_SECRET) != 0)) {
|
if (sectrue != secret_wiped() &&
|
||||||
|
((vhdr.vtrust & VTRUST_SECRET) != VTRUST_SECRET_ALLOW)) {
|
||||||
MSG_SEND_INIT(Failure);
|
MSG_SEND_INIT(Failure);
|
||||||
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
|
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
|
||||||
MSG_SEND_ASSIGN_STRING(message, "Install restricted");
|
MSG_SEND_ASSIGN_STRING(message, "Install restricted");
|
||||||
|
@ -58,8 +58,14 @@ typedef struct {
|
|||||||
#define VTRUST_RED 0x0010
|
#define VTRUST_RED 0x0010
|
||||||
#define VTRUST_CLICK 0x0020
|
#define VTRUST_CLICK 0x0020
|
||||||
#define VTRUST_STRING 0x0040
|
#define VTRUST_STRING 0x0040
|
||||||
#define VTRUST_SECRET \
|
|
||||||
0x0080 // inverse logic, if set, don't allow to run with secret present
|
// Two bits for historical reasons. On T2B1, only the lower bit was used with
|
||||||
|
// inverted logic (due to late inclusion of the secret handling during
|
||||||
|
// development process). On T3T1, we decided to remedy the situation by
|
||||||
|
// including the upper bit as well.
|
||||||
|
#define VTRUST_SECRET 0x0180
|
||||||
|
#define VTRUST_SECRET_ALLOW 0x0100
|
||||||
|
|
||||||
#define VTRUST_ALL (VTRUST_WAIT | VTRUST_RED | VTRUST_CLICK | VTRUST_STRING)
|
#define VTRUST_ALL (VTRUST_WAIT | VTRUST_RED | VTRUST_CLICK | VTRUST_STRING)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -93,3 +93,12 @@ const flash_area_t ALL_WIPE_AREA = {
|
|||||||
.num_sectors = 21,
|
.num_sectors = 21,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const flash_area_t SECRET_AREA = {
|
||||||
|
.num_subareas = 1,
|
||||||
|
.subarea[0] =
|
||||||
|
{
|
||||||
|
.first_sector = 0,
|
||||||
|
.num_sectors = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
@ -36,9 +36,6 @@ secbool secret_ensure_initialized(void);
|
|||||||
// Erases the entire secret storage
|
// Erases the entire secret storage
|
||||||
void secret_erase(void);
|
void secret_erase(void);
|
||||||
|
|
||||||
// Disables access to the secret storage until next reset
|
|
||||||
void secret_hide(void);
|
|
||||||
|
|
||||||
// Writes the secret header to the secret storage
|
// Writes the secret header to the secret storage
|
||||||
void secret_write_header(void);
|
void secret_write_header(void);
|
||||||
|
|
||||||
@ -55,30 +52,15 @@ secbool secret_optiga_set(const uint8_t secret[SECRET_OPTIGA_KEY_LEN]);
|
|||||||
// was made unavailable by calling secret_optiga_hide
|
// was made unavailable by calling secret_optiga_hide
|
||||||
secbool secret_optiga_get(uint8_t dest[SECRET_OPTIGA_KEY_LEN]);
|
secbool secret_optiga_get(uint8_t dest[SECRET_OPTIGA_KEY_LEN]);
|
||||||
|
|
||||||
// Backs up the optiga pairing secret from the secret storage to the backup
|
|
||||||
// register
|
|
||||||
void secret_optiga_backup(void);
|
|
||||||
|
|
||||||
// Deletes the optiga pairing secret from the register
|
|
||||||
void secret_optiga_hide(void);
|
|
||||||
|
|
||||||
// Locks the BHK register. Once locked, the BHK register can't be accessed by
|
|
||||||
// the software. BHK is made available to the SAES peripheral
|
|
||||||
void secret_bhk_lock(void);
|
|
||||||
|
|
||||||
// Verifies that access to the register has been disabled
|
|
||||||
secbool secret_bhk_locked(void);
|
|
||||||
|
|
||||||
// Regenerates the BHK and writes it to the secret storage
|
// Regenerates the BHK and writes it to the secret storage
|
||||||
void secret_bhk_regenerate(void);
|
void secret_bhk_regenerate(void);
|
||||||
|
|
||||||
// Provision the secret BHK from the secret storage to the BHK register
|
// Prepares the secret storage for running the firmware
|
||||||
// which makes the BHK usable for encryption by the firmware, without having
|
// Provisions secrets/keys to the firmware, depending on the trust level
|
||||||
// read access to it.
|
// Disables access to the secret storage until next reset, if possible
|
||||||
void secret_bhk_provision(void);
|
// This function is called by the bootloader before starting the firmware
|
||||||
|
void secret_prepare_fw(secbool allow_run_with_secret, secbool trust_all);
|
||||||
|
|
||||||
// Checks that the optiga pairing secret is present in the secret storage.
|
// Shows a screen informing the user that installation of custom firmware is
|
||||||
// This functions only works when software has access to the secret storage,
|
// currently restricted
|
||||||
// i.e. in bootloader. Access to secret storage is restricted by calling
|
void secret_show_install_restricted_screen(void);
|
||||||
// secret_hide.
|
|
||||||
secbool secret_optiga_present(void);
|
|
||||||
|
@ -1,21 +1,27 @@
|
|||||||
#include "secret.h"
|
#include "secret.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "display.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
|
|
||||||
|
#ifdef FANCY_FATAL_ERROR
|
||||||
|
#include "rust_ui.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
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 header[sizeof(SECRET_HEADER_MAGIC)] = {0};
|
uint8_t* addr = (uint8_t*)flash_area_get_address(&SECRET_AREA, 0,
|
||||||
|
sizeof(SECRET_HEADER_MAGIC));
|
||||||
|
|
||||||
memcpy(header,
|
if (addr == NULL) {
|
||||||
flash_area_get_address(&SECRET_AREA, 0, sizeof(SECRET_HEADER_MAGIC)),
|
return secfalse;
|
||||||
sizeof(SECRET_HEADER_MAGIC));
|
}
|
||||||
|
|
||||||
bootloader_locked =
|
bootloader_locked =
|
||||||
memcmp(header, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0
|
memcmp(addr, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0
|
||||||
? sectrue
|
? sectrue
|
||||||
: secfalse;
|
: secfalse;
|
||||||
bootloader_locked_set = sectrue;
|
bootloader_locked_set = sectrue;
|
||||||
@ -51,20 +57,25 @@ secbool secret_read(uint8_t* data, uint32_t offset, uint32_t len) {
|
|||||||
return secfalse;
|
return secfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(data, flash_area_get_address(&SECRET_AREA, offset, len), len);
|
uint8_t* addr = (uint8_t*)flash_area_get_address(&SECRET_AREA, offset, len);
|
||||||
|
|
||||||
|
if (addr == NULL) {
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(data, addr, len);
|
||||||
|
|
||||||
return sectrue;
|
return sectrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
secbool secret_wiped(void) {
|
secbool secret_wiped(void) {
|
||||||
flash_area_get_address(&SECRET_AREA, 0, 1);
|
|
||||||
|
|
||||||
flash_area_get_size(&SECRET_AREA);
|
|
||||||
|
|
||||||
uint32_t size = flash_area_get_size(&SECRET_AREA);
|
uint32_t size = flash_area_get_size(&SECRET_AREA);
|
||||||
|
|
||||||
for (int i = 0; i < size; i += 4) {
|
for (int i = 0; i < size; i += 4) {
|
||||||
uint32_t* addr = (uint32_t*)flash_area_get_address(&SECRET_AREA, i, 4);
|
uint32_t* addr = (uint32_t*)flash_area_get_address(&SECRET_AREA, i, 4);
|
||||||
|
if (addr == NULL) {
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
if (*addr != 0xFFFFFFFF) {
|
if (*addr != 0xFFFFFFFF) {
|
||||||
return secfalse;
|
return secfalse;
|
||||||
}
|
}
|
||||||
@ -86,3 +97,24 @@ secbool secret_optiga_set(const uint8_t secret[SECRET_OPTIGA_KEY_LEN]) {
|
|||||||
secbool secret_optiga_get(uint8_t dest[SECRET_OPTIGA_KEY_LEN]) {
|
secbool secret_optiga_get(uint8_t dest[SECRET_OPTIGA_KEY_LEN]) {
|
||||||
return secret_read(dest, SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN);
|
return secret_read(dest, SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void secret_show_install_restricted_screen(void) {
|
||||||
|
#ifdef FANCY_FATAL_ERROR
|
||||||
|
display_clear();
|
||||||
|
screen_fatal_error_rust(
|
||||||
|
"INSTALL RESTRICTED",
|
||||||
|
"Installation of custom firmware is currently restricted.",
|
||||||
|
"Please visit\ntrezor.io/bootloader");
|
||||||
|
|
||||||
|
display_refresh();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void secret_prepare_fw(secbool allow_run_with_secret, secbool _trust_all) {
|
||||||
|
#ifdef USE_OPTIGA
|
||||||
|
if (sectrue != allow_run_with_secret && sectrue != secret_wiped()) {
|
||||||
|
secret_show_install_restricted_screen();
|
||||||
|
trezor_shutdown();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -11,14 +11,15 @@
|
|||||||
static secbool bootloader_locked = secfalse;
|
static secbool bootloader_locked = secfalse;
|
||||||
|
|
||||||
secbool secret_verify_header(void) {
|
secbool secret_verify_header(void) {
|
||||||
uint8_t header[sizeof(SECRET_HEADER_MAGIC)] = {0};
|
uint8_t *addr = (uint8_t *)flash_area_get_address(
|
||||||
|
&SECRET_AREA, 0, sizeof(SECRET_HEADER_MAGIC));
|
||||||
|
|
||||||
memcpy(header,
|
if (addr == NULL) {
|
||||||
flash_area_get_address(&SECRET_AREA, 0, sizeof(SECRET_HEADER_MAGIC)),
|
return secfalse;
|
||||||
sizeof(SECRET_HEADER_MAGIC));
|
}
|
||||||
|
|
||||||
bootloader_locked =
|
bootloader_locked =
|
||||||
memcmp(header, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0
|
memcmp(addr, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0
|
||||||
? sectrue
|
? sectrue
|
||||||
: secfalse;
|
: secfalse;
|
||||||
return bootloader_locked;
|
return bootloader_locked;
|
||||||
@ -63,41 +64,60 @@ secbool secret_read(uint8_t *data, uint32_t offset, uint32_t len) {
|
|||||||
if (sectrue != secret_verify_header()) {
|
if (sectrue != secret_verify_header()) {
|
||||||
return secfalse;
|
return secfalse;
|
||||||
}
|
}
|
||||||
|
uint8_t *addr = (uint8_t *)flash_area_get_address(&SECRET_AREA, offset, len);
|
||||||
|
|
||||||
memcpy(data, flash_area_get_address(&SECRET_AREA, offset, len), len);
|
if (addr == NULL) {
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
memcpy(data, addr, len);
|
||||||
|
|
||||||
return sectrue;
|
return sectrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void secret_hide(void) {
|
static void secret_disable_access(void) {
|
||||||
FLASH->SECHDPCR |= FLASH_SECHDPCR_HDP1_ACCDIS_Msk;
|
FLASH->SECHDPCR |= FLASH_SECHDPCR_HDP1_ACCDIS_Msk;
|
||||||
FLASH->SECHDPCR |= FLASH_SECHDPCR_HDP2_ACCDIS_Msk;
|
FLASH->SECHDPCR |= FLASH_SECHDPCR_HDP2_ACCDIS_Msk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void secret_bhk_lock(void) {
|
// Locks the BHK register. Once locked, the BHK register can't be accessed by
|
||||||
|
// the software. BHK is made available to the SAES peripheral
|
||||||
|
static void secret_bhk_lock(void) {
|
||||||
TAMP_S->SECCFGR = 8 << TAMP_SECCFGR_BKPRWSEC_Pos | TAMP_SECCFGR_BHKLOCK;
|
TAMP_S->SECCFGR = 8 << TAMP_SECCFGR_BKPRWSEC_Pos | TAMP_SECCFGR_BHKLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
secbool secret_bhk_locked(void) {
|
// Verifies that access to the register has been disabled
|
||||||
|
static secbool secret_bhk_locked(void) {
|
||||||
return ((TAMP_S->SECCFGR & TAMP_SECCFGR_BHKLOCK) == TAMP_SECCFGR_BHKLOCK) *
|
return ((TAMP_S->SECCFGR & TAMP_SECCFGR_BHKLOCK) == TAMP_SECCFGR_BHKLOCK) *
|
||||||
sectrue;
|
sectrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static secbool secret_present(uint32_t offset, uint32_t len) {
|
static secbool secret_present(uint32_t offset, uint32_t len) {
|
||||||
uint8_t *optiga_secret =
|
uint8_t *secret =
|
||||||
(uint8_t *)flash_area_get_address(&SECRET_AREA, offset, len);
|
(uint8_t *)flash_area_get_address(&SECRET_AREA, offset, len);
|
||||||
|
|
||||||
int optiga_secret_empty_bytes = 0;
|
if (secret == NULL) {
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
int secret_empty_bytes = 0;
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
if (optiga_secret[i] == 0xFF) {
|
if (secret[i] == 0xFF) {
|
||||||
optiga_secret_empty_bytes++;
|
secret_empty_bytes++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sectrue * (optiga_secret_empty_bytes != len);
|
return sectrue * (secret_empty_bytes != len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void secret_bhk_provision(void) {
|
// Provision the secret BHK from the secret storage to the BHK register
|
||||||
|
// which makes the BHK usable for encryption by the firmware, without having
|
||||||
|
// read access to it.
|
||||||
|
static void secret_bhk_load(void) {
|
||||||
|
if (sectrue == secret_bhk_locked()) {
|
||||||
|
delete_secrets();
|
||||||
|
NVIC_SystemReset();
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t secret[SECRET_BHK_LEN / sizeof(uint32_t)] = {0};
|
uint32_t secret[SECRET_BHK_LEN / sizeof(uint32_t)] = {0};
|
||||||
|
|
||||||
if (sectrue != secret_present(SECRET_BHK_OFFSET, SECRET_BHK_LEN)) {
|
if (sectrue != secret_present(SECRET_BHK_OFFSET, SECRET_BHK_LEN)) {
|
||||||
@ -139,23 +159,18 @@ void secret_bhk_regenerate(void) {
|
|||||||
ensure(flash_lock_write(), "Failed regenerating BHK");
|
ensure(flash_lock_write(), "Failed regenerating BHK");
|
||||||
}
|
}
|
||||||
|
|
||||||
secbool secret_optiga_present(void) {
|
#ifdef USE_OPTIGA
|
||||||
|
// Checks that the optiga pairing secret is present in the secret storage.
|
||||||
|
// This functions only works when software has access to the secret storage,
|
||||||
|
// i.e. in bootloader. Access to secret storage is restricted by calling
|
||||||
|
// secret_hide.
|
||||||
|
static secbool secret_optiga_present(void) {
|
||||||
return secret_present(SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN);
|
return secret_present(SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
secbool secret_optiga_set(const uint8_t secret[SECRET_OPTIGA_KEY_LEN]) {
|
// Backs up the optiga pairing secret from the secret storage to the backup
|
||||||
uint8_t secret_enc[SECRET_OPTIGA_KEY_LEN] = {0};
|
// register
|
||||||
if (sectrue != secure_aes_ecb_encrypt_hw(secret, sizeof(secret_enc),
|
static void secret_optiga_cache(void) {
|
||||||
secret_enc, SECURE_AES_KEY_DHUK)) {
|
|
||||||
return secfalse;
|
|
||||||
}
|
|
||||||
secret_write(secret_enc, SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN);
|
|
||||||
memzero(secret_enc, sizeof(secret_enc));
|
|
||||||
secret_optiga_backup();
|
|
||||||
return sectrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void secret_optiga_backup(void) {
|
|
||||||
uint32_t secret[SECRET_OPTIGA_KEY_LEN / sizeof(uint32_t)] = {0};
|
uint32_t secret[SECRET_OPTIGA_KEY_LEN / sizeof(uint32_t)] = {0};
|
||||||
secbool ok = secret_read((uint8_t *)secret, SECRET_OPTIGA_KEY_OFFSET,
|
secbool ok = secret_read((uint8_t *)secret, SECRET_OPTIGA_KEY_OFFSET,
|
||||||
SECRET_OPTIGA_KEY_LEN);
|
SECRET_OPTIGA_KEY_LEN);
|
||||||
@ -175,6 +190,18 @@ void secret_optiga_backup(void) {
|
|||||||
memzero(secret, sizeof(secret));
|
memzero(secret, sizeof(secret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secbool secret_optiga_set(const uint8_t secret[SECRET_OPTIGA_KEY_LEN]) {
|
||||||
|
uint8_t secret_enc[SECRET_OPTIGA_KEY_LEN] = {0};
|
||||||
|
if (sectrue != secure_aes_ecb_encrypt_hw(secret, sizeof(secret_enc),
|
||||||
|
secret_enc, SECURE_AES_KEY_DHUK)) {
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
secret_write(secret_enc, SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN);
|
||||||
|
memzero(secret_enc, sizeof(secret_enc));
|
||||||
|
secret_optiga_cache();
|
||||||
|
return sectrue;
|
||||||
|
}
|
||||||
|
|
||||||
secbool secret_optiga_get(uint8_t dest[SECRET_OPTIGA_KEY_LEN]) {
|
secbool secret_optiga_get(uint8_t dest[SECRET_OPTIGA_KEY_LEN]) {
|
||||||
uint32_t secret[SECRET_OPTIGA_KEY_LEN / sizeof(uint32_t)] = {0};
|
uint32_t secret[SECRET_OPTIGA_KEY_LEN / sizeof(uint32_t)] = {0};
|
||||||
|
|
||||||
@ -199,14 +226,56 @@ secbool secret_optiga_get(uint8_t dest[SECRET_OPTIGA_KEY_LEN]) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void secret_optiga_hide(void) {
|
// Deletes the optiga pairing secret from the register
|
||||||
|
static void secret_optiga_uncache(void) {
|
||||||
volatile uint32_t *reg1 = &TAMP->BKP8R;
|
volatile uint32_t *reg1 = &TAMP->BKP8R;
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
*reg1 = 0;
|
reg1[i] = 0;
|
||||||
reg1++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void secret_erase(void) {
|
void secret_erase(void) {
|
||||||
ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase");
|
ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void secret_show_install_restricted_screen(void) {
|
||||||
|
// this should never happen on U5
|
||||||
|
__fatal_error("INTERNAL ERROR", "Install restricted", __FILE__, __LINE__,
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
void secret_prepare_fw(secbool allow_run_with_secret, secbool trust_all) {
|
||||||
|
/**
|
||||||
|
* The BHK is copied to the backup registers, which are accessible by the SAES
|
||||||
|
* peripheral. The BHK register is locked, so the BHK can't be accessed by the
|
||||||
|
* software.
|
||||||
|
*
|
||||||
|
* When optiga is paired, pairing secret is copied to the backup registers
|
||||||
|
* and access to the secret storage is disabled. Otherwise, access to the
|
||||||
|
* secret storage kept to allow optiga pairing in prodtest.
|
||||||
|
*
|
||||||
|
* Access to the secret storage is disabled for non-official firmware in
|
||||||
|
* all-cases.
|
||||||
|
*/
|
||||||
|
|
||||||
|
secret_bhk_load();
|
||||||
|
secret_bhk_lock();
|
||||||
|
#ifdef USE_OPTIGA
|
||||||
|
secret_optiga_uncache();
|
||||||
|
if (sectrue == allow_run_with_secret) {
|
||||||
|
if (secfalse != secret_optiga_present()) {
|
||||||
|
secret_optiga_cache();
|
||||||
|
secret_disable_access();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
secret_disable_access();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
secret_disable_access();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (sectrue != trust_all) {
|
||||||
|
secret_disable_access();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"version": [0, 0],
|
"version": [0, 0],
|
||||||
"sig_m": 2,
|
"sig_m": 2,
|
||||||
"trust": {
|
"trust": {
|
||||||
|
"_reserved": 0,
|
||||||
|
"_dont_provide_secret": false,
|
||||||
"allow_run_with_secret": false,
|
"allow_run_with_secret": false,
|
||||||
"show_vendor_string": false,
|
"show_vendor_string": false,
|
||||||
"require_user_click": false,
|
"require_user_click": false,
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"version": [0, 1],
|
"version": [0, 1],
|
||||||
"sig_m": 2,
|
"sig_m": 2,
|
||||||
"trust": {
|
"trust": {
|
||||||
|
"_reserved": 0,
|
||||||
|
"_dont_provide_secret": false,
|
||||||
"allow_run_with_secret": false,
|
"allow_run_with_secret": false,
|
||||||
"show_vendor_string": true,
|
"show_vendor_string": true,
|
||||||
"require_user_click": true,
|
"require_user_click": true,
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -6,6 +6,8 @@
|
|||||||
"version": [0, 1],
|
"version": [0, 1],
|
||||||
"sig_m": 2,
|
"sig_m": 2,
|
||||||
"trust": {
|
"trust": {
|
||||||
|
"_reserved": 0,
|
||||||
|
"_dont_provide_secret": false,
|
||||||
"allow_run_with_secret": true,
|
"allow_run_with_secret": true,
|
||||||
"show_vendor_string": false,
|
"show_vendor_string": false,
|
||||||
"require_user_click": false,
|
"require_user_click": false,
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"version": [0, 1],
|
"version": [0, 1],
|
||||||
"sig_m": 2,
|
"sig_m": 2,
|
||||||
"trust": {
|
"trust": {
|
||||||
|
"_reserved": 0,
|
||||||
|
"_dont_provide_secret": false,
|
||||||
"allow_run_with_secret": true,
|
"allow_run_with_secret": true,
|
||||||
"show_vendor_string": false,
|
"show_vendor_string": false,
|
||||||
"require_user_click": false,
|
"require_user_click": false,
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"version": [0, 2],
|
"version": [0, 2],
|
||||||
"sig_m": 2,
|
"sig_m": 2,
|
||||||
"trust": {
|
"trust": {
|
||||||
|
"_reserved": 0,
|
||||||
|
"_dont_provide_secret": false,
|
||||||
"allow_run_with_secret": true,
|
"allow_run_with_secret": true,
|
||||||
"show_vendor_string": false,
|
"show_vendor_string": false,
|
||||||
"require_user_click": false,
|
"require_user_click": false,
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"version": [0, 1],
|
"version": [0, 1],
|
||||||
"sig_m": 2,
|
"sig_m": 2,
|
||||||
"trust": {
|
"trust": {
|
||||||
|
"_reserved": 0,
|
||||||
|
"_dont_provide_secret": false,
|
||||||
"allow_run_with_secret": true,
|
"allow_run_with_secret": true,
|
||||||
"show_vendor_string": false,
|
"show_vendor_string": false,
|
||||||
"require_user_click": false,
|
"require_user_click": false,
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"version": [0, 2],
|
"version": [0, 2],
|
||||||
"sig_m": 2,
|
"sig_m": 2,
|
||||||
"trust": {
|
"trust": {
|
||||||
|
"_reserved": 0,
|
||||||
|
"_dont_provide_secret": false,
|
||||||
"allow_run_with_secret": false,
|
"allow_run_with_secret": false,
|
||||||
"show_vendor_string": true,
|
"show_vendor_string": true,
|
||||||
"require_user_click": true,
|
"require_user_click": true,
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"version": [0, 0],
|
"version": [0, 0],
|
||||||
"sig_m": 2,
|
"sig_m": 2,
|
||||||
"trust": {
|
"trust": {
|
||||||
|
"_reserved": 0,
|
||||||
|
"_dont_provide_secret": false,
|
||||||
"allow_run_with_secret": false,
|
"allow_run_with_secret": false,
|
||||||
"show_vendor_string": false,
|
"show_vendor_string": false,
|
||||||
"require_user_click": false,
|
"require_user_click": false,
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"version": [0, 0],
|
"version": [0, 0],
|
||||||
"sig_m": 2,
|
"sig_m": 2,
|
||||||
"trust": {
|
"trust": {
|
||||||
|
"_reserved": 0,
|
||||||
|
"_dont_provide_secret": false,
|
||||||
"allow_run_with_secret": false,
|
"allow_run_with_secret": false,
|
||||||
"show_vendor_string": false,
|
"show_vendor_string": false,
|
||||||
"require_user_click": false,
|
"require_user_click": false,
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"version": [0, 1],
|
"version": [0, 1],
|
||||||
"sig_m": 2,
|
"sig_m": 2,
|
||||||
"trust": {
|
"trust": {
|
||||||
|
"_reserved": 0,
|
||||||
|
"_dont_provide_secret": false,
|
||||||
"allow_run_with_secret": false,
|
"allow_run_with_secret": false,
|
||||||
"show_vendor_string": false,
|
"show_vendor_string": false,
|
||||||
"require_user_click": false,
|
"require_user_click": false,
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"version": [0, 1],
|
"version": [0, 1],
|
||||||
"sig_m": 2,
|
"sig_m": 2,
|
||||||
"trust": {
|
"trust": {
|
||||||
|
"_reserved": 0,
|
||||||
|
"_dont_provide_secret": false,
|
||||||
"allow_run_with_secret": false,
|
"allow_run_with_secret": false,
|
||||||
"show_vendor_string": true,
|
"show_vendor_string": true,
|
||||||
"require_user_click": true,
|
"require_user_click": true,
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -49,6 +49,7 @@ def stm32f4_common_files(env, defines, sources, paths):
|
|||||||
"embed/trezorhal/stm32f4/lowlevel.c",
|
"embed/trezorhal/stm32f4/lowlevel.c",
|
||||||
"embed/trezorhal/stm32f4/mpu.c",
|
"embed/trezorhal/stm32f4/mpu.c",
|
||||||
"embed/trezorhal/stm32f4/platform.c",
|
"embed/trezorhal/stm32f4/platform.c",
|
||||||
|
"embed/trezorhal/stm32f4/secret.c",
|
||||||
"embed/trezorhal/stm32f4/systick.c",
|
"embed/trezorhal/stm32f4/systick.c",
|
||||||
"embed/trezorhal/stm32f4/supervise.c",
|
"embed/trezorhal/stm32f4/supervise.c",
|
||||||
"embed/trezorhal/stm32f4/random_delays.c",
|
"embed/trezorhal/stm32f4/random_delays.c",
|
||||||
|
@ -70,7 +70,6 @@ def configure(
|
|||||||
sources += ["embed/trezorhal/optiga/optiga.c"]
|
sources += ["embed/trezorhal/optiga/optiga.c"]
|
||||||
sources += ["embed/trezorhal/optiga/optiga_commands.c"]
|
sources += ["embed/trezorhal/optiga/optiga_commands.c"]
|
||||||
sources += ["embed/trezorhal/optiga/optiga_transport.c"]
|
sources += ["embed/trezorhal/optiga/optiga_transport.c"]
|
||||||
sources += ["embed/trezorhal/stm32f4/secret.c"]
|
|
||||||
sources += ["vendor/trezor-crypto/hash_to_curve.c"]
|
sources += ["vendor/trezor-crypto/hash_to_curve.c"]
|
||||||
features_available.append("optiga")
|
features_available.append("optiga")
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ def _transform_vendor_trust(data: bytes) -> bytes:
|
|||||||
|
|
||||||
|
|
||||||
class VendorTrust(Struct):
|
class VendorTrust(Struct):
|
||||||
|
_dont_provide_secret: bool
|
||||||
allow_run_with_secret: bool
|
allow_run_with_secret: bool
|
||||||
show_vendor_string: bool
|
show_vendor_string: bool
|
||||||
require_user_click: bool
|
require_user_click: bool
|
||||||
@ -57,7 +58,9 @@ class VendorTrust(Struct):
|
|||||||
|
|
||||||
SUBCON = c.Transformed(
|
SUBCON = c.Transformed(
|
||||||
c.BitStruct(
|
c.BitStruct(
|
||||||
"_reserved" / c.Default(c.BitsInteger(8), 0),
|
"_reserved" / c.Default(c.BitsInteger(7), 0b1111111),
|
||||||
|
"_dont_provide_secret"
|
||||||
|
/ c.Default(c.Flag, lambda this: not this.allow_run_with_secret),
|
||||||
"allow_run_with_secret" / c.Flag,
|
"allow_run_with_secret" / c.Flag,
|
||||||
"show_vendor_string" / c.Flag,
|
"show_vendor_string" / c.Flag,
|
||||||
"require_user_click" / c.Flag,
|
"require_user_click" / c.Flag,
|
||||||
|
Loading…
Reference in New Issue
Block a user