polyval/backend/
autodetect.rs1use 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 Polyval {
40 pub fn new_with_init_block(h: &Key, init_block: u128) -> 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_with_init_block(
47 h, init_block,
48 )),
49 }
50 } else {
51 Inner {
52 soft: ManuallyDrop::new(soft::Polyval::new_with_init_block(h, init_block)),
53 }
54 };
55
56 Self { inner, token }
57 }
58}
59
60impl KeyInit for Polyval {
61 fn new(h: &Key) -> Self {
63 Self::new_with_init_block(h, 0)
64 }
65}
66
67impl BlockSizeUser for Polyval {
68 type BlockSize = U16;
69}
70
71impl UniversalHash for Polyval {
72 fn update_with_backend(
73 &mut self,
74 f: impl universal_hash::UhfClosure<BlockSize = Self::BlockSize>,
75 ) {
76 unsafe {
77 if self.token.get() {
78 f.call(&mut *self.inner.intrinsics)
79 } else {
80 f.call(&mut *self.inner.soft)
81 }
82 }
83 }
84
85 fn finalize(self) -> Tag {
87 unsafe {
88 if self.token.get() {
89 ManuallyDrop::into_inner(self.inner.intrinsics).finalize()
90 } else {
91 ManuallyDrop::into_inner(self.inner.soft).finalize()
92 }
93 }
94 }
95}
96
97impl Clone for Polyval {
98 fn clone(&self) -> Self {
99 let inner = if self.token.get() {
100 Inner {
101 intrinsics: ManuallyDrop::new(unsafe { (*self.inner.intrinsics).clone() }),
102 }
103 } else {
104 Inner {
105 soft: ManuallyDrop::new(unsafe { (*self.inner.soft).clone() }),
106 }
107 };
108
109 Self {
110 inner,
111 token: self.token,
112 }
113 }
114}
115
116impl Reset for Polyval {
117 fn reset(&mut self) {
118 if self.token.get() {
119 unsafe { (*self.inner.intrinsics).reset() }
120 } else {
121 unsafe { (*self.inner.soft).reset() }
122 }
123 }
124}