code wiki / (root) / nx_tls13_client_verify_cv.nx

nx_tls13_client_verify_cv.nx

buildroot/runtime/nx_tls13_client_verify_cv.nx

10419 B182 linesdepth 12pulls 50 transitivereach 498 importersview sourcekind tooltopic tls13
docsdependenciesstructsconstsfunctions

about

nx_tls13_client_verify_cv.nx -- CLOSE THE TLS 1.3 CLIENT AUTH BYPASS. The live client handshake (nx_tls13_client_session_recv_hs -> tls13_client_dispatch_with_validation) validated the server's certificate CHAIN (RFC 5280) but SKIPPED the server's CertificateVerify signature (documented STUB in nx_tls13_client.nx:170 "signature verification deferred to Gap I"). In TLS 1.3 the cert chain is PUBLIC data; only the CertificateVerify signature -- made with the leaf cert's PRIVATE key over Transcript-Hash(ClientHello..Certificate) -- proves the peer actually holds the key. Without it a MITM presents the real public chain + a garbage CertificateVerify and is accepted. The server Finished MAC does NOT save you (it only proves knowledge of the DHE secret the MITM itself negotiated). THIS closes it. Verifies the server CertificateVerify per RFC 8446 sec 4.4.3: signed content = 64*0x20 || "TLS 1.3, server CertificateVerify" || 0x00 || transcript_hash(32), against the leaf cert's public key. Dispatches the modern schemes we hold verifiers for -- ECDSA-secp256r1-SHA256 (0x0403), ECDSA-secp384r1- SHA384 (0x0503), Ed25519 (0x0807) -- and FAILS CLOSED (reject, never accept) on any scheme we cannot yet verify (RSA-PSS is the known follow-up). Re-composes the SAME verify primitives proven by the server-side nx_tls13_server_recv_client_cv gate (4/4) + the ecdsa/ed25519 KATs; accept-valid is proven END-TO-END by a real TLS fetch (nx_https_fetch_follow) landing HTTP 200 with verification enforced. license_tier: ORIGINAL genealogy_id: international-research-sources/ietf/rfc_8446_sec_4_4_3

dependencies 11 imports · 1 importers

nx_syscalls.nx nx_tls13_auth.nx nx_ed25519_signature.nx nx_x509.nx nx_x509_verify_ecdsa.nx nx_x509_verify_ecdsa_p384.nx nx_u256.nx nx_u384.nx nx_u2048.nx nx_x509_pubkey_rsa.nx nx_tls13_client_verify_cv.nx nx_tls13_client_session_recv_hs.nx

diagram shows first 10 each side; +1 more imports, +0 more importers in the complete lists below.

imports: nx_syscalls.nxnx_tls13_auth.nxnx_ed25519_signature.nxnx_x509.nxnx_x509_verify_ecdsa.nxnx_x509_verify_ecdsa_p384.nxnx_u256.nxnx_u384.nxnx_u2048.nxnx_x509_pubkey_rsa.nxnx_rsa_pss_sha256.nx

imported by: nx_tls13_client_session_recv_hs.nx

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main cvv_w sys_write sys_mmap cvv_content cvv_row cvv_w ↻ cvv_build cvv_u24 nx_tls13_client_verify_ser sys_mmap ↻ tls13_parse_certificate_ve tls13_auth_check_handshake tls_read_u16_be cvv_content ↻ x509_parse sys_mmap ↻ asn1_cursor_init asn1_expect_tag sys_mmap ↻ asn1_read_tlv_header asn1_read_tag asn1_read_length asn1_read_length ↻ x509_read_tlv sys_mmap ↻ asn1_expect_tag ↻ x509_read_alg_id sys_mmap ↻ asn1_expect_tag ↻ ed25519_verify_full sys_mmap ↻ ed25519_s_lt_l sys_mmap ↻ ge_p3_alloc sys_mmap ↻ fe_alloc nx_scratch nx_scratch_init nx_scratch_oom

structs

none

consts

33const NX_CVV_OK: i64 = 0
34const NX_CVV_PARSE_FAIL: i64 = 1 // CertificateVerify message malformed
35const NX_CVV_BAD_CERT: i64 = 2 // leaf cert unparseable / wrong key shape for the scheme
36const NX_CVV_VERIFY_FAIL: i64 = 3 // signature did NOT verify -> REJECT (impersonation attempt)
37const NX_CVV_UNSUPPORTED: i64 = 4 // scheme we cannot verify -> fail closed (REJECT)
39const CVV_CONTENT_LEN: i64 = 130
40const CVV_SS_ECDSA_P256: i64 = 0x0403
41const CVV_SS_ECDSA_P384: i64 = 0x0503
42const CVV_SS_ED25519: i64 = 0x0807
43const CVV_SS_RSA_PSS_SHA256: i64 = 0x0804 // rsa_pss_rsae_sha256 -- MANDATORY for RSA-cert TLS 1.3 CertificateVerify

functions

45func nx_tls13_client_cv_is_ok(v: i64) -> i64 { if v == NX_CVV_OK { return 1 } return 0 }
48func cvv_content(th32: *u8, out130: *u8) -> i64
63func nx_tls13_client_verify_server_cv(cv_msg: *u8, cv_msg_len: i64,
119func cvv_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
called by 2: cvv_rowmain calls 1: sys_write
120func cvv_row(name: *u8, ok: i64) -> i64 { if ok == 1 { cvv_w(" PASS " as *u8) } else { cvv_w(" FAIL " as *u8) } cvv_w(name); cvv_w("\n" as *u8); return ok }
called by 1: main calls 1: cvv_w
121func cvv_u24(b: *u8, o: i64, v: i64) -> i64 { b[o] = ((v >> 16) & 0xff) as u8; b[o+1] = ((v >> 8) & 0xff) as u8; b[o+2] = (v & 0xff) as u8; return o + 3 }
called by 1: cvv_build
122func cvv_build(scheme: i64, sig: *u8, sig_len: i64, msg: *u8) -> i64
called by 1: main calls 1: cvv_u24
133func main() -> i64