code wiki / (root) / hkdf_sha384.nx

hkdf_sha384.nx source

↩ module page · 92 lines · 2919 B

1// hkdf_sha384.nx -- HKDF-SHA-384 (RFC 5869). 2// 3// Parallel to hkdf.nx but keyed on HMAC-SHA-384. Required for 4// TLS 1.3 cipher suites that use SHA-384 throughout the key 5// schedule (e.g. TLS_AES_256_GCM_SHA384 per RFC 8446 §B.4). 6// 7// Two-stage design (identical shape to hkdf.nx): 8// Extract(salt, IKM) -> PRK = HMAC-SHA-384(salt, IKM) [48-byte PRK] 9// Expand(PRK, info, L) -> OKM via counter-mode HMAC chain 10// 11// Output capacity: 255 * 48 = 12240 bytes. TLS 1.3 never needs 12// more than a few hundred, so this is ample. 13 14import "syscalls.nx" 15import "hmac_sha384.nx" 16 17const HKDF384_HASH: i64 = 48 18const HKDF384_MAX_L: i64 = 12240 19 20func hkdf384_extract(salt: *u8, salt_len: i64, 21 ikm: *u8, ikm_len: i64, 22 prk: *u8) -> i64 { 23 if salt_len == 0 { 24 let zero_salt: *u8 = sys_mmap(HKDF384_HASH) 25 var i: i64 = 0 26 while i < HKDF384_HASH { zero_salt[i] = 0; i = i + 1 } 27 hmac_sha384(zero_salt, HKDF384_HASH, ikm, ikm_len, prk) 28 } else { 29 hmac_sha384(salt, salt_len, ikm, ikm_len, prk) 30 } 31 return 0 32} 33 34func hkdf384_expand(prk: *u8, 35 info: *u8, info_len: i64, 36 l: i64, out: *u8) -> i64 { 37 if l > HKDF384_MAX_L { return -1 } 38 if l < 0 { return -1 } 39 40 let t_prev: *u8 = sys_mmap(HKDF384_HASH) 41 let t_curr: *u8 = sys_mmap(HKDF384_HASH) 42 let buf_cap: i64 = HKDF384_HASH + info_len + 1 43 let buf: *u8 = sys_mmap(buf_cap) 44 45 var prev_len: i64 = 0 46 var produced: i64 = 0 47 var counter: i64 = 1 48 while produced < l { 49 var bi: i64 = 0 50 var k: i64 = 0 51 while k < prev_len { buf[bi + k] = t_prev[k]; k = k + 1 } 52 bi = bi + prev_len 53 k = 0 54 while k < info_len { buf[bi + k] = info[k]; k = k + 1 } 55 bi = bi + info_len 56 buf[bi] = counter & 0xFF 57 bi = bi + 1 58 59 hmac_sha384(prk, HKDF384_HASH, buf, bi, t_curr) 60 61 let remain: i64 = l - produced 62 var take: i64 = HKDF384_HASH 63 if remain < HKDF384_HASH { take = remain } 64 k = 0 65 while k < take { out[produced + k] = t_curr[k]; k = k + 1 } 66 produced = produced + take 67 68 k = 0 69 while k < HKDF384_HASH { t_prev[k] = t_curr[k]; k = k + 1 } 70 prev_len = HKDF384_HASH 71 counter = counter + 1 72 } 73 return 0 74} 75 76func main() -> i64 { 77 let ikm: *u8 = sys_mmap(22) 78 let salt: *u8 = sys_mmap(13) 79 let info: *u8 = sys_mmap(10) 80 let prk: *u8 = sys_mmap(48) 81 let okm: *u8 = sys_mmap(64) 82 var i: i64 = 0 83 while i < 22 { ikm[i] = 0x0B; i = i + 1 } 84 i = 0 85 while i < 13 { salt[i] = i as i64; i = i + 1 } 86 i = 0 87 while i < 10 { info[i] = 0xF0 + (i as i64); i = i + 1 } 88 89 hkdf384_extract(salt, 13, ikm, 22, prk) 90 hkdf384_expand(prk, info, 10, 64, okm) 91 return okm[0] as i64 92}