nx_trust_store_load_from_certdata.nx source
↩ module page · 143 lines · 6289 B
1// nx_trust_store_load_from_certdata.nx -- BOOT-TIME CA TRUST
2// STORE LOADER from a Mozilla NSS `certdata.txt` file on disk.
3//
4// Step 6 of the nx_https_client wiring arc -- the convenience
5// wrapper that turns 3 shipped substrate primitives + 1 syscall
6// helper into ONE boot-time call. After this primitive lands,
7// the only remaining gap to first-byte-of-real-public-HTTPS is
8// the actual Mozilla bundle file drop.
9//
10// Composes:
11// 1. sys_read_file -- slurp the whole certdata.txt
12// 2. nx_nss_certdata_parse -- text -> wire-format bundle
13// 3. trust_store_alloc -- allocate the TrustStore
14// 4. nx_x509_trust_store_load -- wire bundle -> populated store
15//
16// Plus internal: caller-tunable intermediate-buffer cap (the
17// parsed wire-format bundle is held in RAM between the parse
18// step and the load step; the buffer is sized at call time).
19//
20// Public API:
21// nx_trust_store_load_from_certdata(
22// path: *u8, NUL-terminated path to certdata.txt
23// max_anchors: i64, trust_store_alloc capacity hint
24// (typical Mozilla bundle ~150 CAs)
25// parse_buf_cap: i64 intermediate wire-bundle buffer cap
26// (typical Mozilla bundle ~250KB DER)
27// ) -> POSITIVE store pointer (cast to i64) | NEGATIVE -verdict
28//
29// nx_trust_store_load_from_certdata_verdict_is_valid(v) -> 0|1
30//
31// Sealed verdict enum:
32// NX_TS_LOAD_CD_OK store loaded + ready to use
33// NX_TS_LOAD_CD_FILE_FAIL sys_read_file returned empty
34// (file missing / permission / IO)
35// NX_TS_LOAD_CD_PARSE_FAIL nx_nss_certdata_parse returned
36// non-OK (malformed/truncated text)
37// NX_TS_LOAD_CD_LOAD_FAIL nx_x509_trust_store_load returned
38// non-OK (bad DER / store full)
39// NX_TS_LOAD_CD_ZERO_CERTS parse succeeded but 0 certs
40//
41// Caller responsibility:
42// - Supply a real Mozilla certdata.txt path (or a custom one in
43// the same NSS PKCS#11 text format the shipped parser knows).
44// Mozilla updates the canonical bundle quarterly at
45// hg.mozilla.org/projects/nss/raw-file/tip/lib/ckfw/builtins/
46// certdata.txt — operator drops it into the nishi repo per
47// [[feedback-west-industrial-build-replenish-not-buy-consume]]
48// (no cloud-pull at runtime, only at operator-curated build).
49// - Size max_anchors >= the expected cert count. Typical
50// Mozilla bundle has ~150 entries; the existing parser caps
51// individual files at its own MAX_CERTS internal limit.
52// - Size parse_buf_cap to hold the parsed DER wire-bundle.
53// Rule of thumb: 1-3KB per cert, so 500-1000 KB for the full
54// Mozilla bundle. Pass 1048576 (1 MB) as a safe default.
55// - Caller is responsible for the lifetime of the returned
56// TrustStore (it lives in sys_mmap'd memory like everything
57// else; the substrate never frees, by design).
58//
59// Per Cardinals 9 (single-responsibility -- THE boot-time loader,
60// no new parsing logic), 12 (defensive at boundaries -- every
61// sub-step verdict mapped explicitly + file-read failure is its
62// own verdict), 19 (composes shipped primitives unchanged), 22
63// (composition -- 4 shipped primitives compose into one boot-time
64// call), 23 (preamble names every caller responsibility item).
65//
66// license_tier: INDEPENDENT_REDERIVE
67// genealogy_id: international-research-sources/mozilla/nss + oasis/pkcs11 + ietf/rfc_5280
68// lineage_id: nishi_trust_store_load_from_certdata_q10
69
70// nx_safety_envelope:
71// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
72// sil_target: SIL1
73// evidence: [bulk_applied_2026-05-19, https-trust-store-loader-step-6]
74// verdict: NOT_YET_EVALUATED
75
76import "nx_syscalls.nx"
77import "nx_x509_trust_store.nx"
78import "nx_x509_trust_store_load.nx"
79import "nx_nss_certdata_parse.nx"
80
81const NX_TS_LOAD_CD_OK: i64 = 1
82const NX_TS_LOAD_CD_FILE_FAIL: i64 = 2
83const NX_TS_LOAD_CD_PARSE_FAIL: i64 = 3
84const NX_TS_LOAD_CD_LOAD_FAIL: i64 = 4
85const NX_TS_LOAD_CD_ZERO_CERTS: i64 = 5
86const NX_TS_LOAD_CD_VERDICT_N: i64 = 6
87
88func nx_trust_store_load_from_certdata_verdict_is_valid(v: i64) -> i64 {
89 if v < NX_TS_LOAD_CD_OK { return 0 }
90 if v >= NX_TS_LOAD_CD_VERDICT_N { return 0 }
91 return 1
92}
93
94// THE BOOT-TIME LOADER. Returns POSITIVE pointer or NEGATIVE
95// -verdict. Caller MUST verify the return is positive before
96// using the result as *TrustStore.
97func nx_trust_store_load_from_certdata(
98 path: *u8,
99 max_anchors: i64,
100 parse_buf_cap: i64
101) -> i64 {
102 // ---- Step 1: slurp certdata.txt ----
103 let file_len_p: *i64 = sys_mmap(16) as *i64
104 let file_buf: *u8 = sys_read_file(path, file_len_p)
105 let file_len: i64 = *file_len_p
106 if file_len <= 0 { return 0 - NX_TS_LOAD_CD_FILE_FAIL }
107 if (file_buf as i64) == 0 { return 0 - NX_TS_LOAD_CD_FILE_FAIL }
108
109 // ---- Step 2: text -> wire-format bundle ----
110 let bundle_buf: *u8 = sys_mmap(parse_buf_cap)
111 let n_certs_p: *i64 = sys_mmap(16) as *i64
112 let parse_v: i64 = nx_nss_certdata_parse(
113 file_buf, file_len,
114 bundle_buf, parse_buf_cap,
115 n_certs_p
116 )
117 if parse_v != NX_NSS_CD_OK { return 0 - NX_TS_LOAD_CD_PARSE_FAIL }
118 if *n_certs_p <= 0 { return 0 - NX_TS_LOAD_CD_ZERO_CERTS }
119
120 // ---- Step 3: allocate TrustStore ----
121 let store: *TrustStore = trust_store_alloc(max_anchors)
122
123 // ---- Step 4: wire bundle -> populated store ----
124 // The loader's outer iteration is bounded by cert_count from the
125 // BE header at bundle_buf[0..2] (written by the parser). It
126 // walks EXACTLY that many records, so passing parse_buf_cap as
127 // bundle_len is safe -- any unwritten tail bytes beyond the
128 // last record are never read. Per-record off+3+cert_len bound
129 // check still catches a malformed (truncated) middle record.
130 let load_v: i64 = nx_x509_trust_store_load(
131 bundle_buf, parse_buf_cap,
132 store
133 )
134 if load_v != NX_TRUST_LOAD_OK { return 0 - NX_TS_LOAD_CD_LOAD_FAIL }
135
136 return store as i64
137}
138
139// Compile-only smoke. Real KAT in
140// nx_trust_store_load_from_certdata_test.nx.
141func main() -> i64 {
142 return 0
143}