1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![cfg_attr(
4 any(
5 keccak_backend = "simd128",
6 keccak_backend = "simd256",
7 keccak_backend = "simd512",
8 ),
9 feature(portable_simd)
10)]
11#![doc = include_str!("../README.md")]
12#![doc(
13 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
14 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
15)]
16
17#[cfg(target_arch = "aarch64")]
18cpufeatures::new!(armv8_sha3_intrinsics, "sha3");
19
20pub mod backends;
21pub mod consts;
22pub mod types;
23
24pub use backends::*;
25pub use consts::*;
26pub use types::*;
27
28#[derive(Debug, Copy, Clone)]
30pub struct Keccak {
31 #[cfg(all(target_arch = "aarch64", not(target_abi = "softfloat")))]
34 armv8_sha3: armv8_sha3_intrinsics::InitToken,
35}
36
37impl Default for Keccak {
38 #[inline]
39 fn default() -> Self {
40 Self {
41 #[cfg(all(target_arch = "aarch64", not(target_abi = "softfloat")))]
42 armv8_sha3: armv8_sha3_intrinsics::init(),
43 }
44 }
45}
46
47impl Keccak {
48 #[inline]
50 #[must_use]
51 pub fn new() -> Self {
52 Self::default()
53 }
54
55 #[inline]
57 #[allow(unreachable_code)]
59 pub fn with_backend(&self, f: impl BackendClosure) {
60 cfg_if::cfg_if!(
61 if #[cfg(any(
62 keccak_backend = "simd128",
63 keccak_backend = "simd256",
64 keccak_backend = "simd512",
65 ))] {
66 return f.call_once::<simd::Backend>()
67 } else if #[cfg(keccak_backend = "aarch64_sha3")] {
68 #[cfg(not(target_arch = "aarch64"))]
69 compile_error!("aarch64_sha3 backend can be used only on AArch64 targets!");
70 #[cfg(target_abi = "softfloat")]
71 compile_error!("aarch64_sha3 backend can not be used with softfloat ABI!");
72 #[cfg(not(target_feature = "sha3"))]
73 compile_error!("aarch64_sha3 backend requires sha3 target feature to be enabled!");
74
75 return f.call_once::<aarch64_sha3::Backend>()
76 } else if #[cfg(keccak_backend = "soft")] {
77 return f.call_once::<soft::Backend>()
78 }
79 );
80
81 #[cfg(all(target_arch = "aarch64", not(target_abi = "softfloat")))]
82 if self.armv8_sha3.get() {
83 #[target_feature(enable = "sha3")]
84 unsafe fn aarch64_sha3_inner(f: impl BackendClosure) {
85 f.call_once::<aarch64_sha3::Backend>();
86 }
87 return unsafe { aarch64_sha3_inner(f) };
89 }
90
91 f.call_once::<soft::Backend>();
92 }
93
94 #[inline]
96 pub fn with_f200(&self, f: impl FnOnce(Fn200)) {
97 self.with_p200::<F200_ROUNDS>(f);
98 }
99
100 #[inline]
102 pub fn with_f400(&self, f: impl FnOnce(Fn400)) {
103 self.with_p400::<F400_ROUNDS>(f);
104 }
105
106 #[inline]
108 pub fn with_f800(&self, f: impl FnOnce(Fn800)) {
109 self.with_p800::<F800_ROUNDS>(f);
110 }
111
112 #[inline]
114 pub fn with_f1600(&self, f: impl FnOnce(Fn1600)) {
115 self.with_p1600::<F1600_ROUNDS>(f);
116 }
117
118 #[inline]
123 pub fn with_p200<const ROUNDS: usize>(&self, f: impl FnOnce(Fn200)) {
124 f(soft::keccak_p::<u8, ROUNDS>);
125 }
126
127 #[inline]
132 pub fn with_p400<const ROUNDS: usize>(&self, f: impl FnOnce(Fn400)) {
133 f(soft::keccak_p::<u16, ROUNDS>);
134 }
135
136 #[inline]
141 pub fn with_p800<const ROUNDS: usize>(&self, f: impl FnOnce(Fn800)) {
142 f(soft::keccak_p::<u32, ROUNDS>);
143 }
144
145 #[inline]
150 pub fn with_p1600<const ROUNDS: usize>(&self, f: impl FnOnce(Fn1600)) {
151 struct Closure<const ROUNDS: usize, F: FnOnce(Fn1600)>(F);
152
153 impl<const ROUNDS: usize, F: FnOnce(Fn1600)> BackendClosure for Closure<ROUNDS, F> {
154 #[inline(always)]
155 fn call_once<B: Backend>(self) {
156 (self.0)(B::get_p1600::<ROUNDS>());
157 }
158 }
159
160 self.with_backend(Closure::<ROUNDS, _>(f));
161 }
162}