Skip to main content

poly1305/
lib.rs

1#![no_std]
2#![doc = include_str!("../README.md")]
3#![doc(
4    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
5    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
6)]
7
8pub use universal_hash;
9
10use core::fmt::{self, Debug};
11use universal_hash::{
12    KeyInit, UhfClosure, UniversalHash,
13    common::{BlockSizeUser, KeySizeUser},
14    consts::{U16, U32},
15};
16
17mod backend;
18
19#[cfg(all(
20    any(target_arch = "x86", target_arch = "x86_64"),
21    not(poly1305_backend = "soft"),
22    target_feature = "avx2", // Fuzz tests bypass AVX2 autodetection code
23    any(fuzzing, test)
24))]
25mod fuzz;
26
27#[cfg(all(
28    any(target_arch = "x86", target_arch = "x86_64"),
29    not(poly1305_backend = "soft")
30))]
31use crate::backend::autodetect::State;
32
33#[cfg(not(all(
34    any(target_arch = "x86", target_arch = "x86_64"),
35    not(poly1305_backend = "soft")
36)))]
37use crate::backend::soft::State;
38
39/// Size of a Poly1305 key
40pub const KEY_SIZE: usize = 32;
41
42/// Size of the blocks Poly1305 acts upon
43pub const BLOCK_SIZE: usize = 16;
44
45/// Poly1305 keys (32-bytes)
46pub type Key = universal_hash::Key<Poly1305>;
47
48/// Poly1305 blocks (16-bytes)
49pub type Block = universal_hash::Block<Poly1305>;
50
51/// Poly1305 tags (16-bytes)
52pub type Tag = universal_hash::Block<Poly1305>;
53
54/// The Poly1305 universal hash function.
55///
56/// Note that Poly1305 is not a traditional MAC and is single-use only
57/// (a.k.a. "one-time authenticator").
58///
59/// For this reason it doesn't impl the `crypto_mac::Mac` trait.
60#[derive(Clone)]
61pub struct Poly1305 {
62    state: State,
63}
64
65impl KeySizeUser for Poly1305 {
66    type KeySize = U32;
67}
68
69impl KeyInit for Poly1305 {
70    /// Initialize Poly1305 with the given key
71    fn new(key: &Key) -> Poly1305 {
72        Poly1305 {
73            state: State::new(key),
74        }
75    }
76}
77
78impl BlockSizeUser for Poly1305 {
79    type BlockSize = U16;
80}
81
82impl UniversalHash for Poly1305 {
83    fn update_with_backend(&mut self, f: impl UhfClosure<BlockSize = Self::BlockSize>) {
84        self.state.update_with_backend(f);
85    }
86
87    /// Get the hashed output
88    fn finalize(self) -> Tag {
89        self.state.finalize()
90    }
91}
92
93impl Poly1305 {
94    /// Compute unpadded Poly1305 for the given input data.
95    ///
96    /// The main use case for this is XSalsa20Poly1305.
97    #[must_use]
98    pub fn compute_unpadded(mut self, data: &[u8]) -> Tag {
99        let (blocks, remaining) = Block::slice_as_chunks(data);
100
101        for block in blocks {
102            self.state.compute_block(block, false);
103        }
104
105        if !remaining.is_empty() {
106            let mut block = Block::default();
107            block[..remaining.len()].copy_from_slice(remaining);
108            block[remaining.len()] = 1;
109            self.state.compute_block(&block, true);
110        }
111
112        self.state.finalize()
113    }
114}
115
116impl Debug for Poly1305 {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        f.debug_struct("Poly1305").finish_non_exhaustive()
119    }
120}
121
122#[cfg(all(
123    any(target_arch = "x86", target_arch = "x86_64"),
124    not(poly1305_backend = "soft"),
125    target_feature = "avx2", // Fuzz tests bypass AVX2 autodetection code
126    any(fuzzing, test)
127))]
128pub use crate::fuzz::fuzz_avx2;