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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#![no_std]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
)]
#![warn(missing_docs, rust_2018_idioms)]
pub use polyval::universal_hash;
use polyval::Polyval;
use universal_hash::{
consts::U16,
crypto_common::{BlockSizeUser, KeySizeUser, ParBlocksSizeUser},
KeyInit, UhfBackend, UhfClosure, UniversalHash,
};
#[cfg(feature = "zeroize")]
use zeroize::Zeroize;
pub type Key = universal_hash::Key<GHash>;
pub type Block = universal_hash::Block<GHash>;
pub type Tag = universal_hash::Block<GHash>;
#[derive(Clone)]
pub struct GHash(Polyval);
impl KeySizeUser for GHash {
type KeySize = U16;
}
impl KeyInit for GHash {
#[inline]
fn new(h: &Key) -> Self {
let mut h = *h;
h.reverse();
#[allow(unused_mut)]
let mut h_polyval = polyval::mulx(&h);
#[cfg(feature = "zeroize")]
h.zeroize();
#[allow(clippy::let_and_return)]
let result = GHash(Polyval::new(&h_polyval));
#[cfg(feature = "zeroize")]
h_polyval.zeroize();
result
}
}
struct GHashBackend<'b, B: UhfBackend>(&'b mut B);
impl<'b, B: UhfBackend> BlockSizeUser for GHashBackend<'b, B> {
type BlockSize = B::BlockSize;
}
impl<'b, B: UhfBackend> ParBlocksSizeUser for GHashBackend<'b, B> {
type ParBlocksSize = B::ParBlocksSize;
}
impl<'b, B: UhfBackend> UhfBackend for GHashBackend<'b, B> {
fn proc_block(&mut self, x: &universal_hash::Block<B>) {
let mut x = x.clone();
x.reverse();
self.0.proc_block(&x);
}
}
impl BlockSizeUser for GHash {
type BlockSize = U16;
}
impl UniversalHash for GHash {
fn update_with_backend(&mut self, f: impl UhfClosure<BlockSize = Self::BlockSize>) {
struct GHashClosure<C: UhfClosure>(C);
impl<C: UhfClosure> BlockSizeUser for GHashClosure<C> {
type BlockSize = C::BlockSize;
}
impl<C: UhfClosure> UhfClosure for GHashClosure<C> {
fn call<B: UhfBackend<BlockSize = Self::BlockSize>>(self, backend: &mut B) {
self.0.call(&mut GHashBackend(backend));
}
}
self.0.update_with_backend(GHashClosure(f));
}
#[inline]
fn finalize(self) -> Tag {
let mut output = self.0.finalize();
output.reverse();
output
}
}
opaque_debug::implement!(GHash);