code wiki / _hdl_build / nx_asn1_der_emit.nx
nx_asn1_der_emit.nx
buildroot/runtime/_hdl_build/nx_asn1_der_emit.nx
about
nx_asn1_der_emit.nx -- F103e RUNG 2: the DER WRITE side.
asn1.nx's own header has said since it was written: "We implement a reader-only subset -- write-side
encoders are future work." This is that work. It is the missing half of every step still ahead on
F103e: a self-signed X.509 certificate, PKCS#7 SignedData, SpcIndirectDataContent and the
EFI_SIGNATURE_LIST enrolment blob are ALL just DER structures, and none of them can be authored
without a correct encoder. (Why we need them: real EDK2 with MS keys refuses our unsigned .efi with
Access Denied, while the SAME secboot firmware in SETUP mode runs it -- so the blocker is the
enrolled key set. Debt 1786237435.)
★THE ORACLE IS THE INCUMBENT READER. Every tooth below encodes with these functions and decodes
with nx_asn1_lib's asn1_expect_tag / asn1_read_length -- two implementations checking each other,
never one implementation agreeing with itself. And T1 reproduces the EXACT byte vector nx_asn1.nx's
own compile-smoke builds BY HAND (30 03 02 01 2A), so the estate supplied its own golden vector.
The two encoder bugs that matter, both tested here because both silently produce parseable output:
1. NON-MINIMAL LENGTH. DER (unlike BER) requires the shortest length form. `81 05` for length 5
decodes fine everywhere and is INVALID DER -- it breaks signature verification because the
verifier re-encodes canonically and gets different bytes.
2. THE INTEGER SIGN BIT. ASN.1 INTEGER is two's complement, so a positive magnitude whose top bit
is set needs a leading 0x00. Emit `02 01 80` and every parser reads -128 instead of 128. An
RSA modulus starts with a high bit set essentially always, so this bug is not an edge case
here -- it is the common path.
Usage: nx_asn1_der_emit selftest (8 teeth, incl. two negative controls)
Exit: 0 GREEN | 1 RED. Log -> knowledge/status/nishi_os.log, verdict= LAST (positional anchor).
Sovereign: syscalls only, no openssl. license_tier: ORIGINAL
dependencies 2 imports · 0 importers
imports: nx_syscalls.nxnx_asn1.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
| 30 | const K_MAGIC_65536: i64 = 65536 |
| 31 | const K_MAGIC_16777216: i64 = 16777216 |
| 32 | const K_MAGIC_70000: i64 = 70000 |
| 33 | const K_MAGIC_65535: i64 = 65535 |
functions
| 42 | func de_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 43 | func de_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 } |
| 44 | func de_fn(fd: i64, v: i64) -> i64 |
| 54 | func de_hex(d: *u8, n: i64) -> i64 |
| 68 | func der_len_size(n: i64) -> i64 |
| 76 | func der_put_len(out: *u8, off: i64, n: i64) -> i64 |
| 104 | func der_put_tlv(out: *u8, off: i64, tag: i64, val: *u8, vlen: i64) -> i64 |
| 115 | func der_put_int(out: *u8, off: i64, mag: *u8, mlen: i64) -> i64 |
| 144 | func de_bytes_eq(a: *u8, b: *u8, n: i64) -> i64 called by 1: de_selftest |
| 150 | func de_selftest() -> i64 |
| 280 | func main(argc: i64, argv: *i64) -> i64 calls 1: de_selftest |