summaryrefslogtreecommitdiffstats
path: root/rust/vendor/polyval/src/backend/autodetect.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:39:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:39:49 +0000
commita0aa2307322cd47bbf416810ac0292925e03be87 (patch)
tree37076262a026c4b48c8a0e84f44ff9187556ca35 /rust/vendor/polyval/src/backend/autodetect.rs
parentInitial commit. (diff)
downloadsuricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz
suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'rust/vendor/polyval/src/backend/autodetect.rs')
-rw-r--r--rust/vendor/polyval/src/backend/autodetect.rs111
1 files changed, 111 insertions, 0 deletions
diff --git a/rust/vendor/polyval/src/backend/autodetect.rs b/rust/vendor/polyval/src/backend/autodetect.rs
new file mode 100644
index 0000000..4d4ee97
--- /dev/null
+++ b/rust/vendor/polyval/src/backend/autodetect.rs
@@ -0,0 +1,111 @@
+//! Autodetection for CPU intrinsics, with fallback to the "soft" backend when
+//! they are unavailable.
+
+use crate::{backend::soft, Block, Key};
+use core::mem::ManuallyDrop;
+use universal_hash::{consts::U16, NewUniversalHash, Output, UniversalHash};
+
+#[cfg(all(target_arch = "aarch64", feature = "armv8"))]
+use super::pmull as intrinsics;
+
+#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
+use super::clmul as intrinsics;
+
+#[cfg(all(target_arch = "aarch64", feature = "armv8"))]
+cpufeatures::new!(mul_intrinsics, "aes"); // `aes` implies PMULL
+
+#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
+cpufeatures::new!(mul_intrinsics, "pclmulqdq", "sse4.1");
+
+/// **POLYVAL**: GHASH-like universal hash over GF(2^128).
+pub struct Polyval {
+ inner: Inner,
+ token: mul_intrinsics::InitToken,
+}
+
+union Inner {
+ intrinsics: ManuallyDrop<intrinsics::Polyval>,
+ soft: ManuallyDrop<soft::Polyval>,
+}
+
+impl NewUniversalHash for Polyval {
+ type KeySize = U16;
+
+ /// Initialize POLYVAL with the given `H` field element
+ fn new(h: &Key) -> Self {
+ let (token, has_intrinsics) = mul_intrinsics::init_get();
+
+ let inner = if has_intrinsics {
+ Inner {
+ intrinsics: ManuallyDrop::new(intrinsics::Polyval::new(h)),
+ }
+ } else {
+ Inner {
+ soft: ManuallyDrop::new(soft::Polyval::new(h)),
+ }
+ };
+
+ Self { inner, token }
+ }
+}
+
+impl UniversalHash for Polyval {
+ type BlockSize = U16;
+
+ /// Input a field element `X` to be authenticated
+ #[inline]
+ fn update(&mut self, x: &Block) {
+ if self.token.get() {
+ unsafe { (*self.inner.intrinsics).update(x) }
+ } else {
+ unsafe { (*self.inner.soft).update(x) }
+ }
+ }
+
+ /// Reset internal state
+ fn reset(&mut self) {
+ if self.token.get() {
+ unsafe { (*self.inner.intrinsics).reset() }
+ } else {
+ unsafe { (*self.inner.soft).reset() }
+ }
+ }
+
+ /// Get POLYVAL result (i.e. computed `S` field element)
+ fn finalize(self) -> Output<Self> {
+ let output_bytes = if self.token.get() {
+ unsafe {
+ ManuallyDrop::into_inner(self.inner.intrinsics)
+ .finalize()
+ .into_bytes()
+ }
+ } else {
+ unsafe {
+ ManuallyDrop::into_inner(self.inner.soft)
+ .finalize()
+ .into_bytes()
+ }
+ };
+
+ Output::new(output_bytes)
+ }
+}
+
+impl Clone for Polyval {
+ fn clone(&self) -> Self {
+ let inner = if self.token.get() {
+ Inner {
+ intrinsics: ManuallyDrop::new(unsafe { (*self.inner.intrinsics).clone() }),
+ }
+ } else {
+ Inner {
+ soft: ManuallyDrop::new(unsafe { (*self.inner.soft).clone() }),
+ }
+ };
+
+ Self {
+ inner,
+ token: self.token,
+ }
+ }
+}