1use crate::hmac;
32
33pub fn extract_sha256(salt: &[u8], ikm: &[u8]) -> [u8; 32] {
54 hmac::hmac_sha256(salt, ikm)
55}
56
57pub fn extract<T: AsRef<[u8]>>(salt: &[u8], ikm: &[u8], hmac: fn(&[u8], &[u8]) -> T) -> T {
59 hmac(salt, ikm)
60}
61
62pub fn expand_sha256(prk: &[u8], info: &[u8], l: usize) -> Box<[u8]> {
84 let mut result: Vec<u8> = Vec::with_capacity(l);
86 let text_max_len = 32 + info.len() + 1;
87
88 let mut t: Vec<u8> = Vec::with_capacity(text_max_len);
89 let mut i = 0usize;
90 while result.len() < l {
91 t.extend_from_slice(info);
92 i += 1;
93 t.push(i as u8);
94 let hmac_hash = hmac::hmac_sha256(prk, &t);
95 t.truncate(0);
96 t.extend_from_slice(&hmac_hash);
97 result.extend_from_slice(&hmac_hash);
98 }
99
100 result.truncate(l);
101 result.into_boxed_slice()
102}
103
104pub fn expand<T: AsRef<[u8]>>(
105 prk: &[u8],
106 info: &[u8],
107 l: usize,
108 hmac: fn(&[u8], &[u8]) -> T,
109) -> Box<[u8]> {
110 let mut result: Vec<u8> = Vec::with_capacity(l);
112 let text_max_len = 64 + info.len() + 1;
113
114 let mut t: Vec<u8> = Vec::with_capacity(text_max_len);
115 let mut i = 0usize;
116 while result.len() < l {
117 t.extend_from_slice(info);
118 i += 1;
119 t.push(i as u8);
120 let hmac_hash = hmac(prk, &t);
121 t.truncate(0);
122 t.extend_from_slice(&hmac_hash.as_ref());
123 result.extend_from_slice(&hmac_hash.as_ref());
124 }
125
126 result.truncate(l);
127 result.into_boxed_slice()
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133 use crate::hmac::hmac_sha256;
134
135 #[test]
136 fn test_extract_expand_sha256_1() {
137 let ikm: [u8; 80] = [
139 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
140 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
141 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
142 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
143 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
144 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
145 ];
146 let salt: [u8; 80] = [
148 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d,
149 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b,
150 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
151 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
152 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5,
153 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
154 ];
155
156 let info: [u8; 80] = [
157 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd,
158 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
159 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
160 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
161 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
162 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
163 ];
164
165 let l = 82usize;
166
167 let prk: [u8; 32] = [
168 0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35,
169 0xb4, 0x5c, 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, 0x4a, 0x19, 0x3f, 0x40,
170 0xc1, 0x5f, 0xc2, 0x44,
171 ];
172
173 let okm: [u8; 82] = [
174 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a,
175 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c,
176 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb,
177 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
178 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec,
179 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87,
180 ];
181
182 let result = extract(&salt, &ikm, hmac_sha256);
183 assert_eq!(result, prk);
184
185 let result: &[u8] = &expand(&prk, &info, l, hmac_sha256);
186 assert_eq!(result.len(), l);
187 assert_eq!(result, &okm[..]);
188 }
189
190 #[test]
191 fn test_extract_expand_sha256_2() {
192 let ikm: [u8; 22] = [
193 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
194 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
195 ];
196 let salt: [u8; 13] = [
198 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
199 ];
200
201 let info: [u8; 10] = [0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9];
202
203 let l = 42usize;
204
205 let prk: [u8; 32] = [
206 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b,
207 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a,
208 0xd7, 0xc2, 0xb3, 0xe5,
209 ];
210
211 let okm: [u8; 42] = [
212 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36,
213 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56,
214 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65,
215 ];
216
217 let result = extract(&salt, &ikm, hmac_sha256);
218 assert_eq!(result, prk);
219
220 let result: &[u8] = &expand(&prk, &info, l, hmac_sha256);
221 assert_eq!(result.len(), l);
222 assert_eq!(result, &okm[..]);
223 }
224
225 #[test]
226 fn test_extract_expand_sha256_3() {
227 let ikm: [u8; 22] = [
228 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
229 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
230 ];
231 let l = 42usize;
232
233 let prk: [u8; 32] = [
234 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64,
235 0x8b, 0xdf, 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, 0xac, 0x43, 0x4c, 0x1c,
236 0x29, 0x3c, 0xcb, 0x04,
237 ];
238
239 let okm: [u8; 42] = [
240 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c,
241 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f,
242 0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8,
243 ];
244
245 let result = extract(&[], &ikm, hmac_sha256);
246 assert_eq!(result, prk);
247
248 let result: &[u8] = &expand(&prk, &[], l, hmac_sha256);
249 assert_eq!(result.len(), l);
250 assert_eq!(result, &okm[..]);
251 }
252}