1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-18 05:28:40 +00:00
trezor-firmware/legacy/debug_signing/fill_t1_fw_signatures.py
Ondrej Mikle e2abd2a9ad feat(legacy): bootloader with v3 SignMessage signatures + signatures debug
Removed oldest v1 style of firmware signature and presence checks.
Added debug helpers for T1 signatures.
Support for v2 and v3 signatures, but can only update FW to v3-style signed.
Support for debugging T1 signatures.
Scripts and README for debugging v2/v3 FW signing scheme.
Firmware in GetFeatures counts only v3 signatures as signed.
Add documentation and comments about signing schemes like a sane person
2022-11-22 15:00:19 +01:00

94 lines
3.1 KiB
Python
Executable File

#!/usr/bin/env python3
import sys
from hashlib import sha256
class Signatures:
# offsets from T1 firmware hash
sig_offsets = [544, 608, 672]
sigindex_offsets = [736, 737, 738]
signature_pairs = [] # list of tupes (int, bytes)
def __init__(self, filename):
"""Load FW, zero out signature fiels, compute header hash"""
self.fw_image = None # mutable bytearray
self.load_fw(filename)
self.header_hash = sha256(self.get_header()).digest()
print(f"Loaded FW image with header hash {self.header_hash_hex()}")
def load_fw(self, filename):
"""Load FW and zero out signature fiels"""
with open(filename, "rb") as f:
data = f.read()
self.fw_image = bytearray(data)
self.zero_sig_fields()
def zero_sig_fields(self):
"""Zero out signature fields to be able to compute header hash"""
for i in range(3):
sigindex_ofs = self.sigindex_offsets[i]
sig_ofs = self.sig_offsets[i]
self.fw_image[sigindex_ofs] = 0
self.fw_image[sig_ofs : sig_ofs + 64] = b"\x00" * 64
def header_hash_hex(self):
return self.header_hash.hex()
def get_header(self):
"""Return header with zeroed out signatures as copy"""
return bytes(self.fw_image[:1024])
def patch_signatures(self):
"""
Patch signatures from signature_pairs.
Requires filling signature_pairs beforehand.
"""
assert len(self.signature_pairs) == 3
for i in range(3):
sigindex_ofs = self.sigindex_offsets[i]
sig_ofs = self.sig_offsets[i]
(sigindex, sig) = self.signature_pairs[i]
print(f"Patching sigindex {sigindex} at offset {sigindex_ofs}")
assert 1 <= sigindex <= 5
self.fw_image[sigindex_ofs] = sigindex
print(f"Patching signature {sig.hex()} at offset {sig_ofs}")
assert len(sig) == 64
self.fw_image[sig_ofs : sig_ofs + 64] = sig
def write_output_fw(self, filename):
print(f"Writing output signed FW file {filename}")
with open(filename, "wb") as signed_fw_file:
signed_fw_file.write(self.fw_image)
if __name__ == "__main__":
# arg1 - unsigned trezor.bin FW
# arg2 - list of 3 signatures and indexes in this format (split by single space):
# index_num signature
# e.g.
# 1 adec956df6282c15ee4344b4cf6edbe435ed4bb13b2b7bebb9920f3d1c4a791a446e492f3ff9b86ca43f28cfce1be97c4eefa65e505e8a936876f01833366d5d
in_fw_fname = sys.argv[1]
signatures_fname = sys.argv[2]
signatures = Signatures(in_fw_fname)
i = 0
for line in open(signatures_fname):
i += 1
print(f"Parsing sig line {i} - {line}")
idx, sig = line.rstrip().split(" ")
idx = int(idx)
sig = bytes.fromhex(sig)
assert idx in range(1, 6) # 1 <= idx <= 5
assert len(sig) == 64
signatures.signature_pairs.append((idx, sig))
out_fw_name = in_fw_fname + ".signed"
signatures.patch_signatures()
signatures.write_output_fw(out_fw_name)