1use std::cmp::min;
11
12use cryptoutil::{read_u32_le, write_u32_le};
13use mac::{Mac, MacResult};
14
15#[derive(Clone, Copy)]
16pub struct Poly1305 {
17 r : [u32; 5],
18 h : [u32; 5],
19 pad : [u32; 4],
20 leftover : usize,
21 buffer : [u8; 16],
22 finalized : bool,
23}
24
25impl Poly1305 {
26 pub fn new(key: &[u8]) -> Poly1305 {
27 assert!(key.len() == 32);
28 let mut poly = Poly1305{ r: [0u32; 5], h: [0u32; 5], pad: [0u32; 4], leftover: 0, buffer: [0u8; 16], finalized: false };
29
30 poly.r[0] = (read_u32_le(&key[0..4]) ) & 0x3ffffff;
32 poly.r[1] = (read_u32_le(&key[3..7]) >> 2) & 0x3ffff03;
33 poly.r[2] = (read_u32_le(&key[6..10]) >> 4) & 0x3ffc0ff;
34 poly.r[3] = (read_u32_le(&key[9..13]) >> 6) & 0x3f03fff;
35 poly.r[4] = (read_u32_le(&key[12..16]) >> 8) & 0x00fffff;
36
37 poly.pad[0] = read_u32_le(&key[16..20]);
38 poly.pad[1] = read_u32_le(&key[20..24]);
39 poly.pad[2] = read_u32_le(&key[24..28]);
40 poly.pad[3] = read_u32_le(&key[28..32]);
41
42 poly
43 }
44
45 fn block(&mut self, m: &[u8]) {
46 let hibit : u32 = if self.finalized { 0 } else { 1 << 24 };
47
48 let r0 = self.r[0];
49 let r1 = self.r[1];
50 let r2 = self.r[2];
51 let r3 = self.r[3];
52 let r4 = self.r[4];
53
54 let s1 = r1 * 5;
55 let s2 = r2 * 5;
56 let s3 = r3 * 5;
57 let s4 = r4 * 5;
58
59 let mut h0 = self.h[0];
60 let mut h1 = self.h[1];
61 let mut h2 = self.h[2];
62 let mut h3 = self.h[3];
63 let mut h4 = self.h[4];
64
65 h0 += (read_u32_le(&m[0..4]) ) & 0x3ffffff;
67 h1 += (read_u32_le(&m[3..7]) >> 2) & 0x3ffffff;
68 h2 += (read_u32_le(&m[6..10]) >> 4) & 0x3ffffff;
69 h3 += (read_u32_le(&m[9..13]) >> 6) & 0x3ffffff;
70 h4 += (read_u32_le(&m[12..16]) >> 8) | hibit;
71
72 let d0 = (h0 as u64 * r0 as u64) + (h1 as u64 * s4 as u64) + (h2 as u64 * s3 as u64) + (h3 as u64 * s2 as u64) + (h4 as u64 * s1 as u64);
74 let mut d1 = (h0 as u64 * r1 as u64) + (h1 as u64 * r0 as u64) + (h2 as u64 * s4 as u64) + (h3 as u64 * s3 as u64) + (h4 as u64 * s2 as u64);
75 let mut d2 = (h0 as u64 * r2 as u64) + (h1 as u64 * r1 as u64) + (h2 as u64 * r0 as u64) + (h3 as u64 * s4 as u64) + (h4 as u64 * s3 as u64);
76 let mut d3 = (h0 as u64 * r3 as u64) + (h1 as u64 * r2 as u64) + (h2 as u64 * r1 as u64) + (h3 as u64 * r0 as u64) + (h4 as u64 * s4 as u64);
77 let mut d4 = (h0 as u64 * r4 as u64) + (h1 as u64 * r3 as u64) + (h2 as u64 * r2 as u64) + (h3 as u64 * r1 as u64) + (h4 as u64 * r0 as u64);
78
79 let mut c : u32;
81 c = (d0 >> 26) as u32; h0 = d0 as u32 & 0x3ffffff;
82 d1 += c as u64; c = (d1 >> 26) as u32; h1 = d1 as u32 & 0x3ffffff;
83 d2 += c as u64; c = (d2 >> 26) as u32; h2 = d2 as u32 & 0x3ffffff;
84 d3 += c as u64; c = (d3 >> 26) as u32; h3 = d3 as u32 & 0x3ffffff;
85 d4 += c as u64; c = (d4 >> 26) as u32; h4 = d4 as u32 & 0x3ffffff;
86 h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
87 h1 += c;
88
89 self.h[0] = h0;
90 self.h[1] = h1;
91 self.h[2] = h2;
92 self.h[3] = h3;
93 self.h[4] = h4;
94 }
95
96 fn finish(&mut self) {
97 if self.leftover > 0 {
98 self.buffer[self.leftover] = 1;
99 for i in self.leftover+1..16 {
100 self.buffer[i] = 0;
101 }
102 self.finalized = true;
103 let tmp = self.buffer;
104 self.block(&tmp);
105 }
106
107 let mut h0 = self.h[0];
109 let mut h1 = self.h[1];
110 let mut h2 = self.h[2];
111 let mut h3 = self.h[3];
112 let mut h4 = self.h[4];
113
114 let mut c : u32;
115 c = h1 >> 26; h1 = h1 & 0x3ffffff;
116 h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
117 h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
118 h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
119 h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
120 h1 += c;
121
122 let mut g0 = h0.wrapping_add(5); c = g0 >> 26; g0 &= 0x3ffffff;
124 let mut g1 = h1.wrapping_add(c); c = g1 >> 26; g1 &= 0x3ffffff;
125 let mut g2 = h2.wrapping_add(c); c = g2 >> 26; g2 &= 0x3ffffff;
126 let mut g3 = h3.wrapping_add(c); c = g3 >> 26; g3 &= 0x3ffffff;
127 let mut g4 = h4.wrapping_add(c).wrapping_sub(1 << 26);
128
129 let mut mask = (g4 >> (32 - 1)).wrapping_sub(1);
131 g0 &= mask;
132 g1 &= mask;
133 g2 &= mask;
134 g3 &= mask;
135 g4 &= mask;
136 mask = !mask;
137 h0 = (h0 & mask) | g0;
138 h1 = (h1 & mask) | g1;
139 h2 = (h2 & mask) | g2;
140 h3 = (h3 & mask) | g3;
141 h4 = (h4 & mask) | g4;
142
143 h0 = ((h0 ) | (h1 << 26)) & 0xffffffff;
145 h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
146 h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
147 h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
148
149 let mut f : u64;
151 f = h0 as u64 + self.pad[0] as u64 ; h0 = f as u32;
152 f = h1 as u64 + self.pad[1] as u64 + (f >> 32); h1 = f as u32;
153 f = h2 as u64 + self.pad[2] as u64 + (f >> 32); h2 = f as u32;
154 f = h3 as u64 + self.pad[3] as u64 + (f >> 32); h3 = f as u32;
155
156 self.h[0] = h0;
157 self.h[1] = h1;
158 self.h[2] = h2;
159 self.h[3] = h3;
160 }
161}
162
163impl Mac for Poly1305 {
164 fn input(&mut self, data: &[u8]) {
165 assert!(!self.finalized);
166 let mut m = data;
167
168 if self.leftover > 0 {
169 let want = min(16 - self.leftover, m.len());
170 for i in 0..want {
171 self.buffer[self.leftover+i] = m[i];
172 }
173 m = &m[want..];
174 self.leftover += want;
175
176 if self.leftover < 16 {
177 return;
178 }
179
180 let tmp = self.buffer;
182 self.block(&tmp);
183
184 self.leftover = 0;
185 }
186
187 while m.len() >= 16 {
188 self.block(&m[0..16]);
189 m = &m[16..];
190 }
191
192 for i in 0..m.len() {
193 self.buffer[i] = m[i];
194 }
195 self.leftover = m.len();
196 }
197
198 fn reset(&mut self) {
199 self.h = [0u32; 5];
200 self.leftover = 0;
201 self.finalized = false;
202 }
203
204 fn result(&mut self) -> MacResult {
205 let mut mac = [0u8; 16];
206 self.raw_result(&mut mac);
207 MacResult::new(&mac[..])
208 }
209
210 fn raw_result(&mut self, output: &mut [u8]) {
211 assert!(output.len() >= 16);
212 if !self.finalized{
213 self.finish();
214 }
215 write_u32_le(&mut output[0..4], self.h[0]);
216 write_u32_le(&mut output[4..8], self.h[1]);
217 write_u32_le(&mut output[8..12], self.h[2]);
218 write_u32_le(&mut output[12..16], self.h[3]);
219 }
220
221 fn output_bytes(&self) -> usize { 16 }
222}
223
224#[cfg(test)]
225mod test {
226 use std::iter::repeat;
227
228 use poly1305::Poly1305;
229 use mac::Mac;
230
231 fn poly1305(key: &[u8], msg: &[u8], mac: &mut [u8]) {
232 let mut poly = Poly1305::new(key);
233 poly.input(msg);
234 poly.raw_result(mac);
235 }
236
237 #[test]
238 fn test_nacl_vector() {
239 let key = [
240 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91,
241 0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25,
242 0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65,
243 0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80,
244 ];
245
246 let msg = [
247 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73,
248 0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce,
249 0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4,
250 0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a,
251 0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b,
252 0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72,
253 0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2,
254 0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38,
255 0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a,
256 0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae,
257 0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea,
258 0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda,
259 0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde,
260 0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3,
261 0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6,
262 0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74,
263 0xe3,0x55,0xa5,
264 ];
265
266 let expected = [
267 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,
268 0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9,
269 ];
270
271 let mut mac = [0u8; 16];
272 poly1305(&key, &msg, &mut mac);
273 assert_eq!(&mac[..], &expected[..]);
274
275 let mut poly = Poly1305::new(&key);
276 poly.input(&msg[0..32]);
277 poly.input(&msg[32..96]);
278 poly.input(&msg[96..112]);
279 poly.input(&msg[112..120]);
280 poly.input(&msg[120..124]);
281 poly.input(&msg[124..126]);
282 poly.input(&msg[126..127]);
283 poly.input(&msg[127..128]);
284 poly.input(&msg[128..129]);
285 poly.input(&msg[129..130]);
286 poly.input(&msg[130..131]);
287 poly.raw_result(&mut mac);
288 assert_eq!(&mac[..], &expected[..]);
289 }
290
291 #[test]
292 fn donna_self_test() {
293 let wrap_key = [
294 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 ];
299
300 let wrap_msg = [
301 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
302 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
303 ];
304
305 let wrap_mac = [
306 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 ];
309
310 let mut mac = [0u8; 16];
311 poly1305(&wrap_key, &wrap_msg, &mut mac);
312 assert_eq!(&mac[..], &wrap_mac[..]);
313
314 let total_key = [
315 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff,
316 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xff, 0xff,
317 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
318 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
319 ];
320
321 let total_mac = [
322 0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd,
323 0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39,
324 ];
325
326 let mut tpoly = Poly1305::new(&total_key);
327 for i in 0..256 {
328 let key: Vec<u8> = repeat(i as u8).take(32).collect();
329 let msg: Vec<u8> = repeat(i as u8).take(256).collect();
330 let mut mac = [0u8; 16];
331 poly1305(&key[..], &msg[0..i], &mut mac);
332 tpoly.input(&mac);
333 }
334 tpoly.raw_result(&mut mac);
335 assert_eq!(&mac[..], &total_mac[..]);
336 }
337
338 #[test]
339 fn test_tls_vectors() {
340 let key = b"this is 32-byte key for Poly1305";
342 let msg = [0u8; 32];
343 let expected = [
344 0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6,
345 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07,
346 ];
347 let mut mac = [0u8; 16];
348 poly1305(key, &msg, &mut mac);
349 assert_eq!(&mac[..], &expected[..]);
350
351 let msg = b"Hello world!";
352 let expected= [
353 0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16,
354 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0,
355 ];
356 poly1305(key, msg, &mut mac);
357 assert_eq!(&mac[..], &expected[..]);
358 }
359}
360
361#[cfg(all(test, feature = "with-bench"))]
362mod bench {
363 use test::Bencher;
364 use mac::Mac;
365 use poly1305::Poly1305;
366
367 #[bench]
368 pub fn poly1305_10(bh: & mut Bencher) {
369 let mut mac = [0u8; 16];
370 let key = [0u8; 32];
371 let bytes = [1u8; 10];
372 bh.iter( || {
373 let mut poly = Poly1305::new(&key);
374 poly.input(&bytes);
375 poly.raw_result(&mut mac);
376 });
377 bh.bytes = bytes.len() as u64;
378 }
379
380 #[bench]
381 pub fn poly1305_1k(bh: & mut Bencher) {
382 let mut mac = [0u8; 16];
383 let key = [0u8; 32];
384 let bytes = [1u8; 1024];
385 bh.iter( || {
386 let mut poly = Poly1305::new(&key);
387 poly.input(&bytes);
388 poly.raw_result(&mut mac);
389 });
390 bh.bytes = bytes.len() as u64;
391 }
392
393 #[bench]
394 pub fn poly1305_64k(bh: & mut Bencher) {
395 let mut mac = [0u8; 16];
396 let key = [0u8; 32];
397 let bytes = [1u8; 65536];
398 bh.iter( || {
399 let mut poly = Poly1305::new(&key);
400 poly.input(&bytes);
401 poly.raw_result(&mut mac);
402 });
403 bh.bytes = bytes.len() as u64;
404 }
405}