1use std::mem;
2
3fn cha_cha_quarter_round(
4 state: &mut [u32; 16],
5 a_index: usize,
6 b_index: usize,
7 c_index: usize,
8 d_index: usize,
9) {
10 let mut a = state[a_index];
11 let mut b = state[b_index];
12 let mut c = state[c_index];
13 let mut d = state[d_index];
14
15 a = a.wrapping_add(b);
16 d = d ^ a;
17 d = d.rotate_left(16);
18
19 c = c.wrapping_add(d);
20 b = b ^ c;
21 b = b.rotate_left(12);
22
23 a = a.wrapping_add(b);
24 d = d ^ a;
25 d = d.rotate_left(8);
26
27 c = c.wrapping_add(d);
28 b = b ^ c;
29 b = b.rotate_left(7);
30
31 state[a_index] = a;
32 state[b_index] = b;
33 state[c_index] = c;
34 state[d_index] = d;
35}
36
37fn cha_cha_20_block(key: &[u8; 32], counter: u32, nonce: &[u8; 12]) -> [u8; 64] {
38 let key: [u32; 8] = unsafe { mem::transmute(*key) };
39 let nonce: [u32; 3] = unsafe { mem::transmute(*nonce) };
40 let mut state: [u32; 16] = [
41 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, key[0], key[1], key[2], key[3], key[4],
42 key[5], key[6], key[7], counter, nonce[0], nonce[1], nonce[2],
43 ];
44
45 let mut working_state = state;
46
47 for _ in 0usize..10 {
48 cha_cha_quarter_round(&mut working_state, 0, 4, 8, 12);
49 cha_cha_quarter_round(&mut working_state, 1, 5, 9, 13);
50 cha_cha_quarter_round(&mut working_state, 2, 6, 10, 14);
51 cha_cha_quarter_round(&mut working_state, 3, 7, 11, 15);
52
53 cha_cha_quarter_round(&mut working_state, 0, 5, 10, 15);
54 cha_cha_quarter_round(&mut working_state, 1, 6, 11, 12);
55 cha_cha_quarter_round(&mut working_state, 2, 7, 8, 13);
56 cha_cha_quarter_round(&mut working_state, 3, 4, 9, 14);
57 }
58
59 for i in 0usize..16 {
60 state[i] = state[i].wrapping_add(working_state[i]);
61 }
62
63 unsafe { mem::transmute::<[u32; 16], [u8; 64]>(state) }
64}
65
66pub fn cha_cha_20_encrypt(
67 key: &[u8; 32],
68 counter: u32,
69 nonce: &[u8; 12],
70 plain_text: &[u8],
71) -> Box<[u8]> {
72 let mut encrypted_message: Vec<u8> = Vec::with_capacity(plain_text.len());
73 let full_block_count = plain_text.len() >> 6;
74 for i in 0..full_block_count {
75 let key_stream = cha_cha_20_block(key, counter + i as u32, nonce);
76 let plain_text = &plain_text[i << 6..];
77 for c in 0..64 {
78 encrypted_message.push(plain_text[c] ^ key_stream[c]);
79 }
80 }
81
82 let plain_text = &plain_text[full_block_count << 6..];
83 let key_stream = cha_cha_20_block(key, counter + full_block_count as u32, nonce);
84 for c in 0..plain_text.len() {
85 encrypted_message.push(plain_text[c] ^ key_stream[c]);
86 }
87
88 encrypted_message.into_boxed_slice()
89}
90
91pub fn poly1305_mac(message: &[u8], key: &[u8; 32]) -> [u8; 16] {
92 let mut accumulator: [u32; 5] = [0; 5];
93 let (r, s) = unsafe { mem::transmute::<[u8; 32], ([u32; 4], [u32; 4])>(*key) };
94 let r: [u32; 4] = [
95 r[0] & 0x0fffffff,
96 r[1] & 0x0ffffffc,
97 r[2] & 0x0ffffffc,
98 r[3] & 0x0ffffffc,
99 ];
100 let mut block: [u32; 4];
101 let mut extended_block: [u32; 5];
102 let mut byte_block: [u8; 16] = [0; 16];
103 let full_block_count = message.len() >> 4;
104
105 for i in 0..full_block_count {
106 let start = i << 4;
107 byte_block.copy_from_slice(&message[start..start + 16]);
108 block = unsafe { mem::transmute(byte_block) };
109 extended_block = [block[0], block[1], block[2], block[3], 1];
110 accumulator = poly1305_add(accumulator, extended_block);
111 poly1305_mul(&mut accumulator, r);
112 }
113
114 let message = &message[full_block_count << 4..];
115 if message.len() > 0 {
116 byte_block = [0; 16];
117 for i in 0..message.len() {
118 byte_block[i] = message[i];
119 }
120 byte_block[message.len()] = 0x1u8;
121 block = unsafe { mem::transmute(byte_block) };
122 extended_block = [block[0], block[1], block[2], block[3], 0];
123 accumulator = poly1305_add(accumulator, extended_block);
124 poly1305_mul(&mut accumulator, r);
125 }
126 accumulator = poly1305_mod(accumulator);
127 extended_block = [s[0], s[1], s[2], s[3], 0];
128 accumulator = poly1305_add(accumulator, extended_block);
129
130 unsafe {
131 mem::transmute([
132 accumulator[0],
133 accumulator[1],
134 accumulator[2],
135 accumulator[3],
136 ])
137 }
138}
139
140fn poly1305_mul(h: &mut [u32; 5], r: [u32; 4]) {
170 let r0: u64 = r[0] as u64;
172 let r1: u64 = r[1] as u64;
173 let r2: u64 = r[2] as u64;
174 let r3: u64 = r[3] as u64;
175
176 let h0: u64 = h[0] as u64;
177 let h1: u64 = h[1] as u64;
178 let h2: u64 = h[2] as u64;
179 let h3: u64 = h[3] as u64;
180 let h4: u64 = h[4] as u64;
181
182 let rr0 = (r0 >> 2) * 5; let rr1 = (r1 >> 2) * 5; let rr2 = (r2 >> 2) * 5; let rr3 = (r3 >> 2) * 5; let x0: u64 = h0 * r0 + h1 * rr3 + h2 * rr2 + h3 * rr1 + h4 * rr0;
189 let x1 = h0 * r1 + h1 * r0 + h2 * rr3 + h3 * rr2 + h4 * rr1;
190 let x2 = h0 * r2 + h1 * r1 + h2 * r0 + h3 * rr3 + h4 * rr2;
191 let x3 = h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * rr3;
192 let x4 = h4 * (r0 & 3); let msb: u64 = x4 + (x3 >> 32);
196 let mut u = (msb >> 2) * 5; u += x0 & 0xffffffff;
198 h[0] = (u & 0xffffffff) as u32;
199 u >>= 32;
200 u += (x1 & 0xffffffff) + (x0 >> 32);
201 h[1] = (u & 0xffffffff) as u32;
202 u >>= 32;
203 u += (x2 & 0xffffffff) + (x1 >> 32);
204 h[2] = (u & 0xffffffff) as u32;
205 u >>= 32;
206 u += (x3 & 0xffffffff) + (x2 >> 32);
207 h[3] = (u & 0xffffffff) as u32;
208 u >>= 32;
209 u += msb & 3 ;
210 h[4] = u as u32;
211}
212
213fn poly1305_add(a: [u32; 5], b: [u32; 5]) -> [u32; 5] {
214 let mut temp: u64 = 0;
215 let mut result: [u32; 5] = Default::default();
216
217 for i in 0..5 {
219 temp += a[i] as u64 + b[i] as u64;
220 result[i] = temp as u32;
221 temp >>= 32;
222 }
223
224 result
225}
226
227fn poly1305_mod(a: [u32; 5]) -> [u32; 5] {
228 if a[4] < 3 {
229 return a;
230 }
231
232 let low_p = 0xfffffffffffffffffffffffffffffffbu128;
233 let low_a: u128 = unsafe { mem::transmute([a[0], a[1], a[2], a[3]]) };
234 if a[4] == 3 && low_p > low_a {
235 return a;
236 }
237 if a[4] == 3 && low_p == low_a {
238 return [0, 0, 0, 0, 0];
239 }
240
241 let mut hi_a = a[4];
242 let low_result = if low_a >= low_p {
243 low_a - low_p
244 } else {
245 hi_a -= 1;
246 !low_p + 1 + low_a
247 };
248
249 let low_result: [u32; 4] = unsafe { mem::transmute(low_result) };
250 [
251 low_result[0],
252 low_result[1],
253 low_result[2],
254 low_result[3],
255 hi_a - 3,
256 ]
257}
258
259pub fn poly1305_key_gen(key: &[u8; 32], nonce: &[u8; 12]) -> [u8; 32] {
260 let counter = 0;
261 let block = &cha_cha_20_block(key, counter, nonce)[..32];
262 let mut result: [u8; 32] = [0; 32];
263 result.copy_from_slice(block);
264 result
265}
266
267pub fn cha_cha_20_aead_encrypt(
268 aad: &[u8],
269 key: &[u8; 32],
270 nonce: [u8; 12],
271 plain_text: &[u8],
272) -> (Box<[u8]>, [u8; 16]) {
273 let otk = poly1305_key_gen(key, &nonce);
274 let cipher_text = cha_cha_20_encrypt(key, 1, &nonce, plain_text);
275 let mut mac_data: Vec<u8> = Vec::with_capacity(aad.len() + cipher_text.len() + 108);
276 mac_data.extend_from_slice(aad);
277 pad16(&mut mac_data);
278
279 mac_data.extend_from_slice(&cipher_text);
280 pad16(&mut mac_data);
281
282 mac_data.extend_from_slice(&(unsafe { mem::transmute::<u64, [u8; 8]>(aad.len() as u64) }));
283 mac_data
284 .extend_from_slice(&(unsafe { mem::transmute::<u64, [u8; 8]>(cipher_text.len() as u64) }));
285 let tag = poly1305_mac(&mac_data, &otk);
286 (cipher_text, tag)
287}
288
289pub fn cha_cha_20_aead_decrypt(
290 aad: &[u8],
291 key: &[u8; 32],
292 nonce: [u8; 12],
293 cipher_text: &[u8],
294) -> (Box<[u8]>, [u8; 16]) {
295 let otk = poly1305_key_gen(key, &nonce);
296 let plain_text = cha_cha_20_encrypt(key, 1, &nonce, cipher_text);
297 let mut mac_data: Vec<u8> = Vec::with_capacity(aad.len() + cipher_text.len() + 108);
298 mac_data.extend_from_slice(aad);
299 pad16(&mut mac_data);
300
301 mac_data.extend_from_slice(&cipher_text);
302 pad16(&mut mac_data);
303
304 mac_data.extend_from_slice(&(unsafe { mem::transmute::<u64, [u8; 8]>(aad.len() as u64) }));
305 mac_data
306 .extend_from_slice(&(unsafe { mem::transmute::<u64, [u8; 8]>(cipher_text.len() as u64) }));
307 let tag = poly1305_mac(&mac_data, &otk);
308 (plain_text, tag)
309}
310
311#[inline]
312fn pad16(data: &mut Vec<u8>) {
313 for _ in 0..(16 - (data.len() & 0xf)) & 0xf {
314 data.push(0);
315 }
316}
317
318#[cfg(test)]
319mod tests {
320 use super::*;
321
322 #[test]
323 fn test_cha_cha_quarter_round() {
324 let mut state: [u32; 16] = [
325 0x879531e0, 0xc5ecf37d, 0x516461b1, 0xc9a62f8a, 0x44c20ef3, 0x3390af7f, 0xd9fc690b,
326 0x2a5f714c, 0x53372767, 0xb00a5631, 0x974c541a, 0x359e9963, 0x5c971061, 0x3d631689,
327 0x2098d9d6, 0x91dbd320,
328 ];
329
330 cha_cha_quarter_round(&mut state, 2, 7, 8, 13);
331
332 assert_eq!(
333 state,
334 [
335 0x879531e0, 0xc5ecf37d, 0xbdb886dc, 0xc9a62f8a, 0x44c20ef3, 0x3390af7f, 0xd9fc690b,
336 0xcfacafd2, 0xe46bea80, 0xb00a5631, 0x974c541a, 0x359e9963, 0x5c971061, 0xccc07c79,
337 0x2098d9d6, 0x91dbd320
338 ]
339 );
340 }
341
342 #[test]
343 fn test_cha_cha_20_block() {
344 let key: [u8; 32] = [
345 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
346 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
347 0x1f,
348 ];
349 let nonce: [u8; 12] = [0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x4a, 0x0, 0x0, 0x0, 0x0];
350
351 let state: &[u8] = &cha_cha_20_block(&key, 1u32, &nonce);
352 let expected: &[u8] = &[
353 0x10u8, 0xf1, 0xe7, 0xe4, 0xd1, 0x3b, 0x59, 0x15, 0x50, 0x0f, 0xdd, 0x1f, 0xa3, 0x20,
354 0x71, 0xc4, 0xc7u8, 0xd1, 0xf4, 0xc7, 0x33, 0xc0, 0x68, 0x03, 0x04, 0x22, 0xaa, 0x9a,
355 0xc3, 0xd4, 0x6c, 0x4e, 0xd2u8, 0x82, 0x64, 0x46, 0x07, 0x9f, 0xaa, 0x09, 0x14, 0xc2,
356 0xd7, 0x05, 0xd9, 0x8b, 0x02, 0xa2, 0xb5u8, 0x12, 0x9c, 0xd1, 0xde, 0x16, 0x4e, 0xb9,
357 0xcb, 0xd0, 0x83, 0xe8, 0xa2, 0x50, 0x3c, 0x4e,
358 ];
359
360 assert_eq!(state, expected);
361 }
362
363 #[test]
364 fn test_cha_cha_20_encrypt() {
365 let key: [u8; 32] = [
366 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
367 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
368 0x1f,
369 ];
370 let nonce: [u8; 12] = [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4a, 0x0, 0x0, 0x0, 0x0];
371 let plain_text: &[u8] = &[
372 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e,
373 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
374 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20,
375 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
376 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e,
377 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
378 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, 0x63, 0x72,
379 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
380 0x74, 0x2e,
381 ];
382
383 let cipher_text: &[u8] = &cha_cha_20_encrypt(&key, 1, &nonce, plain_text);
384 let expected: &[u8] = &[
385 0x6e, 0x2e, 0x35, 0x9a, 0x25, 0x68, 0xf9, 0x80, 0x41, 0xba, 0x07, 0x28, 0xdd, 0x0d,
386 0x69, 0x81, 0xe9, 0x7e, 0x7a, 0xec, 0x1d, 0x43, 0x60, 0xc2, 0x0a, 0x27, 0xaf, 0xcc,
387 0xfd, 0x9f, 0xae, 0x0b, 0xf9, 0x1b, 0x65, 0xc5, 0x52, 0x47, 0x33, 0xab, 0x8f, 0x59,
388 0x3d, 0xab, 0xcd, 0x62, 0xb3, 0x57, 0x16, 0x39, 0xd6, 0x24, 0xe6, 0x51, 0x52, 0xab,
389 0x8f, 0x53, 0x0c, 0x35, 0x9f, 0x08, 0x61, 0xd8, 0x07, 0xca, 0x0d, 0xbf, 0x50, 0x0d,
390 0x6a, 0x61, 0x56, 0xa3, 0x8e, 0x08, 0x8a, 0x22, 0xb6, 0x5e, 0x52, 0xbc, 0x51, 0x4d,
391 0x16, 0xcc, 0xf8, 0x06, 0x81, 0x8c, 0xe9, 0x1a, 0xb7, 0x79, 0x37, 0x36, 0x5a, 0xf9,
392 0x0b, 0xbf, 0x74, 0xa3, 0x5b, 0xe6, 0xb4, 0x0b, 0x8e, 0xed, 0xf2, 0x78, 0x5e, 0x42,
393 0x87, 0x4d,
394 ];
395
396 assert_eq!(cipher_text, expected);
397 }
398
399 #[test]
400 fn test_poly1305_mac() {
401 let key_material: [u8; 32] = [
402 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5,
403 0x06, 0xa8, 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, 0x4a, 0xbf, 0xf6, 0xaf,
404 0x41, 0x49, 0xf5, 0x1b,
405 ];
406 let message = &[
407 0x43u8, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x20,
408 0x46, 0x6f, 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
409 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70,
410 ];
411
412 let tag: &[u8] = &poly1305_mac(message, &key_material);
413 let expected: &[u8] = &[
414 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01,
415 0x27, 0xa9,
416 ];
417
418 assert_eq!(tag, expected);
419 }
420
421 #[test]
422 fn test_poly1305_key_generation() {
423 let key: [u8; 32] = [
424 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
425 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
426 0x9c, 0x9d, 0x9e, 0x9f,
427 ];
428
429 let nonce: [u8; 12] = [
430 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
431 ];
432 let result: [u8; 32] = poly1305_key_gen(&key, &nonce);
433 let expected: [u8; 32] = [
434 0x8a, 0xd5, 0xa0, 0x8b, 0x90, 0x5f, 0x81, 0xcc, 0x81, 0x50, 0x40, 0x27, 0x4a, 0xb2,
435 0x94, 0x71, 0xa8, 0x33, 0xb6, 0x37, 0xe3, 0xfd, 0x0d, 0xa5, 0x08, 0xdb, 0xb8, 0xe2,
436 0xfd, 0xd1, 0xa6, 0x46,
437 ];
438
439 assert_eq!(&result, &expected);
440 }
441
442 #[test]
443 fn test_cha_cha_20_aead_encrypt() {
444 let plain_text: &[u8] = &[
445 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e,
446 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
447 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20,
448 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
449 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e,
450 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
451 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, 0x63, 0x72,
452 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
453 0x74, 0x2e,
454 ];
455
456 let aad: [u8; 12] = [
457 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
458 ];
459 let key: [u8; 32] = [
460 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
461 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
462 0x9c, 0x9d, 0x9e, 0x9f,
463 ];
464
465 let iv: [u8; 8] = [0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47];
466 let constant: [u8; 4] = [0x07, 0x00, 0x00, 0x00];
467 let mut constant_and_iv: [u8; 12] = [0; 12];
468 constant_and_iv[..4].copy_from_slice(&constant);
469 constant_and_iv[4..].copy_from_slice(&iv);
470
471 let expected_cipher_text: &[u8] = &[
472 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef,
473 0x7e, 0xc2, 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, 0xa9, 0xe2, 0xb5, 0xa7,
474 0x36, 0xee, 0x62, 0xd6, 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, 0x82, 0xfa,
475 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
476 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77,
477 0x8b, 0x8c, 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 0xfa, 0xb3, 0x24, 0xe4,
478 0xfa, 0xd6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, 0x3f, 0xf4,
479 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
480 0x61, 0x16,
481 ];
482
483 let expected_tag: [u8; 16] = [
484 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60,
485 0x06, 0x91,
486 ];
487
488 let (cipher_text, tag) = cha_cha_20_aead_encrypt(&aad, &key, constant_and_iv, plain_text);
489 let cipher_text: &[u8] = &cipher_text;
490
491 assert_eq!(cipher_text, expected_cipher_text);
492 assert_eq!(&tag, &expected_tag);
493 }
494
495 #[test]
496 fn test_cha_cha_20_aead_decrypt() {
497 let expected_plain_text: &[u8] = &[
498 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e,
499 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
500 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20,
501 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
502 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e,
503 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
504 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, 0x63, 0x72,
505 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
506 0x74, 0x2e,
507 ];
508
509 let aad: [u8; 12] = [
510 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
511 ];
512 let key: [u8; 32] = [
513 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
514 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
515 0x9c, 0x9d, 0x9e, 0x9f,
516 ];
517
518 let iv: [u8; 8] = [0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47];
519 let constant: [u8; 4] = [0x07, 0x00, 0x00, 0x00];
520 let mut constant_and_iv: [u8; 12] = [0; 12];
521 constant_and_iv[..4].copy_from_slice(&constant);
522 constant_and_iv[4..].copy_from_slice(&iv);
523
524 let cipher_text: &[u8] = &[
525 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef,
526 0x7e, 0xc2, 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, 0xa9, 0xe2, 0xb5, 0xa7,
527 0x36, 0xee, 0x62, 0xd6, 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, 0x82, 0xfa,
528 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
529 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77,
530 0x8b, 0x8c, 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 0xfa, 0xb3, 0x24, 0xe4,
531 0xfa, 0xd6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, 0x3f, 0xf4,
532 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
533 0x61, 0x16,
534 ];
535
536 let expected_tag: [u8; 16] = [
537 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60,
538 0x06, 0x91,
539 ];
540
541 let (plain_text, tag) = cha_cha_20_aead_decrypt(&aad, &key, constant_and_iv, cipher_text);
542
543 assert_eq!(&plain_text as &[u8], expected_plain_text);
544 assert_eq!(&tag, &expected_tag);
545 }
546
547 #[test]
548 fn test_poly1305_mac_2() {
549 let otk = [
550 0xfd, 0x72, 0xb9, 0xc9, 0x9a, 0xa1, 0x50, 0x9c, 0xd4, 0x7e, 0x72, 0x27, 0x0a, 0xc2,
551 0xbf, 0x07, 0xc9, 0x21, 0x98, 0xb5, 0x77, 0xfc, 0x73, 0xaa, 0x0f, 0x36, 0x3c, 0xf6,
552 0x38, 0xd3, 0xa6, 0xd7,
553 ];
554 let message: &[u8] = &[
555 0x17, 0x03, 0x03, 0x03, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x6e, 0xc9, 0x75, 0x08, 0x7a, 0x1a, 0x86, 0x19, 0x66, 0x0f, 0x02, 0x13,
557 0x67, 0x92, 0x64, 0x11, 0xe8, 0xbb, 0x85, 0x8f, 0xab, 0xd2, 0xad, 0xf5, 0xfe, 0xa9,
558 0xfe, 0xb5, 0x35, 0x4f, 0x81, 0xc1, 0x21, 0xe3, 0xf3, 0x02, 0xe1, 0x2a, 0xbc, 0x55,
559 0xa8, 0xd5, 0xa7, 0x08, 0xcd, 0x0e, 0xa9, 0x7d, 0x27, 0x78, 0x8b, 0xe8, 0xf3, 0x7a,
560 0x6d, 0x44, 0x8c, 0x92, 0xbc, 0x16, 0x13, 0xe5, 0x59, 0x94, 0x9a, 0xde, 0xe0, 0x14,
561 0x29, 0xd4, 0xf6, 0x44, 0x20, 0xb1, 0xa7, 0xc3, 0xb7, 0x7d, 0xa9, 0x91, 0xd5, 0x2a,
562 0xa8, 0x0f, 0x90, 0xfc, 0x38, 0x01, 0x27, 0xa4, 0x6b, 0x16, 0xdb, 0x75, 0x0b, 0x06,
563 0x7a, 0x13, 0xbb, 0xf2, 0x95, 0xbb, 0x2e, 0x07, 0x81, 0x92, 0xe1, 0x05, 0x42, 0xd6,
564 0x2e, 0xda, 0xb8, 0xb8, 0x65, 0x95, 0xc7, 0x36, 0x1e, 0x68, 0x17, 0x0c, 0xf3, 0x57,
565 0xdf, 0x2f, 0x60, 0x32, 0x36, 0xdc, 0x57, 0x98, 0x46, 0x22, 0x3c, 0x9f, 0x2d, 0xb6,
566 0xd2, 0x7c, 0xbf, 0x70, 0xe1, 0x82, 0xb5, 0x2e, 0x92, 0xb3, 0x04, 0x3d, 0x17, 0x81,
567 0xde, 0x37, 0x59, 0xa4, 0x12, 0xf2, 0x55, 0xf0, 0x95, 0x82, 0x03, 0xaa, 0x52, 0x89,
568 0xe8, 0x71, 0x70, 0xf7, 0x5a, 0x5f, 0x5c, 0x0d, 0x34, 0x52, 0xc4, 0xb4, 0x65, 0xb6,
569 0x5f, 0x99, 0xf2, 0x0e, 0x02, 0x1e, 0x24, 0xcb, 0xdc, 0x1d, 0xd2, 0xb7, 0x3c, 0x8a,
570 0x4a, 0x64, 0x3a, 0x76, 0xa8, 0x99, 0x60, 0x38, 0x78, 0x53, 0x7e, 0x85, 0xf6, 0x20,
571 0xb7, 0xf4, 0x7d, 0x0a, 0x6c, 0x9c, 0x4d, 0x18, 0xea, 0xa8, 0xdf, 0xf6, 0x18, 0x86,
572 0xab, 0x5a, 0x8a, 0x9e, 0xdf, 0x13, 0xa0, 0x14, 0x0f, 0xae, 0x33, 0x9c, 0x70, 0x0a,
573 0x68, 0x24, 0xc3, 0x34, 0x06, 0x08, 0xe4, 0xdc, 0x1d, 0xeb, 0xa9, 0x49, 0xf4, 0x72,
574 0x9f, 0xd5, 0x4c, 0xaa, 0xa8, 0xf7, 0xc2, 0x3f, 0xf0, 0xd8, 0x0e, 0xe9, 0x1e, 0xb1,
575 0x21, 0x04, 0x98, 0x3e, 0x4c, 0x8e, 0xa1, 0x5c, 0x1a, 0x69, 0x8e, 0x7a, 0x6c, 0x06,
576 0xaa, 0x43, 0xbd, 0x5f, 0x56, 0x24, 0x98, 0xd7, 0x12, 0xd3, 0x1c, 0x2e, 0x6c, 0xd9,
577 0x35, 0x25, 0x28, 0x51, 0xae, 0x4d, 0x62, 0x83, 0xb4, 0x69, 0x36, 0x31, 0xde, 0x8e,
578 0x92, 0x91, 0xc8, 0xd6, 0x28, 0xad, 0x2e, 0x57, 0xe5, 0x74, 0x99, 0x30, 0xc6, 0x30,
579 0x35, 0x55, 0x72, 0x7f, 0x0c, 0xed, 0x5b, 0x75, 0x68, 0x75, 0x51, 0xf8, 0x52, 0x52,
580 0xeb, 0xc2, 0xcc, 0xd7, 0x38, 0xad, 0x3c, 0xb6, 0x23, 0x76, 0xf8, 0xd0, 0x37, 0xb7,
581 0x73, 0x79, 0x07, 0x8a, 0x4a, 0x3e, 0x81, 0xce, 0xfc, 0x44, 0x9b, 0xbc, 0x0c, 0xf4,
582 0x7f, 0x51, 0xae, 0x3b, 0x6a, 0xe5, 0x0d, 0x3c, 0x58, 0xf8, 0xbd, 0x98, 0x98, 0xa2,
583 0xc9, 0x99, 0x44, 0x54, 0x3b, 0x1c, 0x4c, 0x7f, 0x7e, 0xba, 0x85, 0x31, 0x0f, 0x60,
584 0x72, 0xdf, 0x70, 0x7d, 0xf1, 0x2b, 0xe4, 0xdd, 0x76, 0x27, 0x7d, 0x26, 0x58, 0xe8,
585 0x50, 0x3b, 0x24, 0xd2, 0xce, 0xf3, 0xb7, 0x34, 0x93, 0xe6, 0xcd, 0x13, 0x82, 0x29,
586 0xa6, 0x96, 0x01, 0xaf, 0xa9, 0xa8, 0xbf, 0x46, 0x65, 0xbb, 0x24, 0x2b, 0x3b, 0x89,
587 0x1d, 0xfd, 0x4b, 0x90, 0x93, 0xf6, 0x00, 0xb0, 0x1f, 0x6d, 0x99, 0xdd, 0xb0, 0xc1,
588 0x92, 0x75, 0x3a, 0xa6, 0xcd, 0x42, 0xaa, 0x38, 0x5d, 0xe6, 0x5d, 0xbd, 0x5d, 0x92,
589 0x4f, 0x4b, 0x3c, 0x33, 0x7a, 0x6f, 0xc3, 0xc9, 0xc7, 0x06, 0x86, 0x4a, 0x5c, 0xe2,
590 0xbe, 0xeb, 0x63, 0xf9, 0x16, 0x43, 0xd0, 0x56, 0xcc, 0x3e, 0xc5, 0xa5, 0x78, 0xca,
591 0xd6, 0x0d, 0xd5, 0x78, 0xac, 0x5a, 0xea, 0x09, 0x68, 0xe9, 0x5a, 0x16, 0x3c, 0x83,
592 0xf1, 0xbb, 0x34, 0x72, 0xc3, 0x85, 0xf2, 0x51, 0x64, 0x08, 0x74, 0x58, 0xc5, 0xc2,
593 0xf1, 0xfc, 0x48, 0x55, 0x83, 0x8d, 0x87, 0x87, 0xf6, 0x0c, 0x35, 0xc4, 0x43, 0xe4,
594 0x98, 0xdf, 0x63, 0x5f, 0xce, 0x8e, 0xac, 0x67, 0x65, 0x1c, 0xc2, 0xd8, 0xac, 0xb0,
595 0xd9, 0xa2, 0xf5, 0xfd, 0x2f, 0xb5, 0xf2, 0xe5, 0x7e, 0x90, 0xc9, 0x5f, 0x8e, 0x76,
596 0x48, 0x89, 0xb1, 0x30, 0x83, 0x94, 0x2f, 0x52, 0x7a, 0x00, 0x9b, 0xe0, 0xb2, 0x6c,
597 0x98, 0xe0, 0x65, 0x50, 0x7d, 0xa1, 0x00, 0xa0, 0xba, 0x9b, 0x38, 0x5d, 0xaa, 0xca,
598 0x9f, 0x57, 0x0f, 0x4f, 0x12, 0x01, 0x72, 0x87, 0xb6, 0xfb, 0xab, 0x23, 0xf1, 0x93,
599 0xe8, 0x42, 0xa1, 0xfd, 0x23, 0x64, 0xd8, 0x0b, 0xc6, 0xaf, 0x76, 0x38, 0x13, 0xe2,
600 0xe8, 0x76, 0x19, 0x5d, 0xdd, 0xe7, 0x7a, 0xe5, 0xf4, 0x5d, 0xe8, 0xf7, 0x98, 0x7b,
601 0x88, 0x1f, 0xd6, 0x12, 0x0a, 0xbc, 0xa0, 0x6a, 0x5b, 0x26, 0x9c, 0x88, 0x7f, 0x0b,
602 0xf5, 0x9f, 0x3d, 0x88, 0xf4, 0x9d, 0x5a, 0x76, 0xe9, 0x05, 0x30, 0x01, 0x27, 0x2a,
603 0x30, 0x5d, 0xf5, 0x55, 0xa1, 0x79, 0xaf, 0xa0, 0x64, 0xf6, 0xad, 0x5a, 0x89, 0x12,
604 0x56, 0xa1, 0xee, 0x33, 0x4a, 0x96, 0xb7, 0x4f, 0x43, 0xcf, 0x31, 0x00, 0xf5, 0x59,
605 0xb7, 0xef, 0xea, 0x97, 0xce, 0x77, 0x0b, 0xdf, 0x11, 0xe3, 0xc2, 0xf4, 0x0f, 0x36,
606 0xc0, 0xbf, 0xf2, 0x44, 0x69, 0x88, 0x82, 0x11, 0xac, 0xe0, 0x79, 0x82, 0x6e, 0x17,
607 0xef, 0x72, 0x39, 0x08, 0xa4, 0xd9, 0x5a, 0x17, 0x29, 0x6f, 0xcb, 0xb0, 0x66, 0x51,
608 0xd8, 0xe8, 0xa4, 0x29, 0xe1, 0x6c, 0x05, 0x5e, 0x92, 0x2f, 0x01, 0xfd, 0x70, 0x9c,
609 0x78, 0xb2, 0xae, 0xdb, 0xb2, 0xbc, 0x1f, 0x0b, 0x75, 0x57, 0xca, 0xac, 0x87, 0x49,
610 0x26, 0x88, 0x69, 0x90, 0x89, 0xd0, 0x0a, 0x16, 0x9d, 0xae, 0xf6, 0xc7, 0xd2, 0x32,
611 0x5a, 0x96, 0x6d, 0x34, 0x54, 0xca, 0xb1, 0x09, 0x7a, 0xc2, 0xc1, 0xac, 0x17, 0x54,
612 0x8d, 0xfe, 0x33, 0xac, 0xf7, 0xe7, 0xc4, 0xc1, 0x74, 0x39, 0xc2, 0x92, 0x88, 0x26,
613 0x5e, 0x6d, 0x42, 0x6c, 0x5f, 0x7c, 0x4b, 0x1f, 0x72, 0x11, 0xbe, 0xfb, 0x36, 0xfb,
614 0x85, 0xce, 0xd2, 0x19, 0x6a, 0xe7, 0x65, 0x6e, 0x76, 0x55, 0x96, 0x5a, 0x4e, 0x9e,
615 0xdc, 0xa9, 0x60, 0x2b, 0x5c, 0x5d, 0x36, 0xca, 0xfb, 0x4f, 0x6b, 0xd9, 0x8d, 0xde,
616 0x9f, 0xe0, 0x3c, 0xc6, 0xf4, 0xe4, 0xa3, 0x2a, 0x83, 0x33, 0xd0, 0x8b, 0x90, 0xe0,
617 0x18, 0xa6, 0xa3, 0x08, 0x9b, 0x1d, 0xd2, 0x5b, 0x2d, 0x5b, 0x6b, 0xef, 0x3f, 0x7c,
618 0xec, 0xbd, 0xe9, 0x43, 0xa9, 0xc0, 0x98, 0xfc, 0x46, 0x49, 0x8e, 0x99, 0x5a, 0xc9,
619 0xa1, 0x9c, 0xdd, 0xae, 0x7a, 0xd7, 0x30, 0xed, 0xf3, 0x88, 0x47, 0xf5, 0x48, 0xde,
620 0x2e, 0x79, 0x91, 0xeb, 0x35, 0x60, 0x1e, 0x1b, 0x09, 0x45, 0xfb, 0x87, 0x67, 0xb2,
621 0x87, 0x94, 0x76, 0x72, 0x48, 0x7b, 0x3f, 0x28, 0x11, 0xdd, 0xe1, 0x07, 0x88, 0x08,
622 0x75, 0x9f, 0x17, 0x6a, 0x9f, 0xa7, 0x22, 0x63, 0x59, 0x21, 0x61, 0xaa, 0xc2, 0x10,
623 0xdf, 0x00, 0xfc, 0xef, 0xf7, 0x99, 0xc7, 0x26, 0xcc, 0x5f, 0x8a, 0x19, 0x0b, 0x4f,
624 0x6c, 0x93, 0x61, 0x87, 0x2a, 0xf2, 0x99, 0x5d, 0xc8, 0x14, 0xbd, 0xa2, 0xa5, 0x8c,
625 0x21, 0x5e, 0xc3, 0xd9, 0x08, 0xe5, 0xa3, 0x6d, 0xd0, 0x1c, 0xdf, 0xad, 0xb8, 0xc5,
626 0xd3, 0xd7, 0xa6, 0xf7, 0xc4, 0x7c, 0xd3, 0xf2, 0x3b, 0x55, 0x34, 0x63, 0x1b, 0x64,
627 0xb5, 0xf1, 0xf2, 0x73, 0x68, 0x6e, 0x99, 0x08, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00,
628 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x03, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x00,
630 ];
631 let tag = poly1305_mac(message, &otk);
632 let expected_tag = &[
633 0x45, 0x6b, 0x78, 0xfc, 0x85, 0x68, 0xbd, 0x62, 0x07, 0x1e, 0x6b, 0x32, 0x9c, 0x23,
634 0xfb, 0x50,
635 ];
636 assert_eq!(&tag as &[u8], expected_tag);
637 }
638
639 #[test]
640 fn test_pad16() {
641 let mut v: Vec<u8> = vec![];
642 pad16(&mut v);
643 assert_eq!(v.len(), 0);
644
645 let mut v: Vec<u8> = vec![1];
646 pad16(&mut v);
647 assert_eq!(v.len(), 16);
648 }
649
650 #[test]
651 fn test_poly1305_mac_3() {
652 let otk = [
653 0x50, 0xd7, 0x07, 0xbc, 0xa8, 0xe5, 0x35, 0x3d, 0x3d, 0xb1, 0x01, 0xf6, 0x78, 0x10,
654 0xb7, 0x3f, 0x7d, 0x92, 0x02, 0xd8, 0xe4, 0xbd, 0x11, 0x8f, 0xd7, 0xca, 0x44, 0x68,
655 0x54, 0x56, 0xe6, 0x6f,
656 ];
657 let message: &[u8] = &[
658 0x17, 0x03, 0x03, 0x05, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0xde, 0x6c, 0xea, 0x98, 0x72, 0x1c, 0xb8, 0xfc, 0x60, 0xec, 0x26, 0xec,
660 0x15, 0x50, 0x27, 0x0c, 0x43, 0x29, 0x6b, 0x4c, 0x9a, 0x67, 0x9e, 0xe1, 0x7b, 0x88,
661 0xfd, 0x73, 0xae, 0xbf, 0xc8, 0x43, 0xd9, 0xcd, 0x74, 0x8c, 0x4e, 0xd2, 0xd9, 0x8d,
662 0x01, 0x18, 0x63, 0xd9, 0x36, 0xef, 0x81, 0xf6, 0x7a, 0x7e, 0xf0, 0x3a, 0x8f, 0x27,
663 0xac, 0x81, 0xf1, 0x8d, 0xee, 0xbd, 0x2c, 0xb9, 0xe7, 0x9a, 0xb0, 0x2c, 0xad, 0xe7,
664 0x98, 0x9d, 0x16, 0x9d, 0x76, 0xda, 0x78, 0xac, 0x58, 0x26, 0x0b, 0x27, 0xd5, 0x3b,
665 0x66, 0xa4, 0xab, 0x7c, 0x8d, 0x36, 0x2b, 0x9d, 0x12, 0xe3, 0x30, 0x11, 0x9c, 0x49,
666 0xa6, 0xbc, 0x0a, 0xae, 0x31, 0x7d, 0x6f, 0xa8, 0x24, 0x5c, 0x9f, 0xe7, 0xd6, 0x65,
667 0x91, 0x72, 0x89, 0xb4, 0xbc, 0x19, 0x16, 0xe2, 0x3b, 0xe4, 0xcb, 0x5d, 0xb1, 0x4a,
668 0x3b, 0x57, 0x8f, 0x22, 0x2a, 0x6d, 0x87, 0x62, 0x9a, 0xf9, 0x3f, 0x0c, 0x09, 0x7f,
669 0x0f, 0x80, 0x53, 0x9d, 0x4e, 0x15, 0xb9, 0x29, 0xd5, 0x75, 0x97, 0x9e, 0x01, 0xa5,
670 0x7c, 0x8a, 0x0b, 0xf2, 0xf2, 0xfb, 0x7d, 0xcd, 0xa5, 0x0d, 0x76, 0x02, 0xd6, 0x6c,
671 0x43, 0x0b, 0xf2, 0x74, 0xc1, 0x75, 0xc2, 0xc3, 0xe9, 0x25, 0xce, 0xf8, 0x0d, 0xc6,
672 0x0a, 0xd2, 0xe4, 0xef, 0xa3, 0xb7, 0xed, 0x92, 0x58, 0x51, 0xfc, 0xc6, 0x0d, 0x0e,
673 0x8f, 0xe1, 0xbe, 0xde, 0x6c, 0x01, 0xb5, 0x03, 0x4f, 0xbb, 0x47, 0x76, 0xf2, 0x04,
674 0x44, 0xb5, 0x93, 0x83, 0x58, 0xad, 0x06, 0x3e, 0x95, 0x39, 0xbc, 0x16, 0xc9, 0xe7,
675 0x17, 0x45, 0xce, 0xc0, 0x79, 0x0f, 0x50, 0x74, 0x8d, 0x5a, 0xf6, 0xc4, 0xe2, 0xfd,
676 0x97, 0xf2, 0x49, 0x86, 0x75, 0x93, 0x8d, 0x9e, 0xbc, 0x23, 0x04, 0x0e, 0x76, 0x2a,
677 0xf1, 0x66, 0xbd, 0xef, 0xe8, 0xd0, 0xc1, 0xcb, 0xd6, 0x8f, 0x21, 0x6f, 0xfc, 0xd4,
678 0xd2, 0xed, 0x7b, 0xc4, 0x3a, 0x5d, 0xe7, 0x3c, 0xca, 0xa4, 0x56, 0x18, 0x65, 0x42,
679 0x5a, 0x78, 0xf4, 0x4a, 0xe1, 0x31, 0xfe, 0x68, 0xfd, 0xd5, 0x85, 0x10, 0xa6, 0x88,
680 0x45, 0x99, 0xa5, 0x95, 0xd3, 0x3a, 0xe4, 0x6b, 0xd3, 0x03, 0x84, 0xdc, 0xd2, 0x56,
681 0x01, 0x5c, 0xfc, 0x52, 0x1f, 0x47, 0xca, 0x3a, 0xf6, 0x49, 0xf6, 0x24, 0xc8, 0x4d,
682 0xfb, 0x69, 0x06, 0x00, 0xd5, 0x12, 0x6b, 0xcb, 0x98, 0xab, 0x51, 0xe5, 0xcc, 0xbf,
683 0x4d, 0xe9, 0x60, 0x80, 0x8d, 0x41, 0x64, 0x95, 0x36, 0x94, 0x65, 0x4a, 0x04, 0x58,
684 0xc3, 0xf3, 0x43, 0x54, 0xce, 0x11, 0xe3, 0x95, 0xdb, 0x95, 0xfe, 0x51, 0x08, 0x51,
685 0x07, 0x37, 0xef, 0x50, 0xca, 0x20, 0x39, 0x2d, 0xce, 0xed, 0x4e, 0x59, 0x68, 0x38,
686 0x8e, 0x3b, 0xb1, 0xde, 0x21, 0x56, 0xe8, 0xb0, 0x81, 0xb3, 0xcc, 0x66, 0x94, 0x1d,
687 0xeb, 0x40, 0xe6, 0xb5, 0x2d, 0x79, 0x47, 0x35, 0x4e, 0x85, 0x45, 0xb0, 0x62, 0x4b,
688 0x01, 0xb7, 0xe4, 0x0b, 0x8f, 0x77, 0x5a, 0x39, 0x32, 0x58, 0xd1, 0xd4, 0xd1, 0xe7,
689 0xc8, 0x18, 0xd0, 0x75, 0x44, 0x7a, 0x43, 0x41, 0xbe, 0x0e, 0xca, 0xf5, 0x38, 0x9f,
690 0xdd, 0x1b, 0x47, 0x62, 0x30, 0xee, 0xee, 0x16, 0x7b, 0x32, 0xbc, 0xe3, 0x55, 0x70,
691 0x0a, 0xcf, 0xe4, 0xf9, 0x65, 0x01, 0xf4, 0x9e, 0x4a, 0x82, 0x68, 0xe0, 0x62, 0x1a,
692 0xac, 0x14, 0x3c, 0x1b, 0x94, 0x0e, 0xd3, 0x85, 0xa2, 0x1d, 0x61, 0x08, 0xad, 0x5a,
693 0x9c, 0x5e, 0xdc, 0x81, 0x9c, 0x7b, 0xf2, 0xe4, 0x7f, 0x25, 0x53, 0x47, 0x31, 0x66,
694 0x4d, 0xbd, 0x80, 0x36, 0x6f, 0xa1, 0x33, 0x80, 0x05, 0x5b, 0x79, 0xe0, 0x86, 0x5f,
695 0x3c, 0x08, 0xe7, 0x5e, 0x02, 0x7f, 0x42, 0x92, 0xe3, 0x31, 0xf0, 0x6f, 0xbf, 0x91,
696 0x54, 0x12, 0xa9, 0x6e, 0xe4, 0x48, 0xed, 0x75, 0x78, 0x8f, 0x66, 0x59, 0x00, 0xcd,
697 0x0a, 0x5a, 0xeb, 0x62, 0xe7, 0x82, 0x61, 0x21, 0xed, 0xc0, 0xd5, 0xc5, 0x08, 0xf6,
698 0x9a, 0x4c, 0xd0, 0x01, 0x0f, 0xe0, 0xe2, 0x3f, 0xd2, 0xf8, 0x15, 0xc9, 0x91, 0x74,
699 0xec, 0x9a, 0x36, 0x73, 0x71, 0x1a, 0xb4, 0x8c, 0x3a, 0xe3, 0x31, 0xaf, 0xdd, 0xb8,
700 0xc2, 0xef, 0x3b, 0x61, 0xe3, 0x6f, 0x1f, 0xea, 0x28, 0xb3, 0x38, 0x77, 0x03, 0x3d,
701 0x20, 0xa9, 0x79, 0x68, 0x27, 0x68, 0x41, 0x18, 0xea, 0x58, 0xaf, 0xc5, 0x38, 0xae,
702 0xca, 0x56, 0x81, 0x55, 0xec, 0xa6, 0x59, 0xa0, 0xf0, 0x7a, 0x8d, 0xf2, 0x05, 0x17,
703 0xd0, 0x93, 0x47, 0x1f, 0x6a, 0x77, 0xc6, 0x60, 0xdb, 0xb5, 0x60, 0x38, 0xe1, 0xd9,
704 0xf3, 0xc3, 0xae, 0x0a, 0x16, 0x5c, 0x46, 0xd9, 0xdf, 0xf6, 0x8a, 0xa1, 0x6a, 0x09,
705 0x89, 0xac, 0xaa, 0x53, 0xa0, 0x4c, 0x0e, 0x6b, 0x3b, 0x0c, 0x9c, 0x6d, 0xaa, 0xb4,
706 0xef, 0x09, 0x00, 0x63, 0x14, 0xa1, 0xda, 0xef, 0x4a, 0x0b, 0xe9, 0xd6, 0x22, 0x51,
707 0xd5, 0x9b, 0x71, 0xca, 0xd9, 0xbd, 0x43, 0x9b, 0x1e, 0x8b, 0x45, 0x20, 0xb0, 0x94,
708 0x4a, 0x81, 0x62, 0xc2, 0x0d, 0x48, 0x89, 0xd2, 0x33, 0xf8, 0xed, 0xa8, 0x7d, 0xc1,
709 0x10, 0x02, 0x57, 0x83, 0x4a, 0x32, 0x1e, 0x35, 0xf3, 0xf4, 0x6c, 0xb3, 0x01, 0x47,
710 0x3d, 0xe4, 0xb4, 0xc1, 0x7a, 0xfe, 0x19, 0x0f, 0x3a, 0x8c, 0x6f, 0xa7, 0x1d, 0xf0,
711 0x32, 0x80, 0x7f, 0x92, 0x4c, 0x49, 0xc4, 0xb0, 0x41, 0x08, 0xb2, 0x2f, 0x22, 0x3f,
712 0x6d, 0xcc, 0xa3, 0xd0, 0x3a, 0xe7, 0x11, 0x14, 0x5a, 0x57, 0x3f, 0xb3, 0xc8, 0x2b,
713 0x79, 0xe9, 0x53, 0x94, 0x34, 0x74, 0x26, 0x07, 0x85, 0x06, 0x96, 0x4c, 0x93, 0x63,
714 0x1e, 0x11, 0x18, 0xe8, 0x86, 0x19, 0x2e, 0x82, 0xbe, 0x17, 0x6b, 0x37, 0xba, 0x6d,
715 0x1a, 0xa0, 0x68, 0x20, 0x54, 0x12, 0xff, 0x88, 0xbc, 0x4b, 0x87, 0x45, 0x9d, 0x03,
716 0x06, 0x11, 0x57, 0x4d, 0x25, 0x41, 0x3a, 0x5f, 0x11, 0x21, 0x2f, 0xeb, 0xd6, 0xdc,
717 0x34, 0xda, 0xfd, 0x4c, 0xe0, 0xe9, 0x6c, 0xce, 0x35, 0xed, 0x87, 0xf0, 0x6c, 0xda,
718 0xb0, 0x77, 0x3a, 0x24, 0x33, 0xea, 0x88, 0xaf, 0x15, 0x98, 0xef, 0xeb, 0xab, 0xc1,
719 0xc1, 0xf3, 0x8b, 0x9f, 0xbe, 0xdb, 0x34, 0x29, 0x14, 0xf5, 0x9d, 0x58, 0xd1, 0x53,
720 0x4c, 0xbb, 0xc0, 0x1f, 0xc1, 0x7a, 0x2d, 0x94, 0x2a, 0x86, 0xcc, 0x24, 0x95, 0x42,
721 0x69, 0xea, 0x72, 0x22, 0x1d, 0xbd, 0x19, 0xd7, 0x5e, 0xb3, 0xd0, 0x5f, 0xb3, 0xa9,
722 0x4d, 0x52, 0xa0, 0x9a, 0xb0, 0xe3, 0xde, 0x14, 0x2d, 0xf1, 0x3f, 0x82, 0x82, 0x39,
723 0x9f, 0xee, 0x78, 0xa8, 0xec, 0x33, 0x0c, 0x01, 0x9a, 0xdf, 0xcf, 0xb3, 0x54, 0x02,
724 0x2e, 0xcc, 0x58, 0x0b, 0xfd, 0x0e, 0xe3, 0xac, 0x12, 0x0f, 0x8b, 0x87, 0x0a, 0xad,
725 0x1e, 0x4b, 0x1d, 0x45, 0x3e, 0x6c, 0x4c, 0x7d, 0xff, 0x55, 0xb4, 0x81, 0xaa, 0x0b,
726 0xf0, 0x75, 0x32, 0xa8, 0x32, 0x4d, 0x11, 0xf2, 0xb6, 0x58, 0x42, 0xac, 0x37, 0x6b,
727 0x78, 0xe3, 0x93, 0x3a, 0xaf, 0x26, 0x59, 0x3c, 0xa2, 0x81, 0xab, 0xbc, 0x2c, 0x42,
728 0x87, 0xa7, 0x41, 0x55, 0xb1, 0xe2, 0xa3, 0xf1, 0x0a, 0xa8, 0xd8, 0x11, 0xe8, 0xd7,
729 0xb8, 0x03, 0x44, 0xab, 0xa6, 0x66, 0x98, 0x3c, 0x90, 0x17, 0x88, 0xdd, 0xe7, 0x9c,
730 0x1a, 0x27, 0xba, 0xce, 0x04, 0x3d, 0x34, 0x74, 0xd1, 0xe1, 0x5b, 0x41, 0x5e, 0x2c,
731 0x75, 0x30, 0x03, 0xf6, 0x85, 0x17, 0xbb, 0xb8, 0xfb, 0xb7, 0x7a, 0xf9, 0xb7, 0xc2,
732 0x51, 0x29, 0xe5, 0xc5, 0xf8, 0x0b, 0x86, 0x60, 0x7f, 0x7a, 0x81, 0xe6, 0x0b, 0x23,
733 0xdf, 0xd2, 0x60, 0x1c, 0xbc, 0xaf, 0x2e, 0x6f, 0x1d, 0xd5, 0x81, 0x5e, 0x0e, 0xd0,
734 0x07, 0x54, 0x81, 0x29, 0x30, 0xa0, 0x28, 0xa5, 0xe8, 0x48, 0x9d, 0xea, 0x1d, 0xc5,
735 0x60, 0xff, 0xc3, 0xac, 0x1b, 0x0b, 0xa2, 0xbc, 0x14, 0x63, 0x2b, 0x52, 0xea, 0x5d,
736 0x8c, 0x48, 0xdb, 0x63, 0x72, 0x4b, 0x1b, 0x2c, 0x27, 0xfd, 0x0d, 0x51, 0xa4, 0x28,
737 0xec, 0xe2, 0xc2, 0x21, 0xbe, 0x51, 0x77, 0x58, 0x5f, 0x45, 0x81, 0x7e, 0x62, 0x4a,
738 0x07, 0x5f, 0xd2, 0x2d, 0xa2, 0x4f, 0x18, 0x74, 0x63, 0x1a, 0xae, 0x43, 0x09, 0x5d,
739 0xfb, 0x1e, 0x5d, 0xfb, 0x5a, 0xff, 0x10, 0x41, 0x92, 0xb9, 0xd4, 0x26, 0x01, 0x1c,
740 0x45, 0xd1, 0x5c, 0xb1, 0x62, 0x08, 0xad, 0x60, 0x6e, 0xce, 0xdf, 0x27, 0x49, 0x2f,
741 0xb2, 0x00, 0x59, 0x5b, 0x36, 0x0f, 0xe9, 0xdf, 0xc2, 0xd1, 0xc4, 0x32, 0x84, 0x55,
742 0x07, 0x22, 0x5d, 0x91, 0x53, 0x9f, 0xef, 0x13, 0xe6, 0x07, 0xb8, 0x85, 0xbb, 0x9f,
743 0xc7, 0xda, 0x09, 0x3a, 0x68, 0x8d, 0xc9, 0x9f, 0xcd, 0x76, 0xdb, 0x73, 0x6b, 0x57,
744 0x36, 0x3a, 0xbf, 0xc5, 0x97, 0xcb, 0x85, 0xd1, 0x25, 0xc4, 0x10, 0x07, 0x0c, 0x2c,
745 0x6f, 0x1e, 0x11, 0x46, 0xc8, 0xbb, 0x10, 0x95, 0x35, 0x1e, 0x39, 0x27, 0x05, 0x6e,
746 0x91, 0x0d, 0xb5, 0xa6, 0x66, 0xe4, 0xcf, 0xa5, 0xac, 0x4d, 0x2b, 0x48, 0xfd, 0x2d,
747 0x94, 0x4a, 0x84, 0xde, 0xf6, 0x67, 0x63, 0xa5, 0x4a, 0x53, 0x1d, 0x74, 0x6e, 0xe8,
748 0xf0, 0xc5, 0x9c, 0x87, 0xec, 0x30, 0xa9, 0x34, 0x3d, 0x89, 0x52, 0x37, 0x84, 0xa9,
749 0x20, 0x4e, 0xed, 0x89, 0xaa, 0xb3, 0x2e, 0xec, 0x03, 0x38, 0x33, 0xe1, 0x03, 0x35,
750 0x0a, 0xc7, 0xc0, 0x4c, 0x43, 0x36, 0x8e, 0x38, 0xa8, 0xe9, 0xbc, 0x03, 0x42, 0x86,
751 0xaf, 0x14, 0xda, 0x1a, 0x20, 0xca, 0xc6, 0xdc, 0xb8, 0xb5, 0xf7, 0x9e, 0x39, 0x7c,
752 0x9a, 0x43, 0xee, 0xbb, 0x53, 0xe0, 0x6d, 0xa0, 0xef, 0xa7, 0x00, 0xf1, 0x48, 0xc4,
753 0x7d, 0xb2, 0x60, 0xb2, 0x14, 0xaf, 0x7f, 0x24, 0x83, 0x81, 0x40, 0xff, 0xc2, 0x1a,
754 0x0d, 0xe8, 0xaf, 0x8c, 0x6d, 0xdf, 0x6d, 0xfc, 0x90, 0x2a, 0x92, 0xb4, 0xd5, 0x21,
755 0xe5, 0xb4, 0xf2, 0x93, 0xb5, 0x2f, 0x64, 0x45, 0x95, 0xdb, 0x01, 0x87, 0x21, 0x1d,
756 0xa8, 0x44, 0xcb, 0x26, 0x14, 0x1d, 0xd5, 0x1b, 0xd3, 0x7f, 0xf6, 0x11, 0x4e, 0x01,
757 0xa8, 0xa3, 0xb8, 0x90, 0xb3, 0x05, 0xf6, 0xc1, 0x00, 0x0d, 0xd5, 0x5a, 0x48, 0xe9,
758 0x7f, 0x19, 0x43, 0xc4, 0x8b, 0xbb, 0x0b, 0xb2, 0xd0, 0x3c, 0x7f, 0x0d, 0x6c, 0xbd,
759 0xbe, 0xba, 0xee, 0x40, 0x04, 0x93, 0xf7, 0x1f, 0x97, 0xa9, 0x9b, 0xef, 0x0e, 0x18,
760 0x0b, 0x82, 0xfe, 0xe5, 0x7b, 0x0a, 0xc5, 0x1b, 0x02, 0x89, 0x4e, 0x6a, 0x62, 0x69,
761 0x1f, 0x95, 0xa3, 0xb0, 0xeb, 0x87, 0x11, 0xa3, 0x5f, 0xa4, 0x33, 0xbd, 0xeb, 0xd1,
762 0xc2, 0x91, 0x0c, 0xf8, 0x7f, 0x73, 0xa7, 0x48, 0xdd, 0x1c, 0x32, 0x69, 0x1b, 0xbc,
763 0xb8, 0x6d, 0x91, 0xc3, 0xb9, 0x59, 0x1b, 0xf1, 0x0d, 0xbe, 0x20, 0x1f, 0xc3, 0x37,
764 0x91, 0x8c, 0x15, 0xeb, 0xbb, 0xc4, 0xaa, 0xc5, 0x8a, 0xa3, 0xf3, 0x30, 0xad, 0xab,
765 0x48, 0x5a, 0xb9, 0x4d, 0x08, 0xcc, 0x36, 0x7e, 0x8b, 0x01, 0x0b, 0x01, 0xed, 0xfd,
766 0xaa, 0x17, 0x50, 0x4f, 0x28, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
767 0x00, 0x00, 0xdd, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768 ];
769 let tag = poly1305_mac(message, &otk);
770 let expected_tag = &[
771 0x78, 0xfb, 0xe0, 0x05, 0xdb, 0xff, 0x31, 0xf6, 0xdf, 0xdf, 0xe4, 0x58, 0x7b, 0x4d,
772 0xbe, 0x8e,
773 ];
774 assert_eq!(&tag as &[u8], expected_tag);
775 }
776
777 #[test]
778 fn test_poly1305_mod() {
779 let a: [u32; 5] = [0x2dde68f6, 0x672041f6, 0xf0a01508, 0x1ed7f726, 0x04];
780 assert_eq!(
781 poly1305_mod(a),
782 [0x2dde68fb, 0x672041f6, 0xf0a01508, 0x1ed7f726, 0x0]
783 );
784
785 let a: [u32; 5] = [0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x03];
786 assert_eq!(poly1305_mod(a), [0x4, 0, 0, 0, 0]);
787
788 let a: [u32; 5] = [0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x04];
789 assert_eq!(poly1305_mod(a), [0x4, 0, 0, 0, 0x1]);
790
791 let a: [u32; 5] = [0xfffffffa, 0xffffffff, 0xffffffff, 0xffffffff, 0x03];
792 assert_eq!(
793 poly1305_mod(a),
794 [0xfffffffa, 0xffffffff, 0xffffffff, 0xffffffff, 0x3]
795 );
796
797 let a: [u32; 5] = [0xfffffffb, 0xffffffff, 0xffffffff, 0xffffffff, 0x03];
798 assert_eq!(poly1305_mod(a), [0, 0, 0, 0, 0]);
799
800 let a: [u32; 5] = [0xfffffffc, 0xffffffff, 0xffffffff, 0xffffffff, 0x03];
801 assert_eq!(poly1305_mod(a), [1, 0, 0, 0, 0]);
802 }
803}