code wiki / (root) / nx_tls13_client_dispatch_with_validation.nx

nx_tls13_client_dispatch_with_validation.nx source

↩ module page · 124 lines · 5002 B

1// nx_tls13_client_dispatch_with_validation.nx -- TLS 1.3 client 2// dispatcher variant that enforces cert chain validation against 3// a TrustStore at the WAIT_CERT state. 4// 5// Phase 0b §L sub-4 of the TLS client arc. Wraps the existing 6// tls13_client_dispatch_handshake_message (commit pre-dating this 7// session, with the "accept ANY cert" STUB intentionally documented 8// in its preamble) with the cert-validation BRIDGE shipped this 9// session (nx_tls13_client_validate_certificate, commit c5ddbf81). 10// 11// Wrapper protocol: 12// - For state != WAIT_CERT: delegate unchanged to the underlying 13// dispatcher (transcript update + state transition unchanged). 14// - For state == WAIT_CERT: call the bridge FIRST against the 15// Certificate message bytes. If validation fails, return 16// CERT_VERIFY_FAIL (no transcript update, no state advance -- 17// handshake stalls until caller closes the connection). 18// If validation succeeds, delegate to the underlying 19// dispatcher (which advances state to WAIT_CV). 20// 21// Per Cardinal 19 (API contract stability): the existing 22// dispatcher signature is UNCHANGED. Callers without a 23// TrustStore (e.g. the loopback test that uses a self-signed 24// throwaway) keep working in the legacy "accept any" mode. The 25// real Web PKI client uses this variant. 26// 27// Per Cardinal 12 (defensive at boundaries): cert validation 28// happens BEFORE the underlying dispatcher's transcript update, 29// so a rejected cert doesn't poison the transcript hash. 30// 31// Public API: 32// tls13_client_dispatch_with_validation( 33// state, msg, msg_len, 34// server_hs_traffic_secret, 35// transcript_state, 36// out_new_state, 37// val_ctx: *TlsValidationContext 38// ) -> verdict 39// nx_tls13_dwv_verdict_is_valid(v) -> 0|1 40// 41// Sealed verdict enum (separate namespace to keep dispatcher's 42// existing 6-verdict surface stable): 43// NX_TLS13_DWV_OK 44// NX_TLS13_DWV_BAD_MSG_TYPE -- delegated from dispatcher 45// NX_TLS13_DWV_BAD_FORMAT -- delegated from dispatcher 46// NX_TLS13_DWV_SF_BAD_MAC -- delegated from dispatcher 47// NX_TLS13_DWV_BAD_STATE -- delegated from dispatcher 48// NX_TLS13_DWV_CERT_VERIFY_FAIL -- THE new verdict: bridge rejected 49// 50// license_tier: INDEPENDENT_REDERIVE 51// genealogy_id: international-research-sources/ietf/rfc_8446 + rfc_5280 52// lineage_id: nishi_tls13_client_dispatch_with_validation_q10 53 54// nx_safety_envelope: 55// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 56// sil_target: SIL1 57// evidence: [bulk_applied_2026-05-19, tls13-dispatcher-with-validation] 58// verdict: NOT_YET_EVALUATED 59 60import "nx_syscalls.nx" 61import "nx_tls13_client.nx" 62import "nx_tls13_client_validate_certificate.nx" 63 64const NX_TLS13_DWV_OK: i64 = 1 65const NX_TLS13_DWV_BAD_MSG_TYPE: i64 = 2 66const NX_TLS13_DWV_BAD_FORMAT: i64 = 3 67const NX_TLS13_DWV_SF_BAD_MAC: i64 = 4 68const NX_TLS13_DWV_BAD_STATE: i64 = 5 69const NX_TLS13_DWV_CERT_VERIFY_FAIL: i64 = 6 70const NX_TLS13_DWV_VERDICT_N: i64 = 7 71 72func nx_tls13_dwv_verdict_is_valid(v: i64) -> i64 { 73 if v < NX_TLS13_DWV_OK { return 0 } 74 if v >= NX_TLS13_DWV_VERDICT_N { return 0 } 75 return 1 76} 77 78// Map an existing dispatcher verdict into our wrapper namespace. 79// One-to-one preservation; the new verdict CERT_VERIFY_FAIL is 80// added by the WAIT_CERT branch only. 81func _map_dispatcher_verdict(v: i64) -> i64 { 82 if v == NX_TLS13_CLIENT_VERDICT_OK { return NX_TLS13_DWV_OK } 83 if v == NX_TLS13_CLIENT_VERDICT_BAD_MSG_TYPE { return NX_TLS13_DWV_BAD_MSG_TYPE } 84 if v == NX_TLS13_CLIENT_VERDICT_BAD_FORMAT { return NX_TLS13_DWV_BAD_FORMAT } 85 if v == NX_TLS13_CLIENT_VERDICT_SF_BAD_MAC { return NX_TLS13_DWV_SF_BAD_MAC } 86 if v == NX_TLS13_CLIENT_VERDICT_BAD_STATE { return NX_TLS13_DWV_BAD_STATE } 87 return NX_TLS13_DWV_BAD_FORMAT // unknown -> conservative fallback 88} 89 90// Dispatch one decrypted handshake message with cert validation 91// enforced at WAIT_CERT. See preamble for protocol details. 92func tls13_client_dispatch_with_validation( 93 state: i64, 94 msg: *u8, msg_len: i64, 95 server_hs_traffic_secret: *u8, 96 transcript_state: *u8, 97 out_new_state: *i64, 98 val_ctx: *TlsValidationContext 99) -> i64 { 100 if state == NX_TLS13_CSTATE_WAIT_CERT { 101 // Validate BEFORE delegating: keeps transcript clean if 102 // we reject. 103 let cv: i64 = nx_tls13_client_validate_certificate( 104 msg, msg_len, val_ctx 105 ) 106 if cv != NX_TLS13_CLIENT_CV_OK { 107 return NX_TLS13_DWV_CERT_VERIFY_FAIL 108 } 109 } 110 111 let d: i64 = tls13_client_dispatch_handshake_message( 112 state, msg, msg_len, 113 server_hs_traffic_secret, 114 transcript_state, 115 out_new_state 116 ) 117 return _map_dispatcher_verdict(d) 118} 119 120// Compile-only smoke. Real KAT in 121// nx_tls13_client_dispatch_with_validation_test.nx. 122func main() -> i64 { 123 return 0 124}