add vendor trust to vendorheader

This commit is contained in:
Pavol Rusnak 2017-10-05 17:31:05 +02:00
parent 1d9b907342
commit 78f57d083c
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
9 changed files with 41 additions and 20 deletions

View File

@ -149,11 +149,11 @@ gdb_firmware: $(FIRMWARE_BUILD_DIR)/firmware.elf ## start remote gdb session to
## misc commands: ## misc commands:
vendorheader: ## construct default vendor header vendorheader: ## construct default vendor header
./tools/build_vendorheader 'e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351:d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869:772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef' 2 0.0 DEVELOPMENT assets/vendor_devel.toif embed/firmware/vendorheader.bin ./tools/build_vendorheader e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351:d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869:772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef 2 0.0 10 DEVELOPMENT assets/vendor_devel.toif embed/firmware/vendorheader.bin
./tools/binctl embed/firmware/vendorheader.bin -s 1:2 4444444444444444444444444444444444444444444444444444444444444444:4545454545454545454545454545454545454545454545454545454545454545 ./tools/binctl embed/firmware/vendorheader.bin -s 1:2 4444444444444444444444444444444444444444444444444444444444444444:4545454545454545454545454545454545454545454545454545454545454545
vendorheader_sl: ## construct SatoshiLabs vendor header vendorheader_sl: ## construct SatoshiLabs vendor header
./tools/build_vendorheader '47fbdc84d8abef44fe6abde8f87b6ead821b7082ec63b9f7cc33dc53bf6c708d:03fdd9a9c3911652d5effca4540d96ed92d85850a47d256ab0a2d728c0d1a298:2218c25f8ba70c82eba8ed6a321df209c0a7643d014f33bf9317846f62923830' 2 0.0 SatoshiLabs assets/vendor_satoshilabs.toif embed/firmware/vendorheader_sl.bin ./tools/build_vendorheader 47fbdc84d8abef44fe6abde8f87b6ead821b7082ec63b9f7cc33dc53bf6c708d:03fdd9a9c3911652d5effca4540d96ed92d85850a47d256ab0a2d728c0d1a298:2218c25f8ba70c82eba8ed6a321df209c0a7643d014f33bf9317846f62923830 2 0.0 80 SatoshiLabs assets/vendor_satoshilabs.toif embed/firmware/vendorheader_sl.bin
./tools/binctl embed/firmware/vendorheader_sl.bin -s 1:2 trezor:trezor ./tools/binctl embed/firmware/vendorheader_sl.bin -s 1:2 trezor:trezor
binctl: ## print info about binary files binctl: ## print info about binary files

View File

@ -82,14 +82,16 @@ of 512 bytes.
| 0x000D | 1 | vminor | version (minor) | | 0x000D | 1 | vminor | version (minor) |
| 0x000E | 1 | vsig_m | number of signatures needed to run the firmware from this vendor | | 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 | | 0x000F | 1 | vsig_n | number of different pubkeys vendor provides for signing |
| 0x0010 | 32 | vpub1 | vendor pubkey 1 | | 0x0010 | 1 | vtrust | level of vendor trust (0-100) |
| 0x0011 | 15 | reserved | not used yet (zeroed) |
| 0x0020 | 32 | vpub1 | vendor pubkey 1 |
| ... | ... | ... | ... | | ... | ... | ... | ... |
| ? | 32 | vpubn | vendor pubkey n | | ? | 32 | vpubn | vendor pubkey n |
| ? | 1 | vstr_len | vendor string length | | ? | 1 | vstr_len | vendor string length |
| ? | ? | vstr | vendor string | | ? | ? | vstr | vendor string |
| ? | ? | vstrpad | padding to a multiple of 4 bytes | | ? | ? | vstrpad | padding to a multiple of 4 bytes |
| ? | ? | vimg | vendor image (in [TOIf format](toif.md)) | | ? | ? | vimg | vendor image (in [TOIf format](toif.md)) |
| ? | ? | reserved | padding to an address that is -65 modulo 512 | | ? | ? | reserved | padding to an address that is -65 modulo 512 (zeroed) |
| ? | 1 | sigmask | SatoshiLabs signature indexes (bitmap) | | ? | 1 | sigmask | SatoshiLabs signature indexes (bitmap) |
| ? | 64 | sig | SatoshiLabs aggregated signature | | ? | 64 | sig | SatoshiLabs aggregated signature |

View File

@ -92,7 +92,11 @@ void check_and_jump(void)
display_printf("valid firmware signature\n"); display_printf("valid firmware signature\n");
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);
touch_click(); if (vhdr.vtrust < 50) {
touch_click();
} else {
hal_delay(1000);
}
jump_to(FIRMWARE_START + vhdr.hdrlen + HEADER_SIZE); jump_to(FIRMWARE_START + vhdr.hdrlen + HEADER_SIZE);
} else { } else {

View File

@ -71,3 +71,8 @@ void jump_to(uint32_t start)
__asm__ volatile("msr msp, %0"::"g" (*(volatile uint32_t *)start)); __asm__ volatile("msr msp, %0"::"g" (*(volatile uint32_t *)start));
(*(void (**)())(start + 4))(); (*(void (**)())(start + 4))();
} }
void hal_delay(uint32_t ms)
{
HAL_Delay(ms);
}

View File

@ -16,4 +16,6 @@ void __attribute__((noreturn)) nlr_jump_fail(void *val);
void jump_to(uint32_t address); void jump_to(uint32_t address);
void hal_delay(uint32_t ms);
#endif #endif

View File

@ -98,23 +98,24 @@ bool vendor_parse_header(const uint8_t *data, vendor_header *vhdr)
memcpy(&vhdr->vsig_m, data + 14, 1); memcpy(&vhdr->vsig_m, data + 14, 1);
memcpy(&vhdr->vsig_n, data + 15, 1); memcpy(&vhdr->vsig_n, data + 15, 1);
memcpy(&vhdr->vtrust, data + 16, 1);
if (vhdr->vsig_n > MAX_VENDOR_PUBLIC_KEYS) { if (vhdr->vsig_n > MAX_VENDOR_PUBLIC_KEYS) {
return false; return false;
} }
for (int i = 0; i < vhdr->vsig_n; i++) { for (int i = 0; i < vhdr->vsig_n; i++) {
vhdr->vpub[i] = data + 16 + i * 32; vhdr->vpub[i] = data + 32 + i * 32;
} }
for (int i = vhdr->vsig_n; i < MAX_VENDOR_PUBLIC_KEYS; i++) { for (int i = vhdr->vsig_n; i < MAX_VENDOR_PUBLIC_KEYS; i++) {
vhdr->vpub[i] = 0; vhdr->vpub[i] = 0;
} }
memcpy(&vhdr->vstr_len, data + 16 + vhdr->vsig_n * 32, 1); memcpy(&vhdr->vstr_len, data + 32 + vhdr->vsig_n * 32, 1);
vhdr->vstr = data + 16 + vhdr->vsig_n * 32 + 1; vhdr->vstr = data + 32 + vhdr->vsig_n * 32 + 1;
vhdr->vimg = data + 16 + vhdr->vsig_n * 32 + 1 + vhdr->vstr_len; vhdr->vimg = data + 32 + vhdr->vsig_n * 32 + 1 + vhdr->vstr_len;
// align to 4 bytes // align to 4 bytes
vhdr->vimg += (-(uintptr_t)vhdr->vimg) & 3; vhdr->vimg += (-(uintptr_t)vhdr->vimg) & 3;

View File

@ -24,6 +24,8 @@ typedef struct {
uint16_t version; uint16_t version;
uint8_t vsig_m; uint8_t vsig_m;
uint8_t vsig_n; uint8_t vsig_n;
uint8_t vtrust;
// uint8_t reserved[16];
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

@ -172,18 +172,19 @@ class BootloaderImage(BinImage):
class VendorHeader(object): class VendorHeader(object):
def __init__(self, data): def __init__(self, data):
header = struct.unpack('<4sIIBBBB', data[:16]) header = struct.unpack('<4sIIBBBBB', data[:17])
self.magic, \ self.magic, \
self.hdrlen, \ self.hdrlen, \
self.expiry, \ self.expiry, \
self.vmajor, \ self.vmajor, \
self.vminor, \ self.vminor, \
self.vsig_m, \ self.vsig_m, \
self.vsig_n = header self.vsig_n, \
self.vtrust = header
assert self.magic == b'TRZV' assert self.magic == b'TRZV'
assert self.vsig_m > 0 and self.vsig_m <= self.vsig_n assert self.vsig_m > 0 and self.vsig_m <= self.vsig_n
assert self.vsig_n > 0 and self.vsig_n <= 8 assert self.vsig_n > 0 and self.vsig_n <= 8
p = 16 p = 32
self.vpub = [] self.vpub = []
for _ in range(self.vsig_n): for _ in range(self.vsig_n):
self.vpub.append(data[p:p + 32]) self.vpub.append(data[p:p + 32])
@ -200,7 +201,7 @@ class VendorHeader(object):
self.sigmask = data[p] self.sigmask = data[p]
p += 1 p += 1
self.sig = data[p:p + 64] self.sig = data[p:p + 64]
assert len(data) == 4 + 4 + 4 + 1 + 1 + 1 + 1 + \ assert len(data) == 4 + 4 + 4 + 1 + 1 + 1 + 1 + 1 + 15 + \
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 + \
@ -213,6 +214,7 @@ class VendorHeader(object):
print(' * expiry :', self.expiry) print(' * expiry :', self.expiry)
print(' * version : %d.%d' % (self.vmajor, self.vminor)) print(' * version : %d.%d' % (self.vmajor, self.vminor))
print(' * scheme : %d out of %d' % (self.vsig_m, self.vsig_n)) print(' * scheme : %d out of %d' % (self.vsig_m, self.vsig_n))
print(' * trust :', self.vtrust)
for i in range(self.vsig_n): for i in range(self.vsig_n):
print(' * vpub #%d :' % (i + 1), binascii.hexlify(self.vpub[i]).decode('ascii')) print(' * vpub #%d :' % (i + 1), binascii.hexlify(self.vpub[i]).decode('ascii'))
print(' * vstr :', self.vstr.decode('ascii')) print(' * vstr :', self.vstr.decode('ascii'))
@ -221,10 +223,11 @@ class VendorHeader(object):
print(' * sig :', binascii.hexlify(self.sig).decode('ascii')) print(' * sig :', binascii.hexlify(self.sig).decode('ascii'))
def serialize_header(self, sig=True): def serialize_header(self, sig=True):
header = struct.pack('<4sIIBBBB', header = struct.pack('<4sIIBBBBB',
self.magic, self.hdrlen, self.expiry, self.magic, self.hdrlen, self.expiry,
self.vmajor, self.vminor, self.vmajor, self.vminor,
self.vsig_m, self.vsig_n) self.vsig_m, self.vsig_n, self.vtrust)
header += 15 * b'\x00'
for i in range(self.vsig_n): for i in range(self.vsig_n):
header += self.vpub[i] header += self.vpub[i]
header += struct.pack('<B', self.vstr_len) + self.vstr header += struct.pack('<B', self.vstr_len) + self.vstr

View File

@ -21,22 +21,24 @@ def encode_pubkey(pubkey):
def main(): def main():
if len(sys.argv) < 7: if len(sys.argv) < 7:
print('Usage build_vendorheader "pubkey1hex:pubkey2hex:..." m version vendorname vendorimage.toif vendorheader.bin') print('Usage build_vendorheader "pubkey1hex:pubkey2hex:..." m version vendortrust vendorname vendorimage.toif vendorheader.bin')
return 1 return 1
keys = [encode_pubkey(x) for x in sys.argv[1].split(':')] keys = [encode_pubkey(x) for x in sys.argv[1].split(':')]
m = int(sys.argv[2]) m = int(sys.argv[2])
(vmajor, vminor) = [int(x) for x in sys.argv[3].split('.')] (vmajor, vminor) = [int(x) for x in sys.argv[3].split('.')]
vname = sys.argv[4] vtrust = int(sys.argv[4])
ifn = sys.argv[5] vname = sys.argv[5]
ofn = sys.argv[6] ifn = sys.argv[6]
ofn = sys.argv[7]
if not ifn.endswith('.toif'): if not ifn.endswith('.toif'):
print('Must provide TOIF file') print('Must provide TOIF file')
return 2 return 2
expiry = 0 expiry = 0
vheader = b'TRZV' + \ vheader = b'TRZV' + \
struct.pack('<IIBBBB', 0, expiry, vmajor, vminor, m, len(keys)) struct.pack('<IIBBBBB', 0, expiry, vmajor, vminor, m, len(keys), vtrust)
vheader += 15 * b'\0'
for k in keys: for k in keys:
vheader += k vheader += k
vheader += encode_vendor(vname) + open(ifn, 'rb').read() vheader += encode_vendor(vname) + open(ifn, 'rb').read()