Skip to main content

sha3/
lib.rs

1#![no_std]
2#![doc = include_str!("../README.md")]
3#![doc(
4    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
5    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
6)]
7#![cfg_attr(docsrs, feature(doc_cfg))]
8#![forbid(unsafe_code)]
9#![warn(missing_docs, missing_debug_implementations)]
10#![warn(unreachable_pub)]
11
12pub use digest::{self, Digest};
13
14use core::fmt;
15use digest::{
16    FixedOutput, FixedOutputReset, HashMarker, Output, OutputSizeUser, Reset, Update,
17    common::{
18        AlgorithmName, BlockSizeUser,
19        hazmat::{DeserializeStateError, SerializableState, SerializedState},
20    },
21    consts::{U28, U32, U48, U64, U72, U104, U136, U144, U200, U201},
22    typenum::Unsigned,
23};
24use keccak::{Keccak, State1600};
25
26#[cfg(feature = "oid")]
27mod oids;
28mod utils;
29
30macro_rules! impl_sha3_variants {
31    ($(
32        $(#[$attr:meta])*
33        $name:ident($rate_ty:ty, $out_len:ty, $pad:expr);
34    )*) => {$(
35        $(#[$attr])*
36        #[derive(Clone, Default)]
37        pub struct $name {
38            state: State1600,
39            cursor: sponge_cursor::SpongeCursor<{ <$rate_ty>::USIZE }>,
40            keccak: Keccak,
41        }
42
43        impl Reset for $name {
44            #[inline]
45            fn reset(&mut self) {
46                self.state = Default::default();
47                self.cursor = Default::default();
48            }
49        }
50
51        impl HashMarker for $name {}
52
53        impl Update for $name {
54            #[inline]
55            fn update(&mut self, data: &[u8]) {
56                self.keccak.with_f1600(|f1600| {
57                    self.cursor.absorb_u64_le(&mut self.state, f1600, data);
58                });
59            }
60        }
61
62        impl BlockSizeUser for $name {
63            type BlockSize = $rate_ty;
64        }
65
66        impl OutputSizeUser for $name {
67            type OutputSize = $out_len;
68        }
69
70        impl FixedOutput for $name {
71            fn finalize_into(mut self, dst: &mut Output<Self>) {
72                utils::pad::<$pad, { <$rate_ty>::USIZE }>(&mut self.state, &self.cursor);
73                self.keccak.with_f1600(|f1600| {
74                    f1600(&mut self.state);
75                    utils::read_state(&mut self.state, dst);
76                });
77            }
78        }
79
80        impl FixedOutputReset for $name {
81            fn finalize_into_reset(&mut self, dst: &mut Output<Self>) {
82                utils::pad::<$pad, { <$rate_ty>::USIZE }>(&mut self.state, &self.cursor);
83                self.keccak.with_f1600(|f1600| {
84                    f1600(&mut self.state);
85                    utils::read_state(&mut self.state, dst);
86                });
87                Reset::reset(self);
88            }
89        }
90
91        impl AlgorithmName for $name {
92            #[inline]
93            fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
94                f.write_str(stringify!($name))
95            }
96        }
97
98        impl SerializableState for $name {
99            type SerializedStateSize = U201;
100
101            fn serialize(&self) -> SerializedState<Self> {
102                utils::serialize(&self.state, &self.cursor).into()
103            }
104
105            fn deserialize(
106                serialized_state: &SerializedState<Self>,
107            ) -> Result<Self, DeserializeStateError> {
108                utils::deserialize(serialized_state.into())
109                    .ok_or(DeserializeStateError)
110                    .map(|(state, cursor)| Self {
111                        state,
112                        cursor,
113                        keccak: Keccak::new(),
114                    })
115            }
116        }
117
118        impl fmt::Debug for $name {
119            #[inline]
120            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121                f.write_str(concat!(stringify!($name), " { ... }"))
122            }
123        }
124
125        impl Drop for $name {
126            #[inline]
127            fn drop(&mut self) {
128                #[cfg(feature = "zeroize")]
129                {
130                    use digest::zeroize::Zeroize;
131                    self.state.zeroize();
132                    self.cursor.zeroize();
133                }
134            }
135        }
136
137        #[cfg(feature = "zeroize")]
138        impl digest::zeroize::ZeroizeOnDrop for $name {}
139    )*};
140}
141
142const KECCAK_PAD: u8 = 0x01;
143const SHA3_PAD: u8 = 0x06;
144
145impl_sha3_variants!(
146    /// SHA-3-224 hasher.
147    Sha3_224(U144, U28, SHA3_PAD);
148    /// SHA-3-256 hasher.
149    Sha3_256(U136, U32, SHA3_PAD);
150    /// SHA-3-384 hasher.
151    Sha3_384(U104, U48, SHA3_PAD);
152    /// SHA-3-256 hasher.
153    Sha3_512(U72, U64, SHA3_PAD);
154
155    /// Keccak-224 hasher.
156    Keccak224(U144, U28, KECCAK_PAD);
157    /// Keccak-256 hasher.
158    Keccak256(U136, U32, KECCAK_PAD);
159    /// Keccak-384 hasher.
160    Keccak384(U104, U48, KECCAK_PAD);
161    /// Keccak-512 hasher.
162    Keccak512(U72, U64, KECCAK_PAD);
163
164    /// CryptoNight variant of SHA-3.
165    Keccak256Full(U136, U200, KECCAK_PAD);
166);