/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ghash-0.4.4/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 | | html_root_url = "https://docs.rs/ghash/0.4.3" |
30 | | )] |
31 | | #![warn(missing_docs, rust_2018_idioms)] |
32 | | |
33 | | pub use polyval::universal_hash; |
34 | | |
35 | | use polyval::Polyval; |
36 | | use universal_hash::{consts::U16, NewUniversalHash, UniversalHash}; |
37 | | |
38 | | #[cfg(feature = "zeroize")] |
39 | | use zeroize::Zeroize; |
40 | | |
41 | | /// GHASH keys (16-bytes) |
42 | | pub type Key = universal_hash::Key<GHash>; |
43 | | |
44 | | /// GHASH blocks (16-bytes) |
45 | | pub type Block = universal_hash::Block<GHash>; |
46 | | |
47 | | /// GHASH tags (16-bytes) |
48 | | pub 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)] |
55 | | pub struct GHash(Polyval); |
56 | | |
57 | | impl NewUniversalHash for GHash { |
58 | | type KeySize = U16; |
59 | | |
60 | | /// Initialize GHASH with the given `H` field element |
61 | | #[inline] |
62 | 1.32k | fn new(h: &Key) -> Self { |
63 | 1.32k | let mut h = *h; |
64 | 1.32k | h.reverse(); |
65 | | |
66 | | #[allow(unused_mut)] |
67 | 1.32k | let mut h_polyval = polyval::mulx(&h); |
68 | | |
69 | | #[cfg(feature = "zeroize")] |
70 | | h.zeroize(); |
71 | | |
72 | | #[allow(clippy::let_and_return)] |
73 | 1.32k | let result = GHash(Polyval::new(&h_polyval)); |
74 | | |
75 | | #[cfg(feature = "zeroize")] |
76 | | h_polyval.zeroize(); |
77 | | |
78 | 1.32k | result |
79 | 1.32k | } |
80 | | } |
81 | | |
82 | | impl UniversalHash for GHash { |
83 | | type BlockSize = U16; |
84 | | |
85 | | /// Input a field element `X` to be authenticated |
86 | | #[inline] |
87 | 139k | fn update(&mut self, x: &Block) { |
88 | 139k | let mut x = *x; |
89 | 139k | x.reverse(); |
90 | 139k | self.0.update(&x); |
91 | 139k | } |
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 | 3.41k | fn finalize(self) -> Tag { |
102 | 3.41k | let mut output = self.0.finalize().into_bytes(); |
103 | 3.41k | output.reverse(); |
104 | 3.41k | Tag::new(output) |
105 | 3.41k | } |
106 | | } |
107 | | |
108 | | opaque_debug::implement!(GHash); |