/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ghash-0.5.1/src/lib.rs
Line | Count | Source |
1 | | //! **GHASH**: universal hash over GF(2^128) used by AES-GCM for message |
2 | | //! authentication (i.e. GMAC). |
3 | | //! |
4 | | //! ## Implementation Notes |
5 | | //! |
6 | | //! The implementation of GHASH found in this crate internally uses the |
7 | | //! [`polyval`] crate, which provides a similar universal hash function used by |
8 | | //! AES-GCM-SIV (RFC 8452). |
9 | | //! |
10 | | //! By implementing GHASH in terms of POLYVAL, the two universal hash functions |
11 | | //! can share a common core, meaning any optimization work (e.g. CPU-specific |
12 | | //! SIMD implementations) which happens upstream in the `polyval` crate |
13 | | //! benefits GHASH as well. |
14 | | //! |
15 | | //! From RFC 8452 Appendix A: |
16 | | //! <https://tools.ietf.org/html/rfc8452#appendix-A> |
17 | | //! |
18 | | //! > GHASH and POLYVAL both operate in GF(2^128), although with different |
19 | | //! > irreducible polynomials: POLYVAL works modulo x^128 + x^127 + x^126 + |
20 | | //! > x^121 + 1 and GHASH works modulo x^128 + x^7 + x^2 + x + 1. Note |
21 | | //! > that these irreducible polynomials are the "reverse" of each other. |
22 | | //! |
23 | | //! [`polyval`]: https://github.com/RustCrypto/universal-hashes/tree/master/polyval |
24 | | |
25 | | #![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 | | |
32 | | pub use polyval::universal_hash; |
33 | | |
34 | | use polyval::Polyval; |
35 | | use universal_hash::{ |
36 | | consts::U16, |
37 | | crypto_common::{BlockSizeUser, KeySizeUser, ParBlocksSizeUser}, |
38 | | KeyInit, UhfBackend, UhfClosure, UniversalHash, |
39 | | }; |
40 | | |
41 | | #[cfg(feature = "zeroize")] |
42 | | use zeroize::Zeroize; |
43 | | |
44 | | /// GHASH keys (16-bytes) |
45 | | pub type Key = universal_hash::Key<GHash>; |
46 | | |
47 | | /// GHASH blocks (16-bytes) |
48 | | pub type Block = universal_hash::Block<GHash>; |
49 | | |
50 | | /// GHASH tags (16-bytes) |
51 | | pub type Tag = universal_hash::Block<GHash>; |
52 | | |
53 | | /// **GHASH**: universal hash over GF(2^128) used by AES-GCM. |
54 | | /// |
55 | | /// GHASH is a universal hash function used for message authentication in |
56 | | /// the AES-GCM authenticated encryption cipher. |
57 | | #[derive(Clone)] |
58 | | pub struct GHash(Polyval); |
59 | | |
60 | | impl KeySizeUser for GHash { |
61 | | type KeySize = U16; |
62 | | } |
63 | | |
64 | | impl GHash { |
65 | | /// Initialize GHASH with the given `H` field element and initial block |
66 | | #[inline] |
67 | 1.50k | pub fn new_with_init_block(h: &Key, init_block: u128) -> Self { |
68 | 1.50k | let mut h = *h; |
69 | 1.50k | h.reverse(); |
70 | | |
71 | | #[allow(unused_mut)] |
72 | 1.50k | let mut h_polyval = polyval::mulx(&h); |
73 | | |
74 | | #[cfg(feature = "zeroize")] |
75 | | h.zeroize(); |
76 | | |
77 | | #[allow(clippy::let_and_return)] |
78 | 1.50k | let result = GHash(Polyval::new_with_init_block(&h_polyval, init_block)); |
79 | | |
80 | | #[cfg(feature = "zeroize")] |
81 | | h_polyval.zeroize(); |
82 | | |
83 | 1.50k | result |
84 | 1.50k | } |
85 | | } |
86 | | |
87 | | impl KeyInit for GHash { |
88 | | /// Initialize GHASH with the given `H` field element |
89 | | #[inline] |
90 | 1.50k | fn new(h: &Key) -> Self { |
91 | 1.50k | Self::new_with_init_block(h, 0) |
92 | 1.50k | } |
93 | | } |
94 | | |
95 | | struct GHashBackend<'b, B: UhfBackend>(&'b mut B); |
96 | | |
97 | | impl<'b, B: UhfBackend> BlockSizeUser for GHashBackend<'b, B> { |
98 | | type BlockSize = B::BlockSize; |
99 | | } |
100 | | |
101 | | impl<'b, B: UhfBackend> ParBlocksSizeUser for GHashBackend<'b, B> { |
102 | | type ParBlocksSize = B::ParBlocksSize; |
103 | | } |
104 | | |
105 | | impl<'b, B: UhfBackend> UhfBackend for GHashBackend<'b, B> { |
106 | 181k | fn proc_block(&mut self, x: &universal_hash::Block<B>) { |
107 | 181k | let mut x = x.clone(); |
108 | 181k | x.reverse(); |
109 | 181k | self.0.proc_block(&x); |
110 | 181k | } Unexecuted instantiation: <ghash::GHashBackend<polyval::backend::soft::Polyval> as universal_hash::UhfBackend>::proc_block <ghash::GHashBackend<polyval::backend::clmul::Polyval> as universal_hash::UhfBackend>::proc_block Line | Count | Source | 106 | 181k | fn proc_block(&mut self, x: &universal_hash::Block<B>) { | 107 | 181k | let mut x = x.clone(); | 108 | 181k | x.reverse(); | 109 | 181k | self.0.proc_block(&x); | 110 | 181k | } |
|
111 | | } |
112 | | |
113 | | impl BlockSizeUser for GHash { |
114 | | type BlockSize = U16; |
115 | | } |
116 | | |
117 | | impl UniversalHash for GHash { |
118 | 5.87k | 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 | 5.87k | fn call<B: UhfBackend<BlockSize = Self::BlockSize>>(self, backend: &mut B) { |
127 | 5.87k | self.0.call(&mut GHashBackend(backend)); |
128 | 5.87k | } Unexecuted instantiation: <<ghash::GHash as universal_hash::UniversalHash>::update_with_backend::GHashClosure<universal_hash::UniversalHash::update::Ctx<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>>> as universal_hash::UhfClosure>::call::<polyval::backend::soft::Polyval> <<ghash::GHash as universal_hash::UniversalHash>::update_with_backend::GHashClosure<universal_hash::UniversalHash::update::Ctx<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>>> as universal_hash::UhfClosure>::call::<polyval::backend::clmul::Polyval> Line | Count | Source | 126 | 5.87k | fn call<B: UhfBackend<BlockSize = Self::BlockSize>>(self, backend: &mut B) { | 127 | 5.87k | self.0.call(&mut GHashBackend(backend)); | 128 | 5.87k | } |
|
129 | | } |
130 | | |
131 | 5.87k | self.0.update_with_backend(GHashClosure(f)); |
132 | 5.87k | } |
133 | | |
134 | | /// Get GHASH output |
135 | | #[inline] |
136 | 1.19k | fn finalize(self) -> Tag { |
137 | 1.19k | let mut output = self.0.finalize(); |
138 | 1.19k | output.reverse(); |
139 | 1.19k | output |
140 | 1.19k | } |
141 | | } |
142 | | |
143 | | opaque_debug::implement!(GHash); |