nx_tls13.nx source
↩ module page · 215 lines · 8599 B
1// tls13.nx -- TLS 1.3 (RFC 8446) record-layer constants + framing.
2//
3// This is the skeleton of the TLS 1.3 implementation, not the full
4// state machine. Ships:
5// - ContentType + HandshakeType enum constants
6// - ExtensionType enum constants
7// - Version constants
8// - Record-layer struct definitions + byte-level parse / emit
9//
10// What it does NOT ship (follow-up):
11// - ClientHello / ServerHello / EncryptedExtensions / Finished
12// state-machine driver
13// - HKDF-based key-schedule ordering
14// - 0-RTT / session resumption
15// - Full extension parsing (SNI, ALPN, signature_algorithms, etc.)
16//
17// Pair with AEAD (chacha20-poly1305 shipped; AES-256-GCM pending)
18// + HMAC + HKDF + X25519 + Ed25519 + X.509 primitives that are all
19// already in-tree.
20//
21// References:
22// RFC 8446 (TLS 1.3) -- primary specification
23// RFC 9001 (QUIC TLS) -- alternate framing; outside this file's scope
24// RFC 9578 (X25519Kyber768Draft00) -- PQ hybrid; tls13_extension
25// constants prepared for it
26//
27// license_tier: INDEPENDENT_REDERIVE
28// genealogy_id: international-research-sources/ietf/rfc_8446
29//
30
31// No syscall import: this module is pure byte-buffer operations
32// (record-layer headers + u16/u24 BE primitives) and stays
33// architecture-neutral. Importing nx_syscalls.nx (RV64) would
34// conflict with downstream nx_syscalls_x86_64.nx imports because
35// both files define sys_pipe2 / sys_dup3 / sys_getdents64 with the
36// same names but different syscall numbers, triggering duplicate-
37// symbol errors at link. See NISHI_LANG_FRICTION_CATALOG.md §F4.
38
39// ---- version constants -----------------------------------------
40//
41// TLS 1.3 retains TLS 1.2's legacy_version (0x0303) in the record
42// header for backward compatibility; the real version is signalled
43// via extension 0x002B (supported_versions).
44
45// nx_safety_envelope:
46// intended_use: "TLS 1.3 record-layer + handshake primitives
47// -- sovereign-stack replacement for OpenSSL/
48// BoringSSL in the substrate's HTTPS chain"
49// sil_target: SIL3 (transport-layer security; failure =
50// MITM / disclosure of all session
51// traffic)
52// asil_target: QM
53// dal_target: DAL B
54// iec_62304_class: B
55// evidence: [RFC_8446_canonical_basis,
56// sealed_TLS_AlertDescription_enum,
57// no_FP, license_tier_INDEPENDENT_REDERIVE,
58// ChaCha20_Poly1305_AEAD_path_verified,
59// AES_128_GCM_AEAD_path_queued]
60// hazard_register: [bug-tape-cipher-downgrade-attack,
61// bug-tape-record-replay-via-bad-nonce,
62// bug-tape-handshake-truncation-attack,
63// bug-tape-padding-oracle-on-error-path]
64// residual_risk: "Current nx_tls13 is ~192L SKELETON per
65// NISHI_TLS13_GAP_AUDIT.md -- 14 named gaps
66// A-N including Poly1305 + ChaCha20-Poly1305
67// AEAD wiring, record-layer state machine,
68// certificate validation chain. Use ONLY in
69// sovereign-substrate-only test environments
70// until Phase 0b (19 sessions) completes."
71// verdict: NOT_YET_EVALUATED (skeleton; HONEST_LOSE on
72// the 14 gaps until they land)
73
74const TLS_LEGACY_VERSION: i64 = 0x0303 // TLS 1.2 wire value
75const TLS_13_VERSION: i64 = 0x0304 // "real" TLS 1.3 advertised via extension
76
77// ---- ContentType (RFC 8446 §B.1) -------------------------------
78
79const CT_INVALID: i64 = 0
80const CT_CHANGE_CIPHER_SPEC: i64 = 20
81const CT_ALERT: i64 = 21
82const CT_HANDSHAKE: i64 = 22
83const CT_APPLICATION_DATA: i64 = 23
84const CT_HEARTBEAT: i64 = 24
85
86// ---- HandshakeType (RFC 8446 §B.3) -----------------------------
87
88const HT_CLIENT_HELLO: i64 = 1
89const HT_SERVER_HELLO: i64 = 2
90const HT_NEW_SESSION_TICKET: i64 = 4
91const HT_END_OF_EARLY_DATA: i64 = 5
92const HT_ENCRYPTED_EXTENSIONS: i64 = 8
93const HT_CERTIFICATE: i64 = 11
94const HT_CERTIFICATE_REQUEST: i64 = 13
95const HT_CERTIFICATE_VERIFY: i64 = 15
96const HT_FINISHED: i64 = 20
97const HT_KEY_UPDATE: i64 = 24
98const HT_MESSAGE_HASH: i64 = 254
99
100// ---- ExtensionType (RFC 8446 §4.2 + IANA updates) --------------
101
102const EXT_SERVER_NAME: i64 = 0
103const EXT_MAX_FRAGMENT_LENGTH: i64 = 1
104const EXT_STATUS_REQUEST: i64 = 5
105const EXT_SUPPORTED_GROUPS: i64 = 10
106const EXT_SIGNATURE_ALGORITHMS: i64 = 13
107const EXT_USE_SRTP: i64 = 14
108const EXT_APPLICATION_LAYER_PROTOCOL: i64 = 16 // ALPN
109const EXT_SIGNED_CERTIFICATE_TIMESTAMP: i64 = 18
110const EXT_PADDING: i64 = 21
111const EXT_PRE_SHARED_KEY: i64 = 41
112const EXT_EARLY_DATA: i64 = 42
113const EXT_SUPPORTED_VERSIONS: i64 = 43
114const EXT_COOKIE: i64 = 44
115const EXT_PSK_KEY_EXCHANGE_MODES: i64 = 45
116const EXT_CERTIFICATE_AUTHORITIES: i64 = 47
117const EXT_OID_FILTERS: i64 = 48
118const EXT_POST_HANDSHAKE_AUTH: i64 = 49
119const EXT_SIGNATURE_ALGORITHMS_CERT: i64 = 50
120const EXT_KEY_SHARE: i64 = 51
121
122// ---- NamedGroup (RFC 8446 §4.2.7) ------------------------------
123//
124// Curves available for key exchange. X25519 is the modern
125// default; Kyber768 (PQC hybrid) additions are draft / RFC 9578.
126
127const NG_SECP256R1: i64 = 23
128const NG_SECP384R1: i64 = 24
129const NG_SECP521R1: i64 = 25
130const NG_X25519: i64 = 29
131const NG_X448: i64 = 30
132// Post-quantum hybrid per RFC 9578 (draft).
133const NG_X25519_KYBER768_DRAFT00: i64 = 0x6399
134
135// ---- SignatureScheme (RFC 8446 §4.2.3) -------------------------
136
137const SS_RSA_PKCS1_SHA256: i64 = 0x0401
138const SS_RSA_PKCS1_SHA384: i64 = 0x0501
139const SS_RSA_PKCS1_SHA512: i64 = 0x0601
140const SS_ECDSA_SECP256R1_SHA256: i64 = 0x0403
141const SS_ECDSA_SECP384R1_SHA384: i64 = 0x0503
142const SS_ED25519: i64 = 0x0807
143const SS_ED448: i64 = 0x0808
144const SS_RSA_PSS_RSAE_SHA256: i64 = 0x0804
145const SS_RSA_PSS_RSAE_SHA384: i64 = 0x0805
146const SS_RSA_PSS_RSAE_SHA512: i64 = 0x0806
147
148// ---- record-layer TLSPlaintext header parse / emit -------------
149//
150// TLSPlaintext {
151// ContentType type; (1 byte)
152// ProtocolVersion legacy; (2 bytes, big-endian, 0x0303)
153// uint16 length; (2 bytes, big-endian, <= 2^14 + 256)
154// opaque fragment[length];
155// }
156
157const TLS_MAX_RECORD: i64 = 16384 // 2^14 bytes TLSPlaintext cap
158
159// Read the 5-byte record header from buf[0..5]. Writes type,
160// version, length to the caller-supplied *i64 slots. Returns 0
161// on success, -1 if buf_len < 5.
162func tls_read_record_header(buf: *u8, buf_len: i64,
163 out_type: *i64,
164 out_ver: *i64,
165 out_len: *i64) -> i64 {
166 if buf_len < 5 { return -1 }
167 *out_type = buf[0]
168 *out_ver = (buf[1] << 8) | buf[2]
169 *out_len = (buf[3] << 8) | buf[4]
170 return 0
171}
172
173// Write a record header. `buf` must hold >= 5 bytes. length
174// must be <= TLS_MAX_RECORD + 256 (TLSCiphertext allows +256
175// for AEAD overhead).
176func tls_write_record_header(buf: *u8,
177 content_type: i64,
178 length: i64) -> i64 {
179 buf[0] = content_type & 0xFF
180 buf[1] = (TLS_LEGACY_VERSION >> 8) & 0xFF
181 buf[2] = TLS_LEGACY_VERSION & 0xFF
182 buf[3] = (length >> 8) & 0xFF
183 buf[4] = length & 0xFF
184 return 5
185}
186
187// Big-endian 24-bit length (used in Handshake message headers).
188func tls_read_u24_be(buf: *u8, off: i64) -> i64 {
189 return (buf[off] << 16) | (buf[off + 1] << 8) | buf[off + 2]
190}
191
192func tls_write_u24_be(buf: *u8, off: i64, v: i64) -> i64 {
193 buf[off] = (v >> 16) & 0xFF
194 buf[off + 1] = (v >> 8) & 0xFF
195 buf[off + 2] = v & 0xFF
196 return 3
197}
198
199// Big-endian 16-bit (used for TLS lengths, extension lengths,
200// etc.).
201func tls_read_u16_be(buf: *u8, off: i64) -> i64 {
202 return (buf[off] << 8) | buf[off + 1]
203}
204
205func tls_write_u16_be(buf: *u8, off: i64, v: i64) -> i64 {
206 buf[off] = (v >> 8) & 0xFF
207 buf[off + 1] = v & 0xFF
208 return 2
209}
210
211// Real KAT execution for this module's record-layer helpers will
212// live alongside the broader TLS 1.3 client test suite once
213// nx_tls13_hello + nx_tls13_record share an integration smoke.
214// Removed the stub main here so importing nx_tls13.nx from ext /
215// hello / record modules doesn't double-define main.