mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-13 17:00:59 +00:00
feat(core): support checking generated vendor headers as part of make gen_check
[no changelog]
This commit is contained in:
parent
ec06cc5c40
commit
df84d96244
10
Makefile
10
Makefile
@ -130,6 +130,12 @@ ci_docs: ## generate CI documentation
|
|||||||
ci_docs_check: ## check that generated CI documentation is up to date
|
ci_docs_check: ## check that generated CI documentation is up to date
|
||||||
./tools/generate_ci_docs.py --check
|
./tools/generate_ci_docs.py --check
|
||||||
|
|
||||||
gen: mocks icons templates protobuf ci_docs ## regenerate auto-generated files from sources
|
vendorheader: ## generate vendor header
|
||||||
|
./core/embed/vendorheader/generate.sh --quiet
|
||||||
|
|
||||||
gen_check: mocks_check icons_check templates_check protobuf_check ci_docs_check ## check validity of auto-generated files
|
vendorheader_check: ## check that vendor header is up to date
|
||||||
|
./core/embed/vendorheader/generate.sh --quiet --check
|
||||||
|
|
||||||
|
gen: mocks icons templates protobuf ci_docs vendorheader ## regenerate auto-generated files from sources
|
||||||
|
|
||||||
|
gen_check: mocks_check icons_check templates_check protobuf_check ci_docs_check vendorheader_check ## check validity of auto-generated files
|
||||||
|
@ -1,10 +1,21 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
cd $(dirname $0)
|
cd $(dirname $0)
|
||||||
|
|
||||||
BUILDVH=$(realpath ../../tools/build_vendorheader)
|
BUILDVH=$(realpath ../../tools/build_vendorheader)
|
||||||
BINCTL=$(realpath ../../tools/headertool.py)
|
BINCTL=$(realpath ../../tools/headertool.py)
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
if [ "$arg" == "--check" ]; then
|
||||||
|
CHECK="--check"
|
||||||
|
fi
|
||||||
|
if [ "$arg" == "--quiet" ]; then
|
||||||
|
QUIET="--quiet"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
MODELS=(T2T1 T2B1 D001)
|
MODELS=(T2T1 T2B1 D001)
|
||||||
|
|
||||||
for MODEL in ${MODELS[@]}; do
|
for MODEL in ${MODELS[@]}; do
|
||||||
@ -12,13 +23,24 @@ for MODEL in ${MODELS[@]}; do
|
|||||||
# construct all vendor headers
|
# construct all vendor headers
|
||||||
for fn in *.json; do
|
for fn in *.json; do
|
||||||
name=$(echo $fn | sed 's/vendor_\(.*\)\.json/\1/')
|
name=$(echo $fn | sed 's/vendor_\(.*\)\.json/\1/')
|
||||||
$BUILDVH vendor_${name}.json vendor_${name}.toif vendorheader_${name}_unsigned.bin
|
$BUILDVH $QUIET $CHECK vendor_${name}.json vendor_${name}.toif vendorheader_${name}_unsigned.bin
|
||||||
done
|
done
|
||||||
|
|
||||||
|
TMPDIR=$(mktemp -d)
|
||||||
|
trap "rm -rf $TMPDIR" EXIT
|
||||||
# sign dev and QA vendor header
|
# sign dev and QA vendor header
|
||||||
for name in unsafe qa_DO_NOT_SIGN; do
|
for name in unsafe qa_DO_NOT_SIGN; do
|
||||||
cp -a vendorheader_${name}_unsigned.bin vendorheader_${name}_signed_dev.bin
|
SRC_NAME="vendorheader_${name}_unsigned.bin"
|
||||||
$BINCTL -D vendorheader_${name}_signed_dev.bin
|
DEST_NAME="vendorheader_${name}_signed_dev.bin"
|
||||||
|
if [ ! -f "$SRC_NAME" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
cp -a vendorheader_${name}_unsigned.bin "$TMPDIR/$DEST_NAME"
|
||||||
|
$BINCTL $QUIET -D "$TMPDIR/$DEST_NAME"
|
||||||
|
if [ -n "$CHECK" ]; then
|
||||||
|
diff "$DEST_NAME" "$TMPDIR/$DEST_NAME"
|
||||||
|
fi
|
||||||
|
cp -a "$TMPDIR/$DEST_NAME" "$DEST_NAME"
|
||||||
done
|
done
|
||||||
cd ..
|
cd ..
|
||||||
done
|
done
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import json
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
@ -20,8 +21,15 @@ def minimum_header_len(spec):
|
|||||||
@click.command()
|
@click.command()
|
||||||
@click.argument("specfile", type=click.File("r"))
|
@click.argument("specfile", type=click.File("r"))
|
||||||
@click.argument("image", type=click.File("rb"))
|
@click.argument("image", type=click.File("rb"))
|
||||||
@click.argument("outfile", type=click.File("wb"))
|
@click.argument("outfile", type=click.Path(dir_okay=False, writable=True, path_type=Path))
|
||||||
def build_vendorheader(specfile, image, outfile):
|
@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 = json.load(specfile)
|
||||||
spec["pubkeys"] = [bytes.fromhex(k) for k in spec["pubkeys"]]
|
spec["pubkeys"] = [bytes.fromhex(k) for k in spec["pubkeys"]]
|
||||||
spec["image"] = toif.ToifStruct.parse(image.read())
|
spec["image"] = toif.ToifStruct.parse(image.read())
|
||||||
@ -41,16 +49,26 @@ def build_vendorheader(specfile, image, outfile):
|
|||||||
f"Minimum allowable value is {min_length}."
|
f"Minimum allowable value is {min_length}."
|
||||||
)
|
)
|
||||||
elif spec["header_len"] == min_length:
|
elif spec["header_len"] == min_length:
|
||||||
click.echo(f"{specfile.name}: Header has correct length.")
|
echo(f"{specfile.name}: Header has correct length.")
|
||||||
else:
|
else:
|
||||||
click.echo(
|
echo(
|
||||||
f"{specfile.name}: Extending header ({min_length} bytes) to {spec['header_len']} bytes."
|
f"{specfile.name}: Extending header ({min_length} bytes) to {spec['header_len']} bytes."
|
||||||
)
|
)
|
||||||
|
|
||||||
if spec["header_len"] % 512 != 0:
|
if spec["header_len"] % 512 != 0:
|
||||||
raise click.ClickException("Invalid header_len: must be a multiple of 512")
|
raise click.ClickException("Invalid header_len: must be a multiple of 512")
|
||||||
|
|
||||||
outfile.write(firmware.VendorHeader.SUBCON.build(spec))
|
vh_bytes = firmware.VendorHeader.SUBCON.build(spec)
|
||||||
|
if check:
|
||||||
|
if not outfile.exists():
|
||||||
|
raise click.ClickException(f"Header file {outfile.name} does not exist.")
|
||||||
|
outfile_bytes = outfile.read_bytes()
|
||||||
|
if outfile_bytes != vh_bytes:
|
||||||
|
raise click.ClickException(
|
||||||
|
f"Header file {outfile.name} differs from expected header."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
outfile.write_bytes(firmware.VendorHeader.SUBCON.build(spec))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -100,6 +100,7 @@ def do_replace_vendorheader(fw, vh_file) -> None:
|
|||||||
is_flag=True,
|
is_flag=True,
|
||||||
help="Only output header digest for signing and exit.",
|
help="Only output header digest for signing and exit.",
|
||||||
)
|
)
|
||||||
|
@click.option("-q", "--quiet", is_flag=True, help="Do not print anything.")
|
||||||
@click.argument("firmware_file", type=click.File("rb+"))
|
@click.argument("firmware_file", type=click.File("rb+"))
|
||||||
def cli(
|
def cli(
|
||||||
firmware_file,
|
firmware_file,
|
||||||
@ -111,6 +112,7 @@ def cli(
|
|||||||
insert_signature,
|
insert_signature,
|
||||||
replace_vendor_header,
|
replace_vendor_header,
|
||||||
print_digest,
|
print_digest,
|
||||||
|
quiet,
|
||||||
):
|
):
|
||||||
"""Manage firmware headers.
|
"""Manage firmware headers.
|
||||||
|
|
||||||
@ -160,6 +162,11 @@ def cli(
|
|||||||
click.echo(digest.hex())
|
click.echo(digest.hex())
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if quiet:
|
||||||
|
echo = lambda *args, **kwargs: None
|
||||||
|
else:
|
||||||
|
echo = click.echo
|
||||||
|
|
||||||
if replace_vendor_header:
|
if replace_vendor_header:
|
||||||
do_replace_vendorheader(fw, replace_vendor_header)
|
do_replace_vendorheader(fw, replace_vendor_header)
|
||||||
|
|
||||||
@ -174,11 +181,11 @@ def cli(
|
|||||||
signature = None
|
signature = None
|
||||||
|
|
||||||
if privkeys:
|
if privkeys:
|
||||||
click.echo("Signing with local private keys...", err=True)
|
echo("Signing with local private keys...", err=True)
|
||||||
signature = sign_with_privkeys(digest, privkeys)
|
signature = sign_with_privkeys(digest, privkeys)
|
||||||
|
|
||||||
if insert_signature:
|
if insert_signature:
|
||||||
click.echo("Inserting external signature...", err=True)
|
echo("Inserting external signature...", err=True)
|
||||||
sigmask_str, signature = insert_signature
|
sigmask_str, signature = insert_signature
|
||||||
signature = bytes.fromhex(signature)
|
signature = bytes.fromhex(signature)
|
||||||
sigmask = 0
|
sigmask = 0
|
||||||
@ -193,14 +200,14 @@ def cli(
|
|||||||
if signature or rehash:
|
if signature or rehash:
|
||||||
do_rehash(fw)
|
do_rehash(fw)
|
||||||
|
|
||||||
click.echo(f"Detected image type: {fw.NAME}")
|
echo(f"Detected image type: {fw.NAME}")
|
||||||
click.echo(fw.format(verbose))
|
echo(fw.format(verbose))
|
||||||
|
|
||||||
updated_data = fw.build()
|
updated_data = fw.build()
|
||||||
if updated_data == firmware_data:
|
if updated_data == firmware_data:
|
||||||
click.echo("No changes made", err=True)
|
echo("No changes made", err=True)
|
||||||
elif dry_run:
|
elif dry_run:
|
||||||
click.echo("Not saving changes", err=True)
|
echo("Not saving changes", err=True)
|
||||||
else:
|
else:
|
||||||
firmware_file.seek(0)
|
firmware_file.seek(0)
|
||||||
firmware_file.truncate(0)
|
firmware_file.truncate(0)
|
||||||
|
Loading…
Reference in New Issue
Block a user