mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-13 17:00:59 +00:00
core/tools: drop tools obsoleted by headertool
This commit is contained in:
parent
9341f0d584
commit
1b04d1caa7
@ -214,8 +214,8 @@ gdb_firmware: $(FIRMWARE_BUILD_DIR)/firmware.elf ## start remote gdb session to
|
||||
## misc commands:
|
||||
|
||||
binctl: ## print info about binary files
|
||||
./tools/binctl $(BOOTLOADER_BUILD_DIR)/bootloader.bin
|
||||
./tools/binctl $(FIRMWARE_BUILD_DIR)/firmware.bin
|
||||
./tools/headertool.py $(BOOTLOADER_BUILD_DIR)/bootloader.bin
|
||||
./tools/headertool.py $(FIRMWARE_BUILD_DIR)/firmware.bin
|
||||
|
||||
bloaty: ## run bloaty size profiler
|
||||
bloaty -d symbols -n 0 -s file $(FIRMWARE_BUILD_DIR)/firmware.elf | less
|
||||
|
@ -160,8 +160,7 @@ env.Replace(
|
||||
ASPPFLAGS='$CFLAGS $CCFLAGS', )
|
||||
|
||||
env.Replace(
|
||||
BINCTL='tools/binctl',
|
||||
KEYCTL='tools/keyctl',
|
||||
HEADERTOOL='tools/headertool.py',
|
||||
)
|
||||
|
||||
#
|
||||
@ -186,6 +185,5 @@ program_bin = env.Command(
|
||||
source=program_elf,
|
||||
action=[
|
||||
'$OBJCOPY -O binary -j .header -j .flash -j .data $SOURCE $TARGET',
|
||||
'$BINCTL $TARGET -h',
|
||||
'$BINCTL $TARGET -s 1:2 `$KEYCTL sign bootloader $TARGET 4141414141414141414141414141414141414141414141414141414141414141 4242424242424242424242424242424242424242424242424242424242424242`' if ARGUMENTS.get('PRODUCTION', '0') == '0' else '',
|
||||
'$HEADERTOOL $TARGET ' + ('-D' if ARGUMENTS.get('PRODUCTION', '0') == '0' else ''),
|
||||
], )
|
||||
|
@ -397,8 +397,7 @@ env.Replace(
|
||||
ASPPFLAGS='$CFLAGS $CCFLAGS', )
|
||||
|
||||
env.Replace(
|
||||
BINCTL='tools/binctl',
|
||||
KEYCTL='tools/keyctl',
|
||||
HEADERTOOL='tools/headertool.py',
|
||||
PYTHON='python',
|
||||
MAKEQSTRDATA='$PYTHON vendor/micropython/py/makeqstrdata.py',
|
||||
MAKEVERSIONHDR='$PYTHON vendor/micropython/py/makeversionhdr.py',
|
||||
@ -613,8 +612,7 @@ if env.get('TREZOR_MODEL') == 'T':
|
||||
'$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data --pad-to 0x08100000 $SOURCE ${TARGET}.p1',
|
||||
'$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2',
|
||||
'$CAT ${TARGET}.p1 ${TARGET}.p2 > $TARGET',
|
||||
'$BINCTL $TARGET -h',
|
||||
'$BINCTL $TARGET -s 1:2 `$KEYCTL sign firmware $TARGET 4747474747474747474747474747474747474747474747474747474747474747 4848484848484848484848484848484848484848484848484848484848484848`' if ARGUMENTS.get('PRODUCTION', '0') == '0' else '',
|
||||
'$HEADERTOOL $TARGET ' + ('-D' if ARGUMENTS.get('PRODUCTION', '0') == '0' else ''),
|
||||
'$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6',
|
||||
]
|
||||
else:
|
||||
|
@ -136,8 +136,7 @@ env.Replace(
|
||||
ASPPFLAGS='$CFLAGS $CCFLAGS', )
|
||||
|
||||
env.Replace(
|
||||
BINCTL='tools/binctl',
|
||||
KEYCTL='tools/keyctl',
|
||||
HEADERTOOL='tools/headertool.py',
|
||||
)
|
||||
|
||||
#
|
||||
@ -172,6 +171,5 @@ program_bin = env.Command(
|
||||
source=program_elf,
|
||||
action=[
|
||||
'$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data $SOURCE $TARGET',
|
||||
'$BINCTL $TARGET -h',
|
||||
'$BINCTL $TARGET -s 1:2 `$KEYCTL sign firmware $TARGET 4747474747474747474747474747474747474747474747474747474747474747 4848484848484848484848484848484848484848484848484848484848484848`' if ARGUMENTS.get('PRODUCTION', '0') == '0' else '',
|
||||
'$HEADERTOOL $TARGET ' + ('-D' if ARGUMENTS.get('PRODUCTION', '0') == '0' else ''),
|
||||
], )
|
||||
|
@ -130,8 +130,7 @@ env.Replace(
|
||||
ASPPFLAGS='$CFLAGS $CCFLAGS', )
|
||||
|
||||
env.Replace(
|
||||
BINCTL='tools/binctl',
|
||||
KEYCTL='tools/keyctl',
|
||||
HEADERTOOL='tools/headertool.py',
|
||||
)
|
||||
|
||||
#
|
||||
@ -166,6 +165,5 @@ program_bin = env.Command(
|
||||
source=program_elf,
|
||||
action=[
|
||||
'$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data $SOURCE $TARGET',
|
||||
'$BINCTL $TARGET -h',
|
||||
'$BINCTL $TARGET -s 1:2 `$KEYCTL sign firmware $TARGET 4747474747474747474747474747474747474747474747474747474747474747 4848484848484848484848484848484848484848484848484848484848484848`' if ARGUMENTS.get('PRODUCTION', '0') == '0' else '',
|
||||
'$HEADERTOOL $TARGET ' + ('-D' if ARGUMENTS.get('PRODUCTION', '0') == '0' else ''),
|
||||
], )
|
||||
|
@ -1,363 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import struct
|
||||
import binascii
|
||||
|
||||
import pyblake2
|
||||
|
||||
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))
|
||||
|
||||
|
||||
def format_vtrust(vtrust):
|
||||
bits = [str(b) if vtrust & (1 << b) == 0 else "." for b in range(16)]
|
||||
# see docs/bootloader.md for vtrust constants
|
||||
desc = ""
|
||||
wait = (vtrust & 0x000F) ^ 0x000F
|
||||
if wait > 0:
|
||||
desc = "WAIT_%d" % wait
|
||||
if vtrust & 0x0010 == 0:
|
||||
desc += " RED"
|
||||
if vtrust & 0x0020 == 0:
|
||||
desc += " CLICK"
|
||||
if vtrust & 0x0040 == 0:
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
)
|
||||
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 len(self.code) == self.codelen
|
||||
|
||||
def print(self):
|
||||
if self.magic == b"TRZF":
|
||||
print("Trezor Firmware Image")
|
||||
total_len = self.vhdrlen + self.hdrlen + self.codelen
|
||||
elif self.magic == b"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"))
|
||||
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()
|
||||
|
||||
def compute_hashes(self):
|
||||
if self.magic == b"TRZF":
|
||||
hdrlen = self.vhdrlen + self.hdrlen
|
||||
else:
|
||||
hdrlen = self.hdrlen
|
||||
hashes = b""
|
||||
for i in range(16):
|
||||
if i == 0:
|
||||
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]
|
||||
if len(d) > 0:
|
||||
h = pyblake2.blake2s(d).digest()
|
||||
else:
|
||||
h = 32 * b"\x00"
|
||||
hashes += h
|
||||
return hashes
|
||||
|
||||
def check_hashes(self):
|
||||
return self.hashes == self.compute_hashes()
|
||||
|
||||
def update_hashes(self):
|
||||
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,
|
||||
)
|
||||
if sig:
|
||||
header += struct.pack("<B64s", self.sigmask, self.sig)
|
||||
else:
|
||||
header += IMAGE_SIG_SIZE * b"\x00"
|
||||
assert len(header) == self.hdrlen
|
||||
return header
|
||||
|
||||
def fingerprint(self):
|
||||
return pyblake2.blake2s(self.serialize_header(sig=False)).hexdigest()
|
||||
|
||||
def sign(self, sigmask, signature):
|
||||
header = self.serialize_header(sig=False)
|
||||
data = header + self.code
|
||||
assert len(data) == self.hdrlen + self.codelen
|
||||
self.sigmask = sigmask
|
||||
self.sig = signature
|
||||
|
||||
def write(self, filename):
|
||||
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,
|
||||
)
|
||||
self.vhdrlen = vhdrlen
|
||||
self.vheader = data[:vhdrlen]
|
||||
|
||||
def write(self, filename):
|
||||
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
|
||||
)
|
||||
|
||||
|
||||
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)
|
||||
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])
|
||||
p += 32
|
||||
self.vstr_len = data[p]
|
||||
p += 1
|
||||
self.vstr = data[p : p + self.vstr_len]
|
||||
p += self.vstr_len
|
||||
vstr_pad = -p & 3
|
||||
p += vstr_pad
|
||||
self.vimg_len = len(data) - IMAGE_SIG_SIZE - p
|
||||
self.vimg = data[p : p + self.vimg_len]
|
||||
p += self.vimg_len
|
||||
self.sigmask = data[p]
|
||||
p += 1
|
||||
self.sig = data[p : p + 64]
|
||||
assert (
|
||||
len(data)
|
||||
== 4
|
||||
+ 4
|
||||
+ 4
|
||||
+ 1
|
||||
+ 1
|
||||
+ 1
|
||||
+ 1
|
||||
+ 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))
|
||||
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()
|
||||
|
||||
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"
|
||||
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 += self.vimg
|
||||
if sig:
|
||||
header += struct.pack("<B64s", self.sigmask, self.sig)
|
||||
else:
|
||||
header += IMAGE_SIG_SIZE * b"\x00"
|
||||
assert len(header) == self.hdrlen
|
||||
return header
|
||||
|
||||
def fingerprint(self):
|
||||
return pyblake2.blake2s(self.serialize_header(sig=False)).hexdigest()
|
||||
|
||||
def vhash(self):
|
||||
h = pyblake2.blake2s()
|
||||
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)
|
||||
return h.digest()
|
||||
|
||||
def sign(self, sigmask, signature):
|
||||
header = self.serialize_header(sig=False)
|
||||
assert len(header) == self.hdrlen
|
||||
self.sigmask = sigmask
|
||||
self.sig = signature
|
||||
|
||||
def write(self, filename):
|
||||
with open(filename, "wb") as f:
|
||||
f.write(self.serialize_header())
|
||||
|
||||
|
||||
def binopen(filename):
|
||||
data = open(filename, "rb").read()
|
||||
magic = data[:4]
|
||||
if magic == b"TRZB":
|
||||
return BootloaderImage(data)
|
||||
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":
|
||||
firmware = FirmwareImage(data, vheader.hdrlen)
|
||||
# check signatures against signing keys in the vendor header
|
||||
if firmware.sigmask > 0:
|
||||
hdr = (
|
||||
subdata[: IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE]
|
||||
+ IMAGE_SIG_SIZE * b"\x00"
|
||||
)
|
||||
digest = pyblake2.blake2s(hdr).digest()
|
||||
try:
|
||||
cosi.verify(
|
||||
firmware.sig,
|
||||
digest,
|
||||
vheader.vsig_m,
|
||||
vheader.vpub,
|
||||
firmware.sigmask,
|
||||
)
|
||||
print("Firmware signature OK")
|
||||
except ValueError:
|
||||
print("Firmware signature INCORRECT")
|
||||
else:
|
||||
print("No firmware signature")
|
||||
return firmware
|
||||
if magic == b"TRZF":
|
||||
return FirmwareImage(data, 0)
|
||||
raise Exception("Unknown file format")
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
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"
|
||||
b = binopen(fn)
|
||||
if sign:
|
||||
sigmask = 0
|
||||
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)
|
||||
signature = binascii.unhexlify(sys.argv[4])
|
||||
b.sign(sigmask, signature)
|
||||
b.write(fn)
|
||||
if rehash:
|
||||
b.update_hashes()
|
||||
b.write(fn)
|
||||
b.print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,63 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import binascii
|
||||
import struct
|
||||
import click
|
||||
import pyblake2
|
||||
from trezorlib import cosi
|
||||
|
||||
indexmap = {"bootloader": 0, "vendorheader": 1, "firmware": 2}
|
||||
|
||||
|
||||
def header_digest(index, filename):
|
||||
data = open(filename, "rb").read()
|
||||
z = bytes(65 * [0x00])
|
||||
if index == "bootloader":
|
||||
header = data[:0x03BF] + z
|
||||
elif index == "vendorheader":
|
||||
header = data[:-65] + 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()
|
||||
|
||||
|
||||
@click.group()
|
||||
def cli():
|
||||
pass
|
||||
|
||||
|
||||
@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)
|
||||
# collect commits
|
||||
pks, nonces, Rs = [], [], []
|
||||
for ctr, seckey in enumerate(seckeys):
|
||||
sk = binascii.unhexlify(seckey)
|
||||
pk = cosi.pubkey_from_privkey(sk)
|
||||
r, R = cosi.get_nonce(sk, digest, ctr)
|
||||
pks.append(pk)
|
||||
nonces.append(r)
|
||||
Rs.append(R)
|
||||
# compute global commit
|
||||
global_pk = cosi.combine_keys(pks)
|
||||
global_R = cosi.combine_keys(Rs)
|
||||
# collect signatures
|
||||
sigs = []
|
||||
for seckey, nonce in zip(seckeys, nonces):
|
||||
sk = binascii.unhexlify(seckey)
|
||||
sig = cosi.sign_with_privkey(digest, sk, global_pk, nonce, global_R)
|
||||
sigs.append(sig)
|
||||
# compute global signature
|
||||
sig = cosi.combine_sig(global_R, sigs)
|
||||
cosi.verify_combined(sig, digest, global_pk)
|
||||
print(binascii.hexlify(sig).decode())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli()
|
@ -1,74 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import binascii
|
||||
import struct
|
||||
import click
|
||||
import pyblake2
|
||||
import Pyro4
|
||||
from trezorlib import cosi
|
||||
|
||||
Pyro4.config.SERIALIZER = "marshal"
|
||||
|
||||
PORT = 5001
|
||||
indexmap = {"bootloader": 0, "vendorheader": 1, "firmware": 2}
|
||||
|
||||
|
||||
def header_digest(index, filename):
|
||||
data = open(filename, "rb").read()
|
||||
z = bytes(65 * [0x00])
|
||||
if index == "bootloader":
|
||||
header = data[:0x03BF] + z
|
||||
elif index == "vendorheader":
|
||||
header = data[:-65] + 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()
|
||||
|
||||
|
||||
@click.group()
|
||||
def cli():
|
||||
pass
|
||||
|
||||
|
||||
@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))
|
||||
proxy = []
|
||||
for p in participants:
|
||||
uri = "PYRO:keyctl@%s:%d" % (p, PORT)
|
||||
proxy.append(Pyro4.Proxy(uri))
|
||||
# collect commits
|
||||
pks, Rs = [], []
|
||||
for i, p in enumerate(proxy):
|
||||
pk, R = p.get_commit(index, digest)
|
||||
pks.append(pk)
|
||||
Rs.append(R)
|
||||
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)
|
||||
# collect signatures
|
||||
sigs = []
|
||||
for i, p in enumerate(proxy):
|
||||
sig = p.get_signature(index, digest, global_R, global_pk)
|
||||
sigs.append(sig)
|
||||
print("collected signature #%d from %s" % (i, p._pyroUri.host))
|
||||
# compute global signature
|
||||
sig = cosi.combine_sig(global_R, sigs)
|
||||
cosi.verify_combined(sig, digest, global_pk)
|
||||
print("global signature:")
|
||||
print(binascii.hexlify(sig).decode())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli()
|
@ -16,7 +16,7 @@
|
||||
|
||||
import hashlib
|
||||
from enum import Enum
|
||||
from typing import Callable, List, NewType, Tuple
|
||||
from typing import Callable, List, Tuple
|
||||
|
||||
import construct as c
|
||||
import ecdsa
|
||||
|
Loading…
Reference in New Issue
Block a user