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:
parent
0c6ee14ee1
commit
3c974095aa
@ -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
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
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
|
# 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)
|
||||||
|
Loading…
Reference in New Issue
Block a user