1use std::iter::repeat;
11use cryptoutil::copy_memory;
12
13use digest::Digest;
14use hmac::Hmac;
15use mac::Mac;
16
17pub fn hkdf_extract<D: Digest>(mut digest: D, salt: &[u8], ikm: &[u8], prk: &mut [u8]) {
27 assert!(prk.len() == digest.output_bytes());
28 digest.reset();
29
30 let mut mac = Hmac::new(digest, salt);
31 mac.input(ikm);
32 mac.raw_result(prk);
33 mac.reset();
34}
35
36pub fn hkdf_expand<D: Digest>(mut digest: D, prk: &[u8], info: &[u8], okm: &mut [u8]) {
45 digest.reset();
46
47 let mut mac = Hmac::new(digest, prk);
48 let os = mac.output_bytes();
49 let mut t: Vec<u8> = repeat(0).take(os).collect();
50 let mut n: u8 = 0;
51
52 for chunk in okm.chunks_mut(os) {
53 n = n.checked_add(1).expect("HKDF size limit exceeded.");
55
56 if n != 1 {
57 mac.input(&t[..]);
58 }
59 let nbuf = [n];
60 mac.input(info);
61 mac.input(&nbuf);
62 mac.raw_result(&mut t);
63 mac.reset();
64 let chunk_len = chunk.len();
65 copy_memory(&t[..chunk_len], chunk);
66 }
67}
68
69#[cfg(test)]
70mod test {
71 use std::iter::repeat;
72
73 use digest::Digest;
74 use sha1::Sha1;
75 use sha2::Sha256;
76 use hkdf::{hkdf_extract, hkdf_expand};
77
78 struct TestVector<D: Digest>{
79 digest: D,
80 ikm: Vec<u8>,
81 salt: Vec<u8>,
82 info: Vec<u8>,
83 l: usize,
84
85 prk: Vec<u8>,
86 okm: Vec<u8>,
87 }
88
89 #[test]
90 fn test_hkdf_rfc5869_sha256_vectors() {
91 let test_vectors = vec!(
92 TestVector{
93 digest: Sha256::new(),
94 ikm: repeat(0x0b).take(22).collect(),
95 salt: (0x00..0x0c + 1).collect(),
96 info: (0xf0..0xf9 + 1).collect(),
97 l: 42,
98 prk: vec![
99 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf,
100 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63,
101 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31,
102 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5 ],
103 okm: vec![
104 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
105 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
106 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
107 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
108 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
109 0x58, 0x65 ],
110 },
111 TestVector{
112 digest: Sha256::new(),
113 ikm: (0x00..0x4f + 1).collect(),
114 salt: (0x60..0xaf + 1).collect(),
115 info: (0xb0..0xff + 1).map(|x| x as u8).collect(),
116 l: 82,
117 prk: vec![
118 0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a,
119 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c,
120 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01,
121 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44 ],
122 okm: vec![
123 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1,
124 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34,
125 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
126 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c,
127 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72,
128 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
129 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
130 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71,
131 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87,
132 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f,
133 0x1d, 0x87 ],
134 },
135 TestVector{
136 digest: Sha256::new(),
137 ikm: repeat(0x0b).take(22).collect(),
138 salt: vec![],
139 info: vec![],
140 l:42,
141 prk: vec![
142 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16,
143 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf,
144 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77,
145 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04 ],
146 okm: vec![
147 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f,
148 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31,
149 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
150 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d,
151 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a,
152 0x96, 0xc8 ],
153 },
154 );
155
156 for t in test_vectors.iter() {
157 let mut prk: Vec<u8> = repeat(0).take(t.prk.len()).collect();
158 hkdf_extract(t.digest, &t.salt[..], &t.ikm[..], &mut prk);
159 assert!(prk == t.prk);
160
161 let mut okm: Vec<u8> = repeat(0).take(t.okm.len()).collect();
162 assert!(okm.len() == t.l);
163 hkdf_expand(t.digest, &prk[..], &t.info[..], &mut okm);
164 assert!(okm == t.okm);
165 }
166 }
167
168 #[test]
169 fn test_hkdf_rfc5869_sha1_vectors() {
170 let test_vectors = vec!(
171 TestVector{
172 digest: Sha1::new(),
173 ikm: repeat(0x0b).take(11).collect(),
174 salt: (0x00..0x0c + 1).collect(),
175 info: (0xf0..0xf9 + 1).collect(),
176 l: 42,
177 prk: vec![
178 0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f,
179 0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b,
180 0xaa, 0x2b, 0xa2, 0x43 ],
181 okm: vec![
182 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69,
183 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81,
184 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15,
185 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2,
186 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3,
187 0xf8, 0x96 ],
188 },
189 TestVector{
190 digest: Sha1::new(),
191 ikm: (0x00..0x4f + 1).collect(),
192 salt: (0x60..0xaf + 1).collect(),
193 info: (0xb0..0xff + 1).map(|x| x as u8).collect(),
194 l: 82,
195 prk: vec![
196 0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59,
197 0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a,
198 0x22, 0x4c, 0xfa, 0xf6 ],
199 okm: vec![
200 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7,
201 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb,
202 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19,
203 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe,
204 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3,
205 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c,
206 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed,
207 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e,
208 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43,
209 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52,
210 0xd3, 0xb4 ],
211 },
212 TestVector{
213 digest: Sha1::new(),
214 ikm: repeat(0x0b).take(22).collect(),
215 salt: vec![],
216 info: vec![],
217 l:42,
218 prk: vec![
219 0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28,
220 0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a,
221 0xa0, 0xd3, 0x2d, 0x01 ],
222 okm: vec![
223 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61,
224 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06,
225 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06,
226 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0,
227 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3,
228 0x49, 0x18 ],
229 },
230 );
231
232 for t in test_vectors.iter() {
233 let mut prk: Vec<u8> = repeat(0).take(t.prk.len()).collect();
234 hkdf_extract(t.digest, &t.salt[..], &t.ikm[..], &mut prk);
235 assert!(prk == t.prk);
236
237 let mut okm: Vec<u8> = repeat(0).take(t.okm.len()).collect();
238 assert!(okm.len() == t.l);
239 hkdf_expand(t.digest, &prk[..], &t.info[..], &mut okm);
240 assert!(okm == t.okm);
241 }
242 }
243}