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);