code wiki / _hdl_build / nx_pe_authhash.nx
nx_pe_authhash.nx
buildroot/runtime/_hdl_build/nx_pe_authhash.nx
about
nx_pe_authhash.nx -- F103e RUNG 1: the Authenticode PE hash.
WHY THIS EXISTS (measured 2026-08-08): real EDK2 with Microsoft keys enrolled REFUSES our unsigned
EFI application -- `BdsDxe: failed to load Boot0001 ... : Access Denied` -- while the SAME secboot
firmware in SETUP mode (no Platform Key) runs it and prints NISHI. So the refusal is the ENROLLED
KEY SET, not Secure Boot, and the remedy is to enroll our own key and SIGN the image. Debt
1786237435. Signing starts here, because every later step (SpcIndirectDataContent -> PKCS#7
SignedData -> WIN_CERTIFICATE) carries THIS hash and is worthless if it is wrong.
The Authenticode hash is NOT the hash of the file. Three ranges are excluded, because each is
written or rewritten AFTER signing and would otherwise invalidate the signature:
1. the OptionalHeader CheckSum (4 bytes @ OPT+64)
2. the Certificate Table data directory (8 bytes @ datadir[4]) -- it points AT the signature
3. the attribute certificate table itself (the appended signature blob)
Everything else is hashed: headers up to SizeOfHeaders, then every section's raw data IN ASCENDING
PointerToRawData ORDER (file order, NOT section-table order -- they are allowed to differ), then
any trailing bytes that are not the certificate table.
★THE ANTI-VACUITY PROBLEM IS THE WHOLE POINT: a trivial "sha256 the whole file" implementation
passes every test that mutates .text and fails ONLY on the exclusion ranges. So T1/T2 below mutate
INSIDE the excluded fields and demand the hash NOT move -- those are the teeth a wrong
implementation cannot pass, and they are the reason this organ is not just a call to sha256_digest.
There is no external Authenticode oracle on this host (sbsign/pesign/osslsigncode all MEASURED
MISSING), so the teeth ARE the specification, stated as properties rather than a golden vector.
⚠That is a REAL limit and it is named, not hidden: this proves the exclusion semantics and
determinism; it does NOT prove byte-agreement with Microsoft's implementation. A golden vector
from a signed EFI binary is the next tooth to add when one is obtainable.
Usage: nx_pe_authhash <file> -> "<64 hex> <path>" exit 0
nx_pe_authhash selftest -> property teeth exit 0 GREEN / 1 RED
Exit: 0 ok | 1 RED | 2 refused (not a PE we can hash) | 3 UNPROVEN (cannot read input)
Log -> knowledge/status/nishi_os.log, canonical verdict= LAST (positional anchor).
Sovereign: syscalls only, no openssl/sbsign. license_tier: ORIGINAL
dependencies 2 imports · 2 importers
imports: nx_syscalls.nxnx_sha256.nx
imported by: nx_authenticode_sign.nxnx_efivars_enrol.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 37 | const PAH_MAGIC_4096: i64 = 4096 |
| 39 | const PAH_MAXSEC: i64 = 96 // refuse absurd section counts rather than walk off the header |
| 40 | const PAH_DOS_LFA: i64 = 0x3C |
| 41 | const PAH_MAG_P32P: i64 = 0x20B |
| 42 | const PAH_MAG_P32: i64 = 0x10B |
functions
| 44 | func ph_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 45 | func ph_fp(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 } |
| 46 | func ph_fn(fd: i64, v: i64) -> i64 |
| 56 | func ph_hex(fd: i64, d: *u8, n: i64) -> i64 |
| 67 | func ph_eq(a: *u8, b: *u8) -> i64 called by 1: main |
| 73 | func ph_r16(b: *u8, o: i64) -> i64 { return (b[o] as i64) | ((b[o+1] as i64) << 8) } |
| 74 | func ph_r32(b: *u8, o: i64) -> i64 |
| 81 | func pe_authhash(f: *u8, flen: i64, out: *u8) -> i64 |
| 165 | func ph_same(a: *u8, b: *u8) -> i64 called by 1: ph_selftest |
| 171 | func ph_selftest(path: *u8) -> i64 |
| 282 | func main(argc: i64, argv: *i64) -> i64 |