code wiki / (root) / nx_quic_aead.nx

nx_quic_aead.nx source

↩ module page · 55 lines · 2633 B

1// nx_quic_aead.nx -- RUNG 5b of the sovereign QUIC transport: AEAD packet protection (RFC 9001 sec 5.3) 2// + header protection (sec 5.4). The QUIC nonce is iv XOR the left-padded packet number; the packet 3// payload is sealed with AES-128-GCM (aad = the header); the header's low first-byte bits + the packet 4// number bytes are masked with AES-ECB(hp_key, ciphertext-sample). With R5a's keys this makes a handshake 5// packet indistinguishable on the wire. Reuses the GCM module's own AES (no second cipher). No float. 6// license_tier: ORIGINAL 7import "nx_aes128_gcm.nx" 8 9// QUIC AEAD nonce (RFC 9001 sec 5.3): the 62-bit packet number, left-padded to 12 bytes, XOR the iv. 10func quic_nonce(iv12: *u8, pn: i64, nonce_out: *u8) -> i64 { 11 var i: i64 = 0 12 while i < 12 { nonce_out[i] = iv12[i]; i = i + 1 } 13 var p: i64 = pn 14 var j: i64 = 11 15 while j >= 4 { 16 nonce_out[j] = ((nonce_out[j] as i64) ^ (p & 0xff)) as u8 17 p = p >> 8 18 j = j - 1 19 } 20 return 0 21} 22 23// header-protection mask = AES-ECB(hp_key, 16-byte ciphertext sample). caller uses mask[0] + mask[1..pn_len]. 24func quic_hp_mask(hp_key: *u8, sample: *u8, mask_out: *u8) -> i64 { 25 let sched: *u8 = sys_mmap(176) 26 aes128_expand_key(hp_key, sched) 27 aes128_encrypt_block(sample, sched, mask_out) 28 return 0 29} 30 31// seal the payload: nonce(iv,pn) then AES-128-GCM(key, nonce, aad=header, pt) -> ct_out + tag16_out. 32func quic_seal(key: *u8, iv: *u8, pn: i64, aad: *u8, aad_len: i64, pt: *u8, pt_len: i64, ct_out: *u8, tag_out: *u8) -> i64 { 33 let nonce: *u8 = sys_mmap(12) 34 quic_nonce(iv, pn, nonce) 35 return nx_aes128_gcm_seal(key, nonce, aad, aad_len, pt, pt_len, ct_out, tag_out) 36} 37// open: nonce(iv,pn) then AES-128-GCM-open. returns the underlying open rc (0 = tag verified). 38func quic_open(key: *u8, iv: *u8, pn: i64, aad: *u8, aad_len: i64, ct: *u8, ct_len: i64, tag: *u8, pt_out: *u8) -> i64 { 39 let nonce: *u8 = sys_mmap(12) 40 quic_nonce(iv, pn, nonce) 41 return nx_aes128_gcm_open(key, nonce, aad, aad_len, ct, ct_len, tag, pt_out) 42} 43 44// apply OR remove header protection (XOR is symmetric). long_hdr=1 -> mask low 4 bits of first byte (0x0f); 45// short header masks 5 bits (0x1f). pn bytes get mask[1..pn_len]. 46func quic_hp_apply(hdr: *u8, pn_off: i64, pn_len: i64, mask: *u8, long_hdr: i64) -> i64 { 47 var lowmask: i64 = 0x1f 48 if long_hdr == 1 { lowmask = 0x0f } 49 hdr[0] = ((hdr[0] as i64) ^ ((mask[0] as i64) & lowmask)) as u8 50 var i: i64 = 0 51 while i < pn_len { hdr[pn_off + i] = ((hdr[pn_off + i] as i64) ^ (mask[1 + i] as i64)) as u8; i = i + 1 } 52 return 0 53} 54 55func main() -> i64 { return 0 }