#![no_std]
#![forbid(unsafe_code)]
#![deny(missing_docs)]
mod simd;
mod generic_keccak;
#[cfg(not(any(hax, eurydice)))]
mod impl_digest_trait;
#[cfg(not(any(hax, eurydice)))]
pub use impl_digest_trait::*;
mod traits;
pub type Sha3_224Digest = [u8; 28];
pub type Sha3_256Digest = [u8; 32];
pub type Sha3_384Digest = [u8; 48];
pub type Sha3_512Digest = [u8; 64];
#[cfg_attr(not(eurydice), derive(Clone, Copy, Debug, PartialEq))]
#[repr(u32)]
pub enum Algorithm {
Sha224 = 1,
Sha256 = 2,
Sha384 = 3,
Sha512 = 4,
}
#[hax_lib::attributes]
impl From<u32> for Algorithm {
#[hax_lib::requires(v <= 4)]
fn from(v: u32) -> Algorithm {
match v {
1 => Algorithm::Sha224,
2 => Algorithm::Sha256,
3 => Algorithm::Sha384,
4 => Algorithm::Sha512,
_ => panic!(),
}
}
}
impl From<Algorithm> for u32 {
fn from(v: Algorithm) -> u32 {
match v {
Algorithm::Sha224 => 1,
Algorithm::Sha256 => 2,
Algorithm::Sha384 => 3,
Algorithm::Sha512 => 4,
}
}
}
pub const fn digest_size(mode: Algorithm) -> usize {
match mode {
Algorithm::Sha224 => 28,
Algorithm::Sha256 => 32,
Algorithm::Sha384 => 48,
Algorithm::Sha512 => 64,
}
}
pub fn hash<const LEN: usize>(algorithm: Algorithm, payload: &[u8]) -> [u8; LEN] {
debug_assert!(payload.len() <= u32::MAX as usize);
let mut out = [0u8; LEN];
match algorithm {
Algorithm::Sha224 => portable::sha224(&mut out, payload),
Algorithm::Sha256 => portable::sha256(&mut out, payload),
Algorithm::Sha384 => portable::sha384(&mut out, payload),
Algorithm::Sha512 => portable::sha512(&mut out, payload),
}
out
}
pub use hash as sha3;
#[cfg_attr(not(eurydice), inline(always))]
pub fn sha224(data: &[u8]) -> Sha3_224Digest {
let mut out = [0u8; 28];
sha224_ema(&mut out, data);
out
}
#[cfg_attr(not(eurydice), inline(always))]
pub fn sha224_ema(digest: &mut [u8], payload: &[u8]) {
debug_assert!(payload.len() <= u32::MAX as usize);
debug_assert!(digest.len() == 28);
portable::sha224(digest, payload)
}
#[cfg_attr(not(eurydice), inline(always))]
pub fn sha256(data: &[u8]) -> Sha3_256Digest {
let mut out = [0u8; 32];
sha256_ema(&mut out, data);
out
}
#[cfg_attr(not(eurydice), inline(always))]
pub fn sha256_ema(digest: &mut [u8], payload: &[u8]) {
debug_assert!(payload.len() <= u32::MAX as usize);
debug_assert!(digest.len() == 32);
portable::sha256(digest, payload)
}
#[cfg_attr(not(eurydice), inline(always))]
pub fn sha384(data: &[u8]) -> Sha3_384Digest {
let mut out = [0u8; 48];
sha384_ema(&mut out, data);
out
}
#[cfg_attr(not(eurydice), inline(always))]
pub fn sha384_ema(digest: &mut [u8], payload: &[u8]) {
debug_assert!(payload.len() <= u32::MAX as usize);
debug_assert!(digest.len() == 48);
portable::sha384(digest, payload)
}
#[cfg_attr(not(eurydice), inline(always))]
pub fn sha512(data: &[u8]) -> Sha3_512Digest {
let mut out = [0u8; 64];
sha512_ema(&mut out, data);
out
}
#[cfg_attr(not(eurydice), inline(always))]
pub fn sha512_ema(digest: &mut [u8], payload: &[u8]) {
debug_assert!(payload.len() <= u32::MAX as usize);
debug_assert!(digest.len() == 64);
portable::sha512(digest, payload)
}
#[cfg_attr(not(eurydice), inline(always))]
pub fn shake128<const BYTES: usize>(data: &[u8]) -> [u8; BYTES] {
let mut out = [0u8; BYTES];
portable::shake128(&mut out, data);
out
}
#[cfg_attr(not(eurydice), inline(always))]
pub fn shake128_ema(out: &mut [u8], data: &[u8]) {
portable::shake128(out, data);
}
#[cfg_attr(not(eurydice), inline(always))]
pub fn shake256<const BYTES: usize>(data: &[u8]) -> [u8; BYTES] {
let mut out = [0u8; BYTES];
portable::shake256(&mut out, data);
out
}
#[cfg_attr(not(eurydice), inline(always))]
pub fn shake256_ema(out: &mut [u8], data: &[u8]) {
portable::shake256(out, data);
}
pub mod portable;
#[cfg(feature = "simd128")]
pub mod neon;
#[cfg(feature = "simd256")]
pub mod avx2;