Coverage Report

Created: 2026-06-07 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/polyval-0.5.3/src/backend/autodetect.rs
Line
Count
Source
1
//! Autodetection for CPU intrinsics, with fallback to the "soft" backend when
2
//! they are unavailable.
3
4
use crate::{backend::soft, Block, Key};
5
use core::mem::ManuallyDrop;
6
use universal_hash::{consts::U16, NewUniversalHash, Output, UniversalHash};
7
8
#[cfg(all(target_arch = "aarch64", feature = "armv8"))]
9
use super::pmull as intrinsics;
10
11
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
12
use super::clmul as intrinsics;
13
14
#[cfg(all(target_arch = "aarch64", feature = "armv8"))]
15
cpufeatures::new!(mul_intrinsics, "aes"); // `aes` implies PMULL
16
17
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
18
cpufeatures::new!(mul_intrinsics, "pclmulqdq", "sse4.1");
19
20
/// **POLYVAL**: GHASH-like universal hash over GF(2^128).
21
pub struct Polyval {
22
    inner: Inner,
23
    token: mul_intrinsics::InitToken,
24
}
25
26
union Inner {
27
    intrinsics: ManuallyDrop<intrinsics::Polyval>,
28
    soft: ManuallyDrop<soft::Polyval>,
29
}
30
31
impl NewUniversalHash for Polyval {
32
    type KeySize = U16;
33
34
    /// Initialize POLYVAL with the given `H` field element
35
1.29k
    fn new(h: &Key) -> Self {
36
1.29k
        let (token, has_intrinsics) = mul_intrinsics::init_get();
37
38
1.29k
        let inner = if has_intrinsics {
39
1.29k
            Inner {
40
1.29k
                intrinsics: ManuallyDrop::new(intrinsics::Polyval::new(h)),
41
1.29k
            }
42
        } else {
43
0
            Inner {
44
0
                soft: ManuallyDrop::new(soft::Polyval::new(h)),
45
0
            }
46
        };
47
48
1.29k
        Self { inner, token }
49
1.29k
    }
50
}
51
52
impl UniversalHash for Polyval {
53
    type BlockSize = U16;
54
55
    /// Input a field element `X` to be authenticated
56
    #[inline]
57
287k
    fn update(&mut self, x: &Block) {
58
287k
        if self.token.get() {
59
287k
            unsafe { (*self.inner.intrinsics).update(x) }
60
        } else {
61
0
            unsafe { (*self.inner.soft).update(x) }
62
        }
63
287k
    }
64
65
    /// Reset internal state
66
0
    fn reset(&mut self) {
67
0
        if self.token.get() {
68
0
            unsafe { (*self.inner.intrinsics).reset() }
69
        } else {
70
0
            unsafe { (*self.inner.soft).reset() }
71
        }
72
0
    }
73
74
    /// Get POLYVAL result (i.e. computed `S` field element)
75
2.83k
    fn finalize(self) -> Output<Self> {
76
2.83k
        let output_bytes = if self.token.get() {
77
            unsafe {
78
2.83k
                ManuallyDrop::into_inner(self.inner.intrinsics)
79
2.83k
                    .finalize()
80
2.83k
                    .into_bytes()
81
            }
82
        } else {
83
            unsafe {
84
0
                ManuallyDrop::into_inner(self.inner.soft)
85
0
                    .finalize()
86
0
                    .into_bytes()
87
            }
88
        };
89
90
2.83k
        Output::new(output_bytes)
91
2.83k
    }
92
}
93
94
impl Clone for Polyval {
95
2.83k
    fn clone(&self) -> Self {
96
2.83k
        let inner = if self.token.get() {
97
2.83k
            Inner {
98
2.83k
                intrinsics: ManuallyDrop::new(unsafe { (*self.inner.intrinsics).clone() }),
99
2.83k
            }
100
        } else {
101
0
            Inner {
102
0
                soft: ManuallyDrop::new(unsafe { (*self.inner.soft).clone() }),
103
0
            }
104
        };
105
106
2.83k
        Self {
107
2.83k
            inner,
108
2.83k
            token: self.token,
109
2.83k
        }
110
2.83k
    }
111
}