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}