#!/usr/bin/env python3 import sys import struct import binascii import ed25519 import pyblake2 def get_sig(data): if False: print('Enter index : ', end='') idx = int(input()) print('Enter privkey : ', end='') seckey = binascii.unhexlify(input()) else: idx = 1 seckey = binascii.unhexlify('4141414141414141414141414141414141414141414141414141414141414141') signkey = ed25519.SigningKey(seckey) digest = pyblake2.blake2s(data).digest() sigmask = 1 << (idx - 1) sig = signkey.sign(digest) return sigmask, sig # loader/firmware headers specification: https://github.com/trezor/trezor-core/blob/master/docs/bootloader.md class BinImage: def __init__(self, data, magic, max_size): header = struct.unpack('<4sIIIBBBB427sB64s', data[:512]) self.magic, \ self.hdrlen, \ self.expiry, \ self.codelen, \ self.vmajor, \ self.vminor, \ self.vpatch, \ self.vbuild, \ self.reserved, \ self.sigmask, \ self.sig = header assert self.magic == magic assert self.hdrlen == 512 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' self.code = data[self.hdrlen:] assert len(self.code) == self.codelen def print(self): if self.magic == b'TRZF': print('TREZOR Firmware Image') total_len = self.vhdrlen + self.hdrlen + self.codelen elif self.magic == b'TRZL': print('TREZOR Loader Image') total_len = self.hdrlen + self.codelen else: print('TREZOR Unknown 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(' * sigmask :', self.sigmask) print(' * sig :', binascii.hexlify(self.sig).decode('ascii')) print(' * total : %d bytes' % total_len) print() def serialize_header(self, sig=True): header = struct.pack('<4sIIIBBBB427s', \ self.magic, self.hdrlen, self.expiry, self.codelen, \ self.vmajor, self.vminor, self.vpatch, self.vbuild, \ self.reserved) if sig: 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 vstr_pad = -p & 3 p += vstr_pad self.vimg_len = len(data) - 65 - p self.vimg = data[p:p + self.vimg_len] p += self.vimg_len self.sigmask = data[p] p += 1 self.sig = data[p:p+64] assert len(data) == 4 + 4 + 4 + 1 + 1 + 1 + 1 + \ 32 * len(self.vpub) + \ 1 + self.vstr_len + vstr_pad + \ self.vimg_len + \ 1 + 64 def print(self): print('TREZOR Vendor Header') print(' * magic :', self.magic.decode('ascii')) print(' * hdrlen :', self.hdrlen) print(' * expiry :', self.expiry) print(' * version : %d.%d' % (self.vmajor, self.vminor)) print(' * scheme : %d out of %d' % (self.vsig_m, self.vsig_n)) for i in range(self.vsig_n): print(' * vpub #%d :' % (i + 1), binascii.hexlify(self.vpub[i]).decode('ascii')) print(' * vstr :', self.vstr.decode('ascii')) print(' * vimg : (%d bytes)' % len(self.vimg)) print(' * sigmask :', self.sigmask) print(' * sig :', binascii.hexlify(self.sig).decode('ascii')) def serialize_header(self, sig=True): header = struct.pack('<4sIIBBBB', \ self.magic, self.hdrlen, self.expiry, \ self.vmajor, self.vminor, \ self.vsig_m, self.vsig_n) for i in range(self.vsig_n): header += self.vpub[i] header += struct.pack(' 2 and sys.argv[2] == '-s' b = binopen(fn) if sign: b.sign() print() b.print() b.write(fn) else: b.print() if __name__ == '__main__': main()