code wiki / _hdl_build / nx_authenticode_sign.nx
nx_authenticode_sign.nx
buildroot/runtime/_hdl_build/nx_authenticode_sign.nx
about
nx_authenticode_sign.nx -- F103e RUNG 10: attach an Authenticode signature to a PE32+ EFI image.
The last software step before enrolment. Real EDK2 with MS keys refuses our unsigned .efi
(Access Denied) while the SAME secboot firmware in SETUP mode runs it (debt 1786237435), so the
image must carry a signature and our cert must be in db.
Assembles, bottom-up:
SpcIndirectDataContent ::= SEQUENCE { SpcAttributeTypeAndOptionalValue, DigestInfo }
PKCS#7 ContentInfo ::= SEQUENCE { OID signedData, [0] SignedData }
WIN_CERTIFICATE ::= dwLength || wRevision(0x0200) || wCertificateType(0x0002) || PKCS#7
then appends it 8-byte aligned and points data directory 4 at it.
★★★★★★THE TOOTH THIS RUNG WAS BUILT AROUND: **AFTER SIGNING, THE AUTHENTICODE HASH MUST BE
BYTE-IDENTICAL TO BEFORE.** The certificate table and its data-directory entry are two of the
three ranges the hash excludes, so if attaching a signature CHANGES the hash, the exclusion logic
in nx_pe_authhash is wrong and every signature we ever produce is invalid. Nothing else in the
chain tests that interaction -- the hasher alone cannot, because it never sees a signed file.
★Every OID is DERIVED by `der_oid_from_arcs` (validated in nx_x509_emit against the estate's own
shipped SHA-256 OID), never a remembered byte string.
⚠SCOPE, NAMED: this produces a structurally complete Authenticode blob whose signature our own
verifier accepts over the SpcIndirectDataContent DER. It is NOT yet proven against EDK2's
AuthenticodeVerify -- that proof is the enrol-and-boot rung, and until it runs this organ's
claim is "well-formed and self-consistent", not "accepted by firmware". Saying otherwise would be
the exact self-certification the third reference exists to prevent.
Usage: nx_authenticode_sign selftest [image.efi]
Exit: 0 GREEN | 1 RED. Log -> knowledge/status/nishi_os.log, verdict= LAST.
license_tier: ORIGINAL
dependencies 17 imports · 0 importers
diagram shows first 10 each side; +7 more imports, +0 more importers in the complete lists below.
imports: nx_syscalls.nxnx_sha256.nxnx_u2048.nxnx_u2048_mul.nxnx_rsa2048_mod.nxnx_rsa2048_mod_exp.nxnx_rsa2048_mont.nxnx_rsa2048_mod_exp_big.nxnx_asn1.nxnx_x509.nxnx_rsa_pkcs1_v1_5_sha256.nxnx_u2048_millerrabin.nxnx_u2048_smallops.nxnx_rsa_keygen.nxnx_rsa_pkcs1_sign.nxnx_pe_authhash.nxnx_x509_emit.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 48 | const AC_MAGIC_1024: i64 = 1024 |
| 49 | const AC_MAGIC_113549: i64 = 113549 |
| 50 | const AC_MAGIC_2048: i64 = 2048 |
| 51 | const AC_MAGIC_4096: i64 = 4096 |
| 52 | const AC_MAGIC_20260808: i64 = 20260808 |
| 53 | const AC_MAGIC_65537: i64 = 65537 |
| 54 | const AC_MAGIC_4097: i64 = 4097 |
| 56 | const AC_BUF: i64 = 16384 |
functions
| 58 | func ac_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 59 | func ac_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 } |
| 60 | func ac_fn(fd: i64, v: i64) -> i64 |
| 70 | func ac_eq_str(a: *u8, b: *u8) -> i64 called by 1: main |
| 76 | func ac_w32le(b: *u8, o: i64, v: i64) -> i64 called by 1: ac_attach |
| 81 | func ac_r32le(b: *u8, o: i64) -> i64 |
| 90 | func ac_spc_indirect(out: *u8, hash32: *u8) -> i64 |
| 152 | func ac_authattrs(out: *u8, spc: *u8, spclen: i64) -> i64 |
| 212 | func ac_pkcs7(out: *u8, spc: *u8, spclen: i64, sig: *u8, cert: *u8, certlen: i64, |
| 302 | func ac_attach(img: *u8, ilen: i64, p7: *u8, p7len: i64, out: *u8) -> i64 |
| 329 | func ac_selftest(path: *u8) -> i64 |
| 520 | func main(argc: i64, argv: *i64) -> i64 |