use generic_keccak::xof::KeccakXofState;
#[cfg(hax)]
use private::CShakeInv;
use super::*;
#[cfg(not(eurydice))]
mod cshake;
#[cfg(not(eurydice))]
pub use cshake::{left_encode, left_encode_byte, right_encode};
mod private {
pub trait Sealed {}
impl Sealed for super::Shake128Xof {}
impl Sealed for super::Shake256Xof {}
#[cfg(not(eurydice))]
impl Sealed for super::CShake128 {}
#[cfg(not(eurydice))]
impl Sealed for super::CShake256 {}
#[cfg(not(eurydice))]
#[hax_lib::attributes]
pub trait CShakeInv {
#[cfg(hax)]
#[hax_lib::requires(true)]
#[hax_lib::ensures(|_| true)]
fn cshake_inv(&self) -> bool;
}
#[hax_lib::attributes]
#[cfg(not(eurydice))]
impl<const RATE: usize> CShakeInv for super::CShakeIncremental<RATE> {
#[cfg(hax)]
#[hax_lib::requires(true)]
#[hax_lib::ensures(|_| true)]
fn cshake_inv(&self) -> bool {
self.state.state_inv()
}
}
}
pub struct Shake128Xof {
state: KeccakXofState<1, 168, u64>,
}
pub struct Shake256Xof {
state: KeccakXofState<1, 136, u64>,
}
#[hax_lib::attributes]
#[cfg(not(eurydice))]
pub trait CShake<const RATE: usize>: private::Sealed + private::CShakeInv {
#[requires(RATE == 136 || RATE == 168)]
#[hax_lib::ensures(|result| result.cshake_inv())]
fn new_cshake(name: &[u8], customization: &[u8]) -> Self;
#[hax_lib::requires(self.cshake_inv())]
#[hax_lib::ensures(|_| future(self).cshake_inv())]
fn absorb_cshake(&mut self, input: &[u8]);
#[hax_lib::requires(self.cshake_inv())]
#[hax_lib::ensures(|_| future(self).cshake_inv())]
fn absorb_final_cshake(&mut self, input: &[u8]);
#[hax_lib::requires(self.cshake_inv())]
#[hax_lib::ensures(|_| future(self).cshake_inv())]
fn squeeze_cshake(&mut self, out: &mut [u8]);
}
pub trait Xof<const RATE: usize>: private::Sealed {
fn new() -> Self;
fn absorb(&mut self, input: &[u8]);
fn absorb_final(&mut self, input: &[u8]);
fn squeeze(&mut self, out: &mut [u8]);
}
#[hax_lib::attributes]
impl Xof<168> for Shake128Xof {
#[hax_lib::ensures(|result|result.state.state_inv())]
fn new() -> Self {
Self {
state: KeccakXofState::<1, 168, u64>::new(),
}
}
#[hax_lib::requires(self.state.state_inv())]
#[hax_lib::ensures(|_| future(self).state.state_inv())]
fn absorb(&mut self, input: &[u8]) {
self.state.absorb(&[input]);
}
#[hax_lib::requires(self.state.state_inv())]
#[hax_lib::ensures(|_| future(self).state.state_inv())]
fn absorb_final(&mut self, input: &[u8]) {
self.state.absorb_final::<0x1fu8>(&[input]);
}
#[hax_lib::requires(
self.state.state_inv()
)]
#[hax_lib::ensures(|_|
future(self).state.state_inv() &&
future(out).len() == out.len()
)]
fn squeeze(&mut self, out: &mut [u8]) {
self.state.squeeze(out);
}
}
#[hax_lib::attributes]
#[cfg(not(eurydice))]
impl Xof<168> for CShake128 {
#[hax_lib::ensures(|result| result.state.state_inv())]
fn new() -> Self {
Self {
state: KeccakXofState::<1, 168, u64>::new(),
}
}
#[hax_lib::requires(self.state.state_inv())]
#[hax_lib::ensures(|_| future(self).state.state_inv())]
fn absorb(&mut self, input: &[u8]) {
self.state.absorb(&[input]);
}
#[hax_lib::requires(self.state.state_inv())]
#[hax_lib::ensures(|_| future(self).state.state_inv())]
fn absorb_final(&mut self, input: &[u8]) {
self.state.absorb_final::<0x4u8>(&[input]);
}
#[hax_lib::requires(
self.state.state_inv()
)]
#[hax_lib::ensures(|_|
self.state.state_inv() &&
future(out).len() == out.len()
)]
fn squeeze(&mut self, out: &mut [u8]) {
self.state.squeeze(out);
}
}
#[hax_lib::attributes]
impl Xof<136> for Shake256Xof {
#[hax_lib::ensures(|result| result.state.state_inv())]
fn new() -> Self {
Self {
state: KeccakXofState::<1, 136, u64>::new(),
}
}
#[hax_lib::requires(self.state.state_inv())]
#[hax_lib::ensures(|_| future(self).state.state_inv())]
fn absorb(&mut self, input: &[u8]) {
self.state.absorb(&[input]);
}
#[hax_lib::requires(self.state.state_inv())]
#[hax_lib::ensures(|_| future(self).state.state_inv())]
fn absorb_final(&mut self, input: &[u8]) {
self.state.absorb_final::<0x1fu8>(&[input]);
}
#[hax_lib::requires(
self.state.state_inv()
)]
#[hax_lib::ensures(|_|
future(self).state.state_inv() &&
future(out).len() == out.len()
)]
fn squeeze(&mut self, out: &mut [u8]) {
self.state.squeeze(out);
}
}
#[hax_lib::attributes]
#[cfg(not(eurydice))]
impl Xof<136> for CShake256 {
#[hax_lib::ensures(|result| result.state.state_inv())]
fn new() -> Self {
Self {
state: KeccakXofState::<1, 136, u64>::new(),
}
}
#[hax_lib::requires(self.state.state_inv())]
#[hax_lib::ensures(|_| future(self).state.state_inv())]
fn absorb(&mut self, input: &[u8]) {
self.state.absorb(&[input]);
}
#[hax_lib::requires(self.state.state_inv())]
#[hax_lib::ensures(|_| future(self).state.state_inv())]
fn absorb_final(&mut self, input: &[u8]) {
self.state.absorb_final::<0x4u8>(&[input]);
}
#[hax_lib::requires(
self.state.state_inv()
)]
#[hax_lib::ensures(|_|
self.state.state_inv() &&
future(out).len() == out.len()
)]
fn squeeze(&mut self, out: &mut [u8]) {
self.state.squeeze(out);
}
}
#[inline(always)]
pub fn shake128_init() -> KeccakState {
KeccakState {
state: GenericState::<1, u64>::new(),
}
}
#[inline(always)]
#[hax_lib::requires(
data0.len().to_int() < hax_lib::int!(168)
)]
pub fn shake128_absorb_final(s: &mut KeccakState, data0: &[u8]) {
s.state
.absorb_final::<168, 0x1fu8>(&[data0], 0, data0.len());
}
#[inline(always)]
#[hax_lib::requires(
out0.len().to_int() >= hax_lib::int!(504) // 3 * 168 = 504
)]
#[hax_lib::ensures(|_| future(out0).len() == out0.len())]
pub fn shake128_squeeze_first_three_blocks(s: &mut KeccakState, out0: &mut [u8]) {
s.state.squeeze_first_three_blocks::<168>(out0);
}
#[inline(always)]
#[hax_lib::requires(
out0.len().to_int() >= hax_lib::int!(840) // 5 * 168 = 840
)]
#[hax_lib::ensures(|_| future(out0).len() == out0.len())]
pub fn shake128_squeeze_first_five_blocks(s: &mut KeccakState, out0: &mut [u8]) {
s.state.squeeze_first_five_blocks::<168>(out0);
}
#[inline(always)]
#[hax_lib::requires(
out0.len().to_int() >= hax_lib::int!(168)
)]
#[hax_lib::ensures(|_| future(out0).len() == out0.len())]
pub fn shake128_squeeze_next_block(s: &mut KeccakState, out0: &mut [u8]) {
s.state.squeeze_next_block::<168>(out0, 0)
}
#[inline(always)]
pub fn shake256_init() -> KeccakState {
KeccakState {
state: GenericState::<1, u64>::new(),
}
}
#[inline(always)]
#[hax_lib::requires(
data.len().to_int() < hax_lib::int!(136)
)]
pub fn shake256_absorb_final(s: &mut KeccakState, data: &[u8]) {
s.state.absorb_final::<136, 0x1fu8>(&[data], 0, data.len());
}
#[inline(always)]
#[hax_lib::requires(
out.len().to_int() >= hax_lib::int!(136)
)]
#[hax_lib::ensures(|_| future(out).len() == out.len())]
pub fn shake256_squeeze_first_block(s: &mut KeccakState, out: &mut [u8]) {
s.state.squeeze_first_block::<136>(out);
}
#[inline(always)]
#[hax_lib::requires(
out.len().to_int() >= hax_lib::int!(136)
)]
#[hax_lib::ensures(|_| future(out).len() == out.len())]
pub fn shake256_squeeze_next_block(s: &mut KeccakState, out: &mut [u8]) {
s.state.squeeze_next_block::<136>(out, 0);
}
#[hax_lib::attributes]
#[cfg(not(eurydice))]
impl<const RATE: usize> CShake<RATE> for CShakeIncremental<RATE>
where
CShakeIncremental<RATE>: private::Sealed,
{
#[requires(RATE == 136 || RATE == 168)]
#[hax_lib::ensures(|result| result.cshake_inv())]
fn new_cshake(name: &[u8], customization: &[u8]) -> Self {
let mut state = KeccakXofState::<1, RATE, u64>::new();
let zeros = [0u8; RATE];
let name_bits = name.len() << 3;
let customization_bits = customization.len() << 3;
let mut b = [0u8; 9];
state.absorb(&[&left_encode_byte(RATE as u8)]);
let name_bits_encoding = left_encode(name_bits, &mut b);
let name_bits_encoding_len = name_bits_encoding.len();
state.absorb(&[name_bits_encoding]);
state.absorb(&[name]);
let customization_encoding = left_encode(customization_bits, &mut b);
let customization_encoding_len = customization_encoding.len();
state.absorb(&[customization_encoding]);
state.absorb(&[customization]);
let buffer_len = 2
+ name.len() % RATE
+ name_bits_encoding_len
+ customization_encoding_len
+ (customization.len() % RATE);
let n_zeros = (RATE - (buffer_len % RATE)) % RATE;
debug_assert!(n_zeros < RATE);
state.absorb(&[&zeros[..n_zeros]]);
Self { state }
}
#[hax_lib::requires(self.cshake_inv())]
#[hax_lib::ensures(|_| future(self).cshake_inv())]
fn absorb_cshake(&mut self, input: &[u8]) {
self.state.absorb(&[input]);
}
#[hax_lib::requires(self.cshake_inv())]
#[hax_lib::ensures(|_| future(self).cshake_inv())]
fn absorb_final_cshake(&mut self, input: &[u8]) {
self.state.absorb_final::<0x4u8>(&[input]);
}
#[hax_lib::requires(self.cshake_inv())]
#[hax_lib::ensures(|_| future(self).cshake_inv())]
fn squeeze_cshake(&mut self, out: &mut [u8]) {
self.state.squeeze(out);
}
}
#[cfg(not(eurydice))]
pub struct CShakeIncremental<const RATE: usize> {
pub(crate) state: KeccakXofState<1, RATE, u64>,
}
#[cfg(not(eurydice))]
pub type CShake128 = CShakeIncremental<168>;
#[cfg(not(eurydice))]
pub type CShake256 = CShakeIncremental<136>;