Coverage Report

Created: 2026-01-16 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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);