aws_lc_rs/aead/
poly1305.rs1use super::{Tag, TAG_LEN};
9use crate::aws_lc::{CRYPTO_poly1305_finish, CRYPTO_poly1305_init, CRYPTO_poly1305_update};
10use crate::cipher::block::BLOCK_LEN;
11use core::mem::MaybeUninit;
12
13pub(super) struct Key {
15 pub(super) key_and_nonce: [u8; KEY_LEN],
16}
17
18const KEY_LEN: usize = 2 * BLOCK_LEN;
19
20impl Key {
21 #[inline]
22 #[allow(dead_code)]
23 pub(super) fn new(key_and_nonce: [u8; KEY_LEN]) -> Self {
24 Self { key_and_nonce }
25 }
26}
27
28pub struct Context {
29 state: poly1305_state,
30}
31
32#[repr(C, align(64))]
37#[allow(non_camel_case_types)]
38struct poly1305_state(aws_lc::poly1305_state);
39
40impl Context {
41 #[inline]
42 pub(super) fn from_key(Key { key_and_nonce }: Key) -> Self {
43 unsafe {
44 let mut state = MaybeUninit::<poly1305_state>::zeroed();
50 CRYPTO_poly1305_init(state.as_mut_ptr().cast(), key_and_nonce.as_ptr());
51 Self {
52 state: state.assume_init(),
53 }
54 }
55 }
56
57 #[inline]
58 pub fn update(&mut self, input: &[u8]) {
59 unsafe {
60 CRYPTO_poly1305_update(
61 self.state.0.as_mut_ptr().cast(),
62 input.as_ptr(),
63 input.len(),
64 );
65 }
66 }
67
68 #[inline]
69 pub(super) fn finish(mut self) -> Tag {
70 unsafe {
71 let mut tag = MaybeUninit::<[u8; TAG_LEN]>::uninit();
72 CRYPTO_poly1305_finish(self.state.0.as_mut_ptr().cast(), tag.as_mut_ptr().cast());
73 crate::fips::set_fips_service_status_unapproved();
74 Tag(tag.assume_init(), TAG_LEN)
75 }
76 }
77}
78
79#[inline]
84pub(super) fn sign(key: Key, input: &[u8]) -> Tag {
85 let mut ctx = Context::from_key(key);
86 ctx.update(input);
87 ctx.finish()
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use crate::{test, test_file};
94
95 #[test]
97 pub fn test_poly1305() {
98 test::run(
99 test_file!("data/poly1305_test.txt"),
100 |section, test_case| {
101 assert_eq!(section, "");
102 let key = test_case.consume_bytes("Key");
103 let key: &[u8; BLOCK_LEN * 2] = key.as_slice().try_into().unwrap();
104 let input = test_case.consume_bytes("Input");
105 let expected_mac = test_case.consume_bytes("MAC");
106 let key = Key::new(*key);
107 let Tag(actual_mac, _) = sign(key, &input);
108 assert_eq!(expected_mac, actual_mac.as_ref());
109
110 Ok(())
111 },
112 );
113 }
114}