code wiki / _hdl_build / nx_trust_store_corroborated.nx

nx_trust_store_corroborated.nx source

↩ module page · 65 lines · 3716 B

1// nx_trust_store_corroborated.nx -- the SPORE builds its whole trust store by CORROBORATION (operator: "build 2// from the hardware layer up so the spore can get this... keep helping them build capabilities"). This is the 3// store-building PASS on top of nx_trust_corroborate: scan M candidate roots, each presented by N independent 4// sources, and ADMIT a root into the store ONLY IF >= K sources agree on bytes the team hashed itself. Hearsay 5// (lone source) and poison (a tampered presentation) are rejected. The admitted index list is what the caller 6// then parses (nx_x509) + adds (trust_store_add) so nx_https_get can validate real chains. The DER bytes come 7// from any (untrusted) source -- the NAS local store, an HTTP-served CA root via the team's own nx_browse_text, 8// a mirror -- because trust is on the corroboration, not the transport. license_tier: ORIGINAL 9import "nx_trust_corroborate.nx" 10import "nx_syscalls.nx" 11 12// build the ADMITTED root set. roots_base packs M roots; root r's N source-presentations start at 13// roots_base + r*(n_sources*der_stride), each presentation der_stride apart, der_len bytes hashed. 14// fills admitted_idx[0..count) with the indices of corroborated roots; returns count. 15func tsc_build(roots_base: *u8, m_roots: i64, n_sources: i64, der_stride: i64, der_len: i64, k: i64, admitted_idx: *i64) -> i64 { 16 var count: i64 = 0; var r: i64 = 0 17 while r < m_roots { 18 let src: *u8 = roots_base + r * (n_sources * der_stride) 19 if tc_admit_root(src, der_stride, der_len, n_sources, k) == 1 { 20 admitted_idx[count] = r; count = count + 1 21 } 22 r = r + 1 23 } 24 return count 25} 26 27// build the ADMITTED set AND name the SOURCE whose bytes must be parsed for each root. 28// ADDED 2026-08-06 (debt 1786068026): tsc_build above returns only the ROOT index, so the caller had 29// to choose a presentation itself -- and the obvious choice is index 0, which under the source-0 30// admission bug was exactly the poison. Fixing tc_admit_root to count the majority does NOT fix the 31// install if the caller still picks its own bytes; it merely gives the poison a quorum's blessing. 32// AN ADMISSION DECISION THAT DOES NOT ALSO NAME THE BYTES IT ADMITTED IS ONLY HALF A DECISION. 33// admitted_src[i] = the source index holding the majority view of admitted_idx[i]. Parse THAT one. 34func tsc_build_sourced(roots_base: *u8, m_roots: i64, n_sources: i64, der_stride: i64, der_len: i64, 35 k: i64, admitted_idx: *i64, admitted_src: *i64) -> i64 { 36 var count: i64 = 0 37 var r: i64 = 0 38 while r < m_roots { 39 let src: *u8 = roots_base + r * (n_sources * der_stride) 40 let si: i64 = tc_admit_root_index(src, der_stride, der_len, n_sources, k) 41 if si >= 0 { 42 admitted_idx[count] = r 43 admitted_src[count] = si 44 count = count + 1 45 } 46 r = r + 1 47 } 48 return count 49} 50 51// SOUNDNESS gate: every admitted root must have had >= K independent corroboration (no hearsay/poison slipped in). 52// the builder is only allowed to hand the store to nx_https_get if this holds. 53func tsc_all_corroborated(roots_base: *u8, admitted_idx: *i64, count: i64, n_sources: i64, der_stride: i64, der_len: i64, k: i64) -> i64 { 54 var i: i64 = 0 55 while i < count { 56 let r: i64 = admitted_idx[i] 57 let src: *u8 = roots_base + r * (n_sources * der_stride) 58 if tc_corroboration_strength(src, der_stride, der_len, n_sources) < k { return 0 } 59 i = i + 1 60 } 61 return 1 62} 63 64// COVERAGE: did we admit at least enough roots to be useful? (a store of 0 roots trusts nothing -> fail closed.) 65func tsc_usable(count: i64) -> i64 { if count > 0 { return 1 } return 0 }