crypto_async_rs/
cha_cha_poly.rs

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
140//pub fn poly1305_mac2(mut message: &[u8], key: &[u8; 32]) -> [u8; 16] {
141//    let mut accumulator = BigInt::zero();
142//    let r = &BigInt::from(&key[..16]) & &BigInt::from(0x0ffffffc0ffffffc0ffffffc0fffffffu128);
143//    let s = BigInt::from(&key[16..]);
144//    let p = (BigInt::one() <<  130) - BigInt::from(5u64);
145//    let mu = BigInt::mu_for_barret_reduction(&p);
146//
147//    let plus_1 = BigInt::one() << 128;
148//    while message.len() >= 16 {
149//        let mut n = BigInt::from(&message[..16]);
150//        n = &n | &plus_1;
151//
152//        accumulator = accumulator + &n;
153//        accumulator = r.modular_multiplication_with_barret_reduction(&accumulator, &p, &mu);
154//        message = &message[16..];
155//    }
156//    if message.len() > 0 {
157//        let mut n = BigInt::from(message);
158//        let plus_1 = BigInt::one() << (message.len() << 3);
159//        n = &n | &plus_1;
160//        accumulator = accumulator + &n;
161//        accumulator = r.modular_multiplication(&accumulator, &p);
162//    }
163//
164//    accumulator = accumulator + s;
165//    unsafe {mem::transmute([accumulator[0], accumulator[1]])}
166//}
167
168// Multiplies h and r, put the result in h
169fn poly1305_mul(h: &mut [u32; 5], r: [u32; 4]) {
170    // These would fit in 32 bits, but we need 64 bit multiplications
171    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; // lose 2 bottom bits...
183    let rr1 = (r1 >> 2) * 5; // 2 bottom bits already cleared
184    let rr2 = (r2 >> 2) * 5; // 2 bottom bits already cleared
185    let rr3 = (r3 >> 2) * 5; // 2 bottom bits already cleared
186
187    // school book modular multiplication (without carry propagation)
188    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); // ...recover those 2 bits
193
194    // carry propagation (put the result back in h)
195    let msb: u64 = x4 + (x3 >> 32);
196    let mut u = (msb >> 2) * 5; // lose 2 bottom bits...
197    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 /* ...recover them */;
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    //Compute R = A + B
218    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}