1 use nettle_sys::{
2     nettle_poly1305_aes_digest, nettle_poly1305_aes_set_key,
3     nettle_poly1305_aes_set_nonce, nettle_poly1305_aes_update,
4     poly1305_aes_ctx, POLY1305_AES_DIGEST_SIZE, POLY1305_AES_KEY_SIZE,
5     POLY1305_AES_NONCE_SIZE,
6 };
7 use std::mem::zeroed;
8 
9 use crate::{Error, mac::Mac, Result};
10 
11 /// D.J. Bernsteins Poly1305-AES message authentication code (RFC 7539).
12 pub struct Poly1305 {
13     context: poly1305_aes_ctx,
14 }
15 
16 impl Poly1305 {
17     /// Create a new MAC instance with secret `key` and public `nonce`.
with_key_and_nonce(key: &[u8], nonce: &[u8]) -> Result<Self>18     pub fn with_key_and_nonce(key: &[u8], nonce: &[u8]) -> Result<Self> {
19         if key.len() != POLY1305_AES_KEY_SIZE as usize {
20             return Err(Error::InvalidArgument { argument_name: "key" }.into());
21         }
22         if nonce.len() != POLY1305_AES_NONCE_SIZE as usize {
23             return Err(Error::InvalidArgument { argument_name: "nonce" }.into());
24         }
25 
26         unsafe {
27             let mut ret: Poly1305 = zeroed();
28 
29             nettle_poly1305_aes_set_key(
30                 &mut ret.context as *mut _,
31                 key.as_ptr(),
32             );
33 
34             nettle_poly1305_aes_set_nonce(
35                 &mut ret.context as *mut _,
36                 nonce.as_ptr(),
37             );
38             Ok(ret)
39         }
40     }
41 }
42 
43 impl Mac for Poly1305 {
mac_size(&self) -> usize44     fn mac_size(&self) -> usize {
45         POLY1305_AES_DIGEST_SIZE as usize
46     }
47 
update(&mut self, data: &[u8])48     fn update(&mut self, data: &[u8]) {
49         unsafe {
50             nettle_poly1305_aes_update(
51                 &mut self.context as *mut _,
52                 data.len(),
53                 data.as_ptr(),
54             );
55         }
56     }
57 
digest(&mut self, digest: &mut [u8]) -> Result<()>58     fn digest(&mut self, digest: &mut [u8]) -> Result<()> {
59         if digest.len() != self.mac_size() {
60             return Err(
61                 Error::InvalidArgument { argument_name: "digest" }.into()
62             );
63         }
64 
65         unsafe {
66             nettle_poly1305_aes_digest(
67                 &mut self.context as *mut _,
68                 digest.len(),
69                 digest.as_mut_ptr(),
70             );
71         }
72 
73         Ok(())
74     }
75 }
76 
77 #[cfg(test)]
78 mod tests {
79     use super::*;
80 
81     #[test]
djb_test_vectors()82     fn djb_test_vectors() {
83         {
84             let key = &b"\xec\x07\x4c\x83\x55\x80\x74\x17\x01\x42\x5b\x62\x32\x35\xad\xd6\x85\x1f\xc4\x0c\x34\x67\xac\x0b\xe0\x5c\xc2\x04\x04\xf3\xf7\x00"[..];
85             let nonce = &b"\xfb\x44\x73\x50\xc4\xe8\x68\xc5\x2a\xc3\x27\x5c\xf9\xd4\x32\x7e"[..];
86             let msg = &b"\xf3\xf6"[..];
87             let mut poly1305 =
88                 Poly1305::with_key_and_nonce(key, nonce).unwrap();
89             let mut mac = vec![0; poly1305.mac_size()];
90 
91             poly1305.update(msg);
92             poly1305.digest(&mut mac).unwrap();
93             assert_eq!(&mac[..], &b"\xf4\xc6\x33\xc3\x04\x4f\xc1\x45\xf8\x4f\x33\x5c\xb8\x19\x53\xde"[..]);
94         }
95 
96         {
97             let key = &b"\x75\xde\xaa\x25\xc0\x9f\x20\x8e\x1d\xc4\xce\x6b\x5c\xad\x3f\xbf\xa0\xf3\x08\x00\x00\xf4\x64\x00\xd0\xc7\xe9\x07\x6c\x83\x44\x03"[..];
98             let nonce = &b"\x61\xee\x09\x21\x8d\x29\xb0\xaa\xed\x7e\x15\x4a\x2c\x55\x09\xcc"[..];
99             let msg = &b""[..];
100             let res = &b"\xdd\x3f\xab\x22\x51\xf1\x1a\xc7\x59\xf0\x88\x71\x29\xcc\x2e\xe7"[..];
101             let mut poly1305 =
102                 Poly1305::with_key_and_nonce(key, nonce).unwrap();
103             let mut mac = vec![0; poly1305.mac_size()];
104 
105             poly1305.update(msg);
106             poly1305.digest(&mut mac).unwrap();
107             assert_eq!(&mac[..], res);
108         }
109 
110         {
111             let key = &b"\x6a\xcb\x5f\x61\xa7\x17\x6d\xd3\x20\xc5\xc1\xeb\x2e\xdc\xdc\x74\x48\x44\x3d\x0b\xb0\xd2\x11\x09\xc8\x9a\x10\x0b\x5c\xe2\xc2\x08"[..];
112             let nonce = &b"\xae\x21\x2a\x55\x39\x97\x29\x59\x5d\xea\x45\x8b\xc6\x21\xff\x0e"[..];
113             let msg = &b"\x66\x3c\xea\x19\x0f\xfb\x83\xd8\x95\x93\xf3\xf4\x76\xb6\xbc\x24\xd7\xe6\x79\x10\x7e\xa2\x6a\xdb\x8c\xaf\x66\x52\xd0\x65\x61\x36"[..];
114             let res = &b"\x0e\xe1\xc1\x6b\xb7\x3f\x0f\x4f\xd1\x98\x81\x75\x3c\x01\xcd\xbe"[..];
115 
116             let mut poly1305 =
117                 Poly1305::with_key_and_nonce(key, nonce).unwrap();
118             let mut mac = vec![0; poly1305.mac_size()];
119 
120             poly1305.update(msg);
121             poly1305.digest(&mut mac).unwrap();
122             assert_eq!(&mac[..], res);
123         }
124 
125         {
126             let key = &b"\xe1\xa5\x66\x8a\x4d\x5b\x66\xa5\xf6\x8c\xc5\x42\x4e\xd5\x98\x2d\x12\x97\x6a\x08\xc4\x42\x6d\x0c\xe8\xa8\x24\x07\xc4\xf4\x82\x07"[..];
127             let nonce = &b"\x9a\xe8\x31\xe7\x43\x97\x8d\x3a\x23\x52\x7c\x71\x28\x14\x9e\x3a"[..];
128             let msg = &b"\xab\x08\x12\x72\x4a\x7f\x1e\x34\x27\x42\xcb\xed\x37\x4d\x94\xd1\x36\xc6\xb8\x79\x5d\x45\xb3\x81\x98\x30\xf2\xc0\x44\x91\xfa\xf0\x99\x0c\x62\xe4\x8b\x80\x18\xb2\xc3\xe4\xa0\xfa\x31\x34\xcb\x67\xfa\x83\xe1\x58\xc9\x94\xd9\x61\xc4\xcb\x21\x09\x5c\x1b\xf9"[..];
129             let res = &b"\x51\x54\xad\x0d\x2c\xb2\x6e\x01\x27\x4f\xc5\x11\x48\x49\x1f\x1b"[..];
130             let mut poly1305 =
131                 Poly1305::with_key_and_nonce(key, nonce).unwrap();
132             let mut mac = vec![0; poly1305.mac_size()];
133 
134             poly1305.update(msg);
135             poly1305.digest(&mut mac).unwrap();
136             assert_eq!(&mac[..], res);
137         }
138     }
139 }
140