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