/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 | | } |