mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 07:28:10 +00:00
feat(core): implement secret handling in bootloader
This commit is contained in:
parent
58bb702498
commit
e8281385f6
@ -516,3 +516,12 @@ message UnlockedPathRequest {
|
||||
*/
|
||||
message ShowDeviceTutorial {
|
||||
}
|
||||
|
||||
/**
|
||||
* Request: Unlocks bootloader, !irreversible!
|
||||
* @start
|
||||
* @next Success
|
||||
* @next Failure
|
||||
*/
|
||||
message UnlockBootloader {
|
||||
}
|
||||
|
@ -121,6 +121,7 @@ enum MessageType {
|
||||
MessageType_UnlockPath = 93 [(bitcoin_only) = true, (wire_in) = true];
|
||||
MessageType_UnlockedPathRequest = 94 [(bitcoin_only) = true, (wire_out) = true];
|
||||
MessageType_ShowDeviceTutorial = 95 [(bitcoin_only) = true, (wire_in) = true];
|
||||
MessageType_UnlockBootloader = 96 [(bitcoin_only) = true, (wire_in) = true];
|
||||
|
||||
MessageType_SetU2FCounter = 63 [(wire_in) = true];
|
||||
MessageType_GetNextU2FCounter = 80 [(wire_in) = true];
|
||||
|
@ -20,7 +20,7 @@ if TREZOR_MODEL in ('1', ):
|
||||
)
|
||||
Return()
|
||||
|
||||
FEATURES_WANTED = ["input", "rgb_led", "consumption_mask", "usb"]
|
||||
FEATURES_WANTED = ["input", "rgb_led", "consumption_mask", "usb", "optiga"]
|
||||
|
||||
CCFLAGS_MOD = ''
|
||||
CPPPATH_MOD = []
|
||||
|
@ -92,6 +92,20 @@ SOURCE_MOD += [
|
||||
'vendor/trezor-storage/flash_common.c',
|
||||
]
|
||||
|
||||
if TREZOR_MODEL in ('1', ):
|
||||
SOURCE_MOD += [
|
||||
'embed/models/model_T1B1_layout.c',
|
||||
]
|
||||
elif TREZOR_MODEL in ('T', ):
|
||||
SOURCE_MOD += [
|
||||
'embed/models/model_T2T1_layout.c',
|
||||
]
|
||||
elif TREZOR_MODEL in ('R', ):
|
||||
SOURCE_MOD += [
|
||||
'embed/models/model_T2B1_layout.c',
|
||||
]
|
||||
|
||||
|
||||
SOURCE_NANOPB = [
|
||||
'vendor/nanopb/pb_common.c',
|
||||
'vendor/nanopb/pb_decode.c',
|
||||
@ -114,6 +128,7 @@ SOURCE_TREZORHAL = [
|
||||
'embed/trezorhal/unix/rng.c',
|
||||
'embed/trezorhal/unix/usb.c',
|
||||
'embed/trezorhal/unix/random_delays.c',
|
||||
'embed/trezorhal/unix/secret.c',
|
||||
]
|
||||
|
||||
SOURCE_UNIX = [
|
||||
|
@ -17,7 +17,7 @@ if TREZOR_MODEL in ('DISC1', ):
|
||||
action=build_prodtest)
|
||||
Return()
|
||||
|
||||
FEATURES_WANTED = ["input", "sbu", "sd_card", "rdb_led", "usb"]
|
||||
FEATURES_WANTED = ["input", "sbu", "sd_card", "rdb_led", "usb", "consumption_mask", "optiga"]
|
||||
|
||||
CCFLAGS_MOD = ''
|
||||
CPPPATH_MOD = []
|
||||
|
1
core/embed/bootloader/.changelog.d/+14e1ae91.added
Normal file
1
core/embed/bootloader/.changelog.d/+14e1ae91.added
Normal file
@ -0,0 +1 @@
|
||||
Locked bootloader support: bootloader will disallow installation of unofficial firmware unless the Optiga pairing secret is erased.
|
1
core/embed/bootloader/.changelog.d/+95c27be5.added
Normal file
1
core/embed/bootloader/.changelog.d/+95c27be5.added
Normal file
@ -0,0 +1 @@
|
||||
Support unlocking the bootloader via `UnlockBootloader` message.
|
@ -19,6 +19,8 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include TREZOR_BOARD
|
||||
|
||||
#include "bootui.h"
|
||||
#include "display.h"
|
||||
#ifdef TREZOR_EMULATOR
|
||||
@ -233,6 +235,12 @@ void ui_screen_boot_empty(bool fading) { screen_boot_empty(fading); }
|
||||
// error UI
|
||||
void ui_screen_fail(void) { screen_install_fail(); }
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
uint32_t ui_screen_unlock_bootloader_confirm(void) {
|
||||
return screen_unlock_bootloader_confirm();
|
||||
}
|
||||
#endif
|
||||
|
||||
// general functions
|
||||
|
||||
void ui_fadein(void) { display_fade(0, BACKLIGHT_NORMAL, 1000); }
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "image.h"
|
||||
#include "secbool.h"
|
||||
#include "stdbool.h"
|
||||
#include TREZOR_BOARD
|
||||
|
||||
typedef enum {
|
||||
SCREEN_INTRO = 0,
|
||||
@ -68,6 +69,10 @@ void ui_set_initial_setup(bool initial);
|
||||
|
||||
void ui_screen_boot_empty(bool fading);
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
uint32_t ui_screen_unlock_bootloader_confirm(void);
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
#define INPUT_CANCEL 0x01 // Cancel button
|
||||
#define INPUT_CONFIRM 0x02 // Confirm button
|
||||
|
@ -24,8 +24,10 @@
|
||||
#include "display.h"
|
||||
#include "flash.h"
|
||||
#include "image.h"
|
||||
#include "messages.pb.h"
|
||||
#include "random_delays.h"
|
||||
#include "secbool.h"
|
||||
#include "secret.h"
|
||||
|
||||
#ifdef USE_DMA2D
|
||||
#include "dma2d.h"
|
||||
@ -149,13 +151,13 @@ static usb_result_t bootloader_usb_loop(const vendor_header *const vhdr,
|
||||
continue;
|
||||
}
|
||||
switch (msg_id) {
|
||||
case 0: // Initialize
|
||||
case MessageType_MessageType_Initialize:
|
||||
process_msg_Initialize(USB_IFACE_NUM, msg_size, buf, vhdr, hdr);
|
||||
break;
|
||||
case 1: // Ping
|
||||
case MessageType_MessageType_Ping:
|
||||
process_msg_Ping(USB_IFACE_NUM, msg_size, buf);
|
||||
break;
|
||||
case 5: // WipeDevice
|
||||
case MessageType_MessageType_WipeDevice:
|
||||
response = ui_screen_wipe_confirm();
|
||||
if (INPUT_CANCEL == response) {
|
||||
send_user_abort(USB_IFACE_NUM, "Wipe cancelled");
|
||||
@ -180,10 +182,10 @@ static usb_result_t bootloader_usb_loop(const vendor_header *const vhdr,
|
||||
return SHUTDOWN;
|
||||
}
|
||||
break;
|
||||
case 6: // FirmwareErase
|
||||
case MessageType_MessageType_FirmwareErase:
|
||||
process_msg_FirmwareErase(USB_IFACE_NUM, msg_size, buf);
|
||||
break;
|
||||
case 7: // FirmwareUpload
|
||||
case MessageType_MessageType_FirmwareUpload:
|
||||
r = process_msg_FirmwareUpload(USB_IFACE_NUM, msg_size, buf);
|
||||
if (r < 0 && r != UPLOAD_ERR_USER_ABORT) { // error, but not user abort
|
||||
ui_screen_fail();
|
||||
@ -210,9 +212,27 @@ static usb_result_t bootloader_usb_loop(const vendor_header *const vhdr,
|
||||
return CONTINUE;
|
||||
}
|
||||
break;
|
||||
case 55: // GetFeatures
|
||||
case MessageType_MessageType_GetFeatures:
|
||||
process_msg_GetFeatures(USB_IFACE_NUM, msg_size, buf, vhdr, hdr);
|
||||
break;
|
||||
#ifdef USE_OPTIGA
|
||||
case MessageType_MessageType_UnlockBootloader:
|
||||
response = ui_screen_unlock_bootloader_confirm();
|
||||
if (INPUT_CANCEL == response) {
|
||||
send_user_abort(USB_IFACE_NUM, "Bootloader unlock cancelled");
|
||||
hal_delay(100);
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return RETURN;
|
||||
}
|
||||
process_msg_AttestationDelete(USB_IFACE_NUM, msg_size, buf);
|
||||
screen_unlock_bootloader_success();
|
||||
hal_delay(100);
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return SHUTDOWN;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
process_msg_unknown(USB_IFACE_NUM, msg_size, buf);
|
||||
break;
|
||||
@ -522,8 +542,20 @@ int bootloader_main(void) {
|
||||
&FIRMWARE_AREA),
|
||||
"Firmware is corrupted");
|
||||
|
||||
// if all VTRUST flags are unset = ultimate trust => skip the procedure
|
||||
#ifdef USE_OPTIGA
|
||||
if (((vhdr.vtrust & VTRUST_SECRET) != 0) && (sectrue != secret_wiped())) {
|
||||
display_clear();
|
||||
screen_fatal_error_rust(
|
||||
"INSTALL RESTRICTED",
|
||||
"Installation of custom firmware is currently restricted.",
|
||||
"Please visit\ntrezor.io/bootloader");
|
||||
|
||||
display_refresh();
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// if all VTRUST flags are unset = ultimate trust => skip the procedure
|
||||
if ((vhdr.vtrust & VTRUST_ALL) != VTRUST_ALL) {
|
||||
ui_fadeout();
|
||||
ui_screen_boot(&vhdr, hdr);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "flash.h"
|
||||
#include "image.h"
|
||||
#include "secbool.h"
|
||||
#include "secret.h"
|
||||
#include "unit_variant.h"
|
||||
#include "usb.h"
|
||||
#include "version.h"
|
||||
@ -572,6 +573,16 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
|
||||
&should_keep_seed, &is_newvendor);
|
||||
}
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
if (sectrue != secret_wiped() && ((vhdr.vtrust & VTRUST_SECRET) != 0)) {
|
||||
MSG_SEND_INIT(Failure);
|
||||
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
|
||||
MSG_SEND_ASSIGN_STRING(message, "Attestation present");
|
||||
MSG_SEND(Failure);
|
||||
return UPLOAD_ERR_ATTESTATION_PRESENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t response = INPUT_CANCEL;
|
||||
if (sectrue == is_new) {
|
||||
// new installation - auto confirm
|
||||
@ -722,3 +733,12 @@ void process_msg_unknown(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) {
|
||||
MSG_SEND_ASSIGN_STRING(message, "Unexpected message");
|
||||
MSG_SEND(Failure);
|
||||
}
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
void process_msg_AttestationDelete(uint8_t iface_num, uint32_t msg_size,
|
||||
uint8_t *buf) {
|
||||
secret_erase();
|
||||
MSG_SEND_INIT(Success);
|
||||
MSG_SEND(Success);
|
||||
}
|
||||
#endif
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <stdint.h>
|
||||
#include "image.h"
|
||||
#include "secbool.h"
|
||||
#include TREZOR_BOARD
|
||||
|
||||
#define USB_TIMEOUT 500
|
||||
#define USB_PACKET_SIZE 64
|
||||
@ -40,6 +41,7 @@ enum {
|
||||
UPLOAD_ERR_USER_ABORT = -7,
|
||||
UPLOAD_ERR_FIRMWARE_TOO_BIG = -8,
|
||||
UPLOAD_ERR_INVALID_CHUNK_HASH = -9,
|
||||
UPLOAD_ERR_ATTESTATION_PRESENT = -10,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -66,6 +68,11 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
|
||||
int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf);
|
||||
void process_msg_unknown(uint8_t iface_num, uint32_t msg_size, uint8_t *buf);
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
void process_msg_AttestationDelete(uint8_t iface_num, uint32_t msg_size,
|
||||
uint8_t *buf);
|
||||
#endif
|
||||
|
||||
secbool bootloader_WipeDevice(void);
|
||||
|
||||
#endif
|
||||
|
@ -39,6 +39,9 @@ PB_BIND(FirmwareRequest, FirmwareRequest, AUTO)
|
||||
PB_BIND(FirmwareUpload, FirmwareUpload, AUTO)
|
||||
|
||||
|
||||
PB_BIND(UnlockBootloader, UnlockBootloader, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -15,13 +15,15 @@ typedef enum _MessageType {
|
||||
MessageType_MessageType_Ping = 1,
|
||||
MessageType_MessageType_Success = 2,
|
||||
MessageType_MessageType_Failure = 3,
|
||||
MessageType_MessageType_WipeDevice = 5,
|
||||
MessageType_MessageType_FirmwareErase = 6,
|
||||
MessageType_MessageType_FirmwareUpload = 7,
|
||||
MessageType_MessageType_FirmwareRequest = 8,
|
||||
MessageType_MessageType_Features = 17,
|
||||
MessageType_MessageType_ButtonRequest = 26,
|
||||
MessageType_MessageType_ButtonAck = 27,
|
||||
MessageType_MessageType_GetFeatures = 55
|
||||
MessageType_MessageType_GetFeatures = 55,
|
||||
MessageType_MessageType_UnlockBootloader = 96
|
||||
} MessageType;
|
||||
|
||||
typedef enum _FailureType {
|
||||
@ -48,6 +50,10 @@ typedef struct _Initialize {
|
||||
char dummy_field;
|
||||
} Initialize;
|
||||
|
||||
typedef struct _UnlockBootloader {
|
||||
char dummy_field;
|
||||
} UnlockBootloader;
|
||||
|
||||
typedef struct _ButtonRequest {
|
||||
bool has_code;
|
||||
ButtonRequestType code;
|
||||
@ -129,8 +135,8 @@ typedef struct _Success {
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _MessageType_MIN MessageType_MessageType_Initialize
|
||||
#define _MessageType_MAX MessageType_MessageType_GetFeatures
|
||||
#define _MessageType_ARRAYSIZE ((MessageType)(MessageType_MessageType_GetFeatures+1))
|
||||
#define _MessageType_MAX MessageType_MessageType_UnlockBootloader
|
||||
#define _MessageType_ARRAYSIZE ((MessageType)(MessageType_MessageType_UnlockBootloader+1))
|
||||
|
||||
#define _FailureType_MIN FailureType_Failure_UnexpectedMessage
|
||||
#define _FailureType_MAX FailureType_Failure_ProcessError
|
||||
@ -157,6 +163,7 @@ extern "C" {
|
||||
#define FirmwareErase_init_default {false, 0}
|
||||
#define FirmwareRequest_init_default {0, 0}
|
||||
#define FirmwareUpload_init_default {{{NULL}, NULL}, false, {0, {0}}}
|
||||
#define UnlockBootloader_init_default {0}
|
||||
#define Initialize_init_zero {0}
|
||||
#define GetFeatures_init_zero {0}
|
||||
#define Features_init_zero {false, "", 0, 0, 0, false, 0, false, "", false, "", false, "", false, 0, false, {0, {0}}, false, 0, false, "", false, 0, false, 0, false, 0, false, "", false, "", false, 0, false, 0}
|
||||
@ -168,6 +175,7 @@ extern "C" {
|
||||
#define FirmwareErase_init_zero {false, 0}
|
||||
#define FirmwareRequest_init_zero {0, 0}
|
||||
#define FirmwareUpload_init_zero {{{NULL}, NULL}, false, {0, {0}}}
|
||||
#define UnlockBootloader_init_zero {0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define ButtonRequest_code_tag 1
|
||||
@ -277,6 +285,11 @@ X(a, STATIC, OPTIONAL, BYTES, hash, 2)
|
||||
#define FirmwareUpload_CALLBACK pb_default_field_callback
|
||||
#define FirmwareUpload_DEFAULT NULL
|
||||
|
||||
#define UnlockBootloader_FIELDLIST(X, a) \
|
||||
|
||||
#define UnlockBootloader_CALLBACK NULL
|
||||
#define UnlockBootloader_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t Initialize_msg;
|
||||
extern const pb_msgdesc_t GetFeatures_msg;
|
||||
extern const pb_msgdesc_t Features_msg;
|
||||
@ -288,6 +301,7 @@ extern const pb_msgdesc_t ButtonAck_msg;
|
||||
extern const pb_msgdesc_t FirmwareErase_msg;
|
||||
extern const pb_msgdesc_t FirmwareRequest_msg;
|
||||
extern const pb_msgdesc_t FirmwareUpload_msg;
|
||||
extern const pb_msgdesc_t UnlockBootloader_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define Initialize_fields &Initialize_msg
|
||||
@ -301,6 +315,7 @@ extern const pb_msgdesc_t FirmwareUpload_msg;
|
||||
#define FirmwareErase_fields &FirmwareErase_msg
|
||||
#define FirmwareRequest_fields &FirmwareRequest_msg
|
||||
#define FirmwareUpload_fields &FirmwareUpload_msg
|
||||
#define UnlockBootloader_fields &UnlockBootloader_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* FirmwareUpload_size depends on runtime parameters */
|
||||
@ -314,6 +329,7 @@ extern const pb_msgdesc_t FirmwareUpload_msg;
|
||||
#define Initialize_size 0
|
||||
#define Ping_size 258
|
||||
#define Success_size 258
|
||||
#define UnlockBootloader_size 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@ -9,6 +9,7 @@ enum MessageType {
|
||||
MessageType_Ping = 1;
|
||||
MessageType_Success = 2;
|
||||
MessageType_Failure = 3;
|
||||
MessageType_WipeDevice = 5;
|
||||
MessageType_FirmwareErase = 6;
|
||||
MessageType_FirmwareUpload = 7;
|
||||
MessageType_FirmwareRequest = 8;
|
||||
@ -16,6 +17,7 @@ enum MessageType {
|
||||
MessageType_ButtonRequest = 26;
|
||||
MessageType_ButtonAck = 27;
|
||||
MessageType_GetFeatures = 55;
|
||||
MessageType_UnlockBootloader = 96;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,3 +145,12 @@ message FirmwareUpload {
|
||||
required bytes payload = 1; // firmware to be loaded into device
|
||||
optional bytes hash = 2; // hash of the payload
|
||||
}
|
||||
|
||||
/**
|
||||
* Request: Unlock bootloader, !irreversible!
|
||||
* @start
|
||||
* @next Success
|
||||
* @next Failure
|
||||
*/
|
||||
message UnlockBootloader {
|
||||
}
|
||||
|
@ -11,4 +11,8 @@
|
||||
#define FIX_VERSION_PATCH 0
|
||||
#define FIX_VERSION_BUILD 0
|
||||
|
||||
#ifdef TREZOR_MODEL_R
|
||||
#define VERSION_MONOTONIC 2
|
||||
#else
|
||||
#define VERSION_MONOTONIC 1
|
||||
#endif
|
||||
|
@ -165,10 +165,7 @@ int main(void) {
|
||||
#endif
|
||||
|
||||
#if !defined TREZOR_MODEL_1
|
||||
// jump to unprivileged mode
|
||||
// http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/CHDBIBGJ.html
|
||||
__asm__ volatile("msr control, %0" ::"r"(0x1));
|
||||
__asm__ volatile("isb");
|
||||
drop_privileges();
|
||||
#endif
|
||||
|
||||
#ifdef USE_SECP256K1_ZKP
|
||||
|
@ -56,6 +56,8 @@ typedef struct {
|
||||
#define VTRUST_RED 0x0010
|
||||
#define VTRUST_CLICK 0x0020
|
||||
#define VTRUST_STRING 0x0040
|
||||
#define VTRUST_SECRET \
|
||||
0x0080 // inverse logic, if set, don't allow to run with secret present
|
||||
#define VTRUST_ALL (VTRUST_WAIT | VTRUST_RED | VTRUST_CLICK | VTRUST_STRING)
|
||||
|
||||
typedef struct {
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
extern const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT];
|
||||
extern const flash_area_t BOARDLOADER_AREA;
|
||||
extern const flash_area_t SECRET_AREA;
|
||||
extern const flash_area_t BOOTLOADER_AREA;
|
||||
extern const flash_area_t FIRMWARE_AREA;
|
||||
extern const flash_area_t WIPE_AREA;
|
||||
|
@ -1 +0,0 @@
|
||||
model_T2T1_layout.c
|
87
core/embed/models/model_T2B1_layout.c
Normal file
87
core/embed/models/model_T2B1_layout.c
Normal file
@ -0,0 +1,87 @@
|
||||
#include "flash.h"
|
||||
#include "model.h"
|
||||
|
||||
const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT] = {
|
||||
{
|
||||
.num_subareas = 1,
|
||||
.subarea[0] =
|
||||
{
|
||||
.first_sector = 4,
|
||||
.num_sectors = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
.num_subareas = 1,
|
||||
.subarea[0] =
|
||||
{
|
||||
.first_sector = 16,
|
||||
.num_sectors = 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const flash_area_t BOARDLOADER_AREA = {
|
||||
.num_subareas = 1,
|
||||
.subarea[0] =
|
||||
{
|
||||
.first_sector = 0,
|
||||
.num_sectors = 3,
|
||||
},
|
||||
};
|
||||
|
||||
const flash_area_t SECRET_AREA = {
|
||||
.num_subareas = 1,
|
||||
.subarea[0] =
|
||||
{
|
||||
.first_sector = 12,
|
||||
.num_sectors = 1,
|
||||
},
|
||||
};
|
||||
|
||||
const flash_area_t BOOTLOADER_AREA = {
|
||||
.num_subareas = 1,
|
||||
.subarea[0] =
|
||||
{
|
||||
.first_sector = 5,
|
||||
.num_sectors = 1,
|
||||
},
|
||||
};
|
||||
|
||||
const flash_area_t FIRMWARE_AREA = {
|
||||
.num_subareas = 2,
|
||||
.subarea[0] =
|
||||
{
|
||||
.first_sector = 6,
|
||||
.num_sectors = 6,
|
||||
},
|
||||
.subarea[1] =
|
||||
{
|
||||
.first_sector = 17,
|
||||
.num_sectors = 7,
|
||||
},
|
||||
};
|
||||
|
||||
const flash_area_t WIPE_AREA = {
|
||||
.num_subareas = 4,
|
||||
.subarea[0] =
|
||||
{
|
||||
.first_sector = 4,
|
||||
.num_sectors = 1,
|
||||
},
|
||||
.subarea[1] =
|
||||
{
|
||||
.first_sector = 6,
|
||||
.num_sectors = 6,
|
||||
},
|
||||
.subarea[2] =
|
||||
{
|
||||
.first_sector = 13,
|
||||
.num_sectors = 2, // sector 15 skipped due to bootloader MPU
|
||||
// settings, sector 12 is secret
|
||||
},
|
||||
.subarea[3] =
|
||||
{
|
||||
.first_sector = 16,
|
||||
.num_sectors = 8,
|
||||
},
|
||||
};
|
@ -25,4 +25,6 @@ uint32_t screen_install_fail(void);
|
||||
void screen_welcome_model(void);
|
||||
void screen_welcome(void);
|
||||
void screen_boot_empty(bool fading);
|
||||
uint32_t screen_unlock_bootloader_confirm(void);
|
||||
void screen_unlock_bootloader_success(void);
|
||||
void display_image(int16_t x, int16_t y, const uint8_t* data, uint32_t datalen);
|
||||
|
@ -858,9 +858,8 @@ pub fn marquee(area: Rect, text: &str, offset: i16, font: Font, fg: Color, bg: C
|
||||
pixeldata_dirty();
|
||||
}
|
||||
|
||||
// Used on T1 only.
|
||||
pub fn dotted_line(start: Point, width: i16, color: Color) {
|
||||
for x in (start.x..width).step_by(2) {
|
||||
pub fn dotted_line(start: Point, width: i16, color: Color, step: i16) {
|
||||
for x in (start.x..width).step_by(step as usize) {
|
||||
display::bar(x, start.y, 1, 1, color.into());
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ pub struct Confirm<'a> {
|
||||
buttons: ButtonController<&'static str>,
|
||||
/// Whether we are on the info screen (optional extra screen)
|
||||
showing_info_screen: bool,
|
||||
two_btn_confirm: bool,
|
||||
}
|
||||
|
||||
impl<'a> Confirm<'a> {
|
||||
@ -48,8 +49,10 @@ impl<'a> Confirm<'a> {
|
||||
message: Label<&'a str>,
|
||||
alert: Option<Label<&'a str>>,
|
||||
button_text: &'static str,
|
||||
two_btn_confirm: bool,
|
||||
) -> Self {
|
||||
let btn_layout = Self::get_button_layout_general(false, button_text, false);
|
||||
let btn_layout =
|
||||
Self::get_button_layout_general(false, button_text, false, two_btn_confirm);
|
||||
Self {
|
||||
bg: Pad::with_background(bg_color).with_clear(),
|
||||
bg_color,
|
||||
@ -61,6 +64,7 @@ impl<'a> Confirm<'a> {
|
||||
button_text,
|
||||
buttons: ButtonController::new(btn_layout),
|
||||
showing_info_screen: false,
|
||||
two_btn_confirm,
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,6 +85,7 @@ impl<'a> Confirm<'a> {
|
||||
self.showing_info_screen,
|
||||
self.button_text,
|
||||
self.has_info_screen(),
|
||||
self.two_btn_confirm,
|
||||
)
|
||||
}
|
||||
|
||||
@ -89,11 +94,14 @@ impl<'a> Confirm<'a> {
|
||||
showing_info_screen: bool,
|
||||
button_text: &'static str,
|
||||
has_info_screen: bool,
|
||||
two_btn_confirm: bool,
|
||||
) -> ButtonLayout<&'static str> {
|
||||
if showing_info_screen {
|
||||
ButtonLayout::arrow_none_none()
|
||||
} else if has_info_screen {
|
||||
ButtonLayout::cancel_armed_info(button_text)
|
||||
} else if two_btn_confirm {
|
||||
ButtonLayout::cancel_armed_none(button_text)
|
||||
} else {
|
||||
ButtonLayout::cancel_none_text(button_text)
|
||||
}
|
||||
@ -166,6 +174,14 @@ impl<'a> Component for Confirm<'a> {
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
} else if self.two_btn_confirm {
|
||||
match msg {
|
||||
Some(ButtonControllerMsg::Triggered(ButtonPos::Left)) => Some(ConfirmMsg::Cancel),
|
||||
Some(ButtonControllerMsg::Triggered(ButtonPos::Middle)) => {
|
||||
Some(ConfirmMsg::Confirm)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
// There is just one main screen without info screen
|
||||
match msg {
|
||||
|
@ -150,7 +150,7 @@ extern "C" fn screen_install_confirm(
|
||||
theme::TEXT_NORMAL,
|
||||
));
|
||||
|
||||
let mut frame = Confirm::new(BLD_BG, title_str, message, alert, "INSTALL")
|
||||
let mut frame = Confirm::new(BLD_BG, title_str, message, alert, "INSTALL", false)
|
||||
.with_info_screen("FW FINGERPRINT", fingerprint);
|
||||
run(&mut frame)
|
||||
}
|
||||
@ -160,11 +160,32 @@ extern "C" fn screen_wipe_confirm() -> u32 {
|
||||
let message = Label::left_aligned("Seed and firmware will be erased!", theme::TEXT_NORMAL)
|
||||
.vertically_centered();
|
||||
|
||||
let mut frame = Confirm::new(BLD_BG, "FACTORY RESET", message, None, "RESET");
|
||||
let mut frame = Confirm::new(BLD_BG, "FACTORY RESET", message, None, "RESET", false);
|
||||
|
||||
run(&mut frame)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn screen_unlock_bootloader_confirm() -> u32 {
|
||||
let message = Label::left_aligned("This action cannot be undone!", theme::TEXT_NORMAL)
|
||||
.vertically_centered();
|
||||
|
||||
let mut frame = Confirm::new(BLD_BG, "UNLOCK BOOTLOADER?", message, None, "UNLOCK", true);
|
||||
|
||||
run(&mut frame)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn screen_unlock_bootloader_success() {
|
||||
let title = Label::centered("Bootloader unlocked", theme::TEXT_BOLD).vertically_centered();
|
||||
|
||||
let content =
|
||||
Label::centered("Please reconnect the\ndevice", theme::TEXT_NORMAL).vertically_centered();
|
||||
|
||||
let mut frame = ResultScreen::new(BLD_FG, BLD_BG, ICON_SPINNER, title, content, true);
|
||||
show(&mut frame);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn screen_menu(_bld_version: *const cty::c_char) -> u32 {
|
||||
run(&mut Menu::new())
|
||||
|
@ -538,6 +538,15 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
/// Left cancel, armed text and blank on right.
|
||||
pub fn cancel_armed_none(middle: T) -> Self {
|
||||
Self::new(
|
||||
Some(ButtonDetails::cancel_icon()),
|
||||
Some(ButtonDetails::armed_text(middle)),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
/// Left back arrow and middle armed text.
|
||||
pub fn arrow_armed_none(text: T) -> Self {
|
||||
Self::new(
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::ui::{
|
||||
component::{Child, Component, Event, EventCtx, Label, Never, Pad},
|
||||
constant::screen,
|
||||
constant::{screen, WIDTH},
|
||||
display,
|
||||
geometry::{Alignment2D, Offset, Point, Rect},
|
||||
};
|
||||
@ -11,7 +11,6 @@ use super::super::{
|
||||
};
|
||||
|
||||
const FOOTER_AREA_HEIGHT: i16 = 20;
|
||||
const MESSAGE_AREA_HEIGHT: i16 = 32;
|
||||
const DIVIDER_POSITION: i16 = 43;
|
||||
|
||||
pub struct ErrorScreen<T> {
|
||||
@ -55,9 +54,15 @@ impl<T: AsRef<str>> Component for ErrorScreen<T> {
|
||||
self.show_icons = false;
|
||||
}
|
||||
|
||||
let top_offset = if self.show_icons {
|
||||
Offset::y(11)
|
||||
} else {
|
||||
Offset::y(8)
|
||||
};
|
||||
|
||||
let message_area = Rect::new(
|
||||
title_area.bottom_left(),
|
||||
title_area.bottom_right() + Offset::y(MESSAGE_AREA_HEIGHT),
|
||||
title_area.top_left() + top_offset,
|
||||
Point::new(title_area.bottom_right().x, DIVIDER_POSITION),
|
||||
);
|
||||
self.message.place(message_area);
|
||||
|
||||
@ -84,12 +89,9 @@ impl<T: AsRef<str>> Component for ErrorScreen<T> {
|
||||
}
|
||||
self.title.paint();
|
||||
self.message.paint();
|
||||
// divider line
|
||||
let bar = Rect::from_center_and_size(
|
||||
Point::new(self.area.center().x, DIVIDER_POSITION),
|
||||
Offset::new(self.area.width(), 1),
|
||||
);
|
||||
display::rect_fill(bar, FG);
|
||||
|
||||
// // divider line
|
||||
display::dotted_line(Point::new(0, DIVIDER_POSITION), WIDTH, FG, 3);
|
||||
|
||||
self.footer.paint();
|
||||
}
|
||||
|
18
core/embed/trezorhal/secret.h
Normal file
18
core/embed/trezorhal/secret.h
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "secbool.h"
|
||||
|
||||
#define SECRET_HEADER_MAGIC "TRZS"
|
||||
#define SECRET_HEADER_LEN 16
|
||||
#define SECRET_OPTIGA_KEY_OFFSET 16
|
||||
#define SECRET_OPTIGA_KEY_LEN 32
|
||||
|
||||
void secret_write(uint8_t* data, uint32_t offset, uint32_t len);
|
||||
|
||||
secbool secret_read(uint8_t* data, uint32_t offset, uint32_t len);
|
||||
|
||||
secbool secret_wiped(void);
|
||||
|
||||
void secret_erase(void);
|
||||
|
||||
void secret_write_header(void);
|
@ -125,12 +125,13 @@ void mpu_config_firmware(void) {
|
||||
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH |
|
||||
LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS |
|
||||
MPU_RASR_XN_Msk;
|
||||
// Storage#2 (0x08110000 - 0x0811FFFF, 64 KiB, read-write, execute never)
|
||||
// Secret + Storage#2 (0x08100000 - 0x0811FFFF, 16 Kib + 64 KiB, read-write,
|
||||
// execute never)
|
||||
MPU->RNR = MPU_REGION_NUMBER2;
|
||||
MPU->RBAR = FLASH_BASE + 0x110000;
|
||||
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH |
|
||||
LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS |
|
||||
MPU_RASR_XN_Msk;
|
||||
LL_MPU_REGION_SIZE_128KB | LL_MPU_REGION_FULL_ACCESS |
|
||||
MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0x0E);
|
||||
|
||||
// Firmware (0x08040000 - 0x080FFFFF, 6 * 128 KiB = 1024 KiB except 2/8 at
|
||||
// start = 768 KiB, read-only)
|
||||
|
@ -195,6 +195,13 @@ void set_core_clock(clock_settings_t settings) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void drop_privileges(void) {
|
||||
// jump to unprivileged mode
|
||||
// http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/CHDBIBGJ.html
|
||||
__asm__ volatile("msr control, %0" ::"r"(0x1));
|
||||
__asm__ volatile("isb");
|
||||
}
|
||||
|
||||
// from util.s
|
||||
extern void shutdown_privileged(void);
|
||||
|
||||
|
@ -40,6 +40,7 @@ void jump_to_unprivileged(uint32_t address);
|
||||
void jump_to_with_flag(uint32_t address, uint32_t register_flag);
|
||||
void ensure_compatible_settings(void);
|
||||
void clear_otg_hs_memory(void);
|
||||
void drop_privileges(void);
|
||||
|
||||
extern uint32_t __stack_chk_guard;
|
||||
|
||||
|
59
core/embed/trezorhal/stm32f4/secret.c
Normal file
59
core/embed/trezorhal/stm32f4/secret.c
Normal file
@ -0,0 +1,59 @@
|
||||
#include "secret.h"
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
#include "flash.h"
|
||||
#include "model.h"
|
||||
|
||||
static secbool verify_header(void) {
|
||||
uint8_t header[SECRET_HEADER_LEN] = {0};
|
||||
|
||||
memcpy(header, flash_area_get_address(&SECRET_AREA, 0, SECRET_HEADER_LEN),
|
||||
SECRET_HEADER_LEN);
|
||||
|
||||
return memcmp(header, SECRET_HEADER_MAGIC, 4) == 0 ? sectrue : secfalse;
|
||||
}
|
||||
|
||||
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(uint8_t* data, uint32_t offset, uint32_t len) {
|
||||
ensure(flash_unlock_write(), "secret write");
|
||||
for (int i = 0; i < len; i++) {
|
||||
ensure(flash_area_write_byte(&SECRET_AREA, offset + i, data[i]),
|
||||
"secret write");
|
||||
}
|
||||
ensure(flash_lock_write(), "secret write");
|
||||
}
|
||||
|
||||
secbool secret_read(uint8_t* data, uint32_t offset, uint32_t len) {
|
||||
if (sectrue != verify_header()) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
memcpy(data, flash_area_get_address(&SECRET_AREA, offset, len), len);
|
||||
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
for (int i = 0; i < size; i += 4) {
|
||||
uint32_t* addr = (uint32_t*)flash_area_get_address(&SECRET_AREA, i, 4);
|
||||
if (*addr != 0xFFFFFFFF) {
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
void secret_erase(void) {
|
||||
ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase");
|
||||
}
|
9
core/embed/trezorhal/unix/secret.c
Normal file
9
core/embed/trezorhal/unix/secret.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include "secret.h"
|
||||
|
||||
void secret_write(uint8_t* data, uint32_t offset, uint32_t len) {}
|
||||
|
||||
void secret_read(uint8_t* data, uint32_t offset, uint32_t len) {}
|
||||
|
||||
secbool secret_wiped(void) { return secfalse; }
|
||||
|
||||
void secret_erase(void) {}
|
@ -6,6 +6,7 @@
|
||||
"version": [0, 1],
|
||||
"sig_m": 2,
|
||||
"trust": {
|
||||
"allow_run_with_secret": false,
|
||||
"show_vendor_string": true,
|
||||
"require_user_click": true,
|
||||
"red_background": true,
|
||||
|
19
core/embed/vendorheader/T2B1/vendor_prodtest.json
Normal file
19
core/embed/vendorheader/T2B1/vendor_prodtest.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"header_len": 4608,
|
||||
"text": "UNSAFE, FACTORY TEST ONLY",
|
||||
"hw_model": "T2B1",
|
||||
"expiry": 0,
|
||||
"version": [0, 0],
|
||||
"sig_m": 2,
|
||||
"trust": {
|
||||
"allow_run_with_secret": true,
|
||||
"show_vendor_string": false,
|
||||
"require_user_click": false,
|
||||
"red_background": false,
|
||||
"delay": 0
|
||||
},
|
||||
"pubkeys": [
|
||||
"0c0b31408416bd1e813e817599c3320bf775eb1e1843344a1108fdec775fee29",
|
||||
"ed5daba70a99d5c816e6d8bec1c2ae1bb7be804ceddbbe42be772521ca561122"
|
||||
]
|
||||
}
|
BIN
core/embed/vendorheader/T2B1/vendor_prodtest.toif
Normal file
BIN
core/embed/vendorheader/T2B1/vendor_prodtest.toif
Normal file
Binary file not shown.
@ -6,6 +6,7 @@
|
||||
"version": [0, 0],
|
||||
"sig_m": 2,
|
||||
"trust": {
|
||||
"allow_run_with_secret": true,
|
||||
"show_vendor_string": false,
|
||||
"require_user_click": false,
|
||||
"red_background": false,
|
||||
|
@ -6,6 +6,7 @@
|
||||
"version": [0, 0],
|
||||
"sig_m": 2,
|
||||
"trust": {
|
||||
"allow_run_with_secret": true,
|
||||
"show_vendor_string": false,
|
||||
"require_user_click": false,
|
||||
"red_background": false,
|
||||
|
@ -6,6 +6,7 @@
|
||||
"version": [0, 0],
|
||||
"sig_m": 2,
|
||||
"trust": {
|
||||
"allow_run_with_secret": false,
|
||||
"show_vendor_string": true,
|
||||
"require_user_click": true,
|
||||
"red_background": true,
|
||||
|
BIN
core/embed/vendorheader/T2B1/vendorheader_prodtest_unsigned.bin
Normal file
BIN
core/embed/vendorheader/T2B1/vendorheader_prodtest_unsigned.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -6,6 +6,7 @@
|
||||
"version": [0, 0],
|
||||
"sig_m": 2,
|
||||
"trust": {
|
||||
"allow_run_with_secret": false,
|
||||
"show_vendor_string": false,
|
||||
"require_user_click": false,
|
||||
"red_background": false,
|
||||
|
@ -6,6 +6,7 @@
|
||||
"version": [0, 0],
|
||||
"sig_m": 2,
|
||||
"trust": {
|
||||
"allow_run_with_secret": false,
|
||||
"show_vendor_string": false,
|
||||
"require_user_click": false,
|
||||
"red_background": false,
|
||||
|
@ -6,6 +6,7 @@
|
||||
"version": [0, 1],
|
||||
"sig_m": 2,
|
||||
"trust": {
|
||||
"allow_run_with_secret": false,
|
||||
"show_vendor_string": false,
|
||||
"require_user_click": false,
|
||||
"red_background": false,
|
||||
|
@ -6,6 +6,7 @@
|
||||
"version": [0, 1],
|
||||
"sig_m": 2,
|
||||
"trust": {
|
||||
"allow_run_with_secret": false,
|
||||
"show_vendor_string": true,
|
||||
"require_user_click": true,
|
||||
"red_background": true,
|
||||
|
@ -70,6 +70,7 @@ def configure(
|
||||
sources += ["embed/trezorhal/stm32f4/optiga_hal.c"]
|
||||
sources += ["embed/trezorhal/optiga/optiga_commands.c"]
|
||||
sources += ["embed/trezorhal/optiga/optiga_transport.c"]
|
||||
sources += ["embed/trezorhal/stm32f4/secret.c"]
|
||||
|
||||
env.get("ENV")["TREZOR_BOARD"] = board
|
||||
env.get("ENV")["MCU_TYPE"] = mcu
|
||||
|
@ -47,6 +47,7 @@ FirmwareHash = 89
|
||||
UnlockPath = 93
|
||||
UnlockedPathRequest = 94
|
||||
ShowDeviceTutorial = 95
|
||||
UnlockBootloader = 96
|
||||
FirmwareErase = 6
|
||||
FirmwareUpload = 7
|
||||
FirmwareRequest = 8
|
||||
|
@ -64,6 +64,7 @@ if TYPE_CHECKING:
|
||||
UnlockPath = 93
|
||||
UnlockedPathRequest = 94
|
||||
ShowDeviceTutorial = 95
|
||||
UnlockBootloader = 96
|
||||
SetU2FCounter = 63
|
||||
GetNextU2FCounter = 80
|
||||
NextU2FCounter = 81
|
||||
|
@ -2628,6 +2628,12 @@ if TYPE_CHECKING:
|
||||
def is_type_of(cls, msg: Any) -> TypeGuard["ShowDeviceTutorial"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class UnlockBootloader(protobuf.MessageType):
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: Any) -> TypeGuard["UnlockBootloader"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class DebugLinkDecision(protobuf.MessageType):
|
||||
button: "DebugButton | None"
|
||||
swipe: "DebugSwipeDirection | None"
|
||||
|
@ -7,7 +7,8 @@ SKIPPED_MESSAGES := Binance Cardano DebugMonero Eos Monero Ontology Ripple SdPro
|
||||
DebugLinkLayout DebugLinkResetDebugEvents GetNonce \
|
||||
TxAckInput TxAckOutput TxAckPrev TxAckPaymentRequest \
|
||||
EthereumSignTypedData EthereumTypedDataStructRequest EthereumTypedDataStructAck \
|
||||
EthereumTypedDataValueRequest EthereumTypedDataValueAck ShowDeviceTutorial
|
||||
EthereumTypedDataValueRequest EthereumTypedDataValueAck ShowDeviceTutorial \
|
||||
UnlockBootloader
|
||||
|
||||
ifeq ($(BITCOIN_ONLY), 1)
|
||||
SKIPPED_MESSAGES += Ethereum NEM Stellar
|
||||
|
1
python/.changelog.d/+68d5cd56.added
Normal file
1
python/.changelog.d/+68d5cd56.added
Normal file
@ -0,0 +1 @@
|
||||
trezorctl: support unlocking bootloader via `trezorctl device unlock-bootloader`.
|
@ -299,6 +299,13 @@ def tutorial(client: "TrezorClient") -> str:
|
||||
return device.show_device_tutorial(client)
|
||||
|
||||
|
||||
@cli.command()
|
||||
@with_client
|
||||
def unlock_bootloader(client: "TrezorClient") -> str:
|
||||
"""Unlocks bootloader. Irreversible."""
|
||||
return device.unlock_bootloader(client)
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.argument("enable", type=ChoiceType({"on": True, "off": False}), required=False)
|
||||
@click.option(
|
||||
|
@ -248,6 +248,12 @@ def show_device_tutorial(client: "TrezorClient") -> "MessageType":
|
||||
return client.call(messages.ShowDeviceTutorial())
|
||||
|
||||
|
||||
@session
|
||||
@expect(messages.Success, field="message", ret_type=str)
|
||||
def unlock_bootloader(client: "TrezorClient") -> "MessageType":
|
||||
return client.call(messages.UnlockBootloader())
|
||||
|
||||
|
||||
@expect(messages.Success, field="message", ret_type=str)
|
||||
@session
|
||||
def set_busy(client: "TrezorClient", expiry_ms: Optional[int]) -> "MessageType":
|
||||
|
@ -47,6 +47,7 @@ def _transform_vendor_trust(data: bytes) -> bytes:
|
||||
|
||||
|
||||
class VendorTrust(Struct):
|
||||
allow_run_with_secret: bool
|
||||
show_vendor_string: bool
|
||||
require_user_click: bool
|
||||
red_background: bool
|
||||
@ -56,7 +57,8 @@ class VendorTrust(Struct):
|
||||
|
||||
SUBCON = c.Transformed(
|
||||
c.BitStruct(
|
||||
"_reserved" / c.Default(c.BitsInteger(9), 0),
|
||||
"_reserved" / c.Default(c.BitsInteger(8), 0),
|
||||
"allow_run_with_secret" / c.Flag,
|
||||
"show_vendor_string" / c.Flag,
|
||||
"require_user_click" / c.Flag,
|
||||
"red_background" / c.Flag,
|
||||
|
@ -72,6 +72,7 @@ class MessageType(IntEnum):
|
||||
UnlockPath = 93
|
||||
UnlockedPathRequest = 94
|
||||
ShowDeviceTutorial = 95
|
||||
UnlockBootloader = 96
|
||||
SetU2FCounter = 63
|
||||
GetNextU2FCounter = 80
|
||||
NextU2FCounter = 81
|
||||
@ -3737,6 +3738,10 @@ class ShowDeviceTutorial(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 95
|
||||
|
||||
|
||||
class UnlockBootloader(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 96
|
||||
|
||||
|
||||
class DebugLinkDecision(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 100
|
||||
FIELDS = {
|
||||
|
Loading…
Reference in New Issue
Block a user