1#![no_std]
26#![doc(
27 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
28 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
29)]
30#![warn(missing_docs, rust_2018_idioms)]
31
32pub use polyval::universal_hash;
33
34use polyval::Polyval;
35use universal_hash::{
36 consts::U16,
37 crypto_common::{BlockSizeUser, KeySizeUser, ParBlocksSizeUser},
38 KeyInit, UhfBackend, UhfClosure, UniversalHash,
39};
40
41#[cfg(feature = "zeroize")]
42use zeroize::Zeroize;
43
44pub type Key = universal_hash::Key<GHash>;
46
47pub type Block = universal_hash::Block<GHash>;
49
50pub type Tag = universal_hash::Block<GHash>;
52
53#[derive(Clone)]
58pub struct GHash(Polyval);
59
60impl KeySizeUser for GHash {
61 type KeySize = U16;
62}
63
64impl GHash {
65 #[inline]
67 pub fn new_with_init_block(h: &Key, init_block: u128) -> Self {
68 let mut h = *h;
69 h.reverse();
70
71 #[allow(unused_mut)]
72 let mut h_polyval = polyval::mulx(&h);
73
74 #[cfg(feature = "zeroize")]
75 h.zeroize();
76
77 #[allow(clippy::let_and_return)]
78 let result = GHash(Polyval::new_with_init_block(&h_polyval, init_block));
79
80 #[cfg(feature = "zeroize")]
81 h_polyval.zeroize();
82
83 result
84 }
85}
86
87impl KeyInit for GHash {
88 #[inline]
90 fn new(h: &Key) -> Self {
91 Self::new_with_init_block(h, 0)
92 }
93}
94
95struct GHashBackend<'b, B: UhfBackend>(&'b mut B);
96
97impl<'b, B: UhfBackend> BlockSizeUser for GHashBackend<'b, B> {
98 type BlockSize = B::BlockSize;
99}
100
101impl<'b, B: UhfBackend> ParBlocksSizeUser for GHashBackend<'b, B> {
102 type ParBlocksSize = B::ParBlocksSize;
103}
104
105impl<'b, B: UhfBackend> UhfBackend for GHashBackend<'b, B> {
106 fn proc_block(&mut self, x: &universal_hash::Block<B>) {
107 let mut x = x.clone();
108 x.reverse();
109 self.0.proc_block(&x);
110 }
111}
112
113impl BlockSizeUser for GHash {
114 type BlockSize = U16;
115}
116
117impl UniversalHash for GHash {
118 fn update_with_backend(&mut self, f: impl UhfClosure<BlockSize = Self::BlockSize>) {
119 struct GHashClosure<C: UhfClosure>(C);
120
121 impl<C: UhfClosure> BlockSizeUser for GHashClosure<C> {
122 type BlockSize = C::BlockSize;
123 }
124
125 impl<C: UhfClosure> UhfClosure for GHashClosure<C> {
126 fn call<B: UhfBackend<BlockSize = Self::BlockSize>>(self, backend: &mut B) {
127 self.0.call(&mut GHashBackend(backend));
128 }
129 }
130
131 self.0.update_with_backend(GHashClosure(f));
132 }
133
134 #[inline]
136 fn finalize(self) -> Tag {
137 let mut output = self.0.finalize();
138 output.reverse();
139 output
140 }
141}
142
143opaque_debug::implement!(GHash);