code wiki / (root) / nx_x509_trust_store_load.nx

nx_x509_trust_store_load.nx source

↩ module page · 128 lines · 5054 B

1// nx_x509_trust_store_load.nx -- bulk-load a TrustStore from a 2// length-prefixed bundle of DER certificates. 3// 4// Phase 0b §I.4 piece 10 of the chain-walker arc. The data- 5// loader that turns "embedded CA root bytes" into "ready-to-use 6// trust store". Format-agnostic about how the bundle was 7// produced (Mozilla NSS certdata.txt parser, hand-curated DER 8// blobs, etc.) -- as long as the input matches the layout below, 9// the loader handles the rest. 10// 11// Bundle wire format: 12// 13// [2 bytes BE] cert_count N 14// for each i in 0..N: 15// [3 bytes BE] cert_len_i 16// [cert_len_i bytes] cert_DER_i 17// 18// Total bundle bytes = 2 + sum_i (3 + cert_len_i). 19// 20// For each cert in the bundle: 21// - x509_parse against the cert bytes (caller's bundle_buf at 22// the appropriate offset) 23// - trust_store_add(store, &cert_bytes, parsed_cert) 24// - If parse fails, the loader returns BAD_CERT and the store 25// is partially populated (caller can inspect trust_store_count 26// to see how many succeeded before the failure). 27// 28// Why a custom wire format (vs. NSS certdata.txt): 29// - Sovereign: parser is bits-up + small. 30// - certdata.txt is a complex text format requiring tokenization 31// and base64 decoding. Parsing it bits-up is a separate 32// primitive (queued: nx_nss_certdata_parse.nx). The wire 33// format here is what that parser would emit; or the user can 34// hand-build it from raw DER blobs. 35// 36// Public API: 37// nx_x509_trust_store_load(bundle_buf, bundle_len, store) 38// -> verdict 39// nx_x509_trust_store_load_verdict_is_valid(v) -> 0|1 40// 41// Sealed verdict enum: 42// NX_TRUST_LOAD_OK all certs loaded 43// NX_TRUST_LOAD_TRUNCATED bundle ended mid-record 44// NX_TRUST_LOAD_BAD_CERT x509_parse failed on some entry 45// NX_TRUST_LOAD_STORE_FULL store hit capacity mid-load 46// NX_TRUST_LOAD_EMPTY bundle declares 0 certs 47// 48// Per Cardinals 9 (single-responsibility -- load, not parse the 49// bundle wire format from a higher-level source like certdata.txt), 50// 12 (defensive at boundaries -- bounded reads + partial-load 51// rollback semantics documented), 22 (composition -- this loader 52// is what a higher-level certdata.txt parser compose on top of), 53// 23 (preamble explains why the format is custom). 54// 55// license_tier: INDEPENDENT_REDERIVE 56// genealogy_id: international-research-sources/ietf/rfc_5280 57// lineage_id: nishi_x509_trust_store_load_q10 58 59// nx_safety_envelope: 60// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 61// sil_target: SIL1 62// evidence: [bulk_applied_2026-05-19, x509-trust-store-bulk-loader] 63// verdict: NOT_YET_EVALUATED 64 65import "nx_syscalls.nx" 66import "nx_x509.nx" 67import "nx_x509_trust_store.nx" 68 69const NX_TRUST_LOAD_OK: i64 = 1 70const NX_TRUST_LOAD_TRUNCATED: i64 = 2 71const NX_TRUST_LOAD_BAD_CERT: i64 = 3 72const NX_TRUST_LOAD_STORE_FULL: i64 = 4 73const NX_TRUST_LOAD_EMPTY: i64 = 5 74const NX_TRUST_LOAD_VERDICT_N: i64 = 6 75 76func nx_x509_trust_store_load_verdict_is_valid(v: i64) -> i64 { 77 if v < NX_TRUST_LOAD_OK { return 0 } 78 if v >= NX_TRUST_LOAD_VERDICT_N { return 0 } 79 return 1 80} 81 82// Bulk-load a TrustStore from a length-prefixed bundle. 83// 84// Returns the number of certs loaded via *out_n_loaded (always 85// written, even on partial failure). Caller can use this to 86// detect "loaded the first K then choked on K+1". 87func nx_x509_trust_store_load( 88 bundle_buf: *u8, bundle_len: i64, 89 store: *TrustStore 90) -> i64 { 91 if bundle_len < 2 { return NX_TRUST_LOAD_TRUNCATED } 92 let cert_count: i64 = ((bundle_buf[0] & 0xff) << 8) | (bundle_buf[1] & 0xff) 93 if cert_count == 0 { return NX_TRUST_LOAD_EMPTY } 94 95 var off: i64 = 2 96 var i: i64 = 0 97 while i < cert_count { 98 if off + 3 > bundle_len { return NX_TRUST_LOAD_TRUNCATED } 99 let cert_len: i64 = ((bundle_buf[off] & 0xff) << 16) 100 | ((bundle_buf[off + 1] & 0xff) << 8) 101 | (bundle_buf[off + 2] & 0xff) 102 if cert_len < 1 { return NX_TRUST_LOAD_BAD_CERT } 103 if off + 3 + cert_len > bundle_len { return NX_TRUST_LOAD_TRUNCATED } 104 105 let cert_der: *u8 = bundle_buf + off + 3 106 // Parse the cert into a fresh X509Cert struct. Allocate 107 // a new struct per anchor; the TrustStore holds pointers 108 // to them so they need to outlive the loader. 109 let cert_raw: *u8 = sys_mmap(256) 110 let cert: *X509Cert = cert_raw as *X509Cert 111 let rc: i64 = x509_parse(cert_der, cert_len, cert) 112 if rc < 0 { return NX_TRUST_LOAD_BAD_CERT } 113 114 let add_v: i64 = trust_store_add(store, cert_der, cert) 115 if add_v == NX_TRUST_STORE_FULL { return NX_TRUST_LOAD_STORE_FULL } 116 if add_v != NX_TRUST_STORE_OK { return NX_TRUST_LOAD_BAD_CERT } 117 118 off = off + 3 + cert_len 119 i = i + 1 120 } 121 122 return NX_TRUST_LOAD_OK 123} 124 125// Compile-only smoke. Real KAT in nx_x509_trust_store_load_test.nx. 126func main() -> i64 { 127 return 0 128}