diff --git a/Makefile b/Makefile index 9fb207e88..44db37305 100644 --- a/Makefile +++ b/Makefile @@ -165,11 +165,11 @@ gdb_firmware: $(FIRMWARE_BUILD_DIR)/firmware.elf ## start remote gdb session to ## misc commands: vendorheader: ## construct and sign the default vendor header - ./tools/build_vendorheader e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351:d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869:772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef 2 0.0 50 DEVELOPMENT assets/vendor_devel.toif embed/firmware/vendorheader.bin + ./tools/build_vendorheader e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351:d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869:772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef 2 0.0 65534 DEVELOPMENT assets/vendor_devel.toif embed/firmware/vendorheader.bin ./tools/binctl embed/firmware/vendorheader.bin -s 1:2 `./tools/combine_sign vendorheader embed/firmware/vendorheader.bin 4444444444444444444444444444444444444444444444444444444444444444 4545454545454545454545454545454545454545454545454545454545454545` vendorheader_sl: ## construct SatoshiLabs vendor header - ./tools/build_vendorheader 47fbdc84d8abef44fe6abde8f87b6ead821b7082ec63b9f7cc33dc53bf6c708d:03fdd9a9c3911652d5effca4540d96ed92d85850a47d256ab0a2d728c0d1a298:2218c25f8ba70c82eba8ed6a321df209c0a7643d014f33bf9317846f62923830 2 0.0 80 SatoshiLabs assets/vendor_satoshilabs.toif embed/firmware/vendorheader_sl.bin + ./tools/build_vendorheader 47fbdc84d8abef44fe6abde8f87b6ead821b7082ec63b9f7cc33dc53bf6c708d:03fdd9a9c3911652d5effca4540d96ed92d85850a47d256ab0a2d728c0d1a298:2218c25f8ba70c82eba8ed6a321df209c0a7643d014f33bf9317846f62923830 2 0.0 65534 SatoshiLabs assets/vendor_satoshilabs.toif embed/firmware/vendorheader_sl.bin binctl: ## print info about binary files ./tools/binctl $(BOOTLOADER_BUILD_DIR)/bootloader.bin diff --git a/docs/bootloader.md b/docs/bootloader.md index 899c6643d..a39e680a1 100644 --- a/docs/bootloader.md +++ b/docs/bootloader.md @@ -112,8 +112,8 @@ of 512 bytes. | 0x000D | 1 | vminor | version (minor) | | 0x000E | 1 | vsig_m | number of signatures needed to run the firmware from this vendor | | 0x000F | 1 | vsig_n | number of different pubkeys vendor provides for signing | -| 0x0010 | 1 | vtrust | level of vendor trust (0-100) | -| 0x0011 | 15 | reserved | not used yet (zeroed) | +| 0x0010 | 2 | vtrust | level of vendor trust (bitmap) | +| 0x0012 | 14 | reserved | not used yet (zeroed) | | 0x0020 | 32 | vpub1 | vendor pubkey 1 | | ... | ... | ... | ... | | ? | 32 | vpubn | vendor pubkey n | @@ -125,6 +125,19 @@ of 512 bytes. | ? | 1 | sigmask | SatoshiLabs signature indexes (bitmap) | | ? | 64 | sig | SatoshiLabs aggregated signature of the vendor header | +#### Vendor Trust + +Vendor trust is stored as bitmap where unset bit means the feature is active. + +| bit | hex | meaning | +|-----|--------|-----------------------------------------| +| 0 | 0x0001 | wait 1 second | +| 1 | 0x0002 | wait 2 seconds | +| 2 | 0x0004 | wait 4 seconds | +| 3 | 0x0008 | wait 8 seconds | +| 4 | 0x0010 | use red background instead of black one | +| 5 | 0x0020 | require user click | + ### Firmware Header Total length of firmware header is always 1024 bytes. diff --git a/embed/bootloader/main.c b/embed/bootloader/main.c index e657b179c..932fc7183 100644 --- a/embed/bootloader/main.c +++ b/embed/bootloader/main.c @@ -89,9 +89,13 @@ void display_welcome(secbool firmware_present) #define VENDOR_IMAGE_RESX 120 #define VENDOR_IMAGE_RESY 120 -void display_vendor(const uint8_t *vimg, const char *vstr, uint32_t vstr_len, uint32_t fw_version) +void display_vendor(const uint8_t *vimg, const char *vstr, uint32_t vstr_len, uint32_t fw_version, char red_background) { - display_clear(); + if (red_background) { + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_BL_RED); + } else { + display_clear(); + } if (memcmp(vimg, "TOIf", 4) != 0) { return; } @@ -102,7 +106,7 @@ void display_vendor(const uint8_t *vimg, const char *vstr, uint32_t vstr_len, ui } uint32_t datalen = *(uint32_t *)(vimg + 8); display_image((DISPLAY_RESX - w) / 2, 32, w, h, vimg + 12, datalen); - display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 48, vstr, vstr_len, FONT_BOLD, COLOR_WHITE, COLOR_BLACK); + display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 48, vstr, vstr_len, FONT_BOLD, COLOR_WHITE, red_background ? COLOR_BL_RED : COLOR_BLACK); char ver_str[32]; mini_snprintf(ver_str, sizeof(ver_str), "%d.%d.%d.%d", (int)(fw_version & 0xFF), @@ -110,7 +114,7 @@ void display_vendor(const uint8_t *vimg, const char *vstr, uint32_t vstr_len, ui (int)((fw_version >> 16) & 0xFF), (int)((fw_version >> 24) & 0xFF) ); - display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 25, ver_str, -1, FONT_BOLD, COLOR_GRAY128, COLOR_BLACK); + display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 25, ver_str, -1, FONT_BOLD, COLOR_GRAY128, red_background ? COLOR_BL_RED : COLOR_BLACK); display_refresh(); } @@ -339,14 +343,26 @@ int main(void) check_image_contents(&hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, sectors, 13), "invalid firmware hash"); - display_vendor(vhdr.vimg, (const char *)vhdr.vstr, vhdr.vstr_len, hdr.version); + display_vendor(vhdr.vimg, (const char *)vhdr.vstr, vhdr.vstr_len, hdr.version, (vhdr.vtrust & 0x0010) == 0); display_fade(0, BACKLIGHT_NORMAL, 1000); - if (vhdr.vtrust < 50) { + + if ((vhdr.vtrust & 0x0001) == 0) { + hal_delay(1000); + } + if ((vhdr.vtrust & 0x0002) == 0) { + hal_delay(2000); + } + if ((vhdr.vtrust & 0x0004) == 0) { + hal_delay(4000); + } + if ((vhdr.vtrust & 0x0008) == 0) { + hal_delay(8000); + } + if ((vhdr.vtrust & 0x0020) == 0) { display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 2, "click to continue ...", -1, FONT_BOLD, COLOR_GRAY64, COLOR_BLACK); touch_click(); - } else { - hal_delay(1000); } + display_fade(BACKLIGHT_NORMAL, 0, 500); display_clear(); diff --git a/embed/trezorhal/image.c b/embed/trezorhal/image.c index c20e0ebaa..d964fb2dd 100644 --- a/embed/trezorhal/image.c +++ b/embed/trezorhal/image.c @@ -88,7 +88,7 @@ secbool load_vendor_header(const uint8_t * const data, uint8_t key_m, uint8_t ke memcpy(&vhdr->vsig_m, data + 14, 1); memcpy(&vhdr->vsig_n, data + 15, 1); - memcpy(&vhdr->vtrust, data + 16, 1); + memcpy(&vhdr->vtrust, data + 16, 2); if (vhdr->vsig_n > MAX_VENDOR_PUBLIC_KEYS) { return secfalse; diff --git a/embed/trezorhal/image.h b/embed/trezorhal/image.h index 87bc75bed..0781700ed 100644 --- a/embed/trezorhal/image.h +++ b/embed/trezorhal/image.h @@ -41,8 +41,8 @@ typedef struct { uint16_t version; uint8_t vsig_m; uint8_t vsig_n; - uint8_t vtrust; - // uint8_t reserved[15]; + uint16_t vtrust; + // uint8_t reserved[14]; const uint8_t *vpub[MAX_VENDOR_PUBLIC_KEYS]; uint8_t vstr_len; const uint8_t *vstr; diff --git a/tools/binctl b/tools/binctl index 452f34e6b..48280ea20 100755 --- a/tools/binctl +++ b/tools/binctl @@ -146,7 +146,7 @@ class BootloaderImage(BinImage): class VendorHeader(object): def __init__(self, data): - header = struct.unpack('<4sIIBBBBB', data[:17]) + header = struct.unpack('<4sIIBBBBH', data[:18]) self.magic, \ self.hdrlen, \ self.expiry, \ @@ -189,7 +189,7 @@ class VendorHeader(object): print(' * expiry :', self.expiry) print(' * version : %d.%d' % (self.vmajor, self.vminor)) print(' * scheme : %d out of %d' % (self.vsig_m, self.vsig_n)) - print(' * trust :', self.vtrust) + print(' * trust :', self.vtrust, '=', bin(self.vtrust)) for i in range(self.vsig_n): print(' * vpub #%d :' % (i + 1), binascii.hexlify(self.vpub[i]).decode()) print(' * vstr :', self.vstr.decode()) @@ -199,11 +199,11 @@ class VendorHeader(object): print() def serialize_header(self, sig=True): - header = struct.pack('<4sIIBBBBB', + header = struct.pack('<4sIIBBBBH', self.magic, self.hdrlen, self.expiry, self.vmajor, self.vminor, self.vsig_m, self.vsig_n, self.vtrust) - header += 15 * b'\x00' + header += 14 * b'\x00' for i in range(self.vsig_n): header += self.vpub[i] header += struct.pack('