code wiki / (root) / nx_quic_keys.nx

nx_quic_keys.nx source

↩ module page · 59 lines · 3152 B

1// nx_quic_keys.nx -- RUNG 5a of the sovereign QUIC transport: the Initial key schedule (RFC 9001 sec 5). 2// Builds on the sovereign HKDF-SHA256 (nx_hkdf) + adds the TLS 1.3 HKDF-Expand-Label (RFC 8446 sec 7.1). 3// QUIC Initial keys are derived purely from the client's Destination Connection ID + a fixed salt -- this 4// is what protects the handshake packets (R5b does the AEAD with these keys). Gated byte-exact against the 5// RFC 9001 A.1 worked example (DCID 0x8394c8f03e515708). No float. license_tier: ORIGINAL 6import "nx_hkdf.nx" 7 8// RFC 9001 sec 5.2 QUIC v1 initial salt (20 bytes). 9func quic_initial_salt(out: *u8) -> i64 { 10 out[0]=0x38 as u8; out[1]=0x76 as u8; out[2]=0x2c as u8; out[3]=0xf7 as u8; out[4]=0xf5 as u8 11 out[5]=0x59 as u8; out[6]=0x34 as u8; out[7]=0xb3 as u8; out[8]=0x4d as u8; out[9]=0x17 as u8 12 out[10]=0x9a as u8; out[11]=0xe6 as u8; out[12]=0xa4 as u8; out[13]=0xc8 as u8; out[14]=0x0c as u8 13 out[15]=0xad as u8; out[16]=0xcc as u8; out[17]=0xbb as u8; out[18]=0x7f as u8; out[19]=0x0a as u8 14 return 20 15} 16 17// HKDF-Expand-Label (RFC 8446 sec 7.1): info = uint16(L) || u8(6+label_len) || "tls13 "||label || u8(ctx_len) || ctx 18func hkdf_expand_label(secret: *u8, label: *u8, label_len: i64, ctx: *u8, ctx_len: i64, l: i64, out: *u8) -> i64 { 19 let info: *u8 = sys_mmap(512) 20 info[0] = ((l >> 8) & 0xff) as u8 21 info[1] = (l & 0xff) as u8 22 var o: i64 = 2 23 info[o] = (6 + label_len) as u8; o = o + 1 24 info[o]=0x74 as u8; info[o+1]=0x6c as u8; info[o+2]=0x73 as u8; info[o+3]=0x31 as u8; info[o+4]=0x33 as u8; info[o+5]=0x20 as u8 // "tls13 " 25 o = o + 6 26 var i: i64 = 0; while i < label_len { info[o + i] = label[i]; i = i + 1 } o = o + label_len 27 info[o] = ctx_len as u8; o = o + 1 28 i = 0; while i < ctx_len { info[o + i] = ctx[i]; i = i + 1 } o = o + ctx_len 29 return hkdf_expand(secret, info, o, l, out) 30} 31 32// derive client_initial_secret + server_initial_secret from the DCID (RFC 9001 sec 5.2). 33func quic_initial_secrets(dcid: *u8, dcil: i64, client_secret: *u8, server_secret: *u8) -> i64 { 34 let salt: *u8 = sys_mmap(20) 35 quic_initial_salt(salt) 36 let initial_secret: *u8 = sys_mmap(32) 37 hkdf_extract(salt, 20, dcid, dcil, initial_secret) 38 hkdf_expand_label(initial_secret, "client in" as *u8, 9, 0 as *u8, 0, 32, client_secret) 39 hkdf_expand_label(initial_secret, "server in" as *u8, 9, 0 as *u8, 0, 32, server_secret) 40 return 0 41} 42 43// also expose the intermediate initial_secret for the gate / debugging. 44func quic_initial_extract(dcid: *u8, dcil: i64, initial_secret: *u8) -> i64 { 45 let salt: *u8 = sys_mmap(20) 46 quic_initial_salt(salt) 47 hkdf_extract(salt, 20, dcid, dcil, initial_secret) 48 return 0 49} 50 51// derive packet-protection key (16B AES-128), iv (12B), header-protection key (16B) from a secret. 52func quic_derive_keys(secret: *u8, key: *u8, iv: *u8, hp: *u8) -> i64 { 53 hkdf_expand_label(secret, "quic key" as *u8, 8, 0 as *u8, 0, 16, key) 54 hkdf_expand_label(secret, "quic iv" as *u8, 7, 0 as *u8, 0, 12, iv) 55 hkdf_expand_label(secret, "quic hp" as *u8, 7, 0 as *u8, 0, 16, hp) 56 return 0 57} 58 59func main() -> i64 { return 0 }