1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#![no_std]
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
#![warn(missing_docs, rust_2018_idioms)]
pub use universal_hash;
use universal_hash::{
consts::{U16, U32},
generic_array::GenericArray,
NewUniversalHash, UniversalHash,
};
mod soft;
pub const KEY_SIZE: usize = 32;
pub const BLOCK_SIZE: usize = 16;
pub type Key = universal_hash::Key<Poly1305>;
pub type Block = universal_hash::Block<Poly1305>;
pub type Tag = universal_hash::Output<Poly1305>;
#[derive(Clone)]
pub struct Poly1305 {
state: soft::State,
}
impl NewUniversalHash for Poly1305 {
type KeySize = U32;
fn new(key: &Key) -> Poly1305 {
Poly1305 {
state: soft::State::new(key),
}
}
}
impl UniversalHash for Poly1305 {
type BlockSize = U16;
fn update(&mut self, block: &Block) {
self.state.compute_block(block, false);
}
fn reset(&mut self) {
self.state.reset();
}
fn finalize(mut self) -> Tag {
self.state.finalize()
}
}
impl Poly1305 {
pub fn compute_unpadded(mut self, data: &[u8]) -> Tag {
for chunk in data.chunks(BLOCK_SIZE) {
if chunk.len() == BLOCK_SIZE {
let block = GenericArray::from_slice(chunk);
self.state.compute_block(block, false);
} else {
let mut block = Block::default();
block[..chunk.len()].copy_from_slice(chunk);
block[chunk.len()] = 1;
self.state.compute_block(&block, true)
}
}
self.state.finalize()
}
}