#!/usr/bin/env python3 import sys import struct import binascii import hashlib import ed25519 # bootloader/firmware headers specification: https://github.com/trezor/trezor-core/blob/master/docs/bootloader.md # converts 8-bit bitmap to tuple of values def bitmap_to_tuple(b): return tuple([ i + 1 for i in range(8) if b & (1 << i) ]) # converts tuple of values to 8-bit bitmap def tuple_to_bitmap(t): b = 0 for i in t: if i >= 1 and i <= 8: b |= (1 << (i - 1)) return b def get_sig(data): print('Enter privkey: ', end='') seckey = binascii.unhexlify(input()) signkey = ed25519.SigningKey(seckey) digest = hashlib.sha256(data).digest() sigidx = (1, ) sig = signkey.sign(digest) return sigidx, sig class BootloaderImage: def __init__(self, data): header = struct.unpack('<4sIIIBBBB171sB64s', data[:256]) self.magic, self.hdrlen, self.expiry, self.codelen, \ self.vmajor, self.vminor, self.vpatch, self.vbuild, \ self.reserved, self.sigidx, self.sig = header assert self.magic == b'TRZB' assert self.hdrlen == 256 assert self.codelen == 64*1024 assert self.reserved == 171 * b'\x00' self.sigidx = bitmap_to_tuple(self.sigidx) self.code = data[256:] assert len(self.code) == self.codelen def print(self): print('TREZOR Bootloader Image') print(' * magic :', self.magic.decode('ascii')) print(' * hdrlen :', self.hdrlen) print(' * expiry :', self.expiry) print(' * codelen :', self.codelen) print(' * version : %d.%d.%d.%d' % (self.vmajor, self.vminor, self.vpatch, self.vbuild)) print(' * sigidx :', self.sigidx) print(' * sig :', binascii.hexlify(self.sig).decode('ascii')) def header(self, sig=True): header = struct.pack('<4sIIIBBBB171s', \ self.magic, self.hdrlen, self.expiry, self.codelen, \ self.vmajor, self.vminor, self.vpatch, self.vbuild, \ self.reserved) if sig: sigidx = tuple_to_bitmap(self.sigidx) header += struct.pack(' 0 and self.vsig_m <= self.vsig_n assert self.vsig_n > 0 and self.vsig_n <= 8 p = 16 self.vpub = [] for _ in range(self.vsig_n): self.vpub.append(data[p:p + 32]) p += 32 self.vstr_len = data[p] p += 1 self.vstr = data[p:p + self.vstr_len] p += self.vstr_len self.vimg_len, _ = struct.unpack(' 2 and sys.argv[2] == '-s' b = binopen(fn) b.print() if sign: print() b.sign() print() b.print() b.write(fn) if __name__ == '__main__': main()