code wiki / (root) / nx_tls12_record.nx

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}