You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/core/tools/build_vendorheader

73 lines
2.4 KiB

#!/usr/bin/env python3
import json
import click
from trezorlib import firmware, toif
def minimum_header_len(spec):
spec = spec.copy()
spec["header_len"] = 512000
reparsed = firmware.VendorHeader.SUBCON.parse(
firmware.VendorHeader.SUBCON.build(spec)
)
data_length = reparsed._end_offset - reparsed._start_offset
# data length + 65 for signatures, rounded up to nearest multiple of 512
return (data_length + 65 + 511) // 512 * 512
@click.command()
@click.argument("specfile", type=click.File("r"))
@click.argument("image", type=click.File("rb"))
@click.argument("outfile", type=click.File("wb"))
@click.option("-c", "--check", is_flag=True, help="Check but do not write header.")
@click.option("-q", "--quiet", is_flag=True, help="Do not print anything.")
def build_vendorheader(specfile, image, outfile, check: bool, quiet: bool):
if quiet:
echo = lambda *args, **kwargs: None
else:
echo = click.echo
spec = json.load(specfile)
spec["pubkeys"] = [bytes.fromhex(k) for k in spec["pubkeys"]]
spec["image"] = toif.ToifStruct.parse(image.read())
spec["sigmask"] = 0
spec["signature"] = b"\x00" * 64
if spec["hw_model"] is None:
spec["hw_model"] = b"\x00\x00\x00\x00"
else:
spec["hw_model"] = spec["hw_model"].encode("ascii")
min_length = minimum_header_len(spec)
if "header_len" not in spec:
spec["header_len"] = min_length
elif spec["header_len"] < min_length:
raise click.ClickException(
f"Specified header_len {spec['header_len']} too low. "
f"Minimum allowable value is {min_length}."
)
elif spec["header_len"] == min_length:
echo(f"{specfile.name}: Header has correct length.")
else:
echo(
f"{specfile.name}: Extending header ({min_length} bytes) to {spec['header_len']} bytes."
)
if spec["header_len"] % 512 != 0:
raise click.ClickException("Invalid header_len: must be a multiple of 512")
vh_bytes = firmware.VendorHeader.SUBCON.build(spec)
if check:
outfile_bytes = outfile.read()
if outfile_bytes != vh_bytes:
raise click.ClickException(
f"Header file {outfile.name} differs from expected header."
)
else:
outfile.write(firmware.VendorHeader.SUBCON.build(spec))
if __name__ == "__main__":
build_vendorheader()