1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-26 00:08:10 +00:00

tools: run black and flake8 on tools/

This commit is contained in:
Pavol Rusnak 2018-07-31 11:35:09 +02:00
parent 481bb4ccab
commit 10396777b8
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
18 changed files with 533 additions and 449 deletions

View File

@ -12,107 +12,101 @@ from trezorlib import cosi
def format_sigmask(sigmask):
bits = [str(b + 1) if sigmask & (1 << b) else '.' for b in range(8)]
return '0x%02x = [%s]' % (sigmask, ' '.join(bits))
bits = [str(b + 1) if sigmask & (1 << b) else "." for b in range(8)]
return "0x%02x = [%s]" % (sigmask, " ".join(bits))
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
desc = ''
desc = ""
wait = (vtrust & 0x000F) ^ 0x000F
if wait > 0:
desc = 'WAIT_%d' % wait
desc = "WAIT_%d" % wait
if vtrust & 0x0010 == 0:
desc += ' RED'
desc += " RED"
if vtrust & 0x0020 == 0:
desc += ' CLICK'
desc += " CLICK"
if vtrust & 0x0040 == 0:
desc += ' STRING'
return '%d = [%s] = [%s]' % (vtrust, ' '.join(bits), desc)
desc += " STRING"
return "%d = [%s] = [%s]" % (vtrust, " ".join(bits), desc)
# bootloader/firmware headers specification: https://github.com/trezor/trezor-core/blob/master/docs/bootloader.md
IMAGE_HEADER_SIZE = 1024
IMAGE_SIG_SIZE = 65
IMAGE_CHUNK_SIZE = 128 * 1024
BOOTLOADER_SECTORS_COUNT = 1
FIRMWARE_SECTORS_COUNT = 6 + 7
IMAGE_HEADER_SIZE = 1024
IMAGE_SIG_SIZE = 65
IMAGE_CHUNK_SIZE = 128 * 1024
BOOTLOADER_SECTORS_COUNT = 1
FIRMWARE_SECTORS_COUNT = 6 + 7
class BinImage(object):
def __init__(self, data, magic, max_size):
header = struct.unpack('<4sIIIBBBBBBBB8s512s415sB64s', data[:IMAGE_HEADER_SIZE])
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 = header
header = struct.unpack("<4sIIIBBBBBBBB8s512s415sB64s", data[:IMAGE_HEADER_SIZE])
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 = (
header
)
assert self.magic == magic
assert self.hdrlen == IMAGE_HEADER_SIZE
total_len = self.hdrlen + self.codelen
assert total_len % 512 == 0
assert total_len >= 4 * 1024
assert total_len <= max_size
assert self.reserved1 == 8 * b'\x00'
assert self.reserved2 == 415 * b'\x00'
self.code = data[self.hdrlen:]
assert self.reserved1 == 8 * b"\x00"
assert self.reserved2 == 415 * 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')
if self.magic == b"TRZF":
print("TREZOR Firmware Image")
total_len = self.vhdrlen + self.hdrlen + self.codelen
elif self.magic == b'TRZB':
print('TREZOR Bootloader Image')
elif self.magic == b"TRZB":
print("TREZOR Bootloader Image")
total_len = self.hdrlen + self.codelen
else:
print('TREZOR Unknown Image')
print(' * magic :', self.magic.decode())
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(' * 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'))
print("TREZOR Unknown Image")
print(" * magic :", self.magic.decode())
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(
" * 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):
print(' - %02d : %s' % (i, binascii.hexlify(self.hashes[i * 32:i * 32 + 32]).decode()))
print(' * sigmask :', format_sigmask(self.sigmask))
print(' * sig :', binascii.hexlify(self.sig).decode())
print(' * total : %d bytes' % total_len)
print(' * fngprnt :', self.fingerprint())
print(
" - %02d : %s"
% (i, binascii.hexlify(self.hashes[i * 32 : i * 32 + 32]).decode())
)
print(" * sigmask :", format_sigmask(self.sigmask))
print(" * sig :", binascii.hexlify(self.sig).decode())
print(" * total : %d bytes" % total_len)
print(" * fngprnt :", self.fingerprint())
print()
def compute_hashes(self):
if self.magic == b'TRZF':
if self.magic == b"TRZF":
hdrlen = self.vhdrlen + self.hdrlen
else:
hdrlen = self.hdrlen
hashes = b''
hashes = b""
for i in range(16):
if i == 0:
d = self.code[:IMAGE_CHUNK_SIZE - hdrlen]
d = self.code[: IMAGE_CHUNK_SIZE - hdrlen]
else:
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:
h = pyblake2.blake2s(d).digest()
else:
h = 32 * b'\x00'
h = 32 * b"\x00"
hashes += h
return hashes
@ -123,15 +117,28 @@ class BinImage(object):
self.hashes = self.compute_hashes()
def serialize_header(self, sig=True):
header = struct.pack('<4sIIIBBBBBBBB8s512s415s',
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)
header = struct.pack(
"<4sIIIBBBBBBBB8s512s415s",
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,
)
if sig:
header += struct.pack('<B64s', self.sigmask, self.sig)
header += struct.pack("<B64s", self.sigmask, self.sig)
else:
header += IMAGE_SIG_SIZE * b'\x00'
header += IMAGE_SIG_SIZE * b"\x00"
assert len(header) == self.hdrlen
return header
@ -146,104 +153,122 @@ class BinImage(object):
self.sig = signature
def write(self, filename):
with open(filename, 'wb') as f:
with open(filename, "wb") as f:
f.write(self.serialize_header())
f.write(self.code)
class FirmwareImage(BinImage):
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.vheader = data[:vhdrlen]
def write(self, filename):
with open(filename, 'wb') as f:
with open(filename, "wb") as f:
f.write(self.vheader)
f.write(self.serialize_header())
f.write(self.code)
class BootloaderImage(BinImage):
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):
def __init__(self, data):
header = struct.unpack('<4sIIBBBBH', data[:18])
self.magic, \
self.hdrlen, \
self.expiry, \
self.vmajor, \
self.vminor, \
self.vsig_m, \
self.vsig_n, \
self.vtrust = header
assert self.magic == b'TRZV'
data = data[:self.hdrlen] # strip remaining data (firmware)
header = struct.unpack("<4sIIBBBBH", data[:18])
self.magic, self.hdrlen, self.expiry, self.vmajor, self.vminor, 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_n > 0 and self.vsig_n <= 8
p = 32
self.vpub = []
for _ in range(self.vsig_n):
self.vpub.append(data[p:p + 32])
self.vpub.append(data[p : p + 32])
p += 32
self.vstr_len = data[p]
p += 1
self.vstr = data[p:p + self.vstr_len]
self.vstr = data[p : p + self.vstr_len]
p += self.vstr_len
vstr_pad = -p & 3
p += vstr_pad
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
self.sigmask = data[p]
p += 1
self.sig = data[p:p + 64]
assert len(data) == 4 + 4 + 4 + 1 + 1 + 1 + 1 + 1 + 15 + \
32 * len(self.vpub) + \
1 + self.vstr_len + vstr_pad + \
self.vimg_len + \
IMAGE_SIG_SIZE
self.sig = data[p : p + 64]
assert (
len(data)
== 4
+ 4
+ 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
def print(self):
print('TREZOR Vendor Header')
print(' * magic :', self.magic.decode())
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))
print(' * trust :', format_vtrust(self.vtrust))
print("TREZOR Vendor Header")
print(" * magic :", self.magic.decode())
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))
print(" * trust :", format_vtrust(self.vtrust))
for i in range(self.vsig_n):
print(' * vpub #%d :' % (i + 1), binascii.hexlify(self.vpub[i]).decode())
print(' * vstr :', self.vstr.decode())
print(' * vhash :', binascii.hexlify(self.vhash()).decode())
print(' * vimg : (%d bytes)' % len(self.vimg))
print(' * sigmask :', format_sigmask(self.sigmask))
print(' * sig :', binascii.hexlify(self.sig).decode())
print(' * fngprnt :', self.fingerprint())
print(" * vpub #%d :" % (i + 1), binascii.hexlify(self.vpub[i]).decode())
print(" * vstr :", self.vstr.decode())
print(" * vhash :", binascii.hexlify(self.vhash()).decode())
print(" * vimg : (%d bytes)" % len(self.vimg))
print(" * sigmask :", format_sigmask(self.sigmask))
print(" * sig :", binascii.hexlify(self.sig).decode())
print(" * fngprnt :", self.fingerprint())
print()
def serialize_header(self, sig=True):
header = struct.pack('<4sIIBBBBH',
self.magic, self.hdrlen, self.expiry,
self.vmajor, self.vminor,
self.vsig_m, self.vsig_n, self.vtrust)
header += 14 * b'\x00'
header = struct.pack(
"<4sIIBBBBH",
self.magic,
self.hdrlen,
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):
header += self.vpub[i]
header += struct.pack('<B', self.vstr_len) + self.vstr
header += (-len(header) & 3) * b'\x00' # vstr_pad
header += struct.pack("<B", self.vstr_len) + self.vstr
header += (-len(header) & 3) * b"\x00" # vstr_pad
header += self.vimg
if sig:
header += struct.pack('<B64s', self.sigmask, self.sig)
header += struct.pack("<B64s", self.sigmask, self.sig)
else:
header += IMAGE_SIG_SIZE * b'\x00'
header += IMAGE_SIG_SIZE * b"\x00"
assert len(header) == self.hdrlen
return header
@ -252,12 +277,12 @@ class VendorHeader(object):
def vhash(self):
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):
if i < self.vsig_n:
h.update(self.vpub[i])
else:
h.update(b'\x00' * 32)
h.update(b"\x00" * 32)
return h.digest()
def sign(self, sigmask, signature):
@ -267,54 +292,57 @@ class VendorHeader(object):
self.sig = signature
def write(self, filename):
with open(filename, 'wb') as f:
with open(filename, "wb") as f:
f.write(self.serialize_header())
def binopen(filename):
data = open(filename, 'rb').read()
data = open(filename, "rb").read()
magic = data[:4]
if magic == b'TRZB':
if magic == b"TRZB":
return BootloaderImage(data)
if magic == b'TRZV':
if magic == b"TRZV":
vheader = VendorHeader(data)
if len(data) == vheader.hdrlen:
return vheader
vheader.print()
subdata = data[vheader.hdrlen:]
if subdata[:4] == b'TRZF':
subdata = data[vheader.hdrlen :]
if subdata[:4] == b"TRZF":
firmware = FirmwareImage(data, vheader.hdrlen)
# check signatures against signing keys in the vendor header
if firmware.sigmask > 0:
pk = [vheader.vpub[i] for i in range(8) if firmware.sigmask & (1 << i)]
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()
try:
cosi.verify(firmware.sig, digest, global_pk)
print('Firmware signature OK')
except:
print('Firmware signature INCORRECT')
print("Firmware signature OK")
except ValueError:
print("Firmware signature INCORRECT")
else:
print('No firmware signature')
print("No firmware signature")
return firmware
if magic == b'TRZF':
if magic == b"TRZF":
return FirmwareImage(data, 0)
raise Exception('Unknown file format')
raise Exception("Unknown file format")
def main():
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
fn = sys.argv[1]
sign = len(sys.argv) > 2 and sys.argv[2] == '-s'
rehash = len(sys.argv) == 3 and sys.argv[2] == '-h'
sign = len(sys.argv) > 2 and sys.argv[2] == "-s"
rehash = len(sys.argv) == 3 and sys.argv[2] == "-h"
b = binopen(fn)
if sign:
sigmask = 0
if ':' in sys.argv[3]:
for idx in sys.argv[3].split(':'):
if ":" in sys.argv[3]:
for idx in sys.argv[3].split(":"):
sigmask |= 1 << (int(idx) - 1)
else:
sigmask = 1 << (int(sys.argv[3]) - 1)
@ -327,5 +355,5 @@ def main():
b.print()
if __name__ == '__main__':
if __name__ == "__main__":
main()

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import os
COMMENT_PREFIX = '/// '
COMMENT_PREFIX = "/// "
current_indent = 0
current_class = None
@ -14,24 +14,24 @@ def split_to_parts(line, mod_desc=None):
global current_class
global current_method
if line.startswith('class '):
current_class = line[6:].split('(')[0].strip(':')
if line.startswith("class "):
current_class = line[6:].split("(")[0].strip(":")
current_indent = 0
yield (current_package, "\n")
yield (current_package, '# ' + mod_desc + "\n")
yield (current_package, "# " + mod_desc + "\n")
elif line.startswith('def '):
current_method = line[4:].split('(')[0]
elif line.startswith("def "):
current_method = line[4:].split("(")[0]
yield (current_package, "\n")
if current_class is None:
yield (current_package, '# ' + mod_desc + "\n")
yield (current_package, "# " + mod_desc + "\n")
else:
current_indent = 4
line = current_indent * ' ' + line
line = current_indent * " " + line
yield (current_package, line)
@ -43,16 +43,16 @@ def store_to_file(dest, parts):
if not os.path.exists(dirpath):
os.makedirs(dirpath)
open(os.path.join(dirpath, '__init__.py'), 'w').close()
open(os.path.join(dirpath, '.mock-generated'), 'w').close()
open(os.path.join(dirpath, "__init__.py"), "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):
with open(filepath, 'a') as f:
f.write('from typing import *\n')
with open(filepath, "a") as f:
f.write("from typing import *\n")
with open(filepath, 'a') as f:
with open(filepath, "a") as f:
f.write(line)
@ -61,24 +61,23 @@ def build_module(mod_file, dest):
global current_class
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
if not os.path.basename(mod_file).startswith('mod'):
if not os.path.basename(mod_file).startswith("mod"):
return
current_indent = 0
current_class = None
current_package = os.path.basename(mod_file) \
.split('.')[0] \
.split('-')[0] \
.replace('mod', '')
mod_desc = mod_file.replace('../embed/extmod', 'extmod')
current_package = (
os.path.basename(mod_file).split(".")[0].split("-")[0].replace("mod", "")
)
mod_desc = mod_file.replace("../embed/extmod", "extmod")
for l in open(mod_file):
if not l.startswith(COMMENT_PREFIX):
continue
l = l[len(COMMENT_PREFIX):] # .strip()
l = l[len(COMMENT_PREFIX) :] # .strip()
store_to_file(dest, split_to_parts(l, mod_desc))
@ -92,7 +91,7 @@ def build_directory(dir, dest):
def clear_directory(top_dir):
print("Clearing up directory", top_dir)
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)
continue
for name in files:
@ -108,6 +107,6 @@ def clear_directory(top_dir):
os.rmdir(root)
if __name__ == '__main__':
clear_directory('../mocks/generated')
build_directory('../embed/extmod', '../mocks/generated')
if __name__ == "__main__":
clear_directory("../mocks/generated")
build_directory("../embed/extmod", "../mocks/generated")

View File

@ -3,58 +3,62 @@ import sys
import struct
import binascii
# encode vendor name, add length byte and padding to multiple of 4
def encode_vendor(vname):
vbin = vname.encode()
vbin = struct.pack('<B', len(vbin)) + vbin
vbin += b'\0' * (-len(vbin) & 3)
vbin = struct.pack("<B", len(vbin)) + vbin
vbin += b"\0" * (-len(vbin) & 3)
return vbin
def encode_pubkey(pubkey):
if len(pubkey) != 64:
raise Exception('Wrong public key length')
raise Exception("Wrong public key length")
return binascii.unhexlify(pubkey)
def decode_vtrust(vtrust):
t = 0xFFFF
for i, b in enumerate(reversed(vtrust)):
if b != '.':
if b != ".":
t &= ~(1 << i)
return t
def main():
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
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])
(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])
vname = sys.argv[5]
ifn = sys.argv[6]
ofn = sys.argv[7]
if not ifn.endswith('.toif'):
print('Must provide TOIF file')
if not ifn.endswith(".toif"):
print("Must provide TOIF file")
return 2
expiry = 0
vheader = b'TRZV' + \
struct.pack('<IIBBBBH', 0, expiry, vmajor, vminor, m, len(keys), vtrust)
vheader += 14 * b'\0'
vheader = b"TRZV" + struct.pack(
"<IIBBBBH", 0, expiry, vmajor, vminor, m, len(keys), vtrust
)
vheader += 14 * b"\0"
for k in keys:
vheader += k
vheader += encode_vendor(vname) + open(ifn, 'rb').read()
vheader += encode_vendor(vname) + open(ifn, "rb").read()
padding = 65 + (-len(vheader) - 65) & 511
vheader += b'\0' * padding
vheader += b"\0" * padding
# 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)

View File

@ -5,16 +5,19 @@ from hashlib import sha256
import requests
REPO = 'certifi/python-certifi'
REPO = "certifi/python-certifi"
def fetch_certdata():
r = requests.get('https://api.github.com/repos/%s/git/refs/heads/master' % REPO)
assert(r.status_code == 200)
commithash = r.json()['object']['sha']
r = requests.get("https://api.github.com/repos/%s/git/refs/heads/master" % REPO)
assert r.status_code == 200
commithash = r.json()["object"]["sha"]
r = requests.get('https://raw.githubusercontent.com/%s/%s/certifi/cacert.pem' % (REPO, commithash))
assert(r.status_code == 200)
r = requests.get(
"https://raw.githubusercontent.com/%s/%s/certifi/cacert.pem"
% (REPO, commithash)
)
assert r.status_code == 200
certdata = r.text
return commithash, certdata
@ -22,21 +25,21 @@ def fetch_certdata():
def process_certdata(data):
certs = {}
lines = [x.strip() for x in data.split('\n')]
lines = [x.strip() for x in data.split("\n")]
label = None
value = None
for line in lines:
if line.startswith('# Label: '):
assert(label is None)
assert(value is None)
if line.startswith("# Label: "):
assert label is None
assert value is None
label = line.split('"')[1]
elif line == '-----BEGIN CERTIFICATE-----':
assert(label is not None)
assert(value is None)
value = ''
elif line == '-----END CERTIFICATE-----':
assert(label is not None)
assert(value is not None)
elif line == "-----BEGIN CERTIFICATE-----":
assert label is not None
assert value is None
value = ""
elif line == "-----END CERTIFICATE-----":
assert label is not None
assert value is not None
certs[label] = b64decode(value)
label, value = None, None
else:
@ -49,22 +52,25 @@ def process_certdata(data):
def main():
commithash, certdata = fetch_certdata()
print('# fetched from https://github.com/%s' % REPO)
print('# commit %s' % commithash)
print("# fetched from https://github.com/%s" % REPO)
print("# commit %s" % commithash)
certs = process_certdata(certdata)
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():
h = sha256(v)
print(' # %s' % k)
print(' # %s' % h.hexdigest())
print(' %s,' % h.digest())
print(']')
print(" # %s" % k)
print(" # %s" % h.hexdigest())
print(" %s," % h.digest())
print("]")
if __name__ == '__main__':
if __name__ == "__main__":
main()

View File

@ -2,43 +2,43 @@
import json
fields = [
'coin_name',
'coin_shortcut',
'address_type',
'address_type_p2sh',
'maxfee_kb',
'signed_message_header',
'xpub_magic',
'bech32_prefix',
'cashaddr_prefix',
'slip44',
'segwit',
'fork_id',
'force_bip143',
'version_group_id',
'bip115',
'curve_name',
"coin_name",
"coin_shortcut",
"address_type",
"address_type_p2sh",
"maxfee_kb",
"signed_message_header",
"xpub_magic",
"bech32_prefix",
"cashaddr_prefix",
"slip44",
"segwit",
"fork_id",
"force_bip143",
"version_group_id",
"bip115",
"curve_name",
]
support = json.load(open('../../vendor/trezor-common/defs/support.json', 'r'))
coins = support['trezor2'].keys()
support = json.load(open("../../vendor/trezor-common/defs/support.json", "r"))
coins = support["trezor2"].keys()
print('COINS = [')
print("COINS = [")
for c in coins:
print(' CoinInfo(')
name = c.replace(' ', '_').lower()
if name == 'testnet':
name = 'bitcoin_testnet'
data = json.load(open('../../vendor/trezor-common/defs/coins/%s.json' % name, 'r'))
print(" CoinInfo(")
name = c.replace(" ", "_").lower()
if name == "testnet":
name = "bitcoin_testnet"
data = json.load(open("../../vendor/trezor-common/defs/coins/%s.json" % name, "r"))
for n in fields:
if n in ['xpub_magic', 'version_group_id']:
v = '0x%08x' % data[n] if data[n] is not None else 'None'
if n in ["xpub_magic", "version_group_id"]:
v = "0x%08x" % data[n] if data[n] is not None else "None"
else:
v = repr(data[n])
if n == 'curve_name':
v = v.replace('_', '-')
print(' %s=%s,' % (n, v))
print(' ),')
if n == "curve_name":
v = v.replace("_", "-")
print(" %s=%s," % (n, v))
print(" ),")
print(']')
print("]")

View File

@ -1,14 +1,14 @@
#!/usr/bin/env python3
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:
print(' NetworkInfo(')
for f in ['chain_id', 'slip44', 'shortcut', 'name', 'rskip60']:
print(' %s=%s,' % (f, repr(n[f])))
print(' ),')
print(" NetworkInfo(")
for f in ["chain_id", "slip44", "shortcut", "name", "rskip60"]:
print(" %s=%s," % (f, repr(n[f])))
print(" ),")
print(']')
print("]")

View File

@ -5,8 +5,8 @@
import freetype
MIN_GLYPH = ord(' ')
MAX_GLYPH = ord('~')
MIN_GLYPH = ord(" ")
MAX_GLYPH = ord("~")
FONT_BPP = 4
@ -14,20 +14,23 @@ FONT_BPP = 4
def process_face(name, style, size):
print('Processing ... %s %s %s' % (name, style, size))
face = freetype.Face('/usr/share/fonts/truetype/%s-%s.ttf' % (name, style))
print("Processing ... %s %s %s" % (name, style, size))
face = freetype.Face("/usr/share/fonts/truetype/%s-%s.ttf" % (name, style))
face.set_pixel_sizes(0, size)
fontname = '%s_%s_%d' % (name.lower(), style.lower(), size)
with open('font_%s.h' % fontname, 'wt') as f:
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))
with open('font_%s.c' % fontname, 'wt') as f:
fontname = "%s_%s_%d" % (name.lower(), style.lower(), size)
with open("font_%s.h" % fontname, "wt") as f:
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)
)
with open("font_%s.c" % fontname, "wt") as f:
f.write('#include "font_%s.h"\n\n' % fontname)
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('// bearingX and bearingY of the horizontal metrics of the glyph\n')
f.write('// rest is packed 4-bit glyph data\n\n')
f.write('// clang-format off\n\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("// bearingX and bearingY of the horizontal metrics of the glyph\n")
f.write("// rest is packed 4-bit glyph data\n\n")
f.write("// clang-format off\n\n")
for i in range(MIN_GLYPH, MAX_GLYPH + 1):
c = chr(i)
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
# 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
if c in 'jy}),/' and bearingX < 0:
if c in "jy}),/" and bearingX < 0:
advance += -bearingX
bearingX = 0
bearingY = metrics.horiBearingY // 64
assert advance >= 0 and advance <= 255
assert bearingX >= 0 and bearingX <= 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))
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))
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,
)
)
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)
if len(buf) > 0:
if FONT_BPP == 2:
for _ in range(4 - len(buf) % 4):
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:
if len(buf) % 2 > 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)]]
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))
buf = [
((a & 0xF0) | (b >> 4))
for a, b in [buf[i : i + 2] for i in range(0, len(buf), 2)]
]
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):
f.write(' Font_%s_%s_%d_glyph_%d,\n' % (name, style, size, i))
f.write('};\n')
f.write(" Font_%s_%s_%d_glyph_%d,\n" % (name, style, size, i))
f.write("};\n")
process_face('Roboto', 'Regular', 20)
process_face('Roboto', 'Bold', 20)
process_face('RobotoMono', 'Regular', 20)
process_face("Roboto", "Regular", 20)
process_face("Roboto", "Bold", 20)
process_face("RobotoMono", "Regular", 20)

View File

@ -5,16 +5,16 @@ from trezorlib import ed25519raw
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()
seckey = c.encode() * 32
seckey_hex = binascii.hexlify(seckey).decode()
print('seckey', seckey_hex)
print(' ', hex_to_c(seckey_hex))
print("seckey", seckey_hex)
print(" ", hex_to_c(seckey_hex))
pubkey = ed25519raw.publickey(seckey)
pubkey_hex = binascii.hexlify(pubkey).decode()
print('pubkey', pubkey_hex)
print(' ', hex_to_c(pubkey_hex))
print("pubkey", pubkey_hex)
print(" ", hex_to_c(pubkey_hex))

View File

@ -3,16 +3,15 @@
# script used to generate /embed/extmod/modtrezorui/loader.h
import math
import sys
outer = 60
inner = 42
with open('loader.h', 'wt') as f:
f.write('static const int img_loader_size = %d;\n' % outer)
f.write('static const uint16_t img_loader[%d][%d] = {\n' % (outer, outer))
with open("loader.h", "wt") as f:
f.write("static const int img_loader_size = %d;\n" % outer)
f.write("static const uint16_t img_loader[%d][%d] = {\n" % (outer, outer))
for y in range(outer):
f.write(' {')
f.write(" {")
for x in range(outer):
d = math.sqrt((outer - 1 - x) ** 2 + (outer - 1 - y) ** 2)
c = {}
@ -33,6 +32,6 @@ with open('loader.h', 'wt') as f:
c[i] = max(0, min(int(c[i]), 15))
a = int(math.atan2((outer - 1 - x), (outer - 1 - y)) * 2 * 249 / math.pi)
v = (a << 8) | (c[15] << 4) | c[5]
f.write('%d,' % v)
f.write('},\n')
f.write('};\n')
f.write("%d," % v)
f.write("},\n")
f.write("};\n")

View File

@ -18,29 +18,31 @@ def format_primitive(value):
fields = [
'name',
'ticker',
'namespace',
'mosaic',
'divisibility',
'levy',
'fee',
'levy_namespace',
'levy_mosaic',
'networks',
"name",
"ticker",
"namespace",
"mosaic",
"divisibility",
"levy",
"fee",
"levy_namespace",
"levy_mosaic",
"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('mosaics = [')
print(
"# generated using gen_nem_mosaics.py from trezor-common nem_mosaics.json - do not edit directly!"
)
print("")
print("mosaics = [")
for m in mosaics:
print(' {')
print(" {")
for name in fields:
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:
# print(' %s: None,' % format_str(name))
print(' },')
print(']')
print(" },")
print("]")

View File

@ -8,9 +8,11 @@ devices = HidTransport.enumerate()
if len(devices) > 0:
t = TrezorClient(devices[0])
else:
raise Exception('No TREZOR found')
raise Exception("No TREZOR found")
for i in [0, 1, 2]:
path = "m/10018'/%d'" % i
pk = t.get_public_node(t.expand_path(path), ecdsa_curve_name='ed25519', show_display=True)
print(path, '=>', binascii.hexlify(pk.node.public_key).decode())
pk = t.get_public_node(
t.expand_path(path), ecdsa_curve_name="ed25519", show_display=True
)
print(path, "=>", binascii.hexlify(pk.node.public_key).decode())

View File

@ -16,11 +16,11 @@ out = bytearray()
for addr, fn in files:
addr = int(addr, 16) - offset
data = open(fn, 'rb').read()
data = open(fn, "rb").read()
if len(out) < addr:
out += b'\x00' * (addr - len(out))
out += b"\x00" * (addr - len(out))
if len(out) != addr:
raise Exception('Alignment failed')
raise Exception("Alignment failed")
out += data
sys.stdout.buffer.write(out)

View File

@ -5,23 +5,19 @@ import click
import pyblake2
from trezorlib import cosi
indexmap = {
'bootloader': 0,
'vendorheader': 1,
'firmware': 2,
}
indexmap = {"bootloader": 0, "vendorheader": 1, "firmware": 2}
def header_digest(index, filename):
data = open(filename, 'rb').read()
data = open(filename, "rb").read()
z = bytes(65 * [0x00])
if index == 'bootloader':
if index == "bootloader":
header = data[:0x03BF] + z
elif index == 'vendorheader':
elif index == "vendorheader":
header = data[:-65] + z
elif index == 'firmware':
vhdrlen = struct.unpack('<I', data[4:8])[0]
header = data[vhdrlen:vhdrlen + 0x03BF] + z
elif index == "firmware":
vhdrlen = struct.unpack("<I", data[4:8])[0]
header = data[vhdrlen : vhdrlen + 0x03BF] + z
else:
raise ValueError('Unknown index "%s"' % index)
return pyblake2.blake2s(header).digest()
@ -32,10 +28,10 @@ def cli():
pass
@cli.command(help='')
@click.argument('index', type=click.Choice(indexmap.keys()))
@click.argument('filename')
@click.argument('seckeys', nargs=-1)
@cli.command(help="")
@click.argument("index", type=click.Choice(indexmap.keys()))
@click.argument("filename")
@click.argument("seckeys", nargs=-1)
def sign(index, filename, seckeys):
# compute header digest
digest = header_digest(index, filename)
@ -63,5 +59,5 @@ def sign(index, filename, seckeys):
print(binascii.hexlify(sig).decode())
if __name__ == '__main__':
if __name__ == "__main__":
cli()

View File

@ -8,23 +8,19 @@ import serpent
from trezorlib import cosi
PORT = 5001
indexmap = {
'bootloader': 0,
'vendorheader': 1,
'firmware': 2,
}
indexmap = {"bootloader": 0, "vendorheader": 1, "firmware": 2}
def header_digest(index, filename):
data = open(filename, 'rb').read()
data = open(filename, "rb").read()
z = bytes(65 * [0x00])
if index == 'bootloader':
if index == "bootloader":
header = data[:0x03BF] + z
elif index == 'vendorheader':
elif index == "vendorheader":
header = data[:-65] + z
elif index == 'firmware':
vhdrlen = struct.unpack('<I', data[4:8])[0]
header = data[vhdrlen:vhdrlen + 0x03BF] + z
elif index == "firmware":
vhdrlen = struct.unpack("<I", data[4:8])[0]
header = data[vhdrlen : vhdrlen + 0x03BF] + z
else:
raise ValueError('Unknown index "%s"' % index)
return pyblake2.blake2s(header).digest()
@ -35,20 +31,20 @@ def cli():
pass
@cli.command(help='')
@click.argument('index', type=click.Choice(indexmap.keys()))
@click.argument('filename')
@click.argument('participants', nargs=-1)
@cli.command(help="")
@click.argument("index", type=click.Choice(indexmap.keys()))
@click.argument("filename")
@click.argument("participants", nargs=-1)
def sign(index, filename, participants):
# compute header digest
digest = header_digest(index, filename)
# create participant proxies
if len(participants) < 1:
raise ValueError('Not enough participants')
print('connecting to %d participants:' % len(participants))
raise ValueError("Not enough participants")
print("connecting to %d participants:" % len(participants))
proxy = []
for p in participants:
uri = 'PYRO:keyctl@%s:%d' % (p, PORT)
uri = "PYRO:keyctl@%s:%d" % (p, PORT)
proxy.append(Pyro4.Proxy(uri))
# collect commits
pks, Rs = [], []
@ -57,7 +53,7 @@ def sign(index, filename, participants):
pk, R = serpent.tobytes(pk), serpent.tobytes(R)
pks.append(pk)
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
global_pk = cosi.combine_keys(pks)
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 = serpent.tobytes(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
sig = cosi.combine_sig(global_R, sigs)
cosi.verify(sig, digest, global_pk)
print('global signature:')
print("global signature:")
print(binascii.hexlify(sig).decode())
if __name__ == '__main__':
if __name__ == "__main__":
cli()

View File

@ -5,16 +5,13 @@ import Pyro4
import serpent
PORT = 5001
indexmap = {
'bootloader': 0,
'vendorheader': 1,
'firmware': 2,
}
indexmap = {"bootloader": 0, "vendorheader": 1, "firmware": 2}
def get_trezor():
from trezorlib.client import TrezorClient
from trezorlib.transport import get_transport
return TrezorClient(get_transport())
@ -24,7 +21,6 @@ def get_path(index):
@Pyro4.expose
class KeyctlProxy(object):
def get_commit(self, index, digest):
digest = serpent.tobytes(digest)
path = get_path(index)
@ -32,41 +28,53 @@ class KeyctlProxy(object):
while commit is None:
try:
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)
except Exception as e:
print(e)
print('Trying again ...')
print("Trying again ...")
pk = commit.pubkey
R = commit.commitment
print('Commitment sent!')
print("Commitment sent!")
return (pk, R)
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)
signature = None
while signature is None:
try:
t = get_trezor()
print('\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)
print(
"\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:
print(e)
print('Trying again ...')
print("Trying again ...")
sig = signature.signature
print('Signature sent!')
print("Signature sent!")
return sig
if __name__ == '__main__':
if __name__ == "__main__":
if len(sys.argv) > 1:
ipaddr = sys.argv[1]
else:
print('Usage: keyctl-proxy ipaddress')
print("Usage: keyctl-proxy ipaddress")
sys.exit(1)
daemon = Pyro4.Daemon(host=ipaddr, port=PORT)
proxy = KeyctlProxy()
uri = daemon.register(proxy, 'keyctl')
uri = daemon.register(proxy, "keyctl")
print('keyctl-proxy running at URI: "%s"' % uri)
daemon.requestLoop()

View File

@ -12,7 +12,7 @@ def process_rgb(w, h, pix):
for i in range(w):
r, g, b = pix[i, j]
c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)
data += struct.pack('>H', c)
data += struct.pack(">H", c)
return data
@ -22,89 +22,95 @@ def process_grayscale(w, h, pix):
for i in range(w // 2):
l1, l2 = pix[i * 2, j], pix[i * 2 + 1, j]
c = (l1 & 0xF0) | (l2 >> 4)
data += struct.pack('>B', c)
data += struct.pack(">B", c)
return data
def process_image(ifn, savefiles=False):
im = Image.open(ifn)
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':
print('Detected RGB mode')
elif im.mode == 'L':
if im.mode == "RGB":
print("Detected RGB mode")
elif im.mode == "L":
if w % 2 > 0:
print('PNG file must have width divisible by 2')
print("PNG file must have width divisible by 2")
return 3
print('Detected GRAYSCALE mode')
print("Detected GRAYSCALE mode")
else:
print('Unknown mode:', im.mode)
print("Unknown mode:", im.mode)
return 4
pix = im.load()
bname = basename(ifn[:-4])
ofn_h = '%s.h' % bname
ofn_py = '%s.py' % bname
ofn_h = "%s.h" % bname
ofn_py = "%s.py" % bname
if im.mode == 'RGB':
ofn = '%s.toif' % bname
if im.mode == "RGB":
ofn = "%s.toif" % bname
pixeldata = process_rgb(w, h, pix)
else:
ofn = '%s.toig' % bname
ofn = "%s.toig" % bname
pixeldata = process_grayscale(w, h, pix)
z = zlib.compressobj(level=9, wbits=10)
zdata = z.compress(pixeldata) + z.flush()
zdata = zdata[2:-4] # strip header and checksum
data = b''
if im.mode == 'RGB':
data += b'TOIf'
data = b""
if im.mode == "RGB":
data += b"TOIf"
else:
data += b'TOIg'
data += struct.pack('<HH', w, h)
data += struct.pack('<I', len(zdata))
data += b"TOIg"
data += struct.pack("<HH", w, h)
data += struct.pack("<I", len(zdata))
data += zdata
if savefiles:
with open(ofn, 'wb') as f:
with open(ofn, "wb") as f:
f.write(data)
print('Written %s ... %d bytes' % (ofn, len(data)))
with open(ofn_py, 'wb') as f:
f.write(('%s = %s\n' % (bname, data)).encode())
print('Written %s ... %d bytes' % (ofn_py, len(data)))
with open(ofn_h, 'wt') as f:
f.write('// clang-format off\n')
f.write('static const uint8_t toi_%s[] = {\n' % bname)
f.write(' // magic\n')
if im.mode == 'RGB':
print("Written %s ... %d bytes" % (ofn, len(data)))
with open(ofn_py, "wb") as f:
f.write(("%s = %s\n" % (bname, data)).encode())
print("Written %s ... %d bytes" % (ofn_py, len(data)))
with open(ofn_h, "wt") as f:
f.write("// clang-format off\n")
f.write("static const uint8_t toi_%s[] = {\n" % bname)
f.write(" // magic\n")
if im.mode == "RGB":
f.write(" 'T', 'O', 'I', 'f',\n")
else:
f.write(" 'T', 'O', 'I', 'g',\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(" // 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)
)
l = len(zdata)
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(' // compressed data\n')
f.write(' ')
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(" // compressed data\n")
f.write(" ")
for b in zdata:
f.write(' 0x%02x,' % b)
f.write('\n};\n')
print('Written %s ... done' % ofn_py)
f.write(" 0x%02x," % b)
f.write("\n};\n")
print("Written %s ... done" % ofn_py)
return data
def main():
if len(sys.argv) < 2:
print('Usage png2toi image.png')
print("Usage png2toi image.png")
return 1
ifn = sys.argv[1]
if not ifn.endswith('.png'):
print('Must provide PNG file')
if not ifn.endswith(".png"):
print("Must provide PNG file")
return 2
process_image(ifn, savefiles=True)

View File

@ -6,20 +6,20 @@ resources = {}
resources_size = 0
os.chdir(os.path.dirname(__file__))
os.chdir('../src/')
os.chdir("../src/")
def process_file(name):
if name.endswith('.gitignore'):
if name.endswith(".gitignore"):
return
if name.endswith('.py'):
if name.endswith(".py"):
return
if os.path.basename(name).startswith('.'):
if os.path.basename(name).startswith("."):
return
with open(name, 'rb') as f:
with open(name, "rb") as f:
data = f.read()
resources[name] = data
print('processing file %s (%d bytes)' % (name, len(data)))
print("processing file %s (%d bytes)" % (name, len(data)))
global resources_size
resources_size += len(data)
@ -33,33 +33,35 @@ def process_dir_rec(dir):
process_dir_rec(path)
process_dir_rec('trezor/res/')
for name in os.listdir('apps/'):
path = os.path.join('apps/', name, 'res/')
process_dir_rec("trezor/res/")
for name in os.listdir("apps/"):
path = os.path.join("apps/", name, "res/")
if os.path.isdir(path):
process_dir_rec(path)
resfile = 'trezor/res/resources.py'
resfile = "trezor/res/resources.py"
bio = io.StringIO()
bio.write('# fmt: off\n')
bio.write('resdata = {\n')
bio.write("# fmt: off\n")
bio.write("resdata = {\n")
for k in sorted(resources.keys()):
bio.write(" '%s': %s,\n" % (k, resources[k]))
bio.write('}\n')
bio.write("}\n")
try:
with open(resfile, 'r') as f:
with open(resfile, "r") as f:
stale = f.read()
except:
except FileNotFoundError:
stale = None
fresh = bio.getvalue()
if stale != fresh:
with open(resfile, 'wt') as f:
with open(resfile, "wt") as f:
f.write(fresh)
print('written %s with %d entries (total %d bytes)' %
(resfile, len(resources), resources_size))
print(
"written %s with %d entries (total %d bytes)"
% (resfile, len(resources), resources_size)
)
else:
print('continuing with %s, no changes detected' % (resfile))
print("continuing with %s, no changes detected" % (resfile))

View File

@ -25,62 +25,64 @@ def process_grayscale(w, h, data):
def process_image(ifn, ofn):
data = open(ifn, 'rb').read()
data = open(ifn, "rb").read()
if ifn.endswith('.toif'):
if data[:4] != b'TOIf':
print('Unknown TOIF header')
if ifn.endswith(".toif"):
if data[:4] != b"TOIf":
print("Unknown TOIF header")
return 1
elif ifn.endswith('.toig'):
if data[:4] != b'TOIg':
print('Unknown TOIG header')
elif ifn.endswith(".toig"):
if data[:4] != b"TOIg":
print("Unknown TOIG header")
return 2
else:
print('Unsupported format')
print("Unsupported format")
return 3
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:]
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
data = zlib.decompress(data, -10)
if ifn.endswith('.toif'):
if ifn.endswith(".toif"):
if len(data) != w * h * 2:
print('Uncompressed data length mismatch (%d vs %d)' %
(len(data), w * h * 2))
print(
"Uncompressed data length mismatch (%d vs %d)" % (len(data), w * h * 2)
)
return 5
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)
print('Written %s ...' % ofn)
print("Written %s ..." % ofn)
if ifn.endswith('.toig'):
if ifn.endswith(".toig"):
if len(data) != w * h // 2:
print('Uncompressed data length mismatch (%d vs %d)' %
(len(data), w * h // 2))
print(
"Uncompressed data length mismatch (%d vs %d)" % (len(data), w * h // 2)
)
return 6
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)
print('Written %s ...' % ofn)
print("Written %s ..." % ofn)
def main():
if len(sys.argv) < 2:
print('Usage: toi2png image.toi[fg] [output]')
print("Usage: toi2png image.toi[fg] [output]")
return 1
ifn = sys.argv[1]
if not ifn.endswith('.toif') and not ifn.endswith('.toig'):
print('Must provide TOIF/TOIG file')
if not ifn.endswith(".toif") and not ifn.endswith(".toig"):
print("Must provide TOIF/TOIG file")
return 2
ofn = sys.argv[2] if len(sys.argv) > 2 else None