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#![warn(missing_docs)]
8
9pub use universal_hash;
10
11use core::fmt::{self, Debug};
12use universal_hash::{
13 KeyInit, UhfClosure, UniversalHash,
14 consts::{U16, U32},
15 crypto_common::{BlockSizeUser, KeySizeUser},
16};
17
18mod backend;
19
20#[cfg(all(
21 any(target_arch = "x86", target_arch = "x86_64"),
22 not(poly1305_force_soft),
23 target_feature = "avx2", any(fuzzing, test)
25))]
26mod fuzz;
27
28#[cfg(all(
29 any(target_arch = "x86", target_arch = "x86_64"),
30 not(poly1305_force_soft)
31))]
32use crate::backend::autodetect::State;
33
34#[cfg(not(all(
35 any(target_arch = "x86", target_arch = "x86_64"),
36 not(poly1305_force_soft)
37)))]
38use crate::backend::soft::State;
39
40pub const KEY_SIZE: usize = 32;
42
43pub const BLOCK_SIZE: usize = 16;
45
46pub type Key = universal_hash::Key<Poly1305>;
48
49pub type Block = universal_hash::Block<Poly1305>;
51
52pub type Tag = universal_hash::Block<Poly1305>;
54
55#[derive(Clone)]
62pub struct Poly1305 {
63 state: State,
64}
65
66impl KeySizeUser for Poly1305 {
67 type KeySize = U32;
68}
69
70impl KeyInit for Poly1305 {
71 fn new(key: &Key) -> Poly1305 {
73 Poly1305 {
74 state: State::new(key),
75 }
76 }
77}
78
79impl BlockSizeUser for Poly1305 {
80 type BlockSize = U16;
81}
82
83impl UniversalHash for Poly1305 {
84 fn update_with_backend(&mut self, f: impl UhfClosure<BlockSize = Self::BlockSize>) {
85 self.state.update_with_backend(f);
86 }
87
88 fn finalize(self) -> Tag {
90 self.state.finalize()
91 }
92}
93
94impl Poly1305 {
95 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_force_soft),
125 target_feature = "avx2", any(fuzzing, test)
127))]
128pub use crate::fuzz::fuzz_avx2;