@@ -104,7 +104,12 @@ def write(self, path):
104104 nxt += 1
105105
106106 pids = []
107- for stream , w , h , img_refs in self .pages :
107+ total_pages = len (self .pages )
108+ for page_num , (stream , w , h , img_refs ) in enumerate (self .pages , 1 ):
109+ # Add page footer: firmware version + page number
110+ footer_left = getattr (self , 'footer_text' , 'KeepKey Firmware Test Report' )
111+ footer = f'0.5 0.5 0.5 rg BT /F1 7 Tf 40 20 Td ({ footer_left } ) Tj ET BT /F1 7 Tf { w - 100 } 20 Td (Page { page_num } of { total_pages } ) Tj ET 0 0 0 rg'
112+ stream = stream + '\n ' + footer
108113 c = zlib .compress (stream .encode ('latin-1' , 'replace' ))
109114 objs .append (f'{ nxt } 0 obj\n << /Length { len (c )} /Filter /FlateDecode >>\n stream\n ' .encode () + c + b'\n endstream\n endobj\n ' )
110115 stream_id = nxt ; nxt += 1
@@ -463,10 +468,14 @@ def parse_junit(path):
463468 ]),
464469
465470 ('B' , 'Bitcoin' , '7.0.0' ,
466- 'Bitcoin is the primary chain and most extensively tested. Covers legacy P2PKH, P2SH-wrapped '
467- 'SegWit, native SegWit (bech32), and Taproot (P2TR). Transaction signing validates that the '
468- 'device correctly displays every output address and amount, calculates fees, detects change '
469- 'outputs, and resists output substitution attacks. Also covers UTXO forks sharing BTC signing code.' ,
471+ 'Bitcoin ($1.8T market cap) is the primary chain and most extensively tested — 28 tests covering '
472+ 'every address type and signing scenario. The KeepKey supports legacy P2PKH (1...), P2SH-wrapped '
473+ 'SegWit (3...), native SegWit bech32 (bc1q...), and Taproot P2TR (bc1p...). Transaction signing '
474+ 'is the most security-critical operation: the device must correctly display every output address '
475+ 'and amount, calculate fees (inputs - outputs), detect change outputs (same xpub), and resist '
476+ 'output substitution attacks where a compromised host swaps the recipient between signing passes. '
477+ 'The OLED shows "TRANSACTION — Do you want to send X BTC from your wallet? This includes a '
478+ 'transaction fee of Y BTC." Also covers UTXO forks (LTC, Dash, BTG, GRS) sharing BTC signing code.' ,
470479 [
471480 'ADDRESS: Derive key from BIP-32 path -> display on OLED with QR code -> user verifies against host' ,
472481 'SIGN TX: Device shows each output (full address + amount) -> shows fee -> user confirms -> signs' ,
@@ -1088,6 +1097,7 @@ def parse_junit(path):
10881097def render (output_path , fw_version , results , screenshot_dir = None ):
10891098 pdf = PDF (); pb = PB (pdf )
10901099 ts = datetime .now ().strftime ('%Y-%m-%d %H:%M' )
1100+ pdf .footer_text = f'KeepKey Firmware { fw_version } Test Report | { ts } '
10911101 active = [(l ,t ,mf ,bg ,fl ,tests ) for l ,t ,mf ,bg ,fl ,tests in SECTIONS if ver_ge (fw_version , mf )]
10921102 # Separate specs section (no tests) from test sections
10931103 specs = [s for s in active if not s [5 ]]
0 commit comments