poly1305/backend/
autodetect.rs1use universal_hash::{consts::U16, crypto_common::BlockSizeUser, UniversalHash};
5
6use crate::{backend, Block, Key, Tag};
7use core::mem::ManuallyDrop;
8
9cpufeatures::new!(avx2_cpuid, "avx2");
10
11pub struct State {
12 inner: Inner,
13 token: avx2_cpuid::InitToken,
14}
15
16union Inner {
17 avx2: ManuallyDrop<backend::avx2::State>,
18 soft: ManuallyDrop<backend::soft::State>,
19}
20
21impl BlockSizeUser for State {
22 type BlockSize = U16;
23}
24
25impl State {
26 #[inline]
28 pub(crate) fn new(key: &Key) -> State {
29 let (token, avx2_present) = avx2_cpuid::init_get();
30
31 let inner = if avx2_present {
32 Inner {
33 avx2: ManuallyDrop::new(backend::avx2::State::new(key)),
34 }
35 } else {
36 Inner {
37 soft: ManuallyDrop::new(backend::soft::State::new(key)),
38 }
39 };
40
41 Self { inner, token }
42 }
43
44 #[inline]
46 pub(crate) fn compute_block(&mut self, block: &Block, partial: bool) {
47 if self.token.get() {
48 unsafe { (*self.inner.avx2).compute_block(block, partial) }
49 } else {
50 unsafe { (*self.inner.soft).compute_block(block, partial) }
51 }
52 }
53}
54
55impl UniversalHash for State {
56 fn update_with_backend(
57 &mut self,
58 f: impl universal_hash::UhfClosure<BlockSize = Self::BlockSize>,
59 ) {
60 if self.token.get() {
61 unsafe { f.call(&mut *self.inner.avx2) }
62 } else {
63 unsafe { f.call(&mut *self.inner.soft) }
64 }
65 }
66
67 #[inline]
69 fn finalize(mut self) -> Tag {
70 if self.token.get() {
71 unsafe { (*self.inner.avx2).finalize() }
72 } else {
73 unsafe { (*self.inner.soft).finalize_mut() }
74 }
75 }
76}
77
78impl Clone for State {
79 fn clone(&self) -> Self {
80 let inner = if self.token.get() {
81 Inner {
82 avx2: ManuallyDrop::new(unsafe { (*self.inner.avx2).clone() }),
83 }
84 } else {
85 Inner {
86 soft: ManuallyDrop::new(unsafe { (*self.inner.soft).clone() }),
87 }
88 };
89
90 Self {
91 inner,
92 token: self.token,
93 }
94 }
95}
96
97#[cfg(feature = "zeroize")]
98impl Drop for State {
99 fn drop(&mut self) {
100 use zeroize::Zeroize;
101 const SIZE: usize = core::mem::size_of::<State>();
102 let state = unsafe { &mut *(self as *mut State as *mut [u8; SIZE]) };
103 state.zeroize();
104 }
105}