2017-10-05 05:41:36 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
import binascii
|
2018-01-29 14:02:32 +00:00
|
|
|
import struct
|
2017-10-05 05:41:36 +00:00
|
|
|
import click
|
|
|
|
import pyblake2
|
2018-05-28 15:59:33 +00:00
|
|
|
from trezorlib import cosi
|
2017-10-05 05:41:36 +00:00
|
|
|
|
2018-07-31 09:35:09 +00:00
|
|
|
indexmap = {"bootloader": 0, "vendorheader": 1, "firmware": 2}
|
2017-10-05 05:41:36 +00:00
|
|
|
|
|
|
|
|
2018-01-29 14:02:32 +00:00
|
|
|
def header_digest(index, filename):
|
2018-07-31 09:35:09 +00:00
|
|
|
data = open(filename, "rb").read()
|
2018-01-28 16:30:46 +00:00
|
|
|
z = bytes(65 * [0x00])
|
2018-07-31 09:35:09 +00:00
|
|
|
if index == "bootloader":
|
2018-01-29 14:02:32 +00:00
|
|
|
header = data[:0x03BF] + z
|
2018-07-31 09:35:09 +00:00
|
|
|
elif index == "vendorheader":
|
2018-01-29 14:02:32 +00:00
|
|
|
header = data[:-65] + z
|
2018-07-31 09:35:09 +00:00
|
|
|
elif index == "firmware":
|
|
|
|
vhdrlen = struct.unpack("<I", data[4:8])[0]
|
|
|
|
header = data[vhdrlen : vhdrlen + 0x03BF] + z
|
2018-01-29 08:10:19 +00:00
|
|
|
else:
|
|
|
|
raise ValueError('Unknown index "%s"' % index)
|
2018-01-29 14:02:32 +00:00
|
|
|
return pyblake2.blake2s(header).digest()
|
2018-01-28 16:30:46 +00:00
|
|
|
|
|
|
|
|
2017-10-05 05:41:36 +00:00
|
|
|
@click.group()
|
|
|
|
def cli():
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2018-07-31 09:35:09 +00:00
|
|
|
@cli.command(help="")
|
|
|
|
@click.argument("index", type=click.Choice(indexmap.keys()))
|
|
|
|
@click.argument("filename")
|
|
|
|
@click.argument("seckeys", nargs=-1)
|
2018-01-29 14:02:32 +00:00
|
|
|
def sign(index, filename, seckeys):
|
|
|
|
# compute header digest
|
|
|
|
digest = header_digest(index, filename)
|
|
|
|
# collect commits
|
2018-05-28 15:59:33 +00:00
|
|
|
pks, nonces, Rs = [], [], []
|
2018-01-29 14:02:32 +00:00
|
|
|
for ctr, seckey in enumerate(seckeys):
|
2017-10-05 05:41:36 +00:00
|
|
|
sk = binascii.unhexlify(seckey)
|
2018-05-28 15:59:33 +00:00
|
|
|
pk = cosi.pubkey_from_privkey(sk)
|
|
|
|
r, R = cosi.get_nonce(sk, digest, ctr)
|
2018-01-29 14:02:32 +00:00
|
|
|
pks.append(pk)
|
2018-05-28 15:59:33 +00:00
|
|
|
nonces.append(r)
|
2018-01-29 14:02:32 +00:00
|
|
|
Rs.append(R)
|
|
|
|
# compute global commit
|
2018-05-28 15:59:33 +00:00
|
|
|
global_pk = cosi.combine_keys(pks)
|
|
|
|
global_R = cosi.combine_keys(Rs)
|
2018-01-29 14:02:32 +00:00
|
|
|
# collect signatures
|
|
|
|
sigs = []
|
2018-05-28 15:59:33 +00:00
|
|
|
for seckey, nonce in zip(seckeys, nonces):
|
2017-10-05 05:41:36 +00:00
|
|
|
sk = binascii.unhexlify(seckey)
|
2018-05-28 15:59:33 +00:00
|
|
|
sig = cosi.sign_with_privkey(digest, sk, global_pk, nonce, global_R)
|
2018-01-29 14:02:32 +00:00
|
|
|
sigs.append(sig)
|
|
|
|
# compute global signature
|
2018-05-28 15:59:33 +00:00
|
|
|
sig = cosi.combine_sig(global_R, sigs)
|
|
|
|
cosi.verify(sig, digest, global_pk)
|
2017-10-05 05:41:36 +00:00
|
|
|
print(binascii.hexlify(sig).decode())
|
|
|
|
|
|
|
|
|
2018-07-31 09:35:09 +00:00
|
|
|
if __name__ == "__main__":
|
2017-10-05 05:41:36 +00:00
|
|
|
cli()
|