nx_tls12_record.nx source
↩ module page · 56 lines · 2642 B
1// nx_tls12_record.nx -- TLS 1.2 AES-128-GCM record protection (rung 4 core of the sovereign TLS 1.2 client).
2// RFC 5246/5288: AEAD record = nonce_explicit(8) || ciphertext || tag(16).
3// GCM nonce(12) = salt(4, from key_block write_IV) || explicit(8, here the sequence number)
4// AAD(13) = seq_num(8) || content_type(1) || version(0x0303) || plaintext_len(2)
5// Composes the RFC-KAT'd nx_aes128_gcm. KAT'd by round-trip + tamper-detect (no network). license_tier: ORIGINAL
6import "nx_syscalls.nx"
7import "nx_aes128_gcm.nx"
8
9func _r12_nonce(salt4: *u8, explicit8: *u8, out12: *u8) -> i64 {
10 var i: i64 = 0
11 while i < 4 { out12[i] = salt4[i]; i = i + 1 }
12 i = 0
13 while i < 8 { out12[4 + i] = explicit8[i]; i = i + 1 }
14 return 12
15}
16
17func _r12_aad(seq8: *u8, ctype: i64, ptlen: i64, out13: *u8) -> i64 {
18 var i: i64 = 0
19 while i < 8 { out13[i] = seq8[i]; i = i + 1 }
20 out13[8] = ctype as u8
21 out13[9] = 0x03 as u8
22 out13[10] = 0x03 as u8
23 out13[11] = ((ptlen >> 8) & 0xff) as u8
24 out13[12] = (ptlen & 0xff) as u8
25 return 13
26}
27
28// Seal a record: out = seq(8 explicit nonce) || ciphertext(ptlen) || tag(16). Returns total payload length.
29func tls12_record_seal(key16: *u8, salt4: *u8, seq8: *u8, ctype: i64, pt: *u8, ptlen: i64, out: *u8) -> i64 {
30 let iv: *u8 = sys_mmap(16)
31 _r12_nonce(salt4, seq8, iv)
32 let aad: *u8 = sys_mmap(16)
33 _r12_aad(seq8, ctype, ptlen, aad)
34 var i: i64 = 0
35 while i < 8 { out[i] = seq8[i]; i = i + 1 } // explicit nonce in the record
36 let ct: *u8 = (out as i64 + 8) as *u8
37 let tag: *u8 = (out as i64 + 8 + ptlen) as *u8
38 nx_aes128_gcm_seal(key16, iv, aad, 13, pt, ptlen, ct, tag)
39 return 8 + ptlen + 16
40}
41
42// Open a record: payload = explicit(8) || ct || tag(16). seq8 = the receiver's expected sequence (for AAD).
43// Returns plaintext length into ptout, or -1 on auth failure / short input.
44func tls12_record_open(key16: *u8, salt4: *u8, seq8: *u8, ctype: i64, payload: *u8, plen: i64, ptout: *u8) -> i64 {
45 if plen < 24 { return 0 - 1 } // need >= 8 explicit + 16 tag
46 let ctlen: i64 = plen - 8 - 16
47 let iv: *u8 = sys_mmap(16)
48 _r12_nonce(salt4, payload, iv) // explicit nonce comes FROM the record
49 let aad: *u8 = sys_mmap(16)
50 _r12_aad(seq8, ctype, ctlen, aad)
51 let ct: *u8 = (payload as i64 + 8) as *u8
52 let tag: *u8 = (payload as i64 + 8 + ctlen) as *u8
53 let v: i64 = nx_aes128_gcm_open(key16, iv, aad, 13, ct, ctlen, tag, ptout)
54 if v != 0 { return 0 - 1 } // nx_aes128_gcm_open: 0 = OK, -1 = auth failure
55 return ctlen
56}