mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-11 16:00:57 +00:00
trezorhal: increase image header size from 512 to 1024 bytes
This commit is contained in:
parent
0c6ee14ee1
commit
3c974095aa
@ -67,7 +67,7 @@ TREZOR Core (second stage) bootloader consists of 2 parts:
|
||||
|
||||
### Bootloader Header
|
||||
|
||||
Total length of bootloader header is always 512 bytes.
|
||||
Total length of bootloader header is always 1024 bytes.
|
||||
|
||||
| offset | length | name | description |
|
||||
|-------:|-------:|------|-------------|
|
||||
@ -79,9 +79,9 @@ Total length of bootloader header is always 512 bytes.
|
||||
| 0x0011 | 1 | vminor | version (minor) |
|
||||
| 0x0012 | 1 | vpatch | version (patch) |
|
||||
| 0x0013 | 1 | vbuild | version (build) |
|
||||
| 0x0014 | 427 | reserved | not used yet (zeroed) |
|
||||
| 0x01BF | 1 | sigmask | SatoshiLabs signature indexes (bitmap) |
|
||||
| 0x01C0 | 64 | sig | SatoshiLabs aggregated signature |
|
||||
| 0x0014 | 939 | reserved | not used yet (zeroed) |
|
||||
| 0x03BF | 1 | sigmask | SatoshiLabs signature indexes (bitmap) |
|
||||
| 0x03C0 | 64 | sig | SatoshiLabs aggregated signature |
|
||||
|
||||
## Firmware Format
|
||||
|
||||
@ -122,7 +122,7 @@ of 512 bytes.
|
||||
|
||||
### Firmware Header
|
||||
|
||||
Total length of firmware header is always 512 bytes.
|
||||
Total length of firmware header is always 1024 bytes.
|
||||
|
||||
| offset | length | name | description |
|
||||
|-------:|-------:|------|-------------|
|
||||
@ -134,9 +134,10 @@ Total length of firmware header is always 512 bytes.
|
||||
| 0x0011 | 1 | vminor | version (minor) |
|
||||
| 0x0012 | 1 | vpatch | version (patch) |
|
||||
| 0x0013 | 1 | vbuild | version (build) |
|
||||
| 0x0014 | 427 | reserved | not used yet (zeroed) |
|
||||
| 0x01BF | 1 | sigmask | vendor signature indexes (bitmap) |
|
||||
| 0x01C0 | 64 | sig | vendor aggregated signature |
|
||||
| 0x0014 | 939 | reserved | not used yet (zeroed) |
|
||||
| 0x03BF | 1 | sigmask | vendor signature indexes (bitmap) |
|
||||
| 0x03C0 | 64 | sig | vendor aggregated signature |
|
||||
|
||||
|
||||
## Various ideas
|
||||
|
||||
|
@ -16,7 +16,7 @@ g_header:
|
||||
.byte VERSION_MINOR // vminor
|
||||
.byte VERSION_PATCH // vpatch
|
||||
.byte VERSION_BUILD // vbuild
|
||||
. = . + 427 // reserved
|
||||
. = . + 939 // reserved
|
||||
.byte 0 // sigmask
|
||||
. = . + 64 // sig
|
||||
g_header_end:
|
||||
|
@ -16,7 +16,7 @@ g_header:
|
||||
.byte VERSION_MINOR // vminor
|
||||
.byte VERSION_PATCH // vpatch
|
||||
.byte VERSION_BUILD // vbuild
|
||||
. = . + 427 // reserved
|
||||
. = . + 939 // reserved
|
||||
.byte 0 // sigmask
|
||||
. = . + 64 // sig
|
||||
g_header_end:
|
||||
|
@ -49,11 +49,11 @@ bool image_parse_header(const uint8_t * const data, const uint32_t magic, const
|
||||
|
||||
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;
|
||||
}
|
||||
@ -63,8 +63,8 @@ bool image_check_signature(const uint8_t *data, const image_header *hdr, uint8_t
|
||||
uint8_t hash[BLAKE2S_DIGEST_LENGTH];
|
||||
BLAKE2S_CTX ctx;
|
||||
blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH);
|
||||
blake2s_Update(&ctx, data, IMAGE_HEADER_SIZE - 65);
|
||||
for (int i = 0; i < 65; i++) {
|
||||
blake2s_Update(&ctx, data, IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE);
|
||||
for (int i = 0; i < IMAGE_SIG_SIZE; i++) {
|
||||
blake2s_Update(&ctx, (const uint8_t *)"\x00", 1);
|
||||
}
|
||||
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
|
||||
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;
|
||||
}
|
||||
@ -126,8 +126,8 @@ bool vendor_check_signature(const uint8_t *data, const vendor_header *vhdr, uint
|
||||
uint8_t hash[BLAKE2S_DIGEST_LENGTH];
|
||||
BLAKE2S_CTX ctx;
|
||||
blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH);
|
||||
blake2s_Update(&ctx, data, vhdr->hdrlen - 65);
|
||||
for (int i = 0; i < 65; i++) {
|
||||
blake2s_Update(&ctx, data, vhdr->hdrlen - IMAGE_SIG_SIZE);
|
||||
for (int i = 0; i < IMAGE_SIG_SIZE; i++) {
|
||||
blake2s_Update(&ctx, (const uint8_t *)"\x00", 1);
|
||||
}
|
||||
blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH);
|
||||
|
@ -7,7 +7,8 @@
|
||||
#define BOARDLOADER_START 0x08000000
|
||||
#define BOOTLOADER_START 0x08020000
|
||||
#define FIRMWARE_START 0x08040000
|
||||
#define IMAGE_HEADER_SIZE 0x200
|
||||
#define IMAGE_HEADER_SIZE 0x400
|
||||
#define IMAGE_SIG_SIZE 65
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
@ -15,7 +16,7 @@ typedef struct {
|
||||
uint32_t expiry;
|
||||
uint32_t codelen;
|
||||
uint32_t version;
|
||||
// uint8_t reserved[427];
|
||||
// uint8_t reserved[939];
|
||||
uint8_t sigmask;
|
||||
uint8_t sig[64];
|
||||
} image_header;
|
||||
@ -30,7 +31,7 @@ typedef struct {
|
||||
uint8_t vsig_m;
|
||||
uint8_t vsig_n;
|
||||
uint8_t vtrust;
|
||||
// uint8_t reserved[16];
|
||||
// uint8_t reserved[15];
|
||||
const uint8_t *vpub[MAX_VENDOR_PUBLIC_KEYS];
|
||||
uint8_t vstr_len;
|
||||
const uint8_t *vstr;
|
||||
|
23
tools/binctl
23
tools/binctl
@ -18,11 +18,14 @@ def format_sigmask(sigmask):
|
||||
|
||||
# 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):
|
||||
|
||||
def __init__(self, data, magic, max_size):
|
||||
header = struct.unpack('<4sIIIBBBB427sB64s', data[:512])
|
||||
header = struct.unpack('<4sIIIBBBB939sB64s', data[:IMAGE_HEADER_SIZE])
|
||||
self.magic, \
|
||||
self.hdrlen, \
|
||||
self.expiry, \
|
||||
@ -35,12 +38,12 @@ class BinImage(object):
|
||||
self.sigmask, \
|
||||
self.sig = header
|
||||
assert self.magic == magic
|
||||
assert self.hdrlen == 512
|
||||
assert self.hdrlen == IMAGE_HEADER_SIZE
|
||||
total_len = self.hdrlen + self.codelen
|
||||
assert total_len % 512 == 0
|
||||
assert total_len >= 4 * 1024
|
||||
assert total_len <= max_size
|
||||
assert self.reserved == 427 * b'\x00'
|
||||
assert self.reserved == 939 * b'\x00'
|
||||
self.code = data[self.hdrlen:]
|
||||
assert len(self.code) == self.codelen
|
||||
|
||||
@ -64,14 +67,14 @@ class BinImage(object):
|
||||
print()
|
||||
|
||||
def serialize_header(self, sig=True):
|
||||
header = struct.pack('<4sIIIBBBB427s',
|
||||
header = struct.pack('<4sIIIBBBB939s',
|
||||
self.magic, self.hdrlen, self.expiry, self.codelen,
|
||||
self.vmajor, self.vminor, self.vpatch, self.vbuild,
|
||||
self.reserved)
|
||||
if sig:
|
||||
header += struct.pack('<B64s', self.sigmask, self.sig)
|
||||
else:
|
||||
header += 65 * b'\x00'
|
||||
header += IMAGE_SIG_SIZE * b'\x00'
|
||||
assert len(header) == self.hdrlen
|
||||
return header
|
||||
|
||||
@ -134,7 +137,7 @@ class VendorHeader(object):
|
||||
p += self.vstr_len
|
||||
vstr_pad = -p & 3
|
||||
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]
|
||||
p += self.vimg_len
|
||||
self.sigmask = data[p]
|
||||
@ -144,7 +147,7 @@ class VendorHeader(object):
|
||||
32 * len(self.vpub) + \
|
||||
1 + self.vstr_len + vstr_pad + \
|
||||
self.vimg_len + \
|
||||
1 + 64
|
||||
IMAGE_SIG_SIZE
|
||||
|
||||
def print(self):
|
||||
print('TREZOR Vendor Header')
|
||||
@ -176,7 +179,7 @@ class VendorHeader(object):
|
||||
if sig:
|
||||
header += struct.pack('<B64s', self.sigmask, self.sig)
|
||||
else:
|
||||
header += 65 * b'\x00'
|
||||
header += IMAGE_SIG_SIZE * b'\x00'
|
||||
assert len(header) == self.hdrlen
|
||||
return header
|
||||
|
||||
@ -212,7 +215,7 @@ def binopen(filename):
|
||||
pk = [vheader.vpub[i] for i in range(8) if firmware.sigmask & (1 << i)]
|
||||
global_pk = ed25519cosi.combine_keys(pk)
|
||||
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()
|
||||
try:
|
||||
ed25519raw.checkvalid(firmware.sig, digest, global_pk)
|
||||
@ -220,7 +223,7 @@ def binopen(filename):
|
||||
except:
|
||||
print('Firmware signature INCORRECT')
|
||||
else:
|
||||
print('No firmware signature')
|
||||
print('No firmware signature')
|
||||
return firmware
|
||||
if magic == b'TRZF':
|
||||
return FirmwareImage(data, 0)
|
||||
|
Loading…
Reference in New Issue
Block a user