1use core::iter::repeat;
18
19use crate::digest::Digest;
20use crate::mac::{Mac, MacResult};
21use alloc::vec::Vec;
22
23pub struct Hmac<D> {
25 digest: D,
26 i_key: Vec<u8>,
27 o_key: Vec<u8>,
28 finished: bool,
29}
30
31fn derive_key(key: &mut [u8], mask: u8) {
32 for elem in key.iter_mut() {
33 *elem ^= mask;
34 }
35}
36
37fn expand_key<D: Digest>(digest: &mut D, key: &[u8]) -> Vec<u8> {
41 let bs = digest.block_size();
42 let mut expanded_key: Vec<u8> = repeat(0).take(bs).collect();
43
44 if key.len() <= bs {
45 expanded_key[0..key.len()].copy_from_slice(key);
46 } else {
47 let output_size = digest.output_bytes();
48 digest.input(key);
49 digest.result(&mut expanded_key[..output_size]);
50 digest.reset();
51 }
52 expanded_key
53}
54
55fn create_keys<D: Digest>(digest: &mut D, key: &[u8]) -> (Vec<u8>, Vec<u8>) {
58 let mut i_key = expand_key(digest, key);
59 let mut o_key = i_key.clone();
60 derive_key(&mut i_key, 0x36);
61 derive_key(&mut o_key, 0x5c);
62 (i_key, o_key)
63}
64
65impl<D: Digest> Hmac<D> {
66 pub fn new(mut digest: D, key: &[u8]) -> Hmac<D> {
73 let (i_key, o_key) = create_keys(&mut digest, key);
74 digest.input(&i_key[..]);
75 Hmac {
76 digest: digest,
77 i_key: i_key,
78 o_key: o_key,
79 finished: false,
80 }
81 }
82}
83
84impl<D: Digest> Mac for Hmac<D> {
85 fn input(&mut self, data: &[u8]) {
86 assert!(!self.finished);
87 self.digest.input(data);
88 }
89
90 fn reset(&mut self) {
91 self.digest.reset();
92 self.digest.input(&self.i_key[..]);
93 self.finished = false;
94 }
95
96 fn result(&mut self) -> MacResult {
97 let output_size = self.digest.output_bytes();
98 let mut code: Vec<u8> = repeat(0).take(output_size).collect();
99
100 self.raw_result(&mut code);
101
102 MacResult::new_from_owned(code)
103 }
104
105 fn raw_result(&mut self, output: &mut [u8]) {
106 if !self.finished {
107 self.digest.result(output);
108
109 self.digest.reset();
110 self.digest.input(&self.o_key[..]);
111 self.digest.input(output);
112
113 self.finished = true;
114 }
115
116 self.digest.result(output);
117 }
118
119 fn output_bytes(&self) -> usize {
120 self.digest.output_bytes()
121 }
122}
123
124#[cfg(test)]
125mod test {
126 use crate::hmac::Hmac;
127 use crate::mac::Mac;
128
129 #[cfg(feature = "blake2")]
130 use crate::blake2s::Blake2s;
131
132 #[cfg(feature = "sha2")]
133 use crate::sha2::Sha256;
134
135 struct Test {
136 key: &'static [u8],
137 data: &'static [u8],
138 expected: &'static [u8],
139 }
140
141 fn tests() -> [Test; 3] {
144 [
145 Test {
146 key: &[
147 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
148 ],
149 data: b"Hi There",
150 expected: &[
151 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf,
152 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9,
153 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7,
154 ],
155 },
156 Test {
157 key: b"Jefe",
158 data: b"what do ya want for nothing?",
159 expected: &[
160 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08,
161 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec,
162 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43,
163 ],
164 },
165 Test {
166 key: &[
167 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
168 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
169 ],
170 data: &[
171 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
172 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
173 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
174 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
175 ],
176 expected: &[
177 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0,
178 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63,
179 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe,
180 ],
181 },
182 ]
183 }
184
185 #[cfg(feature = "sha2")]
186 #[test]
187 fn hmac_sha256() {
188 for t in tests().iter() {
189 let mut h = Hmac::new(Sha256::new(), &t.key[..]);
190 let mut output = [0u8; 32];
191 h.input(&t.data[..]);
192 h.raw_result(&mut output);
193 assert_eq!(&output[..], &t.expected[..]);
194 }
195 }
196
197 #[cfg(feature = "blake2")]
198 #[test]
199 fn hmac_blake2s() {
200 let key = [
201 0x05, 0x5a, 0x62, 0xc4, 0x6f, 0x56, 0x94, 0x0c, 0xb0, 0x00, 0xd5, 0x3d, 0x84, 0x2c,
202 0x0a, 0xbd, 0xba, 0x1c, 0x43, 0xb0, 0xa3, 0x0c, 0xa4, 0xc3, 0x8a, 0xd0, 0x84, 0xc2,
203 0x1c, 0x34, 0x99, 0x86,
204 ];
205 let data = b"hello";
206 let expected = [
207 0x9a, 0x4f, 0xe7, 0x47, 0xf8, 0x28, 0xa6, 0x15, 0x5e, 0xf8, 0x2b, 0xb2, 0x8c, 0xdb,
208 0x8f, 0x41, 0xfa, 0xd5, 0x29, 0xe0, 0x15, 0xf9, 0x25, 0x98, 0x74, 0x24, 0x70, 0x37,
209 0xaf, 0x28, 0xa6, 0x7a,
210 ];
211
212 let mut h = Hmac::new(Blake2s::new(32), &key[..]);
213 let mut output = [0u8; 32];
214 h.input(&data[..]);
215 h.raw_result(&mut output);
216 assert_eq!(&output[..], &expected[..]);
217 }
218}