polyval/backend/
autodetect.rs
1use crate::{backend::soft, Block, Key};
5use core::mem::ManuallyDrop;
6use universal_hash::{consts::U16, NewUniversalHash, Output, UniversalHash};
7
8#[cfg(all(target_arch = "aarch64", feature = "armv8"))]
9use super::pmull as intrinsics;
10
11#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
12use super::clmul as intrinsics;
13
14#[cfg(all(target_arch = "aarch64", feature = "armv8"))]
15cpufeatures::new!(mul_intrinsics, "aes"); #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
18cpufeatures::new!(mul_intrinsics, "pclmulqdq", "sse4.1");
19
20pub struct Polyval {
22 inner: Inner,
23 token: mul_intrinsics::InitToken,
24}
25
26union Inner {
27 intrinsics: ManuallyDrop<intrinsics::Polyval>,
28 soft: ManuallyDrop<soft::Polyval>,
29}
30
31impl NewUniversalHash for Polyval {
32 type KeySize = U16;
33
34 fn new(h: &Key) -> Self {
36 let (token, has_intrinsics) = mul_intrinsics::init_get();
37
38 let inner = if has_intrinsics {
39 Inner {
40 intrinsics: ManuallyDrop::new(intrinsics::Polyval::new(h)),
41 }
42 } else {
43 Inner {
44 soft: ManuallyDrop::new(soft::Polyval::new(h)),
45 }
46 };
47
48 Self { inner, token }
49 }
50}
51
52impl UniversalHash for Polyval {
53 type BlockSize = U16;
54
55 #[inline]
57 fn update(&mut self, x: &Block) {
58 if self.token.get() {
59 unsafe { (*self.inner.intrinsics).update(x) }
60 } else {
61 unsafe { (*self.inner.soft).update(x) }
62 }
63 }
64
65 fn reset(&mut self) {
67 if self.token.get() {
68 unsafe { (*self.inner.intrinsics).reset() }
69 } else {
70 unsafe { (*self.inner.soft).reset() }
71 }
72 }
73
74 fn finalize(self) -> Output<Self> {
76 let output_bytes = if self.token.get() {
77 unsafe {
78 ManuallyDrop::into_inner(self.inner.intrinsics)
79 .finalize()
80 .into_bytes()
81 }
82 } else {
83 unsafe {
84 ManuallyDrop::into_inner(self.inner.soft)
85 .finalize()
86 .into_bytes()
87 }
88 };
89
90 Output::new(output_bytes)
91 }
92}
93
94impl Clone for Polyval {
95 fn clone(&self) -> Self {
96 let inner = if self.token.get() {
97 Inner {
98 intrinsics: ManuallyDrop::new(unsafe { (*self.inner.intrinsics).clone() }),
99 }
100 } else {
101 Inner {
102 soft: ManuallyDrop::new(unsafe { (*self.inner.soft).clone() }),
103 }
104 };
105
106 Self {
107 inner,
108 token: self.token,
109 }
110 }
111}