Reorganize the ciphers crate

This commit is contained in:
Jan Winkelmann (keks)
2025-02-25 11:50:43 +01:00
parent 46ebb6f46c
commit a1f41953b7
20 changed files with 217 additions and 218 deletions

View File

@@ -18,3 +18,94 @@ pub trait KeyedHashInstance<const KEY_LEN: usize, const HASH_LEN: usize> {
out: &mut [u8; HASH_LEN],
) -> Result<(), Self::Error>;
}
use std::marker::PhantomData;
/// This is a helper to allow for type parameter inference when calling functions
/// that need a [KeyedHash].
///
/// Really just binds the [KeyedHash] trait to a dummy variable, so the type of this dummy variable
/// can be used for type inference. Less typing work.
#[derive(Debug, PartialEq, Eq)]
pub struct InferKeyedHash<Static, const KEY_LEN: usize, const HASH_LEN: usize>
where
Static: KeyedHash<KEY_LEN, HASH_LEN>,
{
pub _phantom_keyed_hasher: PhantomData<*const Static>,
}
impl<Static, const KEY_LEN: usize, const HASH_LEN: usize> InferKeyedHash<Static, KEY_LEN, HASH_LEN>
where
Static: KeyedHash<KEY_LEN, HASH_LEN>,
{
pub const KEY_LEN: usize = KEY_LEN;
pub const HASH_LEN: usize = HASH_LEN;
pub const fn new() -> Self {
Self {
_phantom_keyed_hasher: PhantomData,
}
}
/// This just forwards to [KeyedHash::keyed_hash] of the type parameter `Static`
fn keyed_hash_internal<'a>(
&self,
key: &'a [u8; KEY_LEN],
data: &'a [u8],
out: &mut [u8; HASH_LEN],
) -> Result<(), Static::Error> {
Static::keyed_hash(key, data, out)
}
pub const fn key_len(self) -> usize {
Self::KEY_LEN
}
pub const fn hash_len(self) -> usize {
Self::HASH_LEN
}
}
impl<const KEY_LEN: usize, const HASH_LEN: usize, Static: KeyedHash<KEY_LEN, HASH_LEN>>
KeyedHashInstance<KEY_LEN, HASH_LEN> for InferKeyedHash<Static, KEY_LEN, HASH_LEN>
{
type Error = Static::Error;
fn keyed_hash(
&self,
key: &[u8; KEY_LEN],
data: &[u8],
out: &mut [u8; HASH_LEN],
) -> Result<(), Static::Error> {
self.keyed_hash_internal(key, data, out)
}
}
// Helper traits /////////////////////////////////////////////
impl<Static, const KEY_LEN: usize, const OUT_LEN: usize> Default
for InferKeyedHash<Static, KEY_LEN, OUT_LEN>
where
Static: KeyedHash<KEY_LEN, OUT_LEN>,
{
fn default() -> Self {
Self::new()
}
}
impl<Static, const KEY_LEN: usize, const OUT_LEN: usize> Clone
for InferKeyedHash<Static, KEY_LEN, OUT_LEN>
where
Static: KeyedHash<KEY_LEN, OUT_LEN>,
{
fn clone(&self) -> Self {
*self
}
}
impl<Static, const KEY_LEN: usize, const OUT_LEN: usize> Copy
for InferKeyedHash<Static, KEY_LEN, OUT_LEN>
where
Static: KeyedHash<KEY_LEN, OUT_LEN>,
{
}

View File

@@ -1,14 +1,13 @@
//!
//!```rust
//! # use rosenpass_ciphers::hash_domain::{HashDomain, HashDomainNamespace, SecretHashDomain, SecretHashDomainNamespace};
//! use rosenpass_ciphers::subtle::either_hash::EitherShakeOrBlake;
//! use rosenpass_ciphers::subtle::keyed_shake256::SHAKE256Core;
//! use rosenpass_ciphers::keyed_hash::KeyedHash;
//! use rosenpass_secret_memory::Secret;
//! # rosenpass_secret_memory::secret_policy_use_only_malloc_secrets();
//!
//! const PROTOCOL_IDENTIFIER: &str = "MY_PROTOCOL:IDENTIFIER";
//! // create use once hash domain for the protocol identifier
//! let mut hash_domain = HashDomain::zero(EitherShakeOrBlake::Left(SHAKE256Core));
//! let mut hash_domain = HashDomain::zero(KeyedHash::keyed_shake256());
//! hash_domain = hash_domain.mix(PROTOCOL_IDENTIFIER.as_bytes())?;
//! // upgrade to reusable hash domain
//! let hash_domain_namespace: HashDomainNamespace = hash_domain.dup();
@@ -30,12 +29,9 @@
use anyhow::Result;
use rosenpass_secret_memory::Secret;
use rosenpass_to::To;
use crate::keyed_hash as hash;
pub use crate::keyed_hash::{KeyedHash, KEY_LEN};
use crate::subtle::either_hash::KeyedHash;
pub use hash::KEY_LEN;
use rosenpass_cipher_traits::keyed_hash::KeyedHashInstance;
// TODO Use a proper Dec interface
@@ -120,6 +116,8 @@ impl HashDomainNamespace {
}
impl SecretHashDomain {
// XXX: Why is the old hash still used unconditionally?
//
/// Create a new [SecretHashDomain] with the given key `k` and data `d` by calling
/// [hash::hash] with `k` as the `key` and `d` s the `data`, and using the result
/// as the content for the new [SecretHashDomain].
@@ -133,7 +131,7 @@ impl SecretHashDomain {
let mut new_secret_key = Secret::zero();
hash_choice.keyed_hash(k.try_into()?, d, new_secret_key.secret_mut())?;
let mut r = SecretHashDomain(new_secret_key, hash_choice);
hash::hash(k, d).to(r.0.secret_mut())?;
KeyedHash::incorrect_hmac_blake2b().keyed_hash(k.try_into()?, d, r.0.secret_mut())?;
Ok(r)
}
@@ -177,13 +175,23 @@ impl SecretHashDomain {
self.0
}
/// Evaluate [hash::hash] with this [SecretHashDomain]'s data as the `key` and
/// `dst` as the `data` and stores the result as the new data for this [SecretHashDomain].
///
/// It requires that both `v` and `d` consist of exactly [KEY_LEN] many bytes.
pub fn into_secret_slice(mut self, v: &[u8], dst: &[u8]) -> Result<()> {
hash::hash(v, dst).to(self.0.secret_mut())
}
/* XXX: This code was calling the specific hmac-blake2b code as well as the new KeyedHash enum
* (f.k.a. EitherHash). I was confused by the way the code used the local variables, because it
* didn't match the code. I made the code match the documentation, but I'm not sure that is
* correct. Either way, it doesn't look like this is used anywhere. Maybe just remove it?
*
* /// Evaluate [hash::hash] with this [SecretHashDomain]'s data as the `key` and
* /// `dst` as the `data` and stores the result as the new data for this [SecretHashDomain].
* pub fn into_secret_slice(mut self, v: &[u8; KEY_LEN], dst: &[u8; KEY_LEN]) -> Result<()> {
* let SecretHashDomain(secret, hash_choice) = &self;
*
* let mut new_secret = Secret::zero();
* hash_choice.keyed_hash(secret.secret(), dst, new_secret.secret_mut())?;
* self.0 = new_secret;
*
* Ok(())
* }
*/
}
impl SecretHashDomainNamespace {

View File

@@ -13,19 +13,18 @@ const_assert!(KEY_LEN == hash_domain::KEY_LEN);
/// This should only be used for implementation details; anything with relevance
/// to the cryptographic protocol should use the facilities in [hash_domain], (though
/// hash domain uses this module internally)
pub mod keyed_hash {
pub use crate::subtle::incorrect_hmac_blake2b::{
hash, KEY_LEN, KEY_MAX, KEY_MIN, OUT_MAX, OUT_MIN,
};
}
pub use crate::subtle::keyed_hash;
/// Authenticated encryption with associated data
/// Chacha20poly1305 is used.
pub mod aead {
#[cfg(not(feature = "experiment_libcrux"))]
pub use crate::subtle::chacha20poly1305_ietf::{decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN};
#[cfg(feature = "experiment_libcrux")]
pub use crate::subtle::chacha20poly1305_ietf_libcrux::{
pub use crate::subtle::libcrux::chacha20poly1305_ietf::{
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
};
#[cfg(not(feature = "experiment_libcrux"))]
pub use crate::subtle::rust_crypto::chacha20poly1305_ietf::{
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
};
}
@@ -33,7 +32,7 @@ pub mod aead {
/// Authenticated encryption with associated data with a constant nonce
/// XChacha20poly1305 is used.
pub mod xaead {
pub use crate::subtle::xchacha20poly1305_ietf::{
pub use crate::subtle::rust_crypto::xchacha20poly1305_ietf::{
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
};
}

View File

@@ -1,22 +1,16 @@
use anyhow::ensure;
use rosenpass_cipher_traits::keyed_hash::KeyedHash;
use rosenpass_cipher_traits::keyed_hash::{InferKeyedHash, KeyedHash};
use rosenpass_constant_time::xor;
use rosenpass_to::{ops::copy_slice, with_destination, To};
use rosenpass_to::{ops::copy_slice, To};
use zeroize::Zeroizing;
use crate::subtle::hash_functions::blake2b;
use crate::subtle::hash_functions::infer_keyed_hash::InferKeyedHash;
use crate::subtle::rust_crypto::blake2b;
/// The key length, 32 bytes or 256 bits.
pub const KEY_LEN: usize = 32;
/// The minimal key length, identical to [KEY_LEN]
pub const KEY_MIN: usize = KEY_LEN;
/// The maximal key length, identical to [KEY_LEN]
pub const KEY_MAX: usize = KEY_LEN;
/// The minimal output length, see [blake2b::OUT_MIN]
pub const OUT_MIN: usize = blake2b::OUT_MIN;
/// The maximal output length, see [blake2b::OUT_MAX]
pub const OUT_MAX: usize = blake2b::OUT_MAX;
/// The hash length, 32 bytes or 256 bits.
pub const HASH_LEN: usize = 32;
/// This is a woefully incorrect implementation of hmac_blake2b.
/// See <https://github.com/rosenpass/rosenpass/issues/68#issuecomment-1563612222>
@@ -41,12 +35,20 @@ pub const OUT_MAX: usize = blake2b::OUT_MAX;
/// # assert_eq!(hash_data, expected_hash);
///```
///
#[inline]
pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<()>> + 'a {
const IPAD: [u8; KEY_LEN] = [0x36u8; KEY_LEN];
const OPAD: [u8; KEY_LEN] = [0x5Cu8; KEY_LEN];
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct IncorrectHmacBlake2bCore;
impl KeyedHash<KEY_LEN, HASH_LEN> for IncorrectHmacBlake2bCore {
type Error = anyhow::Error;
fn keyed_hash(
key: &[u8; KEY_LEN],
data: &[u8],
out: &mut [u8; HASH_LEN],
) -> Result<(), Self::Error> {
const IPAD: [u8; KEY_LEN] = [0x36u8; KEY_LEN];
const OPAD: [u8; KEY_LEN] = [0x5Cu8; KEY_LEN];
with_destination(|out: &mut [u8]| {
// Not bothering with padding; the implementation
// uses appropriately sized keys.
ensure!(key.len() == KEY_LEN);
@@ -64,18 +66,7 @@ pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<(
blake2b::hash(tmp_key.as_ref(), outer_data.as_ref()).to(out)?;
Ok(())
})
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Blake2bCore;
impl KeyedHash<32, 32> for Blake2bCore {
type Error = anyhow::Error;
fn keyed_hash(key: &[u8; 32], data: &[u8], out: &mut [u8; 32]) -> Result<(), Self::Error> {
hash(key, data).to(out)
}
}
pub type Blake2b = InferKeyedHash<Blake2bCore, 32, 32>;
pub type IncorrectHmacBlake2b = InferKeyedHash<IncorrectHmacBlake2bCore, KEY_LEN, HASH_LEN>;

View File

@@ -0,0 +1,3 @@
//! Own implementations of custom algorithms
pub mod incorrect_hmac_blake2b;

View File

@@ -1,90 +0,0 @@
use anyhow::Result;
use rosenpass_cipher_traits::keyed_hash::{KeyedHash, KeyedHashInstance};
use std::marker::PhantomData;
/// This is a helper to allow for type parameter inference when calling functions
/// that need a [KeyedHash].
///
/// Really just binds the [KeyedHash] trait to a dummy variable, so the type of this dummy variable
/// can be used for type inference. Less typing work.
#[derive(Debug, PartialEq, Eq)]
pub struct InferKeyedHash<Static, const KEY_LEN: usize, const HASH_LEN: usize>
where
Static: KeyedHash<KEY_LEN, HASH_LEN>,
{
pub _phantom_keyed_hasher: PhantomData<*const Static>,
}
impl<Static, const KEY_LEN: usize, const HASH_LEN: usize> InferKeyedHash<Static, KEY_LEN, HASH_LEN>
where
Static: KeyedHash<KEY_LEN, HASH_LEN, Error = anyhow::Error>,
{
pub const KEY_LEN: usize = KEY_LEN;
pub const HASH_LEN: usize = HASH_LEN;
pub const fn new() -> Self {
Self {
_phantom_keyed_hasher: PhantomData,
}
}
/// This just forwards to [KeyedHash::keyed_hash] of the type parameter `Static`
fn keyed_hash_internal<'a>(
&self,
key: &'a [u8; KEY_LEN],
data: &'a [u8],
out: &mut [u8; HASH_LEN],
) -> Result<()> {
Static::keyed_hash(key, data, out)
}
pub const fn key_len(self) -> usize {
Self::KEY_LEN
}
pub const fn hash_len(self) -> usize {
Self::HASH_LEN
}
}
impl<
const KEY_LEN: usize,
const HASH_LEN: usize,
Static: KeyedHash<KEY_LEN, HASH_LEN, Error = anyhow::Error>,
> KeyedHashInstance<KEY_LEN, HASH_LEN> for InferKeyedHash<Static, KEY_LEN, HASH_LEN>
{
type Error = anyhow::Error;
fn keyed_hash(&self, key: &[u8; KEY_LEN], data: &[u8], out: &mut [u8; HASH_LEN]) -> Result<()> {
self.keyed_hash_internal(key, data, out)
}
}
// Helper traits /////////////////////////////////////////////
impl<Static, const KEY_LEN: usize, const OUT_LEN: usize> Default
for InferKeyedHash<Static, KEY_LEN, OUT_LEN>
where
Static: KeyedHash<KEY_LEN, OUT_LEN, Error = anyhow::Error>,
{
fn default() -> Self {
Self::new()
}
}
impl<Static, const KEY_LEN: usize, const OUT_LEN: usize> Clone
for InferKeyedHash<Static, KEY_LEN, OUT_LEN>
where
Static: KeyedHash<KEY_LEN, OUT_LEN, Error = anyhow::Error>,
{
fn clone(&self) -> Self {
*self
}
}
impl<Static, const KEY_LEN: usize, const OUT_LEN: usize> Copy
for InferKeyedHash<Static, KEY_LEN, OUT_LEN>
where
Static: KeyedHash<KEY_LEN, OUT_LEN, Error = anyhow::Error>,
{
}

View File

@@ -1,4 +0,0 @@
pub mod blake2b;
pub mod incorrect_hmac_blake2b;
mod infer_keyed_hash;
pub mod keyed_shake256;

View File

@@ -6,8 +6,8 @@ pub const HASH_LEN: usize = 32;
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum KeyedHash {
KeyedShake256(super::hash_functions::keyed_shake256::SHAKE256<KEY_LEN, HASH_LEN>),
IncorrectHmacBlake2b(super::hash_functions::incorrect_hmac_blake2b::Blake2b),
KeyedShake256(super::rust_crypto::keyed_shake256::SHAKE256<KEY_LEN, HASH_LEN>),
IncorrectHmacBlake2b(super::custom::incorrect_hmac_blake2b::IncorrectHmacBlake2b),
}
impl KeyedHash {

View File

@@ -0,0 +1,3 @@
//! Implementations backed by libcrux, a verified crypto library
pub mod chacha20poly1305_ietf;

View File

@@ -1,15 +1,10 @@
/// This module provides the following cryptographic schemes:
/// - [blake2b]: The blake2b hash function
/// - [chacha20poly1305_ietf]: The Chacha20Poly1305 AEAD as implemented in [RustCrypto](https://crates.io/crates/chacha20poly1305) (only used when the feature `experiment_libcrux` is disabled).
/// - [chacha20poly1305_ietf_libcrux]: The Chacha20Poly1305 AEAD as implemented in [libcrux](https://github.com/cryspen/libcrux) (only used when the feature `experiment_libcrux` is enabled).
/// - [incorrect_hmac_blake2b]: An (incorrect) hmac based on [blake2b].
/// - [xchacha20poly1305_ietf] The Chacha20Poly1305 AEAD as implemented in [RustCrypto](https://crates.io/crates/chacha20poly1305)
#[cfg(not(feature = "experiment_libcrux"))]
pub mod chacha20poly1305_ietf;
#[cfg(feature = "experiment_libcrux")]
pub mod chacha20poly1305_ietf_libcrux;
pub mod either_hash;
mod hash_functions;
pub mod xchacha20poly1305_ietf;
pub mod keyed_hash;
pub use hash_functions::{blake2b, incorrect_hmac_blake2b, keyed_shake256};
pub use custom::incorrect_hmac_blake2b;
pub use rust_crypto::{blake2b, keyed_shake256};
pub mod custom;
pub mod rust_crypto;
#[cfg(feature = "experiment_libcrux")]
pub mod libcrux;

View File

@@ -1,6 +1,5 @@
use crate::subtle::hash_functions::infer_keyed_hash::InferKeyedHash;
use anyhow::ensure;
use rosenpass_cipher_traits::keyed_hash::KeyedHash;
use rosenpass_cipher_traits::keyed_hash::{InferKeyedHash, KeyedHash};
use sha3::digest::{ExtendableOutput, Update, XofReader};
use sha3::Shake256;

View File

@@ -0,0 +1,7 @@
//! Implementations backed by RustCrypto
pub mod blake2b;
pub mod keyed_shake256;
pub mod chacha20poly1305_ietf;
pub mod xchacha20poly1305_ietf;

View File

@@ -1,8 +1,7 @@
use anyhow::{Context, Result};
use heck::ToShoutySnakeCase;
use rosenpass_ciphers::subtle::either_hash::EitherShakeOrBlake;
use rosenpass_ciphers::subtle::incorrect_hmac_blake2b::Blake2bCore;
use rosenpass_ciphers::subtle::keyed_hash::KeyedHash;
use rosenpass_ciphers::subtle::keyed_shake256::SHAKE256Core;
use rosenpass_ciphers::{hash_domain::HashDomain, KEY_LEN};
@@ -15,7 +14,7 @@ fn calculate_hash_value(hd: HashDomain, values: &[&str]) -> Result<[u8; KEY_LEN]
}
/// Print a hash literal for pasting into the Rosenpass source code
fn print_literal(path: &[&str], shake_or_blake: EitherShakeOrBlake) -> Result<()> {
fn print_literal(path: &[&str], shake_or_blake: KeyedHash) -> Result<()> {
let val = calculate_hash_value(HashDomain::zero(shake_or_blake), path)?;
let (last, prefix) = path.split_last().context("developer error!")?;
let var_name = last.to_shouty_snake_case();
@@ -54,7 +53,7 @@ impl Tree {
}
}
fn gen_code_inner(&self, prefix: &[&str], shake_or_blake: EitherShakeOrBlake) -> Result<()> {
fn gen_code_inner(&self, prefix: &[&str], shake_or_blake: KeyedHash) -> Result<()> {
let mut path = prefix.to_owned();
path.push(self.name());
@@ -70,7 +69,7 @@ impl Tree {
Ok(())
}
fn gen_code(&self, shake_or_blake: EitherShakeOrBlake) -> Result<()> {
fn gen_code(&self, shake_or_blake: KeyedHash) -> Result<()> {
self.gen_code_inner(&[], shake_or_blake)
}
}

View File

@@ -13,7 +13,7 @@
//! use rosenpass::{hash_domain, hash_domain_ns};
//! use rosenpass::hash_domains::protocol;
//!
//! use rosenpass_ciphers::subtle::either_hash::EitherShakeOrBlake;
//! use rosenpass_ciphers::subtle::keyed_hash::KeyedHash;
//!
//! // Declaring a custom hash domain
//! hash_domain_ns!(protocol, custom_domain, "my custom hash domain label");
@@ -29,7 +29,7 @@
//! hash_domain!(domain_separators, sep2, "2");
//!
//! // We use the SHAKE256 hash function for this example
//! let hash_choice = EitherShakeOrBlake::Left(rosenpass_ciphers::subtle::keyed_shake256::SHAKE256Core);
//! let hash_choice = KeyedHash::keyed_shake256();
//!
//! // Generating values under hasher1 with both domain separators
//! let h1 = hasher1(hash_choice.clone())?.mix(b"some data")?.dup();
@@ -54,7 +54,7 @@
use anyhow::Result;
use rosenpass_ciphers::hash_domain::HashDomain;
use rosenpass_ciphers::subtle::either_hash::KeyedHash;
use rosenpass_ciphers::subtle::keyed_hash::KeyedHash;
/// Declare a hash function
///

View File

@@ -21,11 +21,11 @@ use rand::Fill as Randomize;
use crate::{hash_domains, msgs::*, RosenpassError};
use memoffset::span_of;
use rosenpass_cipher_traits::keyed_hash::KeyedHashInstance;
use rosenpass_cipher_traits::Kem;
use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace};
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
use rosenpass_ciphers::keyed_hash;
use rosenpass_ciphers::subtle::either_hash::KeyedHash;
use rosenpass_ciphers::subtle::keyed_hash::KeyedHash;
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
use rosenpass_constant_time as constant_time;
use rosenpass_secret_memory::{Public, PublicBox, Secret};
@@ -371,7 +371,7 @@ pub enum ProtocolVersion {
}
impl ProtocolVersion {
pub fn shake_or_blake(&self) -> KeyedHash {
pub fn keyed_hash(&self) -> KeyedHash {
match self {
ProtocolVersion::V02 => KeyedHash::incorrect_hmac_blake2b(),
ProtocolVersion::V03 => KeyedHash::keyed_shake256(),
@@ -720,8 +720,13 @@ impl KnownResponseHasher {
/// Panics in case of a problem with this underlying hash function
pub fn hash<Msg: AsBytes + FromBytes>(&self, msg: &Envelope<Msg>) -> KnownResponseHash {
let data = &msg.as_bytes()[span_of!(Envelope<Msg>, msg_type..cookie)];
let hash = keyed_hash::hash(self.key.secret(), data)
.to_this(Public::<32>::zero)
// TODO: the hash choice hasn't been propagated here so far
let hash_choice =
rosenpass_ciphers::subtle::keyed_hash::KeyedHash::incorrect_hmac_blake2b();
let mut hash = [0; 32];
hash_choice
.keyed_hash(self.key.secret(), data, &mut hash)
.unwrap();
Public::from_slice(&hash[0..16]) // truncate to 16 bytes
}
@@ -1682,7 +1687,7 @@ impl Peer {
#[rustfmt::skip]
pub fn pidt(&self) -> Result<PeerId> {
Ok(Public::new(
hash_domains::peerid(self.protocol_version.shake_or_blake())?
hash_domains::peerid(self.protocol_version.keyed_hash())?
.mix(self.spkt.deref())?
.into_value()))
}
@@ -1695,12 +1700,11 @@ impl Session {
///
/// ```
/// use rosenpass::protocol::{Session, HandshakeRole};
/// use rosenpass_ciphers::subtle::either_hash::EitherShakeOrBlake;
/// use rosenpass_ciphers::subtle::keyed_shake256::SHAKE256Core;
/// use rosenpass_ciphers::keyed_hash::KeyedHash;
///
/// rosenpass_secret_memory::secret_policy_try_use_memfd_secrets();
///
/// let s = Session::zero(EitherShakeOrBlake::keyed_shake256());
/// let s = Session::zero(KeyedHash::keyed_shake256());
/// assert_eq!(s.created_at, 0.0);
/// assert_eq!(s.handshake_role, HandshakeRole::Initiator);
/// ```
@@ -2352,7 +2356,7 @@ impl CryptoServer {
let mut msg_out = truncating_cast_into::<Envelope<InitConf>>(tx_buf)?;
let peer = self.handle_resp_hello(&msg_in.payload, &mut msg_out.payload)?;
ensure!(
msg_in.check_seal(self, peer.get(self).protocol_version.shake_or_blake())?,
msg_in.check_seal(self, peer.get(self).protocol_version.keyed_hash())?,
seal_broken
);
@@ -2374,10 +2378,8 @@ impl CryptoServer {
Some(cached) => {
let peer = cached.peer();
ensure!(
msg_in.check_seal(
self,
peer.get(self).protocol_version.shake_or_blake()
)?,
msg_in
.check_seal(self, peer.get(self).protocol_version.keyed_hash())?,
seal_broken
);
let cached = cached
@@ -2458,7 +2460,7 @@ impl CryptoServer {
/// TODO documentation
fn verify_hash_choice_match(&self, peer: PeerPtr, peer_hash_choice: KeyedHash) -> Result<()> {
match peer.get(self).protocol_version.shake_or_blake() {
match peer.get(self).protocol_version.keyed_hash() {
KeyedHash::KeyedShake256(_) => match peer_hash_choice {
KeyedHash::KeyedShake256(_) => Ok(()),
KeyedHash::IncorrectHmacBlake2b(_) => bail!("Hash function mismatch"),
@@ -3208,7 +3210,7 @@ where
{
/// Internal business logic: Calculate the message authentication code (`mac`) and also append cookie value
pub fn seal(&mut self, peer: PeerPtr, srv: &CryptoServer) -> Result<()> {
let mac = hash_domains::mac(peer.get(srv).protocol_version.shake_or_blake())?
let mac = hash_domains::mac(peer.get(srv).protocol_version.keyed_hash())?
.mix(peer.get(srv).spkt.deref())?
.mix(&self.as_bytes()[span_of!(Self, msg_type..mac)])?;
self.mac.copy_from_slice(mac.into_value()[..16].as_ref());
@@ -3221,7 +3223,7 @@ where
/// This is called inside [Self::seal] and does not need to be called again separately.
pub fn seal_cookie(&mut self, peer: PeerPtr, srv: &CryptoServer) -> Result<()> {
if let Some(cookie_key) = &peer.cv().get(srv) {
let cookie = hash_domains::cookie(peer.get(srv).protocol_version.shake_or_blake())?
let cookie = hash_domains::cookie(peer.get(srv).protocol_version.keyed_hash())?
.mix(cookie_key.value.secret())?
.mix(&self.as_bytes()[span_of!(Self, msg_type..cookie)])?;
self.cookie
@@ -3384,7 +3386,7 @@ impl HandshakeState {
.copy_from_slice(self.ck.clone().danger_into_secret().secret());
// calculate ad contents
let ad = hash_domains::biscuit_ad(peer.get(srv).protocol_version.shake_or_blake())?
let ad = hash_domains::biscuit_ad(peer.get(srv).protocol_version.keyed_hash())?
.mix(srv.spkm.deref())?
.mix(self.sidi.as_slice())?
.mix(self.sidr.as_slice())?
@@ -3446,7 +3448,7 @@ impl HandshakeState {
let ck = SecretHashDomain::danger_from_secret(
Secret::from_slice(&biscuit.ck),
peer.get(srv).protocol_version.shake_or_blake(),
peer.get(srv).protocol_version.keyed_hash(),
)
.dup();
// Reconstruct the handshake state
@@ -3514,7 +3516,7 @@ impl CryptoServer {
Ok(session
.ck
.mix(&hash_domains::osk(
peer.get(self).protocol_version.shake_or_blake(),
peer.get(self).protocol_version.keyed_hash(),
)?)?
.into_secret())
}
@@ -3526,7 +3528,7 @@ impl CryptoServer {
pub fn handle_initiation(&mut self, peer: PeerPtr, ih: &mut InitHello) -> Result<PeerPtr> {
let mut hs = InitiatorHandshake::zero_with_timestamp(
self,
peer.get(self).protocol_version.shake_or_blake(),
peer.get(self).protocol_version.keyed_hash(),
);
// IHI1
@@ -3553,7 +3555,7 @@ impl CryptoServer {
// IHI6
hs.core.encrypt_and_mix(
ih.pidic.as_mut_slice(),
self.pidm(peer.get(self).protocol_version.shake_or_blake())?
self.pidm(peer.get(self).protocol_version.keyed_hash())?
.as_ref(),
)?;
@@ -3729,7 +3731,7 @@ impl CryptoServer {
core.enter_live(
self,
HandshakeRole::Initiator,
peer.get(self).protocol_version.shake_or_blake(),
peer.get(self).protocol_version.keyed_hash(),
)?,
)?;
hs_mut!().core.erase();
@@ -3787,7 +3789,7 @@ impl CryptoServer {
core.enter_live(
self,
HandshakeRole::Responder,
peer.get(self).protocol_version.shake_or_blake(),
peer.get(self).protocol_version.keyed_hash(),
)?,
)?;
// TODO: This should be part of the protocol specification.
@@ -3848,7 +3850,7 @@ impl CryptoServer {
.lookup_handshake(sid)
.with_context(|| format!("Got RespConf packet for non-existent session {sid:?}"))?;
ensure!(
msg_in.check_seal(self, hs.peer().get(self).protocol_version.shake_or_blake())?,
msg_in.check_seal(self, hs.peer().get(self).protocol_version.keyed_hash())?,
seal_broken
);
let ses = hs.peer().session();
@@ -4362,21 +4364,20 @@ mod test {
assert_eq!(PeerPtr(0).cv().lifecycle(&a), Lifecycle::Young);
let expected_cookie_value =
hash_domains::cookie_value(protocol_version.shake_or_blake())
.unwrap()
.mix(
b.active_or_retired_cookie_secrets()[0]
.unwrap()
.get(&b)
.value
.secret(),
)
.unwrap()
.mix(ip_addr_port_a.encode())
.unwrap()
.into_value()[..16]
.to_vec();
let expected_cookie_value = hash_domains::cookie_value(protocol_version.keyed_hash())
.unwrap()
.mix(
b.active_or_retired_cookie_secrets()[0]
.unwrap()
.get(&b)
.value
.secret(),
)
.unwrap()
.mix(ip_addr_port_a.encode())
.unwrap()
.into_value()[..16]
.to_vec();
assert_eq!(
PeerPtr(0).cv().get(&a).map(|x| &x.value.secret()[..]),
@@ -4593,7 +4594,7 @@ mod test {
let res = srv.handle_init_conf(
&ic.payload,
&mut discard_resp_conf,
protocol_version.clone().shake_or_blake(),
protocol_version.clone().keyed_hash(),
);
assert!(res.is_err());

View File

@@ -1,22 +1,19 @@
use std::{
net::SocketAddr,
ops::DerefMut,
path::PathBuf,
str::FromStr,
sync::mpsc,
thread::{self, sleep},
time::Duration,
};
use anyhow::ensure;
use rosenpass::config::ProtocolVersion;
use rosenpass::{
app_server::{ipv4_any_binding, ipv6_any_binding, AppServer, AppServerTest, MAX_B64_KEY_SIZE},
app_server::{AppServer, AppServerTest, MAX_B64_KEY_SIZE},
protocol::{SPk, SSk, SymKey},
};
use rosenpass_cipher_traits::Kem;
use rosenpass_ciphers::kem::StaticKem;
use rosenpass_secret_memory::Secret;
use rosenpass_util::{file::LoadValueB64, functional::run, mem::DiscardResultExt, result::OkExt};
#[test]