@ -34,91 +34,15 @@
# include "ecdsa.h"
# include "ecdsa.h"
# include "secp256k1.h"
# include "secp256k1.h"
# include "memzero.h"
# include "memzero.h"
# include "memory.h"
# include "usb21_standard.h"
# include "usb21_standard.h"
# include "webusb.h"
# include "webusb.h"
# include "winusb.h"
# include "winusb.h"
# define FIRMWARE_MAGIC "TRZR"
# include "usb_desc.h"
# include "usb_send.h"
# define USB_INTERFACE_INDEX_MAIN 0
# include "usb_erase.h"
# define ENDPOINT_ADDRESS_IN (0x81)
# define ENDPOINT_ADDRESS_OUT (0x01)
static bool brand_new_firmware ;
static bool old_was_unsigned ;
static const struct usb_device_descriptor dev_descr = {
. bLength = USB_DT_DEVICE_SIZE ,
. bDescriptorType = USB_DT_DEVICE ,
. bcdUSB = 0x0210 ,
. bDeviceClass = 0 ,
. bDeviceSubClass = 0 ,
. bDeviceProtocol = 0 ,
. bMaxPacketSize0 = 64 ,
. idVendor = 0x1209 ,
. idProduct = 0x53c0 ,
. bcdDevice = 0x0100 ,
. iManufacturer = 1 ,
. iProduct = 2 ,
. iSerialNumber = 3 ,
. bNumConfigurations = 1 ,
} ;
static const struct usb_endpoint_descriptor endpoints [ 2 ] = { {
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
. bEndpointAddress = ENDPOINT_ADDRESS_IN ,
. bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT ,
. wMaxPacketSize = 64 ,
. bInterval = 1 ,
} , {
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
. bEndpointAddress = ENDPOINT_ADDRESS_OUT ,
. bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT ,
. wMaxPacketSize = 64 ,
. bInterval = 1 ,
} } ;
static const struct usb_interface_descriptor iface [ ] = { {
. bLength = USB_DT_INTERFACE_SIZE ,
. bDescriptorType = USB_DT_INTERFACE ,
. bInterfaceNumber = USB_INTERFACE_INDEX_MAIN ,
. bAlternateSetting = 0 ,
. bNumEndpoints = 2 ,
. bInterfaceClass = USB_CLASS_VENDOR ,
. bInterfaceSubClass = 0 ,
. bInterfaceProtocol = 0 ,
. iInterface = 0 ,
. endpoint = endpoints ,
. extra = NULL ,
. extralen = 0 ,
} } ;
static const struct usb_interface ifaces [ ] = { {
. num_altsetting = 1 ,
. altsetting = iface ,
} } ;
static const struct usb_config_descriptor config = {
. bLength = USB_DT_CONFIGURATION_SIZE ,
. bDescriptorType = USB_DT_CONFIGURATION ,
. wTotalLength = 0 ,
. bNumInterfaces = 1 ,
. bConfigurationValue = 1 ,
. iConfiguration = 0 ,
. bmAttributes = 0x80 ,
. bMaxPower = 0x32 ,
. interface = ifaces ,
} ;
static const char * usb_strings [ ] = {
" SatoshiLabs " ,
" TREZOR " ,
" 000000000000000000000000 " ,
} ;
enum {
enum {
STATE_READY ,
STATE_READY ,
@ -130,121 +54,77 @@ enum {
} ;
} ;
static uint32_t flash_pos = 0 , flash_len = 0 ;
static uint32_t flash_pos = 0 , flash_len = 0 ;
static uint32_t chunk_idx = 0 ;
static char flash_state = STATE_READY ;
static char flash_state = STATE_READY ;
static uint8_t flash_anim = 0 ;
static uint16_t msg_id = 0xFFFF ;
static uint32_t msg_size = 0 ;
static uint8_t meta_backup [ FLASH_META_LEN ] ;
static void send_msg_success ( usbd_device * dev )
{
uint8_t response [ 64 ] ;
memzero ( response , sizeof ( response ) ) ;
// response: Success message (id 2), payload len 0
memcpy ( response ,
// header
" ?## "
// msg_id
" \x00 \x02 "
// msg_size
" \x00 \x00 \x00 \x00 " ,
9 ) ;
while ( usbd_ep_write_packet ( dev , ENDPOINT_ADDRESS_IN , response , 64 ) ! = 64 ) { }
}
static void send_msg_failure ( usbd_device * dev )
static uint32_t FW_HEADER [ FLASH_FWHEADER_LEN / sizeof ( uint32_t ) ] ;
{
static uint32_t FW_CHUNK [ FW_CHUNK_SIZE / sizeof ( uint32_t ) ] ;
uint8_t response [ 64 ] ;
memzero ( response , sizeof ( response ) ) ;
// response: Failure message (id 3), payload len 2
// - code = 99 (Failure_FirmwareError)
memcpy ( response ,
// header
" ?## "
// msg_id
" \x00 \x03 "
// msg_size
" \x00 \x00 \x00 \x02 "
// data
" \x08 " " \x63 " ,
11 ) ;
while ( usbd_ep_write_packet ( dev , ENDPOINT_ADDRESS_IN , response , 64 ) ! = 64 ) { }
}
static void send_msg_features ( usbd_device * dev )
{
uint8_t response [ 64 ] ;
memzero ( response , sizeof ( response ) ) ;
// response: Features message (id 17), payload len 25
// - vendor = "trezor.io"
// - major_version = VERSION_MAJOR
// - minor_version = VERSION_MINOR
// - patch_version = VERSION_PATCH
// - bootloader_mode = True
// - firmware_present = True/False
// - model = "1"
memcpy ( response ,
// header
" ?## "
// msg_id
" \x00 \x11 "
// msg_size
" \x00 \x00 \x00 \x16 "
// data
" \x0a " " \x09 " " trezor.io "
" \x10 " VERSION_MAJOR_CHAR
" \x18 " VERSION_MINOR_CHAR
" \x20 " VERSION_PATCH_CHAR
" \x28 " " \x01 "
" \x90 \x01 " " \x00 "
" \xaa " " \x01 " " 1 " ,
34 ) ;
response [ 30 ] = brand_new_firmware ? 0x01 : 0x00 ;
while ( usbd_ep_write_packet ( dev , ENDPOINT_ADDRESS_IN , response , 64 ) ! = 64 ) { }
}
static void send_msg_buttonrequest_firmwarecheck( usbd_device * dev )
static void check_and_write_chunk ( void )
{
{
uint8_t response [ 64 ] ;
uint32_t offset = ( chunk_idx = = 0 ) ? FLASH_FWHEADER_LEN : 0 ;
memzero ( response , sizeof ( response ) ) ;
uint32_t chunk_pos = flash_pos % FW_CHUNK_SIZE ;
// response: ButtonRequest message (id 26), payload len 2
if ( chunk_pos = = 0 ) {
// - code = ButtonRequest_FirmwareCheck (9)
chunk_pos = FW_CHUNK_SIZE ;
memcpy ( response ,
}
// header
uint8_t hash [ 32 ] ;
" ?## "
SHA256_CTX ctx ;
// msg_id
sha256_Init ( & ctx ) ;
" \x00 \x1a "
sha256_Update ( & ctx , ( const uint8_t * ) FW_CHUNK + offset , chunk_pos - offset ) ;
// msg_size
if ( chunk_pos < 64 * 1024 ) {
" \x00 \x00 \x00 \x02 "
// pad with FF
// data
for ( uint32_t i = chunk_pos ; i < 64 * 1024 ; i + = 4 ) {
" \x08 " " \x09 " ,
sha256_Update ( & ctx , ( const uint8_t * ) " \xFF \xFF \xFF \xFF " , 4 ) ;
11
}
) ;
}
while ( usbd_ep_write_packet ( dev , ENDPOINT_ADDRESS_IN , response , 64 ) ! = 64 ) { }
sha256_Final ( & ctx , hash ) ;
}
static void backup_metadata ( uint8_t * backup )
const image_header * hdr = ( const image_header * ) FW_HEADER ;
{
// invalid chunk sent
memcpy ( backup , FLASH_PTR ( FLASH_META_START ) , FLASH_META_LEN ) ;
if ( 0 ! = memcmp ( hash , hdr - > hashes + chunk_idx * 32 , 32 ) ) {
}
// erase storage
erase_storage ( ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
shutdown ( ) ;
return ;
}
static void restore_metadata ( const uint8_t * backup )
flash_wait_for_last_operation ( ) ;
{
flash_clear_status_flags ( ) ;
flash_unlock ( ) ;
flash_unlock ( ) ;
for ( int i = 0 ; i < FLASH_META_LEN / 4 ; i + + ) {
for ( uint32_t i = offset / sizeof ( uint32_t ) ; i < chunk_pos / sizeof ( uint32_t ) ; i + + ) {
const uint32_t * w = ( const uint32_t * ) ( backup + i * 4 ) ;
flash_program_word ( FLASH_FWHEADER_START + chunk_idx * FW_CHUNK_SIZE + i * sizeof ( uint32_t ) , FW_CHUNK [ i ] ) ;
flash_program_word ( FLASH_META_START + i * 4 , * w ) ;
}
}
flash_wait_for_last_operation ( ) ;
flash_lock ( ) ;
flash_lock ( ) ;
// all done
if ( flash_len = = flash_pos ) {
// check remaining chunks if any
for ( uint32_t i = chunk_idx + 1 ; i < 16 ; i + + ) {
// hash should be empty if the chunk is unused
if ( 0 ! = memcmp ( hdr - > hashes + i * 32 , " \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 " , 32 ) ) {
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
shutdown ( ) ;
return ;
}
}
}
memzero ( FW_CHUNK , sizeof ( FW_CHUNK ) ) ;
chunk_idx + + ;
}
}
static void rx_callback ( usbd_device * dev , uint8_t ep )
static void rx_callback ( usbd_device * dev , uint8_t ep )
{
{
( void ) ep ;
( void ) ep ;
static uint16_t msg_id = 0xFFFF ;
static uint8_t buf [ 64 ] __attribute__ ( ( aligned ( 4 ) ) ) ;
static uint8_t buf [ 64 ] __attribute__ ( ( aligned ( 4 ) ) ) ;
static uint8_t towrite [ 4 ] __attribute__ ( ( aligned ( 4 ) ) ) ;
static uint 32_t w ;
static int wi ;
static int wi ;
static int old_was_signed ;
if ( usbd_ep_read_packet ( dev , ENDPOINT_ADDRESS_OUT , buf , 64 ) ! = 64 ) return ;
if ( usbd_ep_read_packet ( dev , ENDPOINT_ADDRESS_OUT , buf , 64 ) ! = 64 ) return ;
@ -258,7 +138,6 @@ static void rx_callback(usbd_device *dev, uint8_t ep)
}
}
// struct.unpack(">HL") => msg, size
// struct.unpack(">HL") => msg, size
msg_id = ( buf [ 3 ] < < 8 ) + buf [ 4 ] ;
msg_id = ( buf [ 3 ] < < 8 ) + buf [ 4 ] ;
msg_size = ( ( uint32_t ) buf [ 5 ] < < 24 ) + ( buf [ 6 ] < < 16 ) + ( buf [ 7 ] < < 8 ) + buf [ 8 ] ;
}
}
if ( flash_state = = STATE_READY | | flash_state = = STATE_OPEN ) {
if ( flash_state = = STATE_READY | | flash_state = = STATE_OPEN ) {
@ -277,26 +156,9 @@ static void rx_callback(usbd_device *dev, uint8_t ep)
}
}
if ( msg_id = = 0x0005 ) { // WipeDevice message (id 5)
if ( msg_id = = 0x0005 ) { // WipeDevice message (id 5)
layoutDialog ( & bmp_icon_question , " Cancel " , " Confirm " , NULL , " Do you really want to " , " wipe the device? " , NULL , " All data will be lost. " , NULL , NULL ) ;
layoutDialog ( & bmp_icon_question , " Cancel " , " Confirm " , NULL , " Do you really want to " , " wipe the device? " , NULL , " All data will be lost. " , NULL , NULL ) ;
do {
bool but = get_button_response ( ) ;
delay ( 100000 ) ;
if ( but ) {
buttonUpdate ( ) ;
erase_storage_code_progress ( ) ;
} while ( ! button . YesUp & & ! button . NoUp ) ;
if ( button . YesUp ) {
flash_wait_for_last_operation ( ) ;
flash_clear_status_flags ( ) ;
flash_unlock ( ) ;
// erase metadata area
for ( int i = FLASH_META_SECTOR_FIRST ; i < = FLASH_META_SECTOR_LAST ; i + + ) {
layoutProgress ( " PREPARING ... Please wait " , 1000 * ( i - FLASH_META_SECTOR_FIRST ) / ( FLASH_CODE_SECTOR_LAST - FLASH_META_SECTOR_FIRST ) ) ;
flash_erase_sector ( i , FLASH_CR_PROGRAM_X32 ) ;
}
// erase code area
for ( int i = FLASH_CODE_SECTOR_FIRST ; i < = FLASH_CODE_SECTOR_LAST ; i + + ) {
layoutProgress ( " PREPARING ... Please wait " , 1000 * ( i - FLASH_META_SECTOR_FIRST ) / ( FLASH_CODE_SECTOR_LAST - FLASH_META_SECTOR_FIRST ) ) ;
flash_erase_sector ( i , FLASH_CR_PROGRAM_X32 ) ;
}
flash_wait_for_last_operation ( ) ;
flash_lock ( ) ;
flash_state = STATE_END ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_ok , NULL , NULL , NULL , " Device " , " successfully wiped. " , NULL , " You may now " , " unplug your TREZOR. " , NULL ) ;
layoutDialog ( & bmp_icon_ok , NULL , NULL , NULL , " Device " , " successfully wiped. " , NULL , " You may now " , " unplug your TREZOR. " , NULL ) ;
send_msg_success ( dev ) ;
send_msg_success ( dev ) ;
@ -311,59 +173,31 @@ static void rx_callback(usbd_device *dev, uint8_t ep)
if ( flash_state = = STATE_OPEN ) {
if ( flash_state = = STATE_OPEN ) {
if ( msg_id = = 0x0006 ) { // FirmwareErase message (id 6)
if ( msg_id = = 0x0006 ) { // FirmwareErase message (id 6)
if ( ! brand_new_firmware ) {
bool proceed = false ;
if ( firmware_present_new ( ) ) {
layoutDialog ( & bmp_icon_question , " Abort " , " Continue " , NULL , " Install new " , " firmware? " , NULL , " Never do this without " , " your recovery card! " , NULL ) ;
layoutDialog ( & bmp_icon_question , " Abort " , " Continue " , NULL , " Install new " , " firmware? " , NULL , " Never do this without " , " your recovery card! " , NULL ) ;
do {
proceed = get_button_response ( ) ;
delay ( 100000 ) ;
} else {
buttonUpdate ( ) ;
proceed = true ;
} while ( ! button . YesUp & & ! button . NoUp ) ;
}
}
if ( brand_new_firmware | | button . YesUp ) {
if ( proceed ) {
// check whether current firmware is signed
// check whether the current firmware is signed (old or new method)
if ( ! brand_new_firmware & & SIG_OK = = signatures_ok ( NULL ) ) {
if ( firmware_present_new ( ) ) {
old_was_unsigned = false ;
const image_header * hdr = ( const image_header * ) FLASH_PTR ( FLASH_FWHEADER_START ) ;
// backup metadata
old_was_signed = ( SIG_OK = = signatures_new_ok ( hdr , NULL ) ) & & ( SIG_OK = = check_firmware_hashes ( hdr ) ) ;
backup_metadata ( meta_backup ) ;
} else if ( firmware_present_old ( ) ) {
old_was_signed = signatures_old_ok ( ) ;
} else {
} else {
old_was_unsigned = true ;
old_was_signed = SIG_FAIL ;
}
flash_wait_for_last_operation ( ) ;
flash_clear_status_flags ( ) ;
flash_unlock ( ) ;
// erase metadata area
for ( int i = FLASH_META_SECTOR_FIRST ; i < = FLASH_META_SECTOR_LAST ; i + + ) {
layoutProgress ( " PREPARING ... Please wait " , 1000 * ( i - FLASH_META_SECTOR_FIRST ) / ( FLASH_CODE_SECTOR_LAST - FLASH_META_SECTOR_FIRST ) ) ;
flash_erase_sector ( i , FLASH_CR_PROGRAM_X32 ) ;
}
}
// erase code area
erase_code_progress ( ) ;
for ( int i = FLASH_CODE_SECTOR_FIRST ; i < = FLASH_CODE_SECTOR_LAST ; i + + ) {
layoutProgress ( " PREPARING ... Please wait " , 1000 * ( i - FLASH_META_SECTOR_FIRST ) / ( FLASH_CODE_SECTOR_LAST - FLASH_META_SECTOR_FIRST ) ) ;
flash_erase_sector ( i , FLASH_CR_PROGRAM_X32 ) ;
}
layoutProgress ( " INSTALLING ... Please wait " , 0 ) ;
flash_wait_for_last_operation ( ) ;
flash_lock ( ) ;
// check that metadata was succesfully erased
// flash status register should show now error and
// the config block should contain only \xff.
uint8_t hash [ 32 ] ;
sha256_Raw ( FLASH_PTR ( FLASH_META_START ) , FLASH_META_LEN , hash ) ;
if ( ( FLASH_SR & ( FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR | FLASH_SR_WRPERR ) ) ! = 0
| | memcmp ( hash , " \x2d \x86 \x4c \x0b \x78 \x9a \x43 \x21 \x4e \xee \x85 \x24 \xd3 \x18 \x20 \x75 \x12 \x5e \x5c \xa2 \xcd \x52 \x7f \x35 \x82 \xec \x87 \xff \xd9 \x40 \x76 \xbc " , 32 ) ! = 0 ) {
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
return ;
}
send_msg_success ( dev ) ;
send_msg_success ( dev ) ;
flash_state = STATE_FLASHSTART ;
flash_state = STATE_FLASHSTART ;
return ;
} else {
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_warning , NULL , NULL , NULL , " Firmware installation " , " aborted. " , NULL , " You may now " , " unplug your TREZOR. " , NULL ) ;
}
}
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_warning , NULL , NULL , NULL , " Firmware installation " , " aborted. " , NULL , " You may now " , " unplug your TREZOR. " , NULL ) ;
return ;
return ;
}
}
return ;
return ;
@ -375,41 +209,47 @@ static void rx_callback(usbd_device *dev, uint8_t ep)
send_msg_failure ( dev ) ;
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
shutdown ( ) ;
return ;
return ;
}
}
// read payload length
// read payload length
const uint8_t * p = buf + 10 ;
const uint8_t * p = buf + 10 ;
flash_len = readprotobufint ( & p ) ;
flash_len = readprotobufint ( & p ) ;
if ( flash_len > FLASH_TOTAL_SIZE + FLASH_META_DESC_LEN - ( FLASH_APP_START - FLASH_ORIGIN ) ) { // firmware is too big
if ( flash_len < = FLASH_FWHEADER_LEN ) { // firmware is too small
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Firmware is too small. " , NULL , " Get official firmware " , " from trezor.io/start " , NULL , NULL ) ;
return ;
}
if ( flash_len > FLASH_FWHEADER_LEN + FLASH_APP_LEN ) { // firmware is too big
send_msg_failure ( dev ) ;
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Firmware is too big. " , NULL , " Get official firmware " , " from trezor.io/start " , NULL , NULL ) ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Firmware is too big. " , NULL , " Get official firmware " , " from trezor.io/start " , NULL , NULL ) ;
return ;
return ;
}
}
// check firmware magic
// check firmware magic
if ( memcmp ( p , FIRMWARE_MAGIC , 4 ) ! = 0 ) {
if ( memcmp ( p , & FIRMWARE_MAGIC _NEW , 4 ) ! = 0 ) {
send_msg_failure ( dev ) ;
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Wrong firmware header. " , NULL , " Get official firmware " , " from trezor.io/start " , NULL , NULL ) ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Wrong firmware header. " , NULL , " Get official firmware " , " from trezor.io/start " , NULL , NULL ) ;
return ;
return ;
}
}
memzero ( FW_HEADER , sizeof ( FW_HEADER ) ) ;
memzero ( FW_CHUNK , sizeof ( FW_CHUNK ) ) ;
flash_state = STATE_FLASHING ;
flash_state = STATE_FLASHING ;
p + = 4 ; // Don't flash firmware header yet.
flash_pos = 0 ;
flash_pos = 4 ;
chunk_idx = 0 ;
wi = 0 ;
w = 0 ;
flash_unlock ( ) ;
while ( p < buf + 64 ) {
while ( p < buf + 64 ) {
towrite[ wi ] = * p ;
w = ( w > > 8 ) | ( * p < < 24 ) ; // assign byte to first byte of uint32_t w
wi + + ;
wi + + ;
if ( wi = = 4 ) {
if ( wi = = 4 ) {
const uint32_t * w = ( uint32_t * ) towrite ;
FW_HEADER [ flash_pos / 4 ] = w ;
flash_program_word ( FLASH_META_START + flash_pos , * w ) ;
flash_pos + = 4 ;
flash_pos + = 4 ;
wi = 0 ;
wi = 0 ;
}
}
p + + ;
p + + ;
}
}
flash_lock ( ) ;
return ;
return ;
}
}
return ;
return ;
@ -420,34 +260,44 @@ static void rx_callback(usbd_device *dev, uint8_t ep)
send_msg_failure ( dev ) ;
send_msg_failure ( dev ) ;
flash_state = STATE_END ;
flash_state = STATE_END ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
shutdown ( ) ;
return ;
return ;
}
}
const uint8_t * p = buf + 1 ;
static uint8_t flash_anim = 0 ;
if ( flash_anim % 32 = = 4 ) {
if ( flash_anim % 32 = = 4 ) {
layoutProgress ( " INSTALLING ... Please wait " , 1000 * flash_pos / flash_len ) ;
layoutProgress ( " INSTALLING ... Please wait " , 1000 * flash_pos / flash_len ) ;
}
}
flash_anim + + ;
flash_anim + + ;
flash_unlock ( ) ;
const uint8_t * p = buf + 1 ;
while ( p < buf + 64 & & flash_pos < flash_len ) {
while ( p < buf + 64 & & flash_pos < flash_len ) {
towrite[ wi ] = * p ;
w = ( w > > 8 ) | ( * p < < 24 ) ; // assign byte to first byte of uint32_t w
wi + + ;
wi + + ;
if ( wi = = 4 ) {
if ( wi = = 4 ) {
const uint32_t * w = ( const uint32_t * ) towrite ;
if ( flash_pos < FLASH_FWHEADER_LEN ) {
if ( flash_pos < FLASH_META_DESC_LEN ) {
FW_HEADER [ flash_pos / 4 ] = w ;
flash_program_word ( FLASH_META_START + flash_pos , * w ) ; // the first 256 bytes of firmware is metadata descriptor
} else {
} else {
flash_program_word ( FLASH_APP_START + ( flash_pos - FLASH_META_DESC_LEN ) , * w ) ; // the rest is code
FW_CHUNK [ ( flash_pos % FW_CHUNK_SIZE ) / 4 ] = w ;
}
}
flash_pos + = 4 ;
flash_pos + = 4 ;
wi = 0 ;
wi = 0 ;
// finished the whole chunk
if ( flash_pos % FW_CHUNK_SIZE = = 0 ) {
check_and_write_chunk ( ) ;
}
}
}
p + + ;
p + + ;
}
}
flash_lock ( ) ;
// flashing done
// flashing done
if ( flash_pos = = flash_len ) {
if ( flash_pos = = flash_len ) {
// flush remaining data in the last chunk
if ( flash_pos % FW_CHUNK_SIZE > 0 ) {
check_and_write_chunk ( ) ;
}
flash_state = STATE_CHECK ;
flash_state = STATE_CHECK ;
if ( ! brand_new_firmware ) {
const image_header * hdr = ( const image_header * ) FW_HEADER ;
if ( SIG_OK ! = signatures_new_ok ( hdr , NULL ) ) {
send_msg_buttonrequest_firmwarecheck ( dev ) ;
send_msg_buttonrequest_firmwarecheck ( dev ) ;
return ;
return ;
}
}
@ -458,55 +308,69 @@ static void rx_callback(usbd_device *dev, uint8_t ep)
if ( flash_state = = STATE_CHECK ) {
if ( flash_state = = STATE_CHECK ) {
if ( ! brand_new_firmware ) {
// use the firmware header from RAM
const image_header * hdr = ( const image_header * ) FW_HEADER ;
bool hash_check_ok ;
// show fingerprint of unsigned firmware
if ( SIG_OK ! = signatures_new_ok ( hdr , NULL ) ) {
if ( msg_id ! = 0x001B ) { // ButtonAck message (id 27)
if ( msg_id ! = 0x001B ) { // ButtonAck message (id 27)
return ;
return ;
}
}
uint8_t hash [ 32 ] ;
uint8_t hash [ 32 ] ;
sha256_Raw ( FLASH_PTR ( FLASH_APP_START ) , flash_len - FLASH_META_DESC_LEN , hash ) ;
compute_firmware_fingerprint ( hdr , hash ) ;
layoutFirmwareHash ( hash ) ;
layoutFirmwareFingerprint ( hash ) ;
do {
hash_check_ok = get_button_response ( ) ;
delay ( 100000 ) ;
} else {
buttonUpdate ( ) ;
hash_check_ok = true ;
} while ( ! button . YesUp & & ! button . NoUp ) ;
}
}
bool hash_check_ok = brand_new_firmware | | button . YesUp ;
layoutProgress ( " INSTALLING ... Please wait " , 1000 ) ;
layoutProgress ( " INSTALLING ... Please wait " , 1000 ) ;
uint8_t flags = * FLASH_PTR ( FLASH_META_FLAGS ) ;
// wipe storage if:
// wipe storage if:
// 0) there was no firmware
// 1) old firmware was unsigned or not present
// 1) old firmware was unsigned
// 2) signatures are not OK
// 2) firmware restore flag isn't set
// 3) hashes are not OK
// 3) signatures are not ok
if ( SIG_OK ! = old_was_signed | | SIG_OK ! = signatures_new_ok ( hdr , NULL ) | | SIG_OK ! = check_firmware_hashes ( hdr ) ) {
if ( brand_new_firmware | | old_was_unsigned | | ( flags & 0x01 ) = = 0 | | SIG_OK ! = signatures_ok ( NULL ) ) {
// erase storage
memzero ( meta_backup , sizeof ( meta_backup ) ) ;
erase_storage ( ) ;
// check erasure
uint8_t hash [ 32 ] ;
sha256_Raw ( FLASH_PTR ( FLASH_STORAGE_START ) , FLASH_STORAGE_LEN , hash ) ;
if ( memcmp ( hash , " \x2d \x86 \x4c \x0b \x78 \x9a \x43 \x21 \x4e \xee \x85 \x24 \xd3 \x18 \x20 \x75 \x12 \x5e \x5c \xa2 \xcd \x52 \x7f \x35 \x82 \xec \x87 \xff \xd9 \x40 \x76 \xbc " , 32 ) ! = 0 ) {
send_msg_failure ( dev ) ;
layoutDialog ( & bmp_icon_error , NULL , NULL , NULL , " Error installing " , " firmware. " , NULL , " Unplug your TREZOR " , " and try again. " , NULL ) ;
shutdown ( ) ;
return ;
}
}
}
// copy new firmware header
flash_wait_for_last_operation ( ) ;
memcpy ( meta_backup , ( void * ) FLASH_META_START , FLASH_META_DESC_LEN ) ;
flash_clear_status_flags ( ) ;
// write "TRZR" in header only when hash was confirmed
flash_unlock ( ) ;
// write firmware header only when hash was confirmed
if ( hash_check_ok ) {
if ( hash_check_ok ) {
memcpy ( meta_backup , FIRMWARE_MAGIC , 4 ) ;
for ( size_t i = 0 ; i < FLASH_FWHEADER_LEN / sizeof ( uint32_t ) ; i + + ) {
flash_program_word ( FLASH_FWHEADER_START + i * sizeof ( uint32_t ) , FW_HEADER [ i ] ) ;
}
} else {
} else {
memzero ( meta_backup , 4 ) ;
for ( size_t i = 0 ; i < FLASH_FWHEADER_LEN / sizeof ( uint32_t ) ; i + + ) {
flash_program_word ( FLASH_FWHEADER_START + i * sizeof ( uint32_t ) , 0 ) ;
}
}
}
flash_wait_for_last_operation ( ) ;
// no need to erase, because we are not changing any already flashed byte.
flash_lock ( ) ;
restore_metadata ( meta_backup ) ;
memzero ( meta_backup , sizeof ( meta_backup ) ) ;
flash_state = STATE_END ;
flash_state = STATE_END ;
if ( hash_check_ok ) {
if ( hash_check_ok ) {
layoutDialog ( & bmp_icon_ok , NULL , NULL , NULL , " New firmware " , " successfully installed. " , NULL , " You may now " , " unplug your TREZOR. " , NULL ) ;
layoutDialog ( & bmp_icon_ok , NULL , NULL , NULL , " New firmware " , " successfully installed. " , NULL , " You may now " , " unplug your TREZOR. " , NULL ) ;
send_msg_success ( dev ) ;
send_msg_success ( dev ) ;
shutdown ( ) ;
} else {
} else {
layoutDialog ( & bmp_icon_warning , NULL , NULL , NULL , " Firmware installation " , " aborted. " , NULL , " You need to repeat " , " the procedure with " , " the correct firmware. " ) ;
layoutDialog ( & bmp_icon_warning , NULL , NULL , NULL , " Firmware installation " , " aborted. " , NULL , " You need to repeat " , " the procedure with " , " the correct firmware. " ) ;
send_msg_failure ( dev ) ;
send_msg_failure ( dev ) ;
shutdown ( ) ;
}
}
return ;
return ;
}
}
}
}
static void set_config ( usbd_device * dev , uint16_t wValue )
static void set_config ( usbd_device * dev , uint16_t wValue )
@ -531,7 +395,7 @@ static const struct usb_bos_descriptor bos_descriptor = {
. capabilities = capabilities
. capabilities = capabilities
} ;
} ;
void usbInit ( void )
static void usbInit ( void )
{
{
usbd_dev = usbd_init ( & otgfs_usb_driver , & dev_descr , & config , usb_strings , sizeof ( usb_strings ) / sizeof ( const char * ) , usbd_control_buffer , sizeof ( usbd_control_buffer ) ) ;
usbd_dev = usbd_init ( & otgfs_usb_driver , & dev_descr , & config , usb_strings , sizeof ( usb_strings ) / sizeof ( const char * ) , usbd_control_buffer , sizeof ( usbd_control_buffer ) ) ;
usbd_register_set_config_callback ( usbd_dev , set_config ) ;
usbd_register_set_config_callback ( usbd_dev , set_config ) ;
@ -540,7 +404,7 @@ void usbInit(void)
winusb_setup ( usbd_dev , USB_INTERFACE_INDEX_MAIN ) ;
winusb_setup ( usbd_dev , USB_INTERFACE_INDEX_MAIN ) ;
}
}
void checkButtons ( void )
static void checkButtons ( void )
{
{
static bool btn_left = false , btn_right = false , btn_final = false ;
static bool btn_left = false , btn_right = false , btn_final = false ;
if ( btn_final ) {
if ( btn_final ) {
@ -569,13 +433,13 @@ void checkButtons(void)
}
}
}
}
void usbLoop ( bool firmware_present )
void usbLoop ( void )
{
{
brand_new_firmware = ! firmware_present ;
bool firmware_present = firmware_present_new ( ) ;
usbInit ( ) ;
usbInit ( ) ;
for ( ; ; ) {
for ( ; ; ) {
usbd_poll ( usbd_dev ) ;
usbd_poll ( usbd_dev ) ;
if ( brand_new_ firmware & & ( flash_state = = STATE_READY | | flash_state = = STATE_OPEN ) ) {
if ( ! firmware_present & & ( flash_state = = STATE_READY | | flash_state = = STATE_OPEN ) ) {
checkButtons ( ) ;
checkButtons ( ) ;
}
}
}
}