1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-04 13:52:35 +00:00

trezorhal: increase image header size from 512 to 1024 bytes

This commit is contained in:
Pavol Rusnak 2017-10-26 02:09:06 +02:00
parent 0c6ee14ee1
commit 3c974095aa
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
6 changed files with 38 additions and 33 deletions

View File

@ -67,7 +67,7 @@ TREZOR Core (second stage) bootloader consists of 2 parts:
### Bootloader Header ### Bootloader Header
Total length of bootloader header is always 512 bytes. Total length of bootloader header is always 1024 bytes.
| offset | length | name | description | | offset | length | name | description |
|-------:|-------:|------|-------------| |-------:|-------:|------|-------------|
@ -79,9 +79,9 @@ Total length of bootloader header is always 512 bytes.
| 0x0011 | 1 | vminor | version (minor) | | 0x0011 | 1 | vminor | version (minor) |
| 0x0012 | 1 | vpatch | version (patch) | | 0x0012 | 1 | vpatch | version (patch) |
| 0x0013 | 1 | vbuild | version (build) | | 0x0013 | 1 | vbuild | version (build) |
| 0x0014 | 427 | reserved | not used yet (zeroed) | | 0x0014 | 939 | reserved | not used yet (zeroed) |
| 0x01BF | 1 | sigmask | SatoshiLabs signature indexes (bitmap) | | 0x03BF | 1 | sigmask | SatoshiLabs signature indexes (bitmap) |
| 0x01C0 | 64 | sig | SatoshiLabs aggregated signature | | 0x03C0 | 64 | sig | SatoshiLabs aggregated signature |
## Firmware Format ## Firmware Format
@ -122,7 +122,7 @@ of 512 bytes.
### Firmware Header ### Firmware Header
Total length of firmware header is always 512 bytes. Total length of firmware header is always 1024 bytes.
| offset | length | name | description | | offset | length | name | description |
|-------:|-------:|------|-------------| |-------:|-------:|------|-------------|
@ -134,9 +134,10 @@ Total length of firmware header is always 512 bytes.
| 0x0011 | 1 | vminor | version (minor) | | 0x0011 | 1 | vminor | version (minor) |
| 0x0012 | 1 | vpatch | version (patch) | | 0x0012 | 1 | vpatch | version (patch) |
| 0x0013 | 1 | vbuild | version (build) | | 0x0013 | 1 | vbuild | version (build) |
| 0x0014 | 427 | reserved | not used yet (zeroed) | | 0x0014 | 939 | reserved | not used yet (zeroed) |
| 0x01BF | 1 | sigmask | vendor signature indexes (bitmap) | | 0x03BF | 1 | sigmask | vendor signature indexes (bitmap) |
| 0x01C0 | 64 | sig | vendor aggregated signature | | 0x03C0 | 64 | sig | vendor aggregated signature |
## Various ideas ## Various ideas

View File

@ -16,7 +16,7 @@ g_header:
.byte VERSION_MINOR // vminor .byte VERSION_MINOR // vminor
.byte VERSION_PATCH // vpatch .byte VERSION_PATCH // vpatch
.byte VERSION_BUILD // vbuild .byte VERSION_BUILD // vbuild
. = . + 427 // reserved . = . + 939 // reserved
.byte 0 // sigmask .byte 0 // sigmask
. = . + 64 // sig . = . + 64 // sig
g_header_end: g_header_end:

View File

@ -16,7 +16,7 @@ g_header:
.byte VERSION_MINOR // vminor .byte VERSION_MINOR // vminor
.byte VERSION_PATCH // vpatch .byte VERSION_PATCH // vpatch
.byte VERSION_BUILD // vbuild .byte VERSION_BUILD // vbuild
. = . + 427 // reserved . = . + 939 // reserved
.byte 0 // sigmask .byte 0 // sigmask
. = . + 64 // sig . = . + 64 // sig
g_header_end: g_header_end:

View File

@ -49,11 +49,11 @@ bool image_parse_header(const uint8_t * const data, const uint32_t magic, const
memcpy(&hdr->version, data + 16, 4); memcpy(&hdr->version, data + 16, 4);
// uint8_t reserved[427]; // uint8_t reserved[939];
memcpy(&hdr->sigmask, data + 0x01BF, 1); memcpy(&hdr->sigmask, data + IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE, 1);
memcpy(hdr->sig, data + 0x01C0, 64); memcpy(hdr->sig, data + IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE + 1, IMAGE_SIG_SIZE - 1);
return true; return true;
} }
@ -63,8 +63,8 @@ bool image_check_signature(const uint8_t *data, const image_header *hdr, uint8_t
uint8_t hash[BLAKE2S_DIGEST_LENGTH]; uint8_t hash[BLAKE2S_DIGEST_LENGTH];
BLAKE2S_CTX ctx; BLAKE2S_CTX ctx;
blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH);
blake2s_Update(&ctx, data, IMAGE_HEADER_SIZE - 65); blake2s_Update(&ctx, data, IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE);
for (int i = 0; i < 65; i++) { for (int i = 0; i < IMAGE_SIG_SIZE; i++) {
blake2s_Update(&ctx, (const uint8_t *)"\x00", 1); blake2s_Update(&ctx, (const uint8_t *)"\x00", 1);
} }
blake2s_Update(&ctx, data + IMAGE_HEADER_SIZE, hdr->codelen); blake2s_Update(&ctx, data + IMAGE_HEADER_SIZE, hdr->codelen);
@ -112,11 +112,11 @@ bool vendor_parse_header(const uint8_t * const data, vendor_header * const vhdr)
// align to 4 bytes // align to 4 bytes
vhdr->vimg += (-(uintptr_t)vhdr->vimg) & 3; vhdr->vimg += (-(uintptr_t)vhdr->vimg) & 3;
// uint8_t reserved[427]; // reserved for padding
memcpy(&vhdr->sigmask, data + vhdr->hdrlen - 65, 1); memcpy(&vhdr->sigmask, data + vhdr->hdrlen - IMAGE_SIG_SIZE, 1);
memcpy(vhdr->sig, data + vhdr->hdrlen - 64, 64); memcpy(vhdr->sig, data + vhdr->hdrlen - IMAGE_SIG_SIZE + 1, IMAGE_SIG_SIZE - 1);
return true; return true;
} }
@ -126,8 +126,8 @@ bool vendor_check_signature(const uint8_t *data, const vendor_header *vhdr, uint
uint8_t hash[BLAKE2S_DIGEST_LENGTH]; uint8_t hash[BLAKE2S_DIGEST_LENGTH];
BLAKE2S_CTX ctx; BLAKE2S_CTX ctx;
blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH);
blake2s_Update(&ctx, data, vhdr->hdrlen - 65); blake2s_Update(&ctx, data, vhdr->hdrlen - IMAGE_SIG_SIZE);
for (int i = 0; i < 65; i++) { for (int i = 0; i < IMAGE_SIG_SIZE; i++) {
blake2s_Update(&ctx, (const uint8_t *)"\x00", 1); blake2s_Update(&ctx, (const uint8_t *)"\x00", 1);
} }
blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH); blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH);

View File

@ -7,7 +7,8 @@
#define BOARDLOADER_START 0x08000000 #define BOARDLOADER_START 0x08000000
#define BOOTLOADER_START 0x08020000 #define BOOTLOADER_START 0x08020000
#define FIRMWARE_START 0x08040000 #define FIRMWARE_START 0x08040000
#define IMAGE_HEADER_SIZE 0x200 #define IMAGE_HEADER_SIZE 0x400
#define IMAGE_SIG_SIZE 65
typedef struct { typedef struct {
uint32_t magic; uint32_t magic;
@ -15,7 +16,7 @@ typedef struct {
uint32_t expiry; uint32_t expiry;
uint32_t codelen; uint32_t codelen;
uint32_t version; uint32_t version;
// uint8_t reserved[427]; // uint8_t reserved[939];
uint8_t sigmask; uint8_t sigmask;
uint8_t sig[64]; uint8_t sig[64];
} image_header; } image_header;
@ -30,7 +31,7 @@ typedef struct {
uint8_t vsig_m; uint8_t vsig_m;
uint8_t vsig_n; uint8_t vsig_n;
uint8_t vtrust; uint8_t vtrust;
// uint8_t reserved[16]; // uint8_t reserved[15];
const uint8_t *vpub[MAX_VENDOR_PUBLIC_KEYS]; const uint8_t *vpub[MAX_VENDOR_PUBLIC_KEYS];
uint8_t vstr_len; uint8_t vstr_len;
const uint8_t *vstr; const uint8_t *vstr;

View File

@ -18,11 +18,14 @@ def format_sigmask(sigmask):
# bootloader/firmware headers specification: https://github.com/trezor/trezor-core/blob/master/docs/bootloader.md # bootloader/firmware headers specification: https://github.com/trezor/trezor-core/blob/master/docs/bootloader.md
IMAGE_HEADER_SIZE = 0x400
IMAGE_SIG_SIZE = 65
class BinImage(object): class BinImage(object):
def __init__(self, data, magic, max_size): def __init__(self, data, magic, max_size):
header = struct.unpack('<4sIIIBBBB427sB64s', data[:512]) header = struct.unpack('<4sIIIBBBB939sB64s', data[:IMAGE_HEADER_SIZE])
self.magic, \ self.magic, \
self.hdrlen, \ self.hdrlen, \
self.expiry, \ self.expiry, \
@ -35,12 +38,12 @@ class BinImage(object):
self.sigmask, \ self.sigmask, \
self.sig = header self.sig = header
assert self.magic == magic assert self.magic == magic
assert self.hdrlen == 512 assert self.hdrlen == IMAGE_HEADER_SIZE
total_len = self.hdrlen + self.codelen total_len = self.hdrlen + self.codelen
assert total_len % 512 == 0 assert total_len % 512 == 0
assert total_len >= 4 * 1024 assert total_len >= 4 * 1024
assert total_len <= max_size assert total_len <= max_size
assert self.reserved == 427 * b'\x00' assert self.reserved == 939 * b'\x00'
self.code = data[self.hdrlen:] self.code = data[self.hdrlen:]
assert len(self.code) == self.codelen assert len(self.code) == self.codelen
@ -64,14 +67,14 @@ class BinImage(object):
print() print()
def serialize_header(self, sig=True): def serialize_header(self, sig=True):
header = struct.pack('<4sIIIBBBB427s', header = struct.pack('<4sIIIBBBB939s',
self.magic, self.hdrlen, self.expiry, self.codelen, self.magic, self.hdrlen, self.expiry, self.codelen,
self.vmajor, self.vminor, self.vpatch, self.vbuild, self.vmajor, self.vminor, self.vpatch, self.vbuild,
self.reserved) self.reserved)
if sig: if sig:
header += struct.pack('<B64s', self.sigmask, self.sig) header += struct.pack('<B64s', self.sigmask, self.sig)
else: else:
header += 65 * b'\x00' header += IMAGE_SIG_SIZE * b'\x00'
assert len(header) == self.hdrlen assert len(header) == self.hdrlen
return header return header
@ -134,7 +137,7 @@ class VendorHeader(object):
p += self.vstr_len p += self.vstr_len
vstr_pad = -p & 3 vstr_pad = -p & 3
p += vstr_pad p += vstr_pad
self.vimg_len = len(data) - 65 - p self.vimg_len = len(data) - IMAGE_SIG_SIZE - p
self.vimg = data[p:p + self.vimg_len] self.vimg = data[p:p + self.vimg_len]
p += self.vimg_len p += self.vimg_len
self.sigmask = data[p] self.sigmask = data[p]
@ -144,7 +147,7 @@ class VendorHeader(object):
32 * len(self.vpub) + \ 32 * len(self.vpub) + \
1 + self.vstr_len + vstr_pad + \ 1 + self.vstr_len + vstr_pad + \
self.vimg_len + \ self.vimg_len + \
1 + 64 IMAGE_SIG_SIZE
def print(self): def print(self):
print('TREZOR Vendor Header') print('TREZOR Vendor Header')
@ -176,7 +179,7 @@ class VendorHeader(object):
if sig: if sig:
header += struct.pack('<B64s', self.sigmask, self.sig) header += struct.pack('<B64s', self.sigmask, self.sig)
else: else:
header += 65 * b'\x00' header += IMAGE_SIG_SIZE * b'\x00'
assert len(header) == self.hdrlen assert len(header) == self.hdrlen
return header return header
@ -212,7 +215,7 @@ def binopen(filename):
pk = [vheader.vpub[i] for i in range(8) if firmware.sigmask & (1 << i)] pk = [vheader.vpub[i] for i in range(8) if firmware.sigmask & (1 << i)]
global_pk = ed25519cosi.combine_keys(pk) global_pk = ed25519cosi.combine_keys(pk)
subdata_nosig = bytearray(subdata) subdata_nosig = bytearray(subdata)
subdata_nosig[512 - 65:512] = 65 * b'\x00' subdata_nosig[IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE:IMAGE_HEADER_SIZE] = IMAGE_SIG_SIZE * b'\x00'
digest = pyblake2.blake2s(subdata_nosig).digest() digest = pyblake2.blake2s(subdata_nosig).digest()
try: try:
ed25519raw.checkvalid(firmware.sig, digest, global_pk) ed25519raw.checkvalid(firmware.sig, digest, global_pk)
@ -220,7 +223,7 @@ def binopen(filename):
except: except:
print('Firmware signature INCORRECT') print('Firmware signature INCORRECT')
else: else:
print('No firmware signature') print('No firmware signature')
return firmware return firmware
if magic == b'TRZF': if magic == b'TRZF':
return FirmwareImage(data, 0) return FirmwareImage(data, 0)