mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 15:38:11 +00:00
tools: run black and flake8 on tools/
This commit is contained in:
parent
481bb4ccab
commit
10396777b8
300
tools/binctl
300
tools/binctl
@ -12,107 +12,101 @@ from trezorlib import cosi
|
|||||||
|
|
||||||
|
|
||||||
def format_sigmask(sigmask):
|
def format_sigmask(sigmask):
|
||||||
bits = [str(b + 1) if sigmask & (1 << b) else '.' for b in range(8)]
|
bits = [str(b + 1) if sigmask & (1 << b) else "." for b in range(8)]
|
||||||
return '0x%02x = [%s]' % (sigmask, ' '.join(bits))
|
return "0x%02x = [%s]" % (sigmask, " ".join(bits))
|
||||||
|
|
||||||
|
|
||||||
def format_vtrust(vtrust):
|
def format_vtrust(vtrust):
|
||||||
bits = [str(b) if vtrust & (1 << b) == 0 else '.' for b in range(16)]
|
bits = [str(b) if vtrust & (1 << b) == 0 else "." for b in range(16)]
|
||||||
# see docs/bootloader.md for vtrust constants
|
# see docs/bootloader.md for vtrust constants
|
||||||
desc = ''
|
desc = ""
|
||||||
wait = (vtrust & 0x000F) ^ 0x000F
|
wait = (vtrust & 0x000F) ^ 0x000F
|
||||||
if wait > 0:
|
if wait > 0:
|
||||||
desc = 'WAIT_%d' % wait
|
desc = "WAIT_%d" % wait
|
||||||
if vtrust & 0x0010 == 0:
|
if vtrust & 0x0010 == 0:
|
||||||
desc += ' RED'
|
desc += " RED"
|
||||||
if vtrust & 0x0020 == 0:
|
if vtrust & 0x0020 == 0:
|
||||||
desc += ' CLICK'
|
desc += " CLICK"
|
||||||
if vtrust & 0x0040 == 0:
|
if vtrust & 0x0040 == 0:
|
||||||
desc += ' STRING'
|
desc += " STRING"
|
||||||
return '%d = [%s] = [%s]' % (vtrust, ' '.join(bits), desc)
|
return "%d = [%s] = [%s]" % (vtrust, " ".join(bits), desc)
|
||||||
|
|
||||||
|
|
||||||
# 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 = 1024
|
IMAGE_HEADER_SIZE = 1024
|
||||||
IMAGE_SIG_SIZE = 65
|
IMAGE_SIG_SIZE = 65
|
||||||
IMAGE_CHUNK_SIZE = 128 * 1024
|
IMAGE_CHUNK_SIZE = 128 * 1024
|
||||||
BOOTLOADER_SECTORS_COUNT = 1
|
BOOTLOADER_SECTORS_COUNT = 1
|
||||||
FIRMWARE_SECTORS_COUNT = 6 + 7
|
FIRMWARE_SECTORS_COUNT = 6 + 7
|
||||||
|
|
||||||
|
|
||||||
class BinImage(object):
|
class BinImage(object):
|
||||||
|
|
||||||
def __init__(self, data, magic, max_size):
|
def __init__(self, data, magic, max_size):
|
||||||
header = struct.unpack('<4sIIIBBBBBBBB8s512s415sB64s', data[:IMAGE_HEADER_SIZE])
|
header = struct.unpack("<4sIIIBBBBBBBB8s512s415sB64s", data[:IMAGE_HEADER_SIZE])
|
||||||
self.magic, \
|
self.magic, self.hdrlen, self.expiry, self.codelen, self.vmajor, self.vminor, self.vpatch, self.vbuild, self.fix_vmajor, self.fix_vminor, self.fix_vpatch, self.fix_vbuild, self.reserved1, self.hashes, self.reserved2, self.sigmask, self.sig = (
|
||||||
self.hdrlen, \
|
header
|
||||||
self.expiry, \
|
)
|
||||||
self.codelen, \
|
|
||||||
self.vmajor, \
|
|
||||||
self.vminor, \
|
|
||||||
self.vpatch, \
|
|
||||||
self.vbuild, \
|
|
||||||
self.fix_vmajor, \
|
|
||||||
self.fix_vminor, \
|
|
||||||
self.fix_vpatch, \
|
|
||||||
self.fix_vbuild, \
|
|
||||||
self.reserved1, \
|
|
||||||
self.hashes, \
|
|
||||||
self.reserved2, \
|
|
||||||
self.sigmask, \
|
|
||||||
self.sig = header
|
|
||||||
assert self.magic == magic
|
assert self.magic == magic
|
||||||
assert self.hdrlen == IMAGE_HEADER_SIZE
|
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.reserved1 == 8 * b'\x00'
|
assert self.reserved1 == 8 * b"\x00"
|
||||||
assert self.reserved2 == 415 * b'\x00'
|
assert self.reserved2 == 415 * b"\x00"
|
||||||
self.code = data[self.hdrlen:]
|
self.code = data[self.hdrlen :]
|
||||||
assert len(self.code) == self.codelen
|
assert len(self.code) == self.codelen
|
||||||
|
|
||||||
def print(self):
|
def print(self):
|
||||||
if self.magic == b'TRZF':
|
if self.magic == b"TRZF":
|
||||||
print('TREZOR Firmware Image')
|
print("TREZOR Firmware Image")
|
||||||
total_len = self.vhdrlen + self.hdrlen + self.codelen
|
total_len = self.vhdrlen + self.hdrlen + self.codelen
|
||||||
elif self.magic == b'TRZB':
|
elif self.magic == b"TRZB":
|
||||||
print('TREZOR Bootloader Image')
|
print("TREZOR Bootloader Image")
|
||||||
total_len = self.hdrlen + self.codelen
|
total_len = self.hdrlen + self.codelen
|
||||||
else:
|
else:
|
||||||
print('TREZOR Unknown Image')
|
print("TREZOR Unknown Image")
|
||||||
print(' * magic :', self.magic.decode())
|
print(" * magic :", self.magic.decode())
|
||||||
print(' * hdrlen :', self.hdrlen)
|
print(" * hdrlen :", self.hdrlen)
|
||||||
print(' * expiry :', self.expiry)
|
print(" * expiry :", self.expiry)
|
||||||
print(' * codelen :', self.codelen)
|
print(" * codelen :", self.codelen)
|
||||||
print(' * version : %d.%d.%d.%d' % (self.vmajor, self.vminor, self.vpatch, self.vbuild))
|
print(
|
||||||
print(' * fixver : %d.%d.%d.%d' % (self.fix_vmajor, self.fix_vminor, self.fix_vpatch, self.fix_vbuild))
|
" * version : %d.%d.%d.%d"
|
||||||
print(' * hashes: %s' % ('OK' if self.check_hashes() else 'INCORRECT'))
|
% (self.vmajor, self.vminor, self.vpatch, self.vbuild)
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
" * fixver : %d.%d.%d.%d"
|
||||||
|
% (self.fix_vmajor, self.fix_vminor, self.fix_vpatch, self.fix_vbuild)
|
||||||
|
)
|
||||||
|
print(" * hashes: %s" % ("OK" if self.check_hashes() else "INCORRECT"))
|
||||||
for i in range(16):
|
for i in range(16):
|
||||||
print(' - %02d : %s' % (i, binascii.hexlify(self.hashes[i * 32:i * 32 + 32]).decode()))
|
print(
|
||||||
print(' * sigmask :', format_sigmask(self.sigmask))
|
" - %02d : %s"
|
||||||
print(' * sig :', binascii.hexlify(self.sig).decode())
|
% (i, binascii.hexlify(self.hashes[i * 32 : i * 32 + 32]).decode())
|
||||||
print(' * total : %d bytes' % total_len)
|
)
|
||||||
print(' * fngprnt :', self.fingerprint())
|
print(" * sigmask :", format_sigmask(self.sigmask))
|
||||||
|
print(" * sig :", binascii.hexlify(self.sig).decode())
|
||||||
|
print(" * total : %d bytes" % total_len)
|
||||||
|
print(" * fngprnt :", self.fingerprint())
|
||||||
print()
|
print()
|
||||||
|
|
||||||
def compute_hashes(self):
|
def compute_hashes(self):
|
||||||
if self.magic == b'TRZF':
|
if self.magic == b"TRZF":
|
||||||
hdrlen = self.vhdrlen + self.hdrlen
|
hdrlen = self.vhdrlen + self.hdrlen
|
||||||
else:
|
else:
|
||||||
hdrlen = self.hdrlen
|
hdrlen = self.hdrlen
|
||||||
hashes = b''
|
hashes = b""
|
||||||
for i in range(16):
|
for i in range(16):
|
||||||
if i == 0:
|
if i == 0:
|
||||||
d = self.code[:IMAGE_CHUNK_SIZE - hdrlen]
|
d = self.code[: IMAGE_CHUNK_SIZE - hdrlen]
|
||||||
else:
|
else:
|
||||||
s = IMAGE_CHUNK_SIZE - hdrlen + (i - 1) * IMAGE_CHUNK_SIZE
|
s = IMAGE_CHUNK_SIZE - hdrlen + (i - 1) * IMAGE_CHUNK_SIZE
|
||||||
d = self.code[s:s + IMAGE_CHUNK_SIZE]
|
d = self.code[s : s + IMAGE_CHUNK_SIZE]
|
||||||
if len(d) > 0:
|
if len(d) > 0:
|
||||||
h = pyblake2.blake2s(d).digest()
|
h = pyblake2.blake2s(d).digest()
|
||||||
else:
|
else:
|
||||||
h = 32 * b'\x00'
|
h = 32 * b"\x00"
|
||||||
hashes += h
|
hashes += h
|
||||||
return hashes
|
return hashes
|
||||||
|
|
||||||
@ -123,15 +117,28 @@ class BinImage(object):
|
|||||||
self.hashes = self.compute_hashes()
|
self.hashes = self.compute_hashes()
|
||||||
|
|
||||||
def serialize_header(self, sig=True):
|
def serialize_header(self, sig=True):
|
||||||
header = struct.pack('<4sIIIBBBBBBBB8s512s415s',
|
header = struct.pack(
|
||||||
self.magic, self.hdrlen, self.expiry, self.codelen,
|
"<4sIIIBBBBBBBB8s512s415s",
|
||||||
self.vmajor, self.vminor, self.vpatch, self.vbuild,
|
self.magic,
|
||||||
self.fix_vmajor, self.fix_vminor, self.fix_vpatch, self.fix_vbuild,
|
self.hdrlen,
|
||||||
self.reserved1, self.hashes, self.reserved2)
|
self.expiry,
|
||||||
|
self.codelen,
|
||||||
|
self.vmajor,
|
||||||
|
self.vminor,
|
||||||
|
self.vpatch,
|
||||||
|
self.vbuild,
|
||||||
|
self.fix_vmajor,
|
||||||
|
self.fix_vminor,
|
||||||
|
self.fix_vpatch,
|
||||||
|
self.fix_vbuild,
|
||||||
|
self.reserved1,
|
||||||
|
self.hashes,
|
||||||
|
self.reserved2,
|
||||||
|
)
|
||||||
if sig:
|
if sig:
|
||||||
header += struct.pack('<B64s', self.sigmask, self.sig)
|
header += struct.pack("<B64s", self.sigmask, self.sig)
|
||||||
else:
|
else:
|
||||||
header += IMAGE_SIG_SIZE * b'\x00'
|
header += IMAGE_SIG_SIZE * b"\x00"
|
||||||
assert len(header) == self.hdrlen
|
assert len(header) == self.hdrlen
|
||||||
return header
|
return header
|
||||||
|
|
||||||
@ -146,104 +153,122 @@ class BinImage(object):
|
|||||||
self.sig = signature
|
self.sig = signature
|
||||||
|
|
||||||
def write(self, filename):
|
def write(self, filename):
|
||||||
with open(filename, 'wb') as f:
|
with open(filename, "wb") as f:
|
||||||
f.write(self.serialize_header())
|
f.write(self.serialize_header())
|
||||||
f.write(self.code)
|
f.write(self.code)
|
||||||
|
|
||||||
|
|
||||||
class FirmwareImage(BinImage):
|
class FirmwareImage(BinImage):
|
||||||
|
|
||||||
def __init__(self, data, vhdrlen):
|
def __init__(self, data, vhdrlen):
|
||||||
super(FirmwareImage, self).__init__(data[vhdrlen:], magic=b'TRZF', max_size=FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE)
|
super(FirmwareImage, self).__init__(
|
||||||
|
data[vhdrlen:],
|
||||||
|
magic=b"TRZF",
|
||||||
|
max_size=FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE,
|
||||||
|
)
|
||||||
self.vhdrlen = vhdrlen
|
self.vhdrlen = vhdrlen
|
||||||
self.vheader = data[:vhdrlen]
|
self.vheader = data[:vhdrlen]
|
||||||
|
|
||||||
def write(self, filename):
|
def write(self, filename):
|
||||||
with open(filename, 'wb') as f:
|
with open(filename, "wb") as f:
|
||||||
f.write(self.vheader)
|
f.write(self.vheader)
|
||||||
f.write(self.serialize_header())
|
f.write(self.serialize_header())
|
||||||
f.write(self.code)
|
f.write(self.code)
|
||||||
|
|
||||||
|
|
||||||
class BootloaderImage(BinImage):
|
class BootloaderImage(BinImage):
|
||||||
|
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
super(BootloaderImage, self).__init__(data, magic=b'TRZB', max_size=BOOTLOADER_SECTORS_COUNT * IMAGE_CHUNK_SIZE)
|
super(BootloaderImage, self).__init__(
|
||||||
|
data, magic=b"TRZB", max_size=BOOTLOADER_SECTORS_COUNT * IMAGE_CHUNK_SIZE
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class VendorHeader(object):
|
class VendorHeader(object):
|
||||||
|
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
header = struct.unpack('<4sIIBBBBH', data[:18])
|
header = struct.unpack("<4sIIBBBBH", data[:18])
|
||||||
self.magic, \
|
self.magic, self.hdrlen, self.expiry, self.vmajor, self.vminor, self.vsig_m, self.vsig_n, self.vtrust = (
|
||||||
self.hdrlen, \
|
header
|
||||||
self.expiry, \
|
)
|
||||||
self.vmajor, \
|
assert self.magic == b"TRZV"
|
||||||
self.vminor, \
|
data = data[: self.hdrlen] # strip remaining data (firmware)
|
||||||
self.vsig_m, \
|
|
||||||
self.vsig_n, \
|
|
||||||
self.vtrust = header
|
|
||||||
assert self.magic == b'TRZV'
|
|
||||||
data = data[:self.hdrlen] # strip remaining data (firmware)
|
|
||||||
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 = 32
|
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])
|
||||||
p += 32
|
p += 32
|
||||||
self.vstr_len = data[p]
|
self.vstr_len = data[p]
|
||||||
p += 1
|
p += 1
|
||||||
self.vstr = data[p:p + self.vstr_len]
|
self.vstr = data[p : p + self.vstr_len]
|
||||||
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) - IMAGE_SIG_SIZE - 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]
|
||||||
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 + 1 + 15 + \
|
assert (
|
||||||
32 * len(self.vpub) + \
|
len(data)
|
||||||
1 + self.vstr_len + vstr_pad + \
|
== 4
|
||||||
self.vimg_len + \
|
+ 4
|
||||||
IMAGE_SIG_SIZE
|
+ 4
|
||||||
|
+ 1
|
||||||
|
+ 1
|
||||||
|
+ 1
|
||||||
|
+ 1
|
||||||
|
+ 1
|
||||||
|
+ 15
|
||||||
|
+ 32 * len(self.vpub)
|
||||||
|
+ 1
|
||||||
|
+ self.vstr_len
|
||||||
|
+ vstr_pad
|
||||||
|
+ self.vimg_len
|
||||||
|
+ IMAGE_SIG_SIZE
|
||||||
|
)
|
||||||
assert len(data) % 512 == 0
|
assert len(data) % 512 == 0
|
||||||
|
|
||||||
def print(self):
|
def print(self):
|
||||||
print('TREZOR Vendor Header')
|
print("TREZOR Vendor Header")
|
||||||
print(' * magic :', self.magic.decode())
|
print(" * magic :", self.magic.decode())
|
||||||
print(' * hdrlen :', self.hdrlen)
|
print(" * hdrlen :", self.hdrlen)
|
||||||
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 :', format_vtrust(self.vtrust))
|
print(" * trust :", format_vtrust(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())
|
print(" * vpub #%d :" % (i + 1), binascii.hexlify(self.vpub[i]).decode())
|
||||||
print(' * vstr :', self.vstr.decode())
|
print(" * vstr :", self.vstr.decode())
|
||||||
print(' * vhash :', binascii.hexlify(self.vhash()).decode())
|
print(" * vhash :", binascii.hexlify(self.vhash()).decode())
|
||||||
print(' * vimg : (%d bytes)' % len(self.vimg))
|
print(" * vimg : (%d bytes)" % len(self.vimg))
|
||||||
print(' * sigmask :', format_sigmask(self.sigmask))
|
print(" * sigmask :", format_sigmask(self.sigmask))
|
||||||
print(' * sig :', binascii.hexlify(self.sig).decode())
|
print(" * sig :", binascii.hexlify(self.sig).decode())
|
||||||
print(' * fngprnt :', self.fingerprint())
|
print(" * fngprnt :", self.fingerprint())
|
||||||
print()
|
print()
|
||||||
|
|
||||||
def serialize_header(self, sig=True):
|
def serialize_header(self, sig=True):
|
||||||
header = struct.pack('<4sIIBBBBH',
|
header = struct.pack(
|
||||||
self.magic, self.hdrlen, self.expiry,
|
"<4sIIBBBBH",
|
||||||
self.vmajor, self.vminor,
|
self.magic,
|
||||||
self.vsig_m, self.vsig_n, self.vtrust)
|
self.hdrlen,
|
||||||
header += 14 * b'\x00'
|
self.expiry,
|
||||||
|
self.vmajor,
|
||||||
|
self.vminor,
|
||||||
|
self.vsig_m,
|
||||||
|
self.vsig_n,
|
||||||
|
self.vtrust,
|
||||||
|
)
|
||||||
|
header += 14 * 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
|
||||||
header += (-len(header) & 3) * b'\x00' # vstr_pad
|
header += (-len(header) & 3) * b"\x00" # vstr_pad
|
||||||
header += self.vimg
|
header += self.vimg
|
||||||
if sig:
|
if sig:
|
||||||
header += struct.pack('<B64s', self.sigmask, self.sig)
|
header += struct.pack("<B64s", self.sigmask, self.sig)
|
||||||
else:
|
else:
|
||||||
header += IMAGE_SIG_SIZE * b'\x00'
|
header += IMAGE_SIG_SIZE * b"\x00"
|
||||||
assert len(header) == self.hdrlen
|
assert len(header) == self.hdrlen
|
||||||
return header
|
return header
|
||||||
|
|
||||||
@ -252,12 +277,12 @@ class VendorHeader(object):
|
|||||||
|
|
||||||
def vhash(self):
|
def vhash(self):
|
||||||
h = pyblake2.blake2s()
|
h = pyblake2.blake2s()
|
||||||
h.update(struct.pack('<BB', self.vsig_m, self.vsig_n))
|
h.update(struct.pack("<BB", self.vsig_m, self.vsig_n))
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
if i < self.vsig_n:
|
if i < self.vsig_n:
|
||||||
h.update(self.vpub[i])
|
h.update(self.vpub[i])
|
||||||
else:
|
else:
|
||||||
h.update(b'\x00' * 32)
|
h.update(b"\x00" * 32)
|
||||||
return h.digest()
|
return h.digest()
|
||||||
|
|
||||||
def sign(self, sigmask, signature):
|
def sign(self, sigmask, signature):
|
||||||
@ -267,54 +292,57 @@ class VendorHeader(object):
|
|||||||
self.sig = signature
|
self.sig = signature
|
||||||
|
|
||||||
def write(self, filename):
|
def write(self, filename):
|
||||||
with open(filename, 'wb') as f:
|
with open(filename, "wb") as f:
|
||||||
f.write(self.serialize_header())
|
f.write(self.serialize_header())
|
||||||
|
|
||||||
|
|
||||||
def binopen(filename):
|
def binopen(filename):
|
||||||
data = open(filename, 'rb').read()
|
data = open(filename, "rb").read()
|
||||||
magic = data[:4]
|
magic = data[:4]
|
||||||
if magic == b'TRZB':
|
if magic == b"TRZB":
|
||||||
return BootloaderImage(data)
|
return BootloaderImage(data)
|
||||||
if magic == b'TRZV':
|
if magic == b"TRZV":
|
||||||
vheader = VendorHeader(data)
|
vheader = VendorHeader(data)
|
||||||
if len(data) == vheader.hdrlen:
|
if len(data) == vheader.hdrlen:
|
||||||
return vheader
|
return vheader
|
||||||
vheader.print()
|
vheader.print()
|
||||||
subdata = data[vheader.hdrlen:]
|
subdata = data[vheader.hdrlen :]
|
||||||
if subdata[:4] == b'TRZF':
|
if subdata[:4] == b"TRZF":
|
||||||
firmware = FirmwareImage(data, vheader.hdrlen)
|
firmware = FirmwareImage(data, vheader.hdrlen)
|
||||||
# check signatures against signing keys in the vendor header
|
# check signatures against signing keys in the vendor header
|
||||||
if firmware.sigmask > 0:
|
if firmware.sigmask > 0:
|
||||||
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 = cosi.combine_keys(pk)
|
global_pk = cosi.combine_keys(pk)
|
||||||
hdr = subdata[:IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE] + IMAGE_SIG_SIZE * b'\x00'
|
hdr = (
|
||||||
|
subdata[: IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE]
|
||||||
|
+ IMAGE_SIG_SIZE * b"\x00"
|
||||||
|
)
|
||||||
digest = pyblake2.blake2s(hdr).digest()
|
digest = pyblake2.blake2s(hdr).digest()
|
||||||
try:
|
try:
|
||||||
cosi.verify(firmware.sig, digest, global_pk)
|
cosi.verify(firmware.sig, digest, global_pk)
|
||||||
print('Firmware signature OK')
|
print("Firmware signature OK")
|
||||||
except:
|
except ValueError:
|
||||||
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)
|
||||||
raise Exception('Unknown file format')
|
raise Exception("Unknown file format")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print('Usage: binctl file.bin [-s sigmask signature] [-h]')
|
print("Usage: binctl file.bin [-s sigmask signature] [-h]")
|
||||||
return 1
|
return 1
|
||||||
fn = sys.argv[1]
|
fn = sys.argv[1]
|
||||||
sign = len(sys.argv) > 2 and sys.argv[2] == '-s'
|
sign = len(sys.argv) > 2 and sys.argv[2] == "-s"
|
||||||
rehash = len(sys.argv) == 3 and sys.argv[2] == '-h'
|
rehash = len(sys.argv) == 3 and sys.argv[2] == "-h"
|
||||||
b = binopen(fn)
|
b = binopen(fn)
|
||||||
if sign:
|
if sign:
|
||||||
sigmask = 0
|
sigmask = 0
|
||||||
if ':' in sys.argv[3]:
|
if ":" in sys.argv[3]:
|
||||||
for idx in sys.argv[3].split(':'):
|
for idx in sys.argv[3].split(":"):
|
||||||
sigmask |= 1 << (int(idx) - 1)
|
sigmask |= 1 << (int(idx) - 1)
|
||||||
else:
|
else:
|
||||||
sigmask = 1 << (int(sys.argv[3]) - 1)
|
sigmask = 1 << (int(sys.argv[3]) - 1)
|
||||||
@ -327,5 +355,5 @@ def main():
|
|||||||
b.print()
|
b.print()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import os
|
import os
|
||||||
|
|
||||||
COMMENT_PREFIX = '/// '
|
COMMENT_PREFIX = "/// "
|
||||||
|
|
||||||
current_indent = 0
|
current_indent = 0
|
||||||
current_class = None
|
current_class = None
|
||||||
@ -14,24 +14,24 @@ def split_to_parts(line, mod_desc=None):
|
|||||||
global current_class
|
global current_class
|
||||||
global current_method
|
global current_method
|
||||||
|
|
||||||
if line.startswith('class '):
|
if line.startswith("class "):
|
||||||
current_class = line[6:].split('(')[0].strip(':')
|
current_class = line[6:].split("(")[0].strip(":")
|
||||||
current_indent = 0
|
current_indent = 0
|
||||||
|
|
||||||
yield (current_package, "\n")
|
yield (current_package, "\n")
|
||||||
yield (current_package, '# ' + mod_desc + "\n")
|
yield (current_package, "# " + mod_desc + "\n")
|
||||||
|
|
||||||
elif line.startswith('def '):
|
elif line.startswith("def "):
|
||||||
current_method = line[4:].split('(')[0]
|
current_method = line[4:].split("(")[0]
|
||||||
|
|
||||||
yield (current_package, "\n")
|
yield (current_package, "\n")
|
||||||
|
|
||||||
if current_class is None:
|
if current_class is None:
|
||||||
yield (current_package, '# ' + mod_desc + "\n")
|
yield (current_package, "# " + mod_desc + "\n")
|
||||||
else:
|
else:
|
||||||
current_indent = 4
|
current_indent = 4
|
||||||
|
|
||||||
line = current_indent * ' ' + line
|
line = current_indent * " " + line
|
||||||
|
|
||||||
yield (current_package, line)
|
yield (current_package, line)
|
||||||
|
|
||||||
@ -43,16 +43,16 @@ def store_to_file(dest, parts):
|
|||||||
|
|
||||||
if not os.path.exists(dirpath):
|
if not os.path.exists(dirpath):
|
||||||
os.makedirs(dirpath)
|
os.makedirs(dirpath)
|
||||||
open(os.path.join(dirpath, '__init__.py'), 'w').close()
|
open(os.path.join(dirpath, "__init__.py"), "w").close()
|
||||||
open(os.path.join(dirpath, '.mock-generated'), 'w').close()
|
open(os.path.join(dirpath, ".mock-generated"), "w").close()
|
||||||
|
|
||||||
filepath = os.path.join(dirpath, filename + '.py')
|
filepath = os.path.join(dirpath, filename + ".py")
|
||||||
|
|
||||||
if not os.path.exists(filepath):
|
if not os.path.exists(filepath):
|
||||||
with open(filepath, 'a') as f:
|
with open(filepath, "a") as f:
|
||||||
f.write('from typing import *\n')
|
f.write("from typing import *\n")
|
||||||
|
|
||||||
with open(filepath, 'a') as f:
|
with open(filepath, "a") as f:
|
||||||
f.write(line)
|
f.write(line)
|
||||||
|
|
||||||
|
|
||||||
@ -61,24 +61,23 @@ def build_module(mod_file, dest):
|
|||||||
global current_class
|
global current_class
|
||||||
global current_package
|
global current_package
|
||||||
|
|
||||||
if not (mod_file.endswith('.h') or mod_file.endswith('.c')):
|
if not (mod_file.endswith(".h") or mod_file.endswith(".c")):
|
||||||
return
|
return
|
||||||
if not os.path.basename(mod_file).startswith('mod'):
|
if not os.path.basename(mod_file).startswith("mod"):
|
||||||
return
|
return
|
||||||
|
|
||||||
current_indent = 0
|
current_indent = 0
|
||||||
current_class = None
|
current_class = None
|
||||||
current_package = os.path.basename(mod_file) \
|
current_package = (
|
||||||
.split('.')[0] \
|
os.path.basename(mod_file).split(".")[0].split("-")[0].replace("mod", "")
|
||||||
.split('-')[0] \
|
)
|
||||||
.replace('mod', '')
|
mod_desc = mod_file.replace("../embed/extmod", "extmod")
|
||||||
mod_desc = mod_file.replace('../embed/extmod', 'extmod')
|
|
||||||
|
|
||||||
for l in open(mod_file):
|
for l in open(mod_file):
|
||||||
if not l.startswith(COMMENT_PREFIX):
|
if not l.startswith(COMMENT_PREFIX):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
l = l[len(COMMENT_PREFIX):] # .strip()
|
l = l[len(COMMENT_PREFIX) :] # .strip()
|
||||||
store_to_file(dest, split_to_parts(l, mod_desc))
|
store_to_file(dest, split_to_parts(l, mod_desc))
|
||||||
|
|
||||||
|
|
||||||
@ -92,7 +91,7 @@ def build_directory(dir, dest):
|
|||||||
def clear_directory(top_dir):
|
def clear_directory(top_dir):
|
||||||
print("Clearing up directory", top_dir)
|
print("Clearing up directory", top_dir)
|
||||||
for root, dirs, files in os.walk(top_dir, topdown=False):
|
for root, dirs, files in os.walk(top_dir, topdown=False):
|
||||||
if '.mock-generated' not in files:
|
if ".mock-generated" not in files:
|
||||||
# print("Not a mock directory", root)
|
# print("Not a mock directory", root)
|
||||||
continue
|
continue
|
||||||
for name in files:
|
for name in files:
|
||||||
@ -108,6 +107,6 @@ def clear_directory(top_dir):
|
|||||||
os.rmdir(root)
|
os.rmdir(root)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
clear_directory('../mocks/generated')
|
clear_directory("../mocks/generated")
|
||||||
build_directory('../embed/extmod', '../mocks/generated')
|
build_directory("../embed/extmod", "../mocks/generated")
|
||||||
|
@ -3,58 +3,62 @@ import sys
|
|||||||
import struct
|
import struct
|
||||||
import binascii
|
import binascii
|
||||||
|
|
||||||
|
|
||||||
# encode vendor name, add length byte and padding to multiple of 4
|
# encode vendor name, add length byte and padding to multiple of 4
|
||||||
def encode_vendor(vname):
|
def encode_vendor(vname):
|
||||||
vbin = vname.encode()
|
vbin = vname.encode()
|
||||||
vbin = struct.pack('<B', len(vbin)) + vbin
|
vbin = struct.pack("<B", len(vbin)) + vbin
|
||||||
vbin += b'\0' * (-len(vbin) & 3)
|
vbin += b"\0" * (-len(vbin) & 3)
|
||||||
return vbin
|
return vbin
|
||||||
|
|
||||||
|
|
||||||
def encode_pubkey(pubkey):
|
def encode_pubkey(pubkey):
|
||||||
if len(pubkey) != 64:
|
if len(pubkey) != 64:
|
||||||
raise Exception('Wrong public key length')
|
raise Exception("Wrong public key length")
|
||||||
return binascii.unhexlify(pubkey)
|
return binascii.unhexlify(pubkey)
|
||||||
|
|
||||||
|
|
||||||
def decode_vtrust(vtrust):
|
def decode_vtrust(vtrust):
|
||||||
t = 0xFFFF
|
t = 0xFFFF
|
||||||
for i, b in enumerate(reversed(vtrust)):
|
for i, b in enumerate(reversed(vtrust)):
|
||||||
if b != '.':
|
if b != ".":
|
||||||
t &= ~(1 << i)
|
t &= ~(1 << i)
|
||||||
return t
|
return t
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) < 7:
|
if len(sys.argv) < 7:
|
||||||
print('Usage build_vendorheader "pubkey1hex:pubkey2hex:..." m version vendortrust 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(".")]
|
||||||
vtrust = decode_vtrust(sys.argv[4])
|
vtrust = decode_vtrust(sys.argv[4])
|
||||||
vname = sys.argv[5]
|
vname = sys.argv[5]
|
||||||
ifn = sys.argv[6]
|
ifn = sys.argv[6]
|
||||||
ofn = sys.argv[7]
|
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(
|
||||||
struct.pack('<IIBBBBH', 0, expiry, vmajor, vminor, m, len(keys), vtrust)
|
"<IIBBBBH", 0, expiry, vmajor, vminor, m, len(keys), vtrust
|
||||||
vheader += 14 * b'\0'
|
)
|
||||||
|
vheader += 14 * 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()
|
||||||
padding = 65 + (-len(vheader) - 65) & 511
|
padding = 65 + (-len(vheader) - 65) & 511
|
||||||
vheader += b'\0' * padding
|
vheader += b"\0" * padding
|
||||||
|
|
||||||
# put in length
|
# put in length
|
||||||
vheader = vheader[0:4] + struct.pack('<I', len(vheader)) + vheader[8:]
|
vheader = vheader[0:4] + struct.pack("<I", len(vheader)) + vheader[8:]
|
||||||
|
|
||||||
with open(ofn, 'wb') as f:
|
with open(ofn, "wb") as f:
|
||||||
f.write(vheader)
|
f.write(vheader)
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,16 +5,19 @@ from hashlib import sha256
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
||||||
REPO = 'certifi/python-certifi'
|
REPO = "certifi/python-certifi"
|
||||||
|
|
||||||
|
|
||||||
def fetch_certdata():
|
def fetch_certdata():
|
||||||
r = requests.get('https://api.github.com/repos/%s/git/refs/heads/master' % REPO)
|
r = requests.get("https://api.github.com/repos/%s/git/refs/heads/master" % REPO)
|
||||||
assert(r.status_code == 200)
|
assert r.status_code == 200
|
||||||
commithash = r.json()['object']['sha']
|
commithash = r.json()["object"]["sha"]
|
||||||
|
|
||||||
r = requests.get('https://raw.githubusercontent.com/%s/%s/certifi/cacert.pem' % (REPO, commithash))
|
r = requests.get(
|
||||||
assert(r.status_code == 200)
|
"https://raw.githubusercontent.com/%s/%s/certifi/cacert.pem"
|
||||||
|
% (REPO, commithash)
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
certdata = r.text
|
certdata = r.text
|
||||||
|
|
||||||
return commithash, certdata
|
return commithash, certdata
|
||||||
@ -22,21 +25,21 @@ def fetch_certdata():
|
|||||||
|
|
||||||
def process_certdata(data):
|
def process_certdata(data):
|
||||||
certs = {}
|
certs = {}
|
||||||
lines = [x.strip() for x in data.split('\n')]
|
lines = [x.strip() for x in data.split("\n")]
|
||||||
label = None
|
label = None
|
||||||
value = None
|
value = None
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if line.startswith('# Label: '):
|
if line.startswith("# Label: "):
|
||||||
assert(label is None)
|
assert label is None
|
||||||
assert(value is None)
|
assert value is None
|
||||||
label = line.split('"')[1]
|
label = line.split('"')[1]
|
||||||
elif line == '-----BEGIN CERTIFICATE-----':
|
elif line == "-----BEGIN CERTIFICATE-----":
|
||||||
assert(label is not None)
|
assert label is not None
|
||||||
assert(value is None)
|
assert value is None
|
||||||
value = ''
|
value = ""
|
||||||
elif line == '-----END CERTIFICATE-----':
|
elif line == "-----END CERTIFICATE-----":
|
||||||
assert(label is not None)
|
assert label is not None
|
||||||
assert(value is not None)
|
assert value is not None
|
||||||
certs[label] = b64decode(value)
|
certs[label] = b64decode(value)
|
||||||
label, value = None, None
|
label, value = None, None
|
||||||
else:
|
else:
|
||||||
@ -49,22 +52,25 @@ def process_certdata(data):
|
|||||||
def main():
|
def main():
|
||||||
commithash, certdata = fetch_certdata()
|
commithash, certdata = fetch_certdata()
|
||||||
|
|
||||||
print('# fetched from https://github.com/%s' % REPO)
|
print("# fetched from https://github.com/%s" % REPO)
|
||||||
print('# commit %s' % commithash)
|
print("# commit %s" % commithash)
|
||||||
|
|
||||||
certs = process_certdata(certdata)
|
certs = process_certdata(certdata)
|
||||||
|
|
||||||
size = sum([len(x) for x in certs.values()])
|
size = sum([len(x) for x in certs.values()])
|
||||||
print('# certs: %d | digests size: %d | total size: %d' % (len(certs), len(certs) * 32, size))
|
print(
|
||||||
|
"# certs: %d | digests size: %d | total size: %d"
|
||||||
|
% (len(certs), len(certs) * 32, size)
|
||||||
|
)
|
||||||
|
|
||||||
print('cert_bundle = [')
|
print("cert_bundle = [")
|
||||||
for k, v in certs.items():
|
for k, v in certs.items():
|
||||||
h = sha256(v)
|
h = sha256(v)
|
||||||
print(' # %s' % k)
|
print(" # %s" % k)
|
||||||
print(' # %s' % h.hexdigest())
|
print(" # %s" % h.hexdigest())
|
||||||
print(' %s,' % h.digest())
|
print(" %s," % h.digest())
|
||||||
print(']')
|
print("]")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -2,43 +2,43 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
fields = [
|
fields = [
|
||||||
'coin_name',
|
"coin_name",
|
||||||
'coin_shortcut',
|
"coin_shortcut",
|
||||||
'address_type',
|
"address_type",
|
||||||
'address_type_p2sh',
|
"address_type_p2sh",
|
||||||
'maxfee_kb',
|
"maxfee_kb",
|
||||||
'signed_message_header',
|
"signed_message_header",
|
||||||
'xpub_magic',
|
"xpub_magic",
|
||||||
'bech32_prefix',
|
"bech32_prefix",
|
||||||
'cashaddr_prefix',
|
"cashaddr_prefix",
|
||||||
'slip44',
|
"slip44",
|
||||||
'segwit',
|
"segwit",
|
||||||
'fork_id',
|
"fork_id",
|
||||||
'force_bip143',
|
"force_bip143",
|
||||||
'version_group_id',
|
"version_group_id",
|
||||||
'bip115',
|
"bip115",
|
||||||
'curve_name',
|
"curve_name",
|
||||||
]
|
]
|
||||||
|
|
||||||
support = json.load(open('../../vendor/trezor-common/defs/support.json', 'r'))
|
support = json.load(open("../../vendor/trezor-common/defs/support.json", "r"))
|
||||||
coins = support['trezor2'].keys()
|
coins = support["trezor2"].keys()
|
||||||
|
|
||||||
print('COINS = [')
|
print("COINS = [")
|
||||||
|
|
||||||
for c in coins:
|
for c in coins:
|
||||||
print(' CoinInfo(')
|
print(" CoinInfo(")
|
||||||
name = c.replace(' ', '_').lower()
|
name = c.replace(" ", "_").lower()
|
||||||
if name == 'testnet':
|
if name == "testnet":
|
||||||
name = 'bitcoin_testnet'
|
name = "bitcoin_testnet"
|
||||||
data = json.load(open('../../vendor/trezor-common/defs/coins/%s.json' % name, 'r'))
|
data = json.load(open("../../vendor/trezor-common/defs/coins/%s.json" % name, "r"))
|
||||||
for n in fields:
|
for n in fields:
|
||||||
if n in ['xpub_magic', 'version_group_id']:
|
if n in ["xpub_magic", "version_group_id"]:
|
||||||
v = '0x%08x' % data[n] if data[n] is not None else 'None'
|
v = "0x%08x" % data[n] if data[n] is not None else "None"
|
||||||
else:
|
else:
|
||||||
v = repr(data[n])
|
v = repr(data[n])
|
||||||
if n == 'curve_name':
|
if n == "curve_name":
|
||||||
v = v.replace('_', '-')
|
v = v.replace("_", "-")
|
||||||
print(' %s=%s,' % (n, v))
|
print(" %s=%s," % (n, v))
|
||||||
print(' ),')
|
print(" ),")
|
||||||
|
|
||||||
print(']')
|
print("]")
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import json
|
import json
|
||||||
|
|
||||||
j = json.load(open('../../vendor/trezor-common/defs/ethereum/networks.json', 'r'))
|
j = json.load(open("../../vendor/trezor-common/defs/ethereum/networks.json", "r"))
|
||||||
|
|
||||||
print('NETWORKS = [')
|
print("NETWORKS = [")
|
||||||
|
|
||||||
for n in j:
|
for n in j:
|
||||||
print(' NetworkInfo(')
|
print(" NetworkInfo(")
|
||||||
for f in ['chain_id', 'slip44', 'shortcut', 'name', 'rskip60']:
|
for f in ["chain_id", "slip44", "shortcut", "name", "rskip60"]:
|
||||||
print(' %s=%s,' % (f, repr(n[f])))
|
print(" %s=%s," % (f, repr(n[f])))
|
||||||
print(' ),')
|
print(" ),")
|
||||||
|
|
||||||
print(']')
|
print("]")
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
import freetype
|
import freetype
|
||||||
|
|
||||||
MIN_GLYPH = ord(' ')
|
MIN_GLYPH = ord(" ")
|
||||||
MAX_GLYPH = ord('~')
|
MAX_GLYPH = ord("~")
|
||||||
|
|
||||||
FONT_BPP = 4
|
FONT_BPP = 4
|
||||||
|
|
||||||
@ -14,20 +14,23 @@ FONT_BPP = 4
|
|||||||
|
|
||||||
|
|
||||||
def process_face(name, style, size):
|
def process_face(name, style, size):
|
||||||
print('Processing ... %s %s %s' % (name, style, size))
|
print("Processing ... %s %s %s" % (name, style, size))
|
||||||
face = freetype.Face('/usr/share/fonts/truetype/%s-%s.ttf' % (name, style))
|
face = freetype.Face("/usr/share/fonts/truetype/%s-%s.ttf" % (name, style))
|
||||||
face.set_pixel_sizes(0, size)
|
face.set_pixel_sizes(0, size)
|
||||||
fontname = '%s_%s_%d' % (name.lower(), style.lower(), size)
|
fontname = "%s_%s_%d" % (name.lower(), style.lower(), size)
|
||||||
with open('font_%s.h' % fontname, 'wt') as f:
|
with open("font_%s.h" % fontname, "wt") as f:
|
||||||
f.write('#include <stdint.h>\n\n')
|
f.write("#include <stdint.h>\n\n")
|
||||||
f.write('extern const uint8_t* const Font_%s_%s_%d[%d + 1 - %d];\n' % (name, style, size, MAX_GLYPH, MIN_GLYPH))
|
f.write(
|
||||||
with open('font_%s.c' % fontname, 'wt') as f:
|
"extern const uint8_t* const Font_%s_%s_%d[%d + 1 - %d];\n"
|
||||||
|
% (name, style, size, MAX_GLYPH, MIN_GLYPH)
|
||||||
|
)
|
||||||
|
with open("font_%s.c" % fontname, "wt") as f:
|
||||||
f.write('#include "font_%s.h"\n\n' % fontname)
|
f.write('#include "font_%s.h"\n\n' % fontname)
|
||||||
f.write('// first two bytes are width and height of the glyph\n')
|
f.write("// first two bytes are width and height of the glyph\n")
|
||||||
f.write('// third, fourth and fifth bytes are advance\n')
|
f.write("// third, fourth and fifth bytes are advance\n")
|
||||||
f.write('// bearingX and bearingY of the horizontal metrics of the glyph\n')
|
f.write("// bearingX and bearingY of the horizontal metrics of the glyph\n")
|
||||||
f.write('// rest is packed 4-bit glyph data\n\n')
|
f.write("// rest is packed 4-bit glyph data\n\n")
|
||||||
f.write('// clang-format off\n\n')
|
f.write("// clang-format off\n\n")
|
||||||
for i in range(MIN_GLYPH, MAX_GLYPH + 1):
|
for i in range(MIN_GLYPH, MAX_GLYPH + 1):
|
||||||
c = chr(i)
|
c = chr(i)
|
||||||
face.load_char(c, freetype.FT_LOAD_RENDER | freetype.FT_LOAD_TARGET_NORMAL)
|
face.load_char(c, freetype.FT_LOAD_RENDER | freetype.FT_LOAD_TARGET_NORMAL)
|
||||||
@ -48,33 +51,64 @@ def process_face(name, style, size):
|
|||||||
bearingX = metrics.horiBearingX // 64
|
bearingX = metrics.horiBearingX // 64
|
||||||
# the following code is here just for some letters (listed below)
|
# the following code is here just for some letters (listed below)
|
||||||
# not using negative bearingX makes life so much easier; add it to advance instead
|
# not using negative bearingX makes life so much easier; add it to advance instead
|
||||||
if c in 'jy}),/' and bearingX < 0:
|
if c in "jy}),/" and bearingX < 0:
|
||||||
advance += -bearingX
|
advance += -bearingX
|
||||||
bearingX = 0
|
bearingX = 0
|
||||||
bearingY = metrics.horiBearingY // 64
|
bearingY = metrics.horiBearingY // 64
|
||||||
assert advance >= 0 and advance <= 255
|
assert advance >= 0 and advance <= 255
|
||||||
assert bearingX >= 0 and bearingX <= 255
|
assert bearingX >= 0 and bearingX <= 255
|
||||||
assert bearingY >= 0 and bearingY <= 255
|
assert bearingY >= 0 and bearingY <= 255
|
||||||
print('Loaded glyph "%c" ... %d x %d @ %d grays (%d bytes, metrics: %d, %d, %d)' % (c, bitmap.width, bitmap.rows, bitmap.num_grays, len(bitmap.buffer), advance, bearingX, bearingY))
|
print(
|
||||||
f.write('/* %c */ static const uint8_t Font_%s_%s_%d_glyph_%d[] = { %d, %d, %d, %d, %d' % (c, name, style, size, i, width, rows, advance, bearingX, bearingY))
|
'Loaded glyph "%c" ... %d x %d @ %d grays (%d bytes, metrics: %d, %d, %d)'
|
||||||
|
% (
|
||||||
|
c,
|
||||||
|
bitmap.width,
|
||||||
|
bitmap.rows,
|
||||||
|
bitmap.num_grays,
|
||||||
|
len(bitmap.buffer),
|
||||||
|
advance,
|
||||||
|
bearingX,
|
||||||
|
bearingY,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
f.write(
|
||||||
|
"/* %c */ static const uint8_t Font_%s_%s_%d_glyph_%d[] = { %d, %d, %d, %d, %d"
|
||||||
|
% (c, name, style, size, i, width, rows, advance, bearingX, bearingY)
|
||||||
|
)
|
||||||
buf = list(bitmap.buffer)
|
buf = list(bitmap.buffer)
|
||||||
if len(buf) > 0:
|
if len(buf) > 0:
|
||||||
if FONT_BPP == 2:
|
if FONT_BPP == 2:
|
||||||
for _ in range(4 - len(buf) % 4):
|
for _ in range(4 - len(buf) % 4):
|
||||||
buf.append(0)
|
buf.append(0)
|
||||||
buf = [((a & 0xC0) | ((b & 0xC0) >> 2) | ((c & 0xC0) >> 4) | ((d & 0xC0) >> 6)) for a, b, c, d in [buf[i:i + 4] for i in range(0, len(buf), 4)]]
|
buf = [
|
||||||
|
(
|
||||||
|
(a & 0xC0)
|
||||||
|
| ((b & 0xC0) >> 2)
|
||||||
|
| ((c & 0xC0) >> 4)
|
||||||
|
| ((d & 0xC0) >> 6)
|
||||||
|
)
|
||||||
|
for a, b, c, d in [
|
||||||
|
buf[i : i + 4] for i in range(0, len(buf), 4)
|
||||||
|
]
|
||||||
|
]
|
||||||
elif FONT_BPP == 4:
|
elif FONT_BPP == 4:
|
||||||
if len(buf) % 2 > 0:
|
if len(buf) % 2 > 0:
|
||||||
buf.append(0)
|
buf.append(0)
|
||||||
buf = [((a & 0xF0) | (b >> 4)) for a, b in [buf[i:i + 2] for i in range(0, len(buf), 2)]]
|
buf = [
|
||||||
f.write(', ' + ', '.join(['%d' % x for x in buf]))
|
((a & 0xF0) | (b >> 4))
|
||||||
f.write(' };\n')
|
for a, b in [buf[i : i + 2] for i in range(0, len(buf), 2)]
|
||||||
f.write('\nconst uint8_t * const Font_%s_%s_%d[%d + 1 - %d] = {\n' % (name, style, size, MAX_GLYPH, MIN_GLYPH))
|
]
|
||||||
|
f.write(", " + ", ".join(["%d" % x for x in buf]))
|
||||||
|
f.write(" };\n")
|
||||||
|
f.write(
|
||||||
|
"\nconst uint8_t * const Font_%s_%s_%d[%d + 1 - %d] = {\n"
|
||||||
|
% (name, style, size, MAX_GLYPH, MIN_GLYPH)
|
||||||
|
)
|
||||||
for i in range(MIN_GLYPH, MAX_GLYPH + 1):
|
for i in range(MIN_GLYPH, MAX_GLYPH + 1):
|
||||||
f.write(' Font_%s_%s_%d_glyph_%d,\n' % (name, style, size, i))
|
f.write(" Font_%s_%s_%d_glyph_%d,\n" % (name, style, size, i))
|
||||||
f.write('};\n')
|
f.write("};\n")
|
||||||
|
|
||||||
|
|
||||||
process_face('Roboto', 'Regular', 20)
|
process_face("Roboto", "Regular", 20)
|
||||||
process_face('Roboto', 'Bold', 20)
|
process_face("Roboto", "Bold", 20)
|
||||||
process_face('RobotoMono', 'Regular', 20)
|
process_face("RobotoMono", "Regular", 20)
|
||||||
|
@ -5,16 +5,16 @@ from trezorlib import ed25519raw
|
|||||||
|
|
||||||
|
|
||||||
def hex_to_c(s):
|
def hex_to_c(s):
|
||||||
return '"\\x' + '\\x'.join([s[i:i + 2] for i in range(0, len(s), 2)]) + '"'
|
return '"\\x' + "\\x".join([s[i : i + 2] for i in range(0, len(s), 2)]) + '"'
|
||||||
|
|
||||||
|
|
||||||
for c in 'ABCDEFGHI':
|
for c in "ABCDEFGHI":
|
||||||
print()
|
print()
|
||||||
seckey = c.encode() * 32
|
seckey = c.encode() * 32
|
||||||
seckey_hex = binascii.hexlify(seckey).decode()
|
seckey_hex = binascii.hexlify(seckey).decode()
|
||||||
print('seckey', seckey_hex)
|
print("seckey", seckey_hex)
|
||||||
print(' ', hex_to_c(seckey_hex))
|
print(" ", hex_to_c(seckey_hex))
|
||||||
pubkey = ed25519raw.publickey(seckey)
|
pubkey = ed25519raw.publickey(seckey)
|
||||||
pubkey_hex = binascii.hexlify(pubkey).decode()
|
pubkey_hex = binascii.hexlify(pubkey).decode()
|
||||||
print('pubkey', pubkey_hex)
|
print("pubkey", pubkey_hex)
|
||||||
print(' ', hex_to_c(pubkey_hex))
|
print(" ", hex_to_c(pubkey_hex))
|
||||||
|
@ -3,16 +3,15 @@
|
|||||||
# script used to generate /embed/extmod/modtrezorui/loader.h
|
# script used to generate /embed/extmod/modtrezorui/loader.h
|
||||||
|
|
||||||
import math
|
import math
|
||||||
import sys
|
|
||||||
|
|
||||||
outer = 60
|
outer = 60
|
||||||
inner = 42
|
inner = 42
|
||||||
|
|
||||||
with open('loader.h', 'wt') as f:
|
with open("loader.h", "wt") as f:
|
||||||
f.write('static const int img_loader_size = %d;\n' % outer)
|
f.write("static const int img_loader_size = %d;\n" % outer)
|
||||||
f.write('static const uint16_t img_loader[%d][%d] = {\n' % (outer, outer))
|
f.write("static const uint16_t img_loader[%d][%d] = {\n" % (outer, outer))
|
||||||
for y in range(outer):
|
for y in range(outer):
|
||||||
f.write(' {')
|
f.write(" {")
|
||||||
for x in range(outer):
|
for x in range(outer):
|
||||||
d = math.sqrt((outer - 1 - x) ** 2 + (outer - 1 - y) ** 2)
|
d = math.sqrt((outer - 1 - x) ** 2 + (outer - 1 - y) ** 2)
|
||||||
c = {}
|
c = {}
|
||||||
@ -33,6 +32,6 @@ with open('loader.h', 'wt') as f:
|
|||||||
c[i] = max(0, min(int(c[i]), 15))
|
c[i] = max(0, min(int(c[i]), 15))
|
||||||
a = int(math.atan2((outer - 1 - x), (outer - 1 - y)) * 2 * 249 / math.pi)
|
a = int(math.atan2((outer - 1 - x), (outer - 1 - y)) * 2 * 249 / math.pi)
|
||||||
v = (a << 8) | (c[15] << 4) | c[5]
|
v = (a << 8) | (c[15] << 4) | c[5]
|
||||||
f.write('%d,' % v)
|
f.write("%d," % v)
|
||||||
f.write('},\n')
|
f.write("},\n")
|
||||||
f.write('};\n')
|
f.write("};\n")
|
||||||
|
@ -18,29 +18,31 @@ def format_primitive(value):
|
|||||||
|
|
||||||
|
|
||||||
fields = [
|
fields = [
|
||||||
'name',
|
"name",
|
||||||
'ticker',
|
"ticker",
|
||||||
'namespace',
|
"namespace",
|
||||||
'mosaic',
|
"mosaic",
|
||||||
'divisibility',
|
"divisibility",
|
||||||
'levy',
|
"levy",
|
||||||
'fee',
|
"fee",
|
||||||
'levy_namespace',
|
"levy_namespace",
|
||||||
'levy_mosaic',
|
"levy_mosaic",
|
||||||
'networks',
|
"networks",
|
||||||
]
|
]
|
||||||
|
|
||||||
mosaics = json.load(open('../../vendor/trezor-common/defs/nem/nem_mosaics.json', 'r'))
|
mosaics = json.load(open("../../vendor/trezor-common/defs/nem/nem_mosaics.json", "r"))
|
||||||
|
|
||||||
print('# generated using gen_nem_mosaics.py from trezor-common nem_mosaics.json - do not edit directly!')
|
print(
|
||||||
print('')
|
"# generated using gen_nem_mosaics.py from trezor-common nem_mosaics.json - do not edit directly!"
|
||||||
print('mosaics = [')
|
)
|
||||||
|
print("")
|
||||||
|
print("mosaics = [")
|
||||||
for m in mosaics:
|
for m in mosaics:
|
||||||
print(' {')
|
print(" {")
|
||||||
for name in fields:
|
for name in fields:
|
||||||
if name in m:
|
if name in m:
|
||||||
print(' %s: %s,' % (format_str(name), format_primitive(m[name])))
|
print(" %s: %s," % (format_str(name), format_primitive(m[name])))
|
||||||
# else:
|
# else:
|
||||||
# print(' %s: None,' % format_str(name))
|
# print(' %s: None,' % format_str(name))
|
||||||
print(' },')
|
print(" },")
|
||||||
print(']')
|
print("]")
|
||||||
|
@ -8,9 +8,11 @@ devices = HidTransport.enumerate()
|
|||||||
if len(devices) > 0:
|
if len(devices) > 0:
|
||||||
t = TrezorClient(devices[0])
|
t = TrezorClient(devices[0])
|
||||||
else:
|
else:
|
||||||
raise Exception('No TREZOR found')
|
raise Exception("No TREZOR found")
|
||||||
|
|
||||||
for i in [0, 1, 2]:
|
for i in [0, 1, 2]:
|
||||||
path = "m/10018'/%d'" % i
|
path = "m/10018'/%d'" % i
|
||||||
pk = t.get_public_node(t.expand_path(path), ecdsa_curve_name='ed25519', show_display=True)
|
pk = t.get_public_node(
|
||||||
print(path, '=>', binascii.hexlify(pk.node.public_key).decode())
|
t.expand_path(path), ecdsa_curve_name="ed25519", show_display=True
|
||||||
|
)
|
||||||
|
print(path, "=>", binascii.hexlify(pk.node.public_key).decode())
|
||||||
|
@ -16,11 +16,11 @@ out = bytearray()
|
|||||||
|
|
||||||
for addr, fn in files:
|
for addr, fn in files:
|
||||||
addr = int(addr, 16) - offset
|
addr = int(addr, 16) - offset
|
||||||
data = open(fn, 'rb').read()
|
data = open(fn, "rb").read()
|
||||||
if len(out) < addr:
|
if len(out) < addr:
|
||||||
out += b'\x00' * (addr - len(out))
|
out += b"\x00" * (addr - len(out))
|
||||||
if len(out) != addr:
|
if len(out) != addr:
|
||||||
raise Exception('Alignment failed')
|
raise Exception("Alignment failed")
|
||||||
out += data
|
out += data
|
||||||
|
|
||||||
sys.stdout.buffer.write(out)
|
sys.stdout.buffer.write(out)
|
||||||
|
28
tools/keyctl
28
tools/keyctl
@ -5,23 +5,19 @@ import click
|
|||||||
import pyblake2
|
import pyblake2
|
||||||
from trezorlib import cosi
|
from trezorlib import cosi
|
||||||
|
|
||||||
indexmap = {
|
indexmap = {"bootloader": 0, "vendorheader": 1, "firmware": 2}
|
||||||
'bootloader': 0,
|
|
||||||
'vendorheader': 1,
|
|
||||||
'firmware': 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def header_digest(index, filename):
|
def header_digest(index, filename):
|
||||||
data = open(filename, 'rb').read()
|
data = open(filename, "rb").read()
|
||||||
z = bytes(65 * [0x00])
|
z = bytes(65 * [0x00])
|
||||||
if index == 'bootloader':
|
if index == "bootloader":
|
||||||
header = data[:0x03BF] + z
|
header = data[:0x03BF] + z
|
||||||
elif index == 'vendorheader':
|
elif index == "vendorheader":
|
||||||
header = data[:-65] + z
|
header = data[:-65] + z
|
||||||
elif index == 'firmware':
|
elif index == "firmware":
|
||||||
vhdrlen = struct.unpack('<I', data[4:8])[0]
|
vhdrlen = struct.unpack("<I", data[4:8])[0]
|
||||||
header = data[vhdrlen:vhdrlen + 0x03BF] + z
|
header = data[vhdrlen : vhdrlen + 0x03BF] + z
|
||||||
else:
|
else:
|
||||||
raise ValueError('Unknown index "%s"' % index)
|
raise ValueError('Unknown index "%s"' % index)
|
||||||
return pyblake2.blake2s(header).digest()
|
return pyblake2.blake2s(header).digest()
|
||||||
@ -32,10 +28,10 @@ def cli():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@cli.command(help='')
|
@cli.command(help="")
|
||||||
@click.argument('index', type=click.Choice(indexmap.keys()))
|
@click.argument("index", type=click.Choice(indexmap.keys()))
|
||||||
@click.argument('filename')
|
@click.argument("filename")
|
||||||
@click.argument('seckeys', nargs=-1)
|
@click.argument("seckeys", nargs=-1)
|
||||||
def sign(index, filename, seckeys):
|
def sign(index, filename, seckeys):
|
||||||
# compute header digest
|
# compute header digest
|
||||||
digest = header_digest(index, filename)
|
digest = header_digest(index, filename)
|
||||||
@ -63,5 +59,5 @@ def sign(index, filename, seckeys):
|
|||||||
print(binascii.hexlify(sig).decode())
|
print(binascii.hexlify(sig).decode())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
cli()
|
cli()
|
||||||
|
@ -8,23 +8,19 @@ import serpent
|
|||||||
from trezorlib import cosi
|
from trezorlib import cosi
|
||||||
|
|
||||||
PORT = 5001
|
PORT = 5001
|
||||||
indexmap = {
|
indexmap = {"bootloader": 0, "vendorheader": 1, "firmware": 2}
|
||||||
'bootloader': 0,
|
|
||||||
'vendorheader': 1,
|
|
||||||
'firmware': 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def header_digest(index, filename):
|
def header_digest(index, filename):
|
||||||
data = open(filename, 'rb').read()
|
data = open(filename, "rb").read()
|
||||||
z = bytes(65 * [0x00])
|
z = bytes(65 * [0x00])
|
||||||
if index == 'bootloader':
|
if index == "bootloader":
|
||||||
header = data[:0x03BF] + z
|
header = data[:0x03BF] + z
|
||||||
elif index == 'vendorheader':
|
elif index == "vendorheader":
|
||||||
header = data[:-65] + z
|
header = data[:-65] + z
|
||||||
elif index == 'firmware':
|
elif index == "firmware":
|
||||||
vhdrlen = struct.unpack('<I', data[4:8])[0]
|
vhdrlen = struct.unpack("<I", data[4:8])[0]
|
||||||
header = data[vhdrlen:vhdrlen + 0x03BF] + z
|
header = data[vhdrlen : vhdrlen + 0x03BF] + z
|
||||||
else:
|
else:
|
||||||
raise ValueError('Unknown index "%s"' % index)
|
raise ValueError('Unknown index "%s"' % index)
|
||||||
return pyblake2.blake2s(header).digest()
|
return pyblake2.blake2s(header).digest()
|
||||||
@ -35,20 +31,20 @@ def cli():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@cli.command(help='')
|
@cli.command(help="")
|
||||||
@click.argument('index', type=click.Choice(indexmap.keys()))
|
@click.argument("index", type=click.Choice(indexmap.keys()))
|
||||||
@click.argument('filename')
|
@click.argument("filename")
|
||||||
@click.argument('participants', nargs=-1)
|
@click.argument("participants", nargs=-1)
|
||||||
def sign(index, filename, participants):
|
def sign(index, filename, participants):
|
||||||
# compute header digest
|
# compute header digest
|
||||||
digest = header_digest(index, filename)
|
digest = header_digest(index, filename)
|
||||||
# create participant proxies
|
# create participant proxies
|
||||||
if len(participants) < 1:
|
if len(participants) < 1:
|
||||||
raise ValueError('Not enough participants')
|
raise ValueError("Not enough participants")
|
||||||
print('connecting to %d participants:' % len(participants))
|
print("connecting to %d participants:" % len(participants))
|
||||||
proxy = []
|
proxy = []
|
||||||
for p in participants:
|
for p in participants:
|
||||||
uri = 'PYRO:keyctl@%s:%d' % (p, PORT)
|
uri = "PYRO:keyctl@%s:%d" % (p, PORT)
|
||||||
proxy.append(Pyro4.Proxy(uri))
|
proxy.append(Pyro4.Proxy(uri))
|
||||||
# collect commits
|
# collect commits
|
||||||
pks, Rs = [], []
|
pks, Rs = [], []
|
||||||
@ -57,7 +53,7 @@ def sign(index, filename, participants):
|
|||||||
pk, R = serpent.tobytes(pk), serpent.tobytes(R)
|
pk, R = serpent.tobytes(pk), serpent.tobytes(R)
|
||||||
pks.append(pk)
|
pks.append(pk)
|
||||||
Rs.append(R)
|
Rs.append(R)
|
||||||
print('collected commit #%d from %s' % (i, p._pyroUri.host))
|
print("collected commit #%d from %s" % (i, p._pyroUri.host))
|
||||||
# compute global commit
|
# compute global commit
|
||||||
global_pk = cosi.combine_keys(pks)
|
global_pk = cosi.combine_keys(pks)
|
||||||
global_R = cosi.combine_keys(Rs)
|
global_R = cosi.combine_keys(Rs)
|
||||||
@ -67,13 +63,13 @@ def sign(index, filename, participants):
|
|||||||
sig = p.get_signature(index, digest, global_R, global_pk)
|
sig = p.get_signature(index, digest, global_R, global_pk)
|
||||||
sig = serpent.tobytes(sig)
|
sig = serpent.tobytes(sig)
|
||||||
sigs.append(sig)
|
sigs.append(sig)
|
||||||
print('collected signature #%d from %s' % (i, p._pyroUri.host))
|
print("collected signature #%d from %s" % (i, p._pyroUri.host))
|
||||||
# compute global signature
|
# compute global signature
|
||||||
sig = cosi.combine_sig(global_R, sigs)
|
sig = cosi.combine_sig(global_R, sigs)
|
||||||
cosi.verify(sig, digest, global_pk)
|
cosi.verify(sig, digest, global_pk)
|
||||||
print('global signature:')
|
print("global signature:")
|
||||||
print(binascii.hexlify(sig).decode())
|
print(binascii.hexlify(sig).decode())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
cli()
|
cli()
|
||||||
|
@ -5,16 +5,13 @@ import Pyro4
|
|||||||
import serpent
|
import serpent
|
||||||
|
|
||||||
PORT = 5001
|
PORT = 5001
|
||||||
indexmap = {
|
indexmap = {"bootloader": 0, "vendorheader": 1, "firmware": 2}
|
||||||
'bootloader': 0,
|
|
||||||
'vendorheader': 1,
|
|
||||||
'firmware': 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_trezor():
|
def get_trezor():
|
||||||
from trezorlib.client import TrezorClient
|
from trezorlib.client import TrezorClient
|
||||||
from trezorlib.transport import get_transport
|
from trezorlib.transport import get_transport
|
||||||
|
|
||||||
return TrezorClient(get_transport())
|
return TrezorClient(get_transport())
|
||||||
|
|
||||||
|
|
||||||
@ -24,7 +21,6 @@ def get_path(index):
|
|||||||
|
|
||||||
@Pyro4.expose
|
@Pyro4.expose
|
||||||
class KeyctlProxy(object):
|
class KeyctlProxy(object):
|
||||||
|
|
||||||
def get_commit(self, index, digest):
|
def get_commit(self, index, digest):
|
||||||
digest = serpent.tobytes(digest)
|
digest = serpent.tobytes(digest)
|
||||||
path = get_path(index)
|
path = get_path(index)
|
||||||
@ -32,41 +28,53 @@ class KeyctlProxy(object):
|
|||||||
while commit is None:
|
while commit is None:
|
||||||
try:
|
try:
|
||||||
t = get_trezor()
|
t = get_trezor()
|
||||||
print('\n\n\nCommiting to hash %s with path %s:' % (binascii.hexlify(digest).decode(), path))
|
print(
|
||||||
|
"\n\n\nCommiting to hash %s with path %s:"
|
||||||
|
% (binascii.hexlify(digest).decode(), path)
|
||||||
|
)
|
||||||
commit = t.cosi_commit(t.expand_path(path), digest)
|
commit = t.cosi_commit(t.expand_path(path), digest)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
print('Trying again ...')
|
print("Trying again ...")
|
||||||
pk = commit.pubkey
|
pk = commit.pubkey
|
||||||
R = commit.commitment
|
R = commit.commitment
|
||||||
print('Commitment sent!')
|
print("Commitment sent!")
|
||||||
return (pk, R)
|
return (pk, R)
|
||||||
|
|
||||||
def get_signature(self, index, digest, global_R, global_pk):
|
def get_signature(self, index, digest, global_R, global_pk):
|
||||||
digest, global_R, global_pk = serpent.tobytes(digest), serpent.tobytes(global_R), serpent.tobytes(global_pk)
|
digest, global_R, global_pk = (
|
||||||
|
serpent.tobytes(digest),
|
||||||
|
serpent.tobytes(global_R),
|
||||||
|
serpent.tobytes(global_pk),
|
||||||
|
)
|
||||||
path = get_path(index)
|
path = get_path(index)
|
||||||
signature = None
|
signature = None
|
||||||
while signature is None:
|
while signature is None:
|
||||||
try:
|
try:
|
||||||
t = get_trezor()
|
t = get_trezor()
|
||||||
print('\n\n\nSigning hash %s with path %s:' % (binascii.hexlify(digest).decode(), path))
|
print(
|
||||||
signature = t.cosi_sign(t.expand_path(path), digest, global_R, global_pk)
|
"\n\n\nSigning hash %s with path %s:"
|
||||||
|
% (binascii.hexlify(digest).decode(), path)
|
||||||
|
)
|
||||||
|
signature = t.cosi_sign(
|
||||||
|
t.expand_path(path), digest, global_R, global_pk
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
print('Trying again ...')
|
print("Trying again ...")
|
||||||
sig = signature.signature
|
sig = signature.signature
|
||||||
print('Signature sent!')
|
print("Signature sent!")
|
||||||
return sig
|
return sig
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
ipaddr = sys.argv[1]
|
ipaddr = sys.argv[1]
|
||||||
else:
|
else:
|
||||||
print('Usage: keyctl-proxy ipaddress')
|
print("Usage: keyctl-proxy ipaddress")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
daemon = Pyro4.Daemon(host=ipaddr, port=PORT)
|
daemon = Pyro4.Daemon(host=ipaddr, port=PORT)
|
||||||
proxy = KeyctlProxy()
|
proxy = KeyctlProxy()
|
||||||
uri = daemon.register(proxy, 'keyctl')
|
uri = daemon.register(proxy, "keyctl")
|
||||||
print('keyctl-proxy running at URI: "%s"' % uri)
|
print('keyctl-proxy running at URI: "%s"' % uri)
|
||||||
daemon.requestLoop()
|
daemon.requestLoop()
|
||||||
|
@ -12,7 +12,7 @@ def process_rgb(w, h, pix):
|
|||||||
for i in range(w):
|
for i in range(w):
|
||||||
r, g, b = pix[i, j]
|
r, g, b = pix[i, j]
|
||||||
c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)
|
c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)
|
||||||
data += struct.pack('>H', c)
|
data += struct.pack(">H", c)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
@ -22,89 +22,95 @@ def process_grayscale(w, h, pix):
|
|||||||
for i in range(w // 2):
|
for i in range(w // 2):
|
||||||
l1, l2 = pix[i * 2, j], pix[i * 2 + 1, j]
|
l1, l2 = pix[i * 2, j], pix[i * 2 + 1, j]
|
||||||
c = (l1 & 0xF0) | (l2 >> 4)
|
c = (l1 & 0xF0) | (l2 >> 4)
|
||||||
data += struct.pack('>B', c)
|
data += struct.pack(">B", c)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def process_image(ifn, savefiles=False):
|
def process_image(ifn, savefiles=False):
|
||||||
im = Image.open(ifn)
|
im = Image.open(ifn)
|
||||||
w, h = im.size
|
w, h = im.size
|
||||||
print('Opened %s ... %d x %d @ %s' % (ifn, w, h, im.mode))
|
print("Opened %s ... %d x %d @ %s" % (ifn, w, h, im.mode))
|
||||||
|
|
||||||
if im.mode == 'RGB':
|
if im.mode == "RGB":
|
||||||
print('Detected RGB mode')
|
print("Detected RGB mode")
|
||||||
elif im.mode == 'L':
|
elif im.mode == "L":
|
||||||
if w % 2 > 0:
|
if w % 2 > 0:
|
||||||
print('PNG file must have width divisible by 2')
|
print("PNG file must have width divisible by 2")
|
||||||
return 3
|
return 3
|
||||||
print('Detected GRAYSCALE mode')
|
print("Detected GRAYSCALE mode")
|
||||||
else:
|
else:
|
||||||
print('Unknown mode:', im.mode)
|
print("Unknown mode:", im.mode)
|
||||||
return 4
|
return 4
|
||||||
|
|
||||||
pix = im.load()
|
pix = im.load()
|
||||||
|
|
||||||
bname = basename(ifn[:-4])
|
bname = basename(ifn[:-4])
|
||||||
ofn_h = '%s.h' % bname
|
ofn_h = "%s.h" % bname
|
||||||
ofn_py = '%s.py' % bname
|
ofn_py = "%s.py" % bname
|
||||||
|
|
||||||
if im.mode == 'RGB':
|
if im.mode == "RGB":
|
||||||
ofn = '%s.toif' % bname
|
ofn = "%s.toif" % bname
|
||||||
pixeldata = process_rgb(w, h, pix)
|
pixeldata = process_rgb(w, h, pix)
|
||||||
else:
|
else:
|
||||||
ofn = '%s.toig' % bname
|
ofn = "%s.toig" % bname
|
||||||
pixeldata = process_grayscale(w, h, pix)
|
pixeldata = process_grayscale(w, h, pix)
|
||||||
z = zlib.compressobj(level=9, wbits=10)
|
z = zlib.compressobj(level=9, wbits=10)
|
||||||
zdata = z.compress(pixeldata) + z.flush()
|
zdata = z.compress(pixeldata) + z.flush()
|
||||||
zdata = zdata[2:-4] # strip header and checksum
|
zdata = zdata[2:-4] # strip header and checksum
|
||||||
|
|
||||||
data = b''
|
data = b""
|
||||||
if im.mode == 'RGB':
|
if im.mode == "RGB":
|
||||||
data += b'TOIf'
|
data += b"TOIf"
|
||||||
else:
|
else:
|
||||||
data += b'TOIg'
|
data += b"TOIg"
|
||||||
data += struct.pack('<HH', w, h)
|
data += struct.pack("<HH", w, h)
|
||||||
data += struct.pack('<I', len(zdata))
|
data += struct.pack("<I", len(zdata))
|
||||||
data += zdata
|
data += zdata
|
||||||
|
|
||||||
if savefiles:
|
if savefiles:
|
||||||
with open(ofn, 'wb') as f:
|
with open(ofn, "wb") as f:
|
||||||
f.write(data)
|
f.write(data)
|
||||||
print('Written %s ... %d bytes' % (ofn, len(data)))
|
print("Written %s ... %d bytes" % (ofn, len(data)))
|
||||||
with open(ofn_py, 'wb') as f:
|
with open(ofn_py, "wb") as f:
|
||||||
f.write(('%s = %s\n' % (bname, data)).encode())
|
f.write(("%s = %s\n" % (bname, data)).encode())
|
||||||
print('Written %s ... %d bytes' % (ofn_py, len(data)))
|
print("Written %s ... %d bytes" % (ofn_py, len(data)))
|
||||||
with open(ofn_h, 'wt') as f:
|
with open(ofn_h, "wt") as f:
|
||||||
f.write('// clang-format off\n')
|
f.write("// clang-format off\n")
|
||||||
f.write('static const uint8_t toi_%s[] = {\n' % bname)
|
f.write("static const uint8_t toi_%s[] = {\n" % bname)
|
||||||
f.write(' // magic\n')
|
f.write(" // magic\n")
|
||||||
if im.mode == 'RGB':
|
if im.mode == "RGB":
|
||||||
f.write(" 'T', 'O', 'I', 'f',\n")
|
f.write(" 'T', 'O', 'I', 'f',\n")
|
||||||
else:
|
else:
|
||||||
f.write(" 'T', 'O', 'I', 'g',\n")
|
f.write(" 'T', 'O', 'I', 'g',\n")
|
||||||
f.write(' // width (16-bit), height (16-bit)\n')
|
f.write(" // width (16-bit), height (16-bit)\n")
|
||||||
f.write(' 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n' % (w & 0xFF, w >> 8, h & 0xFF, h >> 8))
|
f.write(
|
||||||
|
" 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n"
|
||||||
|
% (w & 0xFF, w >> 8, h & 0xFF, h >> 8)
|
||||||
|
)
|
||||||
l = len(zdata)
|
l = len(zdata)
|
||||||
f.write(' // compressed data length (32-bit)\n')
|
f.write(" // compressed data length (32-bit)\n")
|
||||||
f.write(' 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n' % (l & 0xFF, (l >> 8) & 0xFF, (l >> 16) & 0xFF, l >> 24))
|
f.write(
|
||||||
f.write(' // compressed data\n')
|
" 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n"
|
||||||
f.write(' ')
|
% (l & 0xFF, (l >> 8) & 0xFF, (l >> 16) & 0xFF, l >> 24)
|
||||||
|
)
|
||||||
|
f.write(" // compressed data\n")
|
||||||
|
f.write(" ")
|
||||||
for b in zdata:
|
for b in zdata:
|
||||||
f.write(' 0x%02x,' % b)
|
f.write(" 0x%02x," % b)
|
||||||
f.write('\n};\n')
|
f.write("\n};\n")
|
||||||
print('Written %s ... done' % ofn_py)
|
print("Written %s ... done" % ofn_py)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print('Usage png2toi image.png')
|
print("Usage png2toi image.png")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
ifn = sys.argv[1]
|
ifn = sys.argv[1]
|
||||||
if not ifn.endswith('.png'):
|
if not ifn.endswith(".png"):
|
||||||
print('Must provide PNG file')
|
print("Must provide PNG file")
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
process_image(ifn, savefiles=True)
|
process_image(ifn, savefiles=True)
|
||||||
|
@ -6,20 +6,20 @@ resources = {}
|
|||||||
resources_size = 0
|
resources_size = 0
|
||||||
|
|
||||||
os.chdir(os.path.dirname(__file__))
|
os.chdir(os.path.dirname(__file__))
|
||||||
os.chdir('../src/')
|
os.chdir("../src/")
|
||||||
|
|
||||||
|
|
||||||
def process_file(name):
|
def process_file(name):
|
||||||
if name.endswith('.gitignore'):
|
if name.endswith(".gitignore"):
|
||||||
return
|
return
|
||||||
if name.endswith('.py'):
|
if name.endswith(".py"):
|
||||||
return
|
return
|
||||||
if os.path.basename(name).startswith('.'):
|
if os.path.basename(name).startswith("."):
|
||||||
return
|
return
|
||||||
with open(name, 'rb') as f:
|
with open(name, "rb") as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
resources[name] = data
|
resources[name] = data
|
||||||
print('processing file %s (%d bytes)' % (name, len(data)))
|
print("processing file %s (%d bytes)" % (name, len(data)))
|
||||||
global resources_size
|
global resources_size
|
||||||
resources_size += len(data)
|
resources_size += len(data)
|
||||||
|
|
||||||
@ -33,33 +33,35 @@ def process_dir_rec(dir):
|
|||||||
process_dir_rec(path)
|
process_dir_rec(path)
|
||||||
|
|
||||||
|
|
||||||
process_dir_rec('trezor/res/')
|
process_dir_rec("trezor/res/")
|
||||||
for name in os.listdir('apps/'):
|
for name in os.listdir("apps/"):
|
||||||
path = os.path.join('apps/', name, 'res/')
|
path = os.path.join("apps/", name, "res/")
|
||||||
if os.path.isdir(path):
|
if os.path.isdir(path):
|
||||||
process_dir_rec(path)
|
process_dir_rec(path)
|
||||||
|
|
||||||
resfile = 'trezor/res/resources.py'
|
resfile = "trezor/res/resources.py"
|
||||||
|
|
||||||
bio = io.StringIO()
|
bio = io.StringIO()
|
||||||
bio.write('# fmt: off\n')
|
bio.write("# fmt: off\n")
|
||||||
bio.write('resdata = {\n')
|
bio.write("resdata = {\n")
|
||||||
for k in sorted(resources.keys()):
|
for k in sorted(resources.keys()):
|
||||||
bio.write(" '%s': %s,\n" % (k, resources[k]))
|
bio.write(" '%s': %s,\n" % (k, resources[k]))
|
||||||
bio.write('}\n')
|
bio.write("}\n")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(resfile, 'r') as f:
|
with open(resfile, "r") as f:
|
||||||
stale = f.read()
|
stale = f.read()
|
||||||
except:
|
except FileNotFoundError:
|
||||||
stale = None
|
stale = None
|
||||||
|
|
||||||
fresh = bio.getvalue()
|
fresh = bio.getvalue()
|
||||||
|
|
||||||
if stale != fresh:
|
if stale != fresh:
|
||||||
with open(resfile, 'wt') as f:
|
with open(resfile, "wt") as f:
|
||||||
f.write(fresh)
|
f.write(fresh)
|
||||||
print('written %s with %d entries (total %d bytes)' %
|
print(
|
||||||
(resfile, len(resources), resources_size))
|
"written %s with %d entries (total %d bytes)"
|
||||||
|
% (resfile, len(resources), resources_size)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
print('continuing with %s, no changes detected' % (resfile))
|
print("continuing with %s, no changes detected" % (resfile))
|
||||||
|
@ -25,62 +25,64 @@ def process_grayscale(w, h, data):
|
|||||||
|
|
||||||
def process_image(ifn, ofn):
|
def process_image(ifn, ofn):
|
||||||
|
|
||||||
data = open(ifn, 'rb').read()
|
data = open(ifn, "rb").read()
|
||||||
|
|
||||||
if ifn.endswith('.toif'):
|
if ifn.endswith(".toif"):
|
||||||
if data[:4] != b'TOIf':
|
if data[:4] != b"TOIf":
|
||||||
print('Unknown TOIF header')
|
print("Unknown TOIF header")
|
||||||
return 1
|
return 1
|
||||||
elif ifn.endswith('.toig'):
|
elif ifn.endswith(".toig"):
|
||||||
if data[:4] != b'TOIg':
|
if data[:4] != b"TOIg":
|
||||||
print('Unknown TOIG header')
|
print("Unknown TOIG header")
|
||||||
return 2
|
return 2
|
||||||
else:
|
else:
|
||||||
print('Unsupported format')
|
print("Unsupported format")
|
||||||
return 3
|
return 3
|
||||||
if ofn is None:
|
if ofn is None:
|
||||||
ofn = '%s.png' % ifn[:-5]
|
ofn = "%s.png" % ifn[:-5]
|
||||||
|
|
||||||
w, h = struct.unpack('<HH', data[4:8])
|
w, h = struct.unpack("<HH", data[4:8])
|
||||||
|
|
||||||
print('Opened %s ... %d x %d' % (ifn, w, h))
|
print("Opened %s ... %d x %d" % (ifn, w, h))
|
||||||
|
|
||||||
l = struct.unpack('<I', data[8:12])[0]
|
l = struct.unpack("<I", data[8:12])[0]
|
||||||
data = data[12:]
|
data = data[12:]
|
||||||
if len(data) != l:
|
if len(data) != l:
|
||||||
print('Compressed data length mismatch (%d vs %d)' % (len(data), l))
|
print("Compressed data length mismatch (%d vs %d)" % (len(data), l))
|
||||||
return 4
|
return 4
|
||||||
data = zlib.decompress(data, -10)
|
data = zlib.decompress(data, -10)
|
||||||
|
|
||||||
if ifn.endswith('.toif'):
|
if ifn.endswith(".toif"):
|
||||||
if len(data) != w * h * 2:
|
if len(data) != w * h * 2:
|
||||||
print('Uncompressed data length mismatch (%d vs %d)' %
|
print(
|
||||||
(len(data), w * h * 2))
|
"Uncompressed data length mismatch (%d vs %d)" % (len(data), w * h * 2)
|
||||||
|
)
|
||||||
return 5
|
return 5
|
||||||
pix = process_rgb(w, h, data)
|
pix = process_rgb(w, h, data)
|
||||||
img = Image.frombuffer('RGB', (w, h), pix, 'raw', 'RGB', 0, 1)
|
img = Image.frombuffer("RGB", (w, h), pix, "raw", "RGB", 0, 1)
|
||||||
img.save(ofn)
|
img.save(ofn)
|
||||||
print('Written %s ...' % ofn)
|
print("Written %s ..." % ofn)
|
||||||
|
|
||||||
if ifn.endswith('.toig'):
|
if ifn.endswith(".toig"):
|
||||||
if len(data) != w * h // 2:
|
if len(data) != w * h // 2:
|
||||||
print('Uncompressed data length mismatch (%d vs %d)' %
|
print(
|
||||||
(len(data), w * h // 2))
|
"Uncompressed data length mismatch (%d vs %d)" % (len(data), w * h // 2)
|
||||||
|
)
|
||||||
return 6
|
return 6
|
||||||
pix = process_grayscale(w, h, data)
|
pix = process_grayscale(w, h, data)
|
||||||
img = Image.frombuffer('L', (w, h), pix, 'raw', 'L', 0, 1)
|
img = Image.frombuffer("L", (w, h), pix, "raw", "L", 0, 1)
|
||||||
img.save(ofn)
|
img.save(ofn)
|
||||||
print('Written %s ...' % ofn)
|
print("Written %s ..." % ofn)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print('Usage: toi2png image.toi[fg] [output]')
|
print("Usage: toi2png image.toi[fg] [output]")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
ifn = sys.argv[1]
|
ifn = sys.argv[1]
|
||||||
if not ifn.endswith('.toif') and not ifn.endswith('.toig'):
|
if not ifn.endswith(".toif") and not ifn.endswith(".toig"):
|
||||||
print('Must provide TOIF/TOIG file')
|
print("Must provide TOIF/TOIG file")
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
ofn = sys.argv[2] if len(sys.argv) > 2 else None
|
ofn = sys.argv[2] if len(sys.argv) > 2 else None
|
||||||
|
Loading…
Reference in New Issue
Block a user