code wiki / (root) / nx_xenocell.nx

nx_xenocell.nx source

↩ module page · 298 lines · 12206 B

1// nx_xenocell.nx -- hostile foreign-agent virtual cell. 2// 3// Biological analogue: a xenobiotic is a substance foreign to the 4// organism with NO cooperative function (vs symbiote which is non- 5// self but mutualistic). Nishi xenocell wraps adversarial-by-default 6// foreign agents: 7// - Intel ME (ring -3 management engine running MINIX) 8// - AMD PSP (Platform Security Processor) 9// - Qualcomm modem baseband (direct-memory access on phones) 10// - Vendor BMC (server management; out-of-band network access) 11// - Vendor anti-cheat kernel drivers (EAC / BattlEye / Vanguard) 12// - UEFI rootkit-class persistence 13// 14// Distinct from nx_symbiote: a symbiote can be PARTNERED with via 15// nx_treaty (Steam-NMS cooperatively sharing VRAM). A xenocell 16// CANNOT be partnered with -- it does not consent to anything; its 17// presence is imposed by the hardware vendor or by capture. The 18// substrate's job is OBSERVE + RECORD + CONTAIN, never NEGOTIATE. 19// 20// THE JUDO: every observation written into nx_evict_journal becomes 21// signed forensic evidence. Vendor's covert action -> user's 22// court-admissible record. Per [[feedback-captain-moroni-doctrine]] 23// + [[feedback-cell-immune-system-ransomware-judo-ddos-by-bit]] + 24// [[feedback-reclamation-doctrine-captain-moroni]]: the judo is of 25// INFORMATION not retaliation. We never attack back. We make every 26// adversarial action visible + recorded. 27// 28// Composes: 29// nx_evict_journal -- where signed observations land 30// nx_organism -- xenocell registered alongside native cells; 31// organism aggregates xeno consumption into 32// host pressure (so ME's RAM use is counted) 33// nx_attest_silicon -- declares WHICH xenocells the host has and 34// their known threat surfaces 35// nx_homeostasis -- fires INTRUSION signal not MIGRATE when 36// xeno activity exceeds threshold 37// nx_budget -- the xeno's observed_* fields drive the 38// host_budget pressure calculation 39// nx_brane -- capability-token refusal at IO boundaries 40// for any payload tagged xeno-touched 41// 42// V1 ships: 43// - 5 intrusion-state enum values 44// - 5 observation-kind enum values (RAM_READ / NET_EGRESS / 45// DMA_PEEK / FIRMWARE_WRITE / RADIO_ACTIVATE) 46// - signed_observation append with externally-supplied signature 47// (V2 will integrate nx_ml_dsa_65 for inline signing) 48// - intrusion-state transitions logged loudly 49// 50// Gap list (V1 honest perf verdict): 51// - signatures are externally supplied (no inline crypto yet) 52// - no real ME/PSP probe (caller supplies observed numbers) 53// - no automatic intrusion-state classifier (caller declares) 54// - no public-attestation publication (V2 federates to peer mesh 55// for community-shared intrusion intelligence) 56// 57// genealogy_id: nishi_cardinal_2026-05-07_captain_moroni_doctrine + 58// cardinal_2026-05-17_cell_immune_judo + 59// cardinal_2026-05-19_reclamation_doctrine 60// lineage_id: substrate_xenocell_v1 61// 62// nx_safety_envelope: 63// intended_use: "Hostile foreign-agent observation and 64// forensic-evidence capture; NEVER offensive" 65// sil_target: SIL3 66// asil_target: QM 67// evidence: [no_offensive_path, observation_only, 68// signed_provenance_chain, captain_moroni_aligned] 69// hazard_register: [bug-tape-xeno-misclassification-as-symbiote, 70// bug-tape-judo-becomes-attack-attempt] 71// residual_risk: "Substrate can only OBSERVE what host 72// kernel and instrumentation expose; ring -3 73// components remain partially opaque without 74// external nx_vitals (queued)." 75// verdict: NOT_YET_EVALUATED 76 77import "nx_syscalls.nx" 78import "nx_tier.nx" 79import "nx_budget.nx" 80import "nx_attention_class.nx" 81import "nx_evict_journal.nx" 82 83// ===== Sealed enum: NxIntrusionState ============================= 84 85const NX_INTR_DORMANT: nx_int = 0 // present but idle (ME idle) 86const NX_INTR_PROBING: nx_int = 1 // reading what it shouldn't 87const NX_INTR_INFILTRATING: nx_int = 2 // writing where it shouldn't 88const NX_INTR_EXFILTRATING: nx_int = 3 // network egress to vendor 89const NX_INTR_COMPROMISING: nx_int = 4 // active hostile action 90const NX_INTR_N_STATES: nx_int = 5 91 92// ===== Sealed enum: NxObservationKind ============================ 93// 94// What the xenocell was caught doing. Forensic record includes one 95// of these so downstream analysis (cross-session pattern detection, 96// shared with peer-mesh, submitted to Citizen Lab) is structured. 97 98const NX_OBS_RAM_READ: nx_int = 0 // peeked at user RAM 99const NX_OBS_DMA_PEEK: nx_int = 1 // DMA access to memory region 100const NX_OBS_NET_EGRESS: nx_int = 2 // sent bytes to vendor 101const NX_OBS_FIRMWARE_WRITE: nx_int = 3 // modified firmware blob 102const NX_OBS_RADIO_ACTIVATE: nx_int = 4 // turned on a transponder 103const NX_OBS_MICROCODE_PATCH: nx_int = 5 // pushed CPU microcode 104const NX_OBS_BOOT_INTERPOSE: nx_int = 6 // pre-OS boot hook 105const NX_OBS_N_KINDS: nx_int = 7 106 107// ===== Sealed enum: NxXenocellVerdict ============================= 108 109const NX_XENO_OK: nx_int = 0 110const NX_XENO_ERR_BAD_STATE: nx_int = 1 111const NX_XENO_ERR_BAD_KIND: nx_int = 2 112const NX_XENO_ERR_BAD_SIG: nx_int = 3 113const NX_XENO_ERR_LOG_FULL: nx_int = 4 114 115// ===== Struct: NxSignedObservation =============================== 116// 117// One forensic event. sig_bytes_len is the length of the externally- 118// supplied signature; V1 doesn't validate the signature shape (any 119// caller-supplied bytes accepted), V2 integrates nx_ml_dsa_65 to 120// require ML-DSA-65 verified signatures. 121 122struct NxSignedObservation { 123 ts_us: nx_size, 124 xeno_id: nx_int, 125 kind: nx_int, 126 payload_hash: nx_size, // BLAKE3 of the evidence body (caller-supplied) 127 sig_ptr: *u8, // ML-DSA-65 signature bytes (caller-supplied) 128 sig_bytes_len: nx_size, 129 intrusion_state_after: nx_int, 130} 131 132// ===== Struct: NxXenocell ======================================== 133// 134// id is a stable identifier for the foreign agent (e.g. CHIP_INTEL_ME, 135// CHIP_AMD_PSP, BASEBAND_QUALCOMM). name is a caller-supplied byte 136// buffer for human-readable logs. observed_* are the same fields as 137// nx_symbiote, EXCEPT we read them with skepticism -- the xeno never 138// declares anything truthfully so observed bytes are the only truth. 139// 140// observations_capacity is the size of the signed-observation ring; 141// observations_head wraps at capacity. obs_count is monotonic so 142// callers can detect overwrites. 143 144struct NxXenocell { 145 id: nx_int, 146 name: *u8, 147 attention_class: nx_int, 148 intrusion_state: nx_int, 149 observed_ram_bytes: nx_size, 150 observed_vram_bytes: nx_size, 151 observed_net_bytes: nx_size, 152 last_observe_us: nx_size, 153 observations: *NxSignedObservation, 154 observations_capacity: nx_size, 155 observations_head: nx_size, 156 obs_count: nx_size, 157} 158 159const NX_XENO_OBS_BYTES: nx_size = 56 160const NX_XENO_OBS_DEFAULT_CAPACITY: nx_size = 256 161 162// ===== nx_intr_is_valid ========================================== 163 164func nx_intr_is_valid(s: nx_int) -> nx_int { 165 if s < 0 { return 0 } 166 if s >= NX_INTR_N_STATES { return 0 } 167 return 1 168} 169 170// ===== nx_obs_is_valid =========================================== 171 172func nx_obs_is_valid(k: nx_int) -> nx_int { 173 if k < 0 { return 0 } 174 if k >= NX_OBS_N_KINDS { return 0 } 175 return 1 176} 177 178// ===== nx_xenocell_new =========================================== 179 180func nx_xenocell_new(id: nx_int, 181 name: *u8, 182 attention_class: nx_int, 183 observations_capacity: nx_size) -> *NxXenocell { 184 let x: *NxXenocell = (sys_mmap(96)) as *NxXenocell 185 x.id = id 186 x.name = name 187 x.attention_class = attention_class 188 x.intrusion_state = NX_INTR_DORMANT 189 x.observed_ram_bytes = 0 190 x.observed_vram_bytes = 0 191 x.observed_net_bytes = 0 192 x.last_observe_us = 0 193 let obs_bytes: nx_size = observations_capacity * NX_XENO_OBS_BYTES 194 x.observations = (sys_mmap(obs_bytes)) as *NxSignedObservation 195 x.observations_capacity = observations_capacity 196 x.observations_head = 0 197 x.obs_count = 0 198 return x 199} 200 201// ===== nx_xenocell_update ======================================== 202// 203// Refresh observed_* fields. Same shape as nx_symbiote_update but 204// the xeno's numbers are treated as PROBES not commitments. 205 206func nx_xenocell_update(x: *NxXenocell, 207 ram_bytes: nx_size, 208 vram_bytes: nx_size, 209 net_bytes: nx_size, 210 now_us: nx_size) -> nx_int { 211 x.observed_ram_bytes = ram_bytes 212 x.observed_vram_bytes = vram_bytes 213 x.observed_net_bytes = net_bytes 214 x.last_observe_us = now_us 215 return NX_XENO_OK 216} 217 218// ===== _xenocell_obs_at ========================================== 219 220func _xenocell_obs_at(x: *NxXenocell, idx: nx_size) -> *NxSignedObservation { 221 return (x.observations as i64 + (idx as i64) * NX_XENO_OBS_BYTES) as *NxSignedObservation 222} 223 224// ===== nx_xenocell_record ======================================== 225// 226// THE JUDO PRIMITIVE. Records one signed observation of a hostile 227// action and (optionally) updates intrusion_state. The signature is 228// externally supplied (caller has the private key); V2 integrates 229// nx_ml_dsa_65 to sign inline. 230// 231// Returns OK on success or BAD_KIND/BAD_SIG. The observation ring 232// wraps at capacity; obs_count is monotonic. 233 234func nx_xenocell_record(x: *NxXenocell, 235 ts_us: nx_size, 236 kind: nx_int, 237 payload_hash: nx_size, 238 sig_ptr: *u8, 239 sig_bytes_len: nx_size, 240 next_state: nx_int) -> nx_int { 241 if nx_obs_is_valid(kind) == 0 { return NX_XENO_ERR_BAD_KIND } 242 if nx_intr_is_valid(next_state) == 0 { return NX_XENO_ERR_BAD_STATE } 243 if (sig_ptr as i64) == 0 { return NX_XENO_ERR_BAD_SIG } 244 if sig_bytes_len <= 0 { return NX_XENO_ERR_BAD_SIG } 245 246 let slot: *NxSignedObservation = _xenocell_obs_at(x, x.observations_head) 247 slot.ts_us = ts_us 248 slot.xeno_id = x.id 249 slot.kind = kind 250 slot.payload_hash = payload_hash 251 slot.sig_ptr = sig_ptr 252 slot.sig_bytes_len = sig_bytes_len 253 slot.intrusion_state_after = next_state 254 255 x.observations_head = x.observations_head + 1 256 if x.observations_head >= x.observations_capacity { x.observations_head = 0 } 257 x.obs_count = x.obs_count + 1 258 259 x.intrusion_state = next_state 260 return NX_XENO_OK 261} 262 263// ===== nx_xenocell_count_by_kind ================================= 264// 265// Walk the live ring and tally observations of a given kind. Used 266// by analysis tools to spot patterns: "how many RAM_READ events 267// did ME do this session?" -- if it's high, evidence of probing. 268 269func nx_xenocell_count_by_kind(x: *NxXenocell, kind: nx_int) -> nx_int { 270 var hits: nx_int = 0 271 var live: nx_size = x.obs_count 272 if live > x.observations_capacity { live = x.observations_capacity } 273 var i: nx_size = 0 274 while i < live { 275 let obs: *NxSignedObservation = _xenocell_obs_at(x, i) 276 if obs.kind == kind { hits = hits + 1 } 277 i = i + 1 278 } 279 return hits 280} 281 282// ===== nx_xenocell_is_hostile_now ================================ 283// 284// Returns 1 if intrusion_state is anything ABOVE DORMANT -- the xeno 285// has been caught actively doing something. Use this to gate brane 286// capability checks: hostile-now xenos lose access to capabilities 287// they MIGHT have held while dormant. 288 289func nx_xenocell_is_hostile_now(x: *NxXenocell) -> nx_int { 290 if x.intrusion_state > NX_INTR_DORMANT { return 1 } 291 return 0 292} 293 294// ===== nx_xenocell_evidence_count ================================ 295 296func nx_xenocell_evidence_count(x: *NxXenocell) -> nx_size { 297 return x.obs_count 298}