ghash/lib.rs
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 html_root_url = "https://docs.rs/ghash/0.4.3"
30)]
31#![warn(missing_docs, rust_2018_idioms)]
32
33pub use polyval::universal_hash;
34
35use polyval::Polyval;
36use universal_hash::{consts::U16, NewUniversalHash, UniversalHash};
37
38#[cfg(feature = "zeroize")]
39use zeroize::Zeroize;
40
41/// GHASH keys (16-bytes)
42pub type Key = universal_hash::Key<GHash>;
43
44/// GHASH blocks (16-bytes)
45pub type Block = universal_hash::Block<GHash>;
46
47/// GHASH tags (16-bytes)
48pub type Tag = universal_hash::Output<GHash>;
49
50/// **GHASH**: universal hash over GF(2^128) used by AES-GCM.
51///
52/// GHASH is a universal hash function used for message authentication in
53/// the AES-GCM authenticated encryption cipher.
54#[derive(Clone)]
55pub struct GHash(Polyval);
56
57impl NewUniversalHash for GHash {
58 type KeySize = U16;
59
60 /// Initialize GHASH with the given `H` field element
61 #[inline]
62 fn new(h: &Key) -> Self {
63 let mut h = *h;
64 h.reverse();
65
66 #[allow(unused_mut)]
67 let mut h_polyval = polyval::mulx(&h);
68
69 #[cfg(feature = "zeroize")]
70 h.zeroize();
71
72 #[allow(clippy::let_and_return)]
73 let result = GHash(Polyval::new(&h_polyval));
74
75 #[cfg(feature = "zeroize")]
76 h_polyval.zeroize();
77
78 result
79 }
80}
81
82impl UniversalHash for GHash {
83 type BlockSize = U16;
84
85 /// Input a field element `X` to be authenticated
86 #[inline]
87 fn update(&mut self, x: &Block) {
88 let mut x = *x;
89 x.reverse();
90 self.0.update(&x);
91 }
92
93 /// Reset internal state
94 #[inline]
95 fn reset(&mut self) {
96 self.0.reset();
97 }
98
99 /// Get GHASH output
100 #[inline]
101 fn finalize(self) -> Tag {
102 let mut output = self.0.finalize().into_bytes();
103 output.reverse();
104 Tag::new(output)
105 }
106}
107
108opaque_debug::implement!(GHash);