diff --git a/cipher-traits/src/keyed_hash.rs b/cipher-traits/src/keyed_hash.rs index dcc0e95..d978556 100644 --- a/cipher-traits/src/keyed_hash.rs +++ b/cipher-traits/src/keyed_hash.rs @@ -1,7 +1,11 @@ pub trait KeyedHash { type Error; - - fn keyed_hash(key: &[u8; KEY_LEN], data: &[u8], out: &mut [u8; HASH_LEN]) -> Result<(), Self::Error>; + + fn keyed_hash( + key: &[u8; KEY_LEN], + data: &[u8], + out: &mut [u8; HASH_LEN], + ) -> Result<(), Self::Error>; } pub trait KeyedHashInstance { @@ -9,5 +13,10 @@ pub trait KeyedHashInstance { type OutputType; type Error; - fn keyed_hash(&self, key: &[u8; KEY_LEN], data: &[u8], out: &mut [u8; HASH_LEN]) -> Result<(), Self::Error>; -} \ No newline at end of file + fn keyed_hash( + &self, + key: &[u8; KEY_LEN], + data: &[u8], + out: &mut [u8; HASH_LEN], + ) -> Result<(), Self::Error>; +} diff --git a/ciphers/src/hash_domain.rs b/ciphers/src/hash_domain.rs index 55443fd..7c5c04f 100644 --- a/ciphers/src/hash_domain.rs +++ b/ciphers/src/hash_domain.rs @@ -4,9 +4,9 @@ use rosenpass_to::To; use crate::keyed_hash as hash; +use crate::subtle::either_hash::EitherShakeOrBlake; pub use hash::KEY_LEN; use rosenpass_cipher_traits::KeyedHashInstance; -use crate::subtle::either_hash::EitherShakeOrBlake; /// ///```rust @@ -125,7 +125,11 @@ impl SecretHashDomain { /// as the content for the new [SecretHashDomain]. /// Both `k` and `d` have to be exactly [KEY_LEN] bytes in length. /// TODO: docu - pub fn invoke_primitive(k: &[u8], d: &[u8], hash_choice: EitherShakeOrBlake) -> Result { + pub fn invoke_primitive( + k: &[u8], + d: &[u8], + hash_choice: EitherShakeOrBlake, + ) -> Result { 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); diff --git a/ciphers/src/subtle/either_hash.rs b/ciphers/src/subtle/either_hash.rs index 6539d53..0902377 100644 --- a/ciphers/src/subtle/either_hash.rs +++ b/ciphers/src/subtle/either_hash.rs @@ -1,18 +1,22 @@ -use rosenpass_cipher_traits::{KeyedHash, KeyedHashInstance}; -use anyhow::Result; use crate::subtle::hash_functions::keyed_shake256::SHAKE256Core; use crate::subtle::incorrect_hmac_blake2b::Blake2bCore; +use anyhow::Result; +use rosenpass_cipher_traits::{KeyedHash, KeyedHashInstance}; #[derive(Debug, Eq, PartialEq)] -pub enum EitherHash, - R: KeyedHash> -{ + R: KeyedHash, +> { Left(L), Right(R), } -impl KeyedHashInstance for EitherHash +impl KeyedHashInstance + for EitherHash where L: KeyedHash, R: KeyedHash, @@ -21,7 +25,12 @@ where type OutputType = [u8; HASH_LEN]; type Error = Error; - fn keyed_hash(&self, key: &[u8; KEY_LEN], data: &[u8], out: &mut [u8; HASH_LEN]) -> Result<(), Self::Error> { + fn keyed_hash( + &self, + key: &[u8; KEY_LEN], + data: &[u8], + out: &mut [u8; HASH_LEN], + ) -> Result<(), Self::Error> { match self { Self::Left(_) => L::keyed_hash(key, data, out), Self::Right(_) => R::keyed_hash(key, data, out), diff --git a/ciphers/src/subtle/hash_functions/incorrect_hmac_blake2b.rs b/ciphers/src/subtle/hash_functions/incorrect_hmac_blake2b.rs index 343945c..50db959 100644 --- a/ciphers/src/subtle/hash_functions/incorrect_hmac_blake2b.rs +++ b/ciphers/src/subtle/hash_functions/incorrect_hmac_blake2b.rs @@ -1,8 +1,8 @@ use anyhow::ensure; -use zeroize::Zeroizing; use rosenpass_cipher_traits::KeyedHash; use rosenpass_constant_time::xor; use rosenpass_to::{ops::copy_slice, with_destination, To}; +use zeroize::Zeroizing; use crate::subtle::hash_functions::blake2b; use crate::subtle::hash_functions::infer_keyed_hash::InferKeyedHash; diff --git a/ciphers/src/subtle/hash_functions/infer_keyed_hash.rs b/ciphers/src/subtle/hash_functions/infer_keyed_hash.rs index 4422881..b38a5ae 100644 --- a/ciphers/src/subtle/hash_functions/infer_keyed_hash.rs +++ b/ciphers/src/subtle/hash_functions/infer_keyed_hash.rs @@ -1,6 +1,6 @@ -use std::marker::PhantomData; use anyhow::Result; use rosenpass_cipher_traits::{KeyedHash, KeyedHashInstance}; +use std::marker::PhantomData; /// This is a helper to allow for type parameter inference when calling functions /// that need a [KeyedHash]. @@ -19,11 +19,13 @@ impl InferKeyedHash, { - pub const KEY_LEN : usize = KEY_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 } + Self { + _phantom_keyed_hasher: PhantomData, + } } /// This just forwards to [KeyedHash::keyed_hash] of the type parameter `Static` @@ -45,7 +47,12 @@ where } } -impl> KeyedHashInstance for InferKeyedHash { +impl< + const KEY_LEN: usize, + const HASH_LEN: usize, + Static: KeyedHash, + > KeyedHashInstance for InferKeyedHash +{ type KeyType = [u8; KEY_LEN]; type OutputType = [u8; HASH_LEN]; type Error = anyhow::Error; @@ -57,7 +64,8 @@ impl Default for InferKeyedHash +impl Default + for InferKeyedHash where Static: KeyedHash, { @@ -66,7 +74,8 @@ where } } -impl Clone for InferKeyedHash +impl Clone + for InferKeyedHash where Static: KeyedHash, { @@ -75,7 +84,8 @@ where } } -impl Copy for InferKeyedHash +impl Copy + for InferKeyedHash where Static: KeyedHash, { diff --git a/ciphers/src/subtle/hash_functions/keyed_shake256.rs b/ciphers/src/subtle/hash_functions/keyed_shake256.rs index 7ff188d..60016c7 100644 --- a/ciphers/src/subtle/hash_functions/keyed_shake256.rs +++ b/ciphers/src/subtle/hash_functions/keyed_shake256.rs @@ -1,13 +1,15 @@ +use crate::subtle::hash_functions::infer_keyed_hash::InferKeyedHash; use anyhow::ensure; +use rosenpass_cipher_traits::KeyedHash; use sha3::digest::{ExtendableOutput, Update, XofReader}; use sha3::Shake256; -use rosenpass_cipher_traits::KeyedHash; -use crate::subtle::hash_functions::infer_keyed_hash::InferKeyedHash; #[derive(Clone, Debug, PartialEq, Eq)] pub struct SHAKE256Core; -impl KeyedHash for SHAKE256Core { +impl KeyedHash + for SHAKE256Core +{ type Error = anyhow::Error; /// TODO: Rework test @@ -36,7 +38,11 @@ impl KeyedHash f /// 108, 50, 224, 48, 19, 197, 253, 105, 136, 95, 34, 95, 203, 149, 192, 124, 223, 243, 87]; /// # assert_eq!(hash_data, expected_hash); /// ``` - fn keyed_hash(key: &[u8; KEY_LEN], data: &[u8], out: &mut [u8; HASH_LEN]) -> Result<(), Self::Error> { + fn keyed_hash( + key: &[u8; KEY_LEN], + data: &[u8], + out: &mut [u8; HASH_LEN], + ) -> Result<(), Self::Error> { // Since SHAKE256 is a XOF, we fix the output length manually to what is required for the // protocol. ensure!(out.len() == HASH_LEN); @@ -59,7 +65,6 @@ impl KeyedHash f } } - impl SHAKE256Core { pub fn new() -> Self { Self @@ -83,7 +88,7 @@ impl SHAKE256Core = -InferKeyedHash, KEY_LEN, HASH_LEN>; + InferKeyedHash, KEY_LEN, HASH_LEN>; /// TODO: Documentation and more interesting test /// ```rust @@ -102,4 +107,3 @@ InferKeyedHash, KEY_LEN, HASH_LEN>; /// # assert_eq!(hash_data, expected_hash); /// ``` pub type SHAKE256_32 = SHAKE256<32, 32>; - diff --git a/ciphers/src/subtle/hash_functions/mod.rs b/ciphers/src/subtle/hash_functions/mod.rs index af0ccb7..6ca1c10 100644 --- a/ciphers/src/subtle/hash_functions/mod.rs +++ b/ciphers/src/subtle/hash_functions/mod.rs @@ -1,4 +1,4 @@ pub mod blake2b; pub mod incorrect_hmac_blake2b; +mod infer_keyed_hash; pub mod keyed_shake256; -mod infer_keyed_hash; \ No newline at end of file diff --git a/ciphers/src/subtle/mod.rs b/ciphers/src/subtle/mod.rs index dbd4a34..bc4de11 100644 --- a/ciphers/src/subtle/mod.rs +++ b/ciphers/src/subtle/mod.rs @@ -8,8 +8,8 @@ pub mod chacha20poly1305_ietf; #[cfg(feature = "experiment_libcrux")] pub mod chacha20poly1305_ietf_libcrux; -pub mod xchacha20poly1305_ietf; -mod hash_functions; pub mod either_hash; +mod hash_functions; +pub mod xchacha20poly1305_ietf; -pub use hash_functions::{blake2b, incorrect_hmac_blake2b, keyed_shake256}; \ No newline at end of file +pub use hash_functions::{blake2b, incorrect_hmac_blake2b, keyed_shake256}; diff --git a/initial b/initial new file mode 160000 index 0000000..f1122f1 --- /dev/null +++ b/initial @@ -0,0 +1 @@ +Subproject commit f1122f1f62fb210a02891ea2101e4f699adf772e diff --git a/rosenpass/benches/handshake.rs b/rosenpass/benches/handshake.rs index 28ca235..5756960 100644 --- a/rosenpass/benches/handshake.rs +++ b/rosenpass/benches/handshake.rs @@ -1,5 +1,7 @@ use anyhow::Result; -use rosenpass::protocol::{CryptoServer, HandleMsgResult, MsgBuf, PeerPtr, ProtocolVersion, SPk, SSk, SymKey}; +use rosenpass::protocol::{ + CryptoServer, HandleMsgResult, MsgBuf, PeerPtr, ProtocolVersion, SPk, SSk, SymKey, +}; use std::ops::DerefMut; use rosenpass_cipher_traits::Kem; diff --git a/rosenpass/src/app_server.rs b/rosenpass/src/app_server.rs index e948a1a..58fc8ed 100644 --- a/rosenpass/src/app_server.rs +++ b/rosenpass/src/app_server.rs @@ -42,6 +42,7 @@ use std::slice; use std::time::Duration; use std::time::Instant; +use crate::config::ProtocolVersion; use crate::protocol::BuildCryptoServer; use crate::protocol::HostIdentification; use crate::{ @@ -50,7 +51,6 @@ use crate::{ }; use rosenpass_util::attempt; use rosenpass_util::b64::B64Display; -use crate::config::ProtocolVersion; /// The maximum size of a base64 encoded symmetric key (estimate) pub const MAX_B64_KEY_SIZE: usize = 32 * 5 / 3; @@ -1043,7 +1043,7 @@ impl AppServer { outfile: Option, broker_peer: Option, hostname: Option, - protocol_version: ProtocolVersion + protocol_version: ProtocolVersion, ) -> anyhow::Result { let PeerPtr(pn) = match &mut self.crypto_site { ConstructionSite::Void => bail!("Crypto server construction site is void"), diff --git a/rosenpass/src/bin/gen-ipc-msg-types.rs b/rosenpass/src/bin/gen-ipc-msg-types.rs index 4b3ea47..5cecdeb 100644 --- a/rosenpass/src/bin/gen-ipc-msg-types.rs +++ b/rosenpass/src/bin/gen-ipc-msg-types.rs @@ -1,10 +1,10 @@ use anyhow::{Context, Result}; use heck::ToShoutySnakeCase; -use rosenpass_ciphers::{hash_domain::HashDomain, KEY_LEN}; use rosenpass_ciphers::subtle::either_hash::EitherShakeOrBlake; use rosenpass_ciphers::subtle::incorrect_hmac_blake2b::Blake2bCore; use rosenpass_ciphers::subtle::keyed_shake256::SHAKE256Core; +use rosenpass_ciphers::{hash_domain::HashDomain, KEY_LEN}; /// Recursively calculate a concrete hash value for an API message type fn calculate_hash_value(hd: HashDomain, values: &[&str]) -> Result<[u8; KEY_LEN]> { diff --git a/rosenpass/src/hash_domains.rs b/rosenpass/src/hash_domains.rs index b9ed261..bd95968 100644 --- a/rosenpass/src/hash_domains.rs +++ b/rosenpass/src/hash_domains.rs @@ -103,7 +103,7 @@ macro_rules! hash_domain { /// used in various places in the rosenpass protocol. /// /// This is generally used to create further hash-domains for specific purposes. See -/// +/// /// TODO: Update documentation /// /// # Examples @@ -114,10 +114,11 @@ macro_rules! hash_domain { pub fn protocol(hash_choice: EitherShakeOrBlake) -> Result { // TODO: Update this string that is mixed in? match hash_choice { - EitherShakeOrBlake::Left(SHAKE256Core) => HashDomain::zero(hash_choice).mix("Rosenpass v1 mceliece460896 Kyber512 ChaChaPoly1305 SHAKE256".as_bytes()), - EitherShakeOrBlake::Right(Blake2bCore) => HashDomain::zero(hash_choice).mix("Rosenpass v1 mceliece460896 Kyber512 ChaChaPoly1305 Blake2b".as_bytes()), + EitherShakeOrBlake::Left(SHAKE256Core) => HashDomain::zero(hash_choice) + .mix("Rosenpass v1 mceliece460896 Kyber512 ChaChaPoly1305 SHAKE256".as_bytes()), + EitherShakeOrBlake::Right(Blake2bCore) => HashDomain::zero(hash_choice) + .mix("Rosenpass v1 mceliece460896 Kyber512 ChaChaPoly1305 Blake2b".as_bytes()), } - } hash_domain_ns!( diff --git a/rosenpass/src/protocol/build_crypto_server.rs b/rosenpass/src/protocol/build_crypto_server.rs index 835cfc1..f372e4e 100644 --- a/rosenpass/src/protocol/build_crypto_server.rs +++ b/rosenpass/src/protocol/build_crypto_server.rs @@ -1,11 +1,11 @@ +use super::{CryptoServer, PeerPtr, SPk, SSk, SymKey}; +use crate::config::ProtocolVersion; use rosenpass_util::{ build::Build, mem::{DiscardResultExt, SwapWithDefaultExt}, result::ensure_or, }; use thiserror::Error; -use crate::config::ProtocolVersion; -use super::{CryptoServer, PeerPtr, SPk, SSk, SymKey}; #[derive(Debug, Clone)] /// A pair of matching public/secret keys used to launch the crypto server. @@ -187,7 +187,15 @@ impl Build for BuildCryptoServer { let mut srv = CryptoServer::new(sk, pk); - for (idx, PeerParams { psk, pk , protocol_version}) in self.peers.into_iter().enumerate() { + for ( + idx, + PeerParams { + psk, + pk, + protocol_version, + }, + ) in self.peers.into_iter().enumerate() + { let PeerPtr(idx2) = srv.add_peer(psk, pk, protocol_version.into())?; assert!(idx == idx2, "Peer id changed during CryptoServer construction from {idx} to {idx2}. This is a developer error.") } @@ -337,14 +345,28 @@ impl BuildCryptoServer { /// assert_eq!(peer.spkt, public_key); /// assert_eq!(peer_psk.secret(), pre_shared_key.secret()); /// ``` - pub fn with_added_peer(&mut self, psk: Option, pk: SPk, protocol_version: ProtocolVersion) -> &mut Self { + pub fn with_added_peer( + &mut self, + psk: Option, + pk: SPk, + protocol_version: ProtocolVersion, + ) -> &mut Self { // TODO: Check here already whether peer was already added - self.peers.push(PeerParams { psk, pk, protocol_version }); + self.peers.push(PeerParams { + psk, + pk, + protocol_version, + }); self } /// Add a new entry to the list of registered peers, with or without a pre-shared key. - pub fn add_peer(&mut self, psk: Option, pk: SPk, protocol_version: ProtocolVersion) -> PeerPtr { + pub fn add_peer( + &mut self, + psk: Option, + pk: SPk, + protocol_version: ProtocolVersion, + ) -> PeerPtr { let id = PeerPtr(self.peers.len()); self.with_added_peer(psk, pk, protocol_version); id diff --git a/rosenpass/src/protocol/protocol.rs b/rosenpass/src/protocol/protocol.rs index 7a3680c..380ea56 100644 --- a/rosenpass/src/protocol/protocol.rs +++ b/rosenpass/src/protocol/protocol.rs @@ -19,11 +19,15 @@ use std::{ use anyhow::{bail, ensure, Context, Result}; use rand::Fill as Randomize; +use crate::{hash_domains, msgs::*, RosenpassError}; use memoffset::span_of; 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::EitherShakeOrBlake; +use rosenpass_ciphers::subtle::incorrect_hmac_blake2b::Blake2bCore; +use rosenpass_ciphers::subtle::keyed_shake256::SHAKE256Core; use rosenpass_ciphers::{aead, xaead, KEY_LEN}; use rosenpass_constant_time as constant_time; use rosenpass_secret_memory::{Public, PublicBox, Secret}; @@ -33,10 +37,6 @@ use rosenpass_util::functional::ApplyExt; use rosenpass_util::mem::DiscardResultExt; use rosenpass_util::{cat, mem::cpy_min, time::Timebase}; use zerocopy::{AsBytes, FromBytes, Ref}; -use rosenpass_ciphers::subtle::either_hash::{EitherShakeOrBlake}; -use rosenpass_ciphers::subtle::incorrect_hmac_blake2b::Blake2bCore; -use rosenpass_ciphers::subtle::keyed_shake256::SHAKE256Core; -use crate::{hash_domains, msgs::*, RosenpassError}; // CONSTANTS & SETTINGS ////////////////////////// @@ -369,7 +369,7 @@ pub enum IndexKey { #[derive(Debug, Clone)] pub enum ProtocolVersion { V02, - V03 + V03, } impl ProtocolVersion { @@ -1434,7 +1434,7 @@ impl CryptoServer { } /// Add a peer with an optional pre shared key (`psk`) and its public key (`pk`) - /// + /// /// TODO: Adapt documentation /// /// ``` @@ -1460,7 +1460,12 @@ impl CryptoServer { /// /// Ok::<(), anyhow::Error>(()) /// ``` - pub fn add_peer(&mut self, psk: Option, pk: SPk, protocol_version: ProtocolVersion) -> Result { + pub fn add_peer( + &mut self, + psk: Option, + pk: SPk, + protocol_version: ProtocolVersion, + ) -> Result { let peer = Peer { psk: psk.unwrap_or_else(SymKey::zero), spkt: pk, @@ -2306,7 +2311,7 @@ impl CryptoServer { log::debug!("Rx {:?}, processing", msg_type); let mut msg_out = truncating_cast_into::>(tx_buf)?; - + let peer = match msg_type { Ok(MsgType::InitHello) => { let msg_in: Ref<&[u8], Envelope> = @@ -2314,23 +2319,31 @@ impl CryptoServer { // At this point, we do not know the hash functon used by the peer, thus we try both, // with a preference for SHAKE256. - let peer_shake256 = self.handle_init_hello(&msg_in.payload, &mut msg_out.payload, EitherShakeOrBlake::Left(SHAKE256Core)); + let peer_shake256 = self.handle_init_hello( + &msg_in.payload, + &mut msg_out.payload, + EitherShakeOrBlake::Left(SHAKE256Core), + ); let (peer, peer_hash_choice) = match peer_shake256 { - Ok(peer ) => (peer, EitherShakeOrBlake::Left(SHAKE256Core)), + Ok(peer) => (peer, EitherShakeOrBlake::Left(SHAKE256Core)), Err(_) => { - let peer_blake2b = self.handle_init_hello(&msg_in.payload, &mut msg_out.payload, EitherShakeOrBlake::Right(Blake2bCore)); + let peer_blake2b = self.handle_init_hello( + &msg_in.payload, + &mut msg_out.payload, + EitherShakeOrBlake::Right(Blake2bCore), + ); match peer_blake2b { Ok(peer) => (peer, EitherShakeOrBlake::Right(Blake2bCore)), - Err(_) => bail!("No valid hash function found for InitHello") + Err(_) => bail!("No valid hash function found for InitHello"), } } }; // Now, we make sure that the hash function used by the peer is the same as the one // that is specified in the local configuration. self.verify_hash_choice_match(peer, peer_hash_choice.clone())?; - + ensure!(msg_in.check_seal(self, peer_hash_choice)?, seal_broken); - + len = self.seal_and_commit_msg(peer, MsgType::RespHello, &mut msg_out)?; peer } @@ -2340,8 +2353,11 @@ impl CryptoServer { let mut msg_out = truncating_cast_into::>(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())?, seal_broken); - + ensure!( + msg_in.check_seal(self, peer.get(self).protocol_version.shake_or_blake())?, + seal_broken + ); + len = self.seal_and_commit_msg(peer, MsgType::InitConf, &mut msg_out)?; peer.hs() .store_msg_for_retransmission(self, &msg_out.as_bytes()[..len])?; @@ -2351,7 +2367,6 @@ impl CryptoServer { Ok(MsgType::InitConf) => { let msg_in: Ref<&[u8], Envelope> = Ref::new(rx_buf).ok_or(RosenpassError::BufferSizeMismatch)?; - let mut msg_out = truncating_cast_into::>(tx_buf)?; @@ -2360,7 +2375,13 @@ impl CryptoServer { // Cached response; copy out of cache Some(cached) => { let peer = cached.peer(); - ensure!(msg_in.check_seal(self, peer.get(self).protocol_version.shake_or_blake())?, seal_broken); + ensure!( + msg_in.check_seal( + self, + peer.get(self).protocol_version.shake_or_blake() + )?, + seal_broken + ); let cached = cached .get(self) .map(|v| v.response.borrow()) @@ -2374,14 +2395,22 @@ impl CryptoServer { None => { // At this point, we do not know the hash functon used by the peer, thus we try both, // with a preference for SHAKE256. - let peer_shake256 = self.handle_init_conf(&msg_in.payload, &mut msg_out.payload, EitherShakeOrBlake::Left(SHAKE256Core)); + let peer_shake256 = self.handle_init_conf( + &msg_in.payload, + &mut msg_out.payload, + EitherShakeOrBlake::Left(SHAKE256Core), + ); let (peer, peer_hash_choice) = match peer_shake256 { Ok(peer) => (peer, EitherShakeOrBlake::Left(SHAKE256Core)), Err(_) => { - let peer_blake2b = self.handle_init_conf(&msg_in.payload, &mut msg_out.payload, EitherShakeOrBlake::Right(Blake2bCore)); + let peer_blake2b = self.handle_init_conf( + &msg_in.payload, + &mut msg_out.payload, + EitherShakeOrBlake::Right(Blake2bCore), + ); match peer_blake2b { Ok(peer) => (peer, EitherShakeOrBlake::Right(Blake2bCore)), - Err(_) => bail!("No valid hash function found for InitHello") + Err(_) => bail!("No valid hash function found for InitHello"), } } }; @@ -2389,7 +2418,7 @@ impl CryptoServer { // that is specified in the local configuration. self.verify_hash_choice_match(peer, peer_hash_choice.clone())?; ensure!(msg_in.check_seal(self, peer_hash_choice)?, seal_broken); - + KnownInitConfResponsePtr::insert_for_request_msg( self, peer, @@ -2428,9 +2457,13 @@ impl CryptoServer { resp: if len == 0 { None } else { Some(len) }, }) } - + /// TODO documentation - fn verify_hash_choice_match(&self, peer: PeerPtr, peer_hash_choice: EitherShakeOrBlake) -> Result<()> { + fn verify_hash_choice_match( + &self, + peer: PeerPtr, + peer_hash_choice: EitherShakeOrBlake, + ) -> Result<()> { match peer.get(self).protocol_version.shake_or_blake() { EitherShakeOrBlake::Left(SHAKE256Core) => match peer_hash_choice { EitherShakeOrBlake::Left(SHAKE256Core) => Ok(()), @@ -2439,7 +2472,7 @@ impl CryptoServer { EitherShakeOrBlake::Right(Blake2bCore) => match peer_hash_choice { EitherShakeOrBlake::Left(SHAKE256Core) => bail!("Hash function mismatch"), EitherShakeOrBlake::Right(Blake2bCore) => Ok(()), - } + }, } } @@ -3209,7 +3242,11 @@ where M: AsBytes + FromBytes, { /// Internal business logic: Check the message authentication code produced by [Self::seal] - pub fn check_seal(&self, srv: &CryptoServer, shake_or_blake: EitherShakeOrBlake) -> Result { + pub fn check_seal( + &self, + srv: &CryptoServer, + shake_or_blake: EitherShakeOrBlake, + ) -> Result { let expected = hash_domains::mac(shake_or_blake)? .mix(srv.spkm.deref())? .mix(&self.as_bytes()[span_of!(Self, msg_type..mac)])?; @@ -3257,21 +3294,31 @@ impl HandshakeState { /// Initialize the handshake state with the responder public key and the protocol domain /// separator pub fn init(&mut self, spkr: &[u8]) -> Result<&mut Self> { - self.ck = hash_domains::ckinit(self.ck.shake_or_blake().clone())?.turn_secret().mix(spkr)?.dup(); + self.ck = hash_domains::ckinit(self.ck.shake_or_blake().clone())? + .turn_secret() + .mix(spkr)? + .dup(); Ok(self) } /// Mix some data into the chaining key. This is used for mixing cryptographic keys and public /// data alike into the chaining key pub fn mix(&mut self, a: &[u8]) -> Result<&mut Self> { - self.ck = self.ck.mix(&hash_domains::mix(self.ck.shake_or_blake().clone())?)?.mix(a)?.dup(); + self.ck = self + .ck + .mix(&hash_domains::mix(self.ck.shake_or_blake().clone())?)? + .mix(a)? + .dup(); Ok(self) } /// Encrypt some data with a value derived from the current chaining key and mix that data /// into the protocol state. pub fn encrypt_and_mix(&mut self, ct: &mut [u8], pt: &[u8]) -> Result<&mut Self> { - let k = self.ck.mix(&hash_domains::hs_enc(self.ck.shake_or_blake().clone())?)?.into_secret(); + let k = self + .ck + .mix(&hash_domains::hs_enc(self.ck.shake_or_blake().clone())?)? + .into_secret(); aead::encrypt(ct, k.secret(), &[0u8; aead::NONCE_LEN], &[], pt)?; self.mix(ct) } @@ -3281,7 +3328,10 @@ impl HandshakeState { /// Makes sure that the same values are mixed into the chaining that where mixed in on the /// sender side. pub fn decrypt_and_mix(&mut self, pt: &mut [u8], ct: &[u8]) -> Result<&mut Self> { - let k = self.ck.mix(&hash_domains::hs_enc(self.ck.shake_or_blake().clone())?)?.into_secret(); + let k = self + .ck + .mix(&hash_domains::hs_enc(self.ck.shake_or_blake().clone())?)? + .into_secret(); aead::decrypt(pt, k.secret(), &[0u8; aead::NONCE_LEN], &[], ct)?; self.mix(ct) } @@ -3373,7 +3423,7 @@ impl HandshakeState { biscuit_ct: &[u8], sidi: SessionId, sidr: SessionId, - shake_or_blake: EitherShakeOrBlake + shake_or_blake: EitherShakeOrBlake, ) -> Result<(PeerPtr, BiscuitId, HandshakeState)> { // The first bit of the biscuit indicates which biscuit key was used let bk = BiscuitKeyPtr(((biscuit_ct[0] & 0b1000_0000) >> 7) as usize); @@ -3404,7 +3454,11 @@ impl HandshakeState { .find_peer(pid) // TODO: FindPeer should return a Result<()> .with_context(|| format!("Could not decode biscuit for peer {pid:?}: No such peer."))?; - let ck = SecretHashDomain::danger_from_secret(Secret::from_slice(&biscuit.ck), peer.get(srv).protocol_version.shake_or_blake()).dup(); + let ck = SecretHashDomain::danger_from_secret( + Secret::from_slice(&biscuit.ck), + peer.get(srv).protocol_version.shake_or_blake(), + ) + .dup(); // Reconstruct the handshake state let mut hs = Self { sidi, sidr, ck }; hs.mix(biscuit_ct)?; @@ -3417,10 +3471,19 @@ impl HandshakeState { /// This called by either party. /// /// `role` indicates whether the local peer was an initiator or responder in the handshake. - pub fn enter_live(self, srv: &CryptoServer, role: HandshakeRole, either_shake_or_blake: EitherShakeOrBlake) -> Result { + pub fn enter_live( + self, + srv: &CryptoServer, + role: HandshakeRole, + either_shake_or_blake: EitherShakeOrBlake, + ) -> Result { let HandshakeState { ck, sidi, sidr } = self; - let tki = ck.mix(&hash_domains::ini_enc(either_shake_or_blake.clone())?)?.into_secret(); - let tkr = ck.mix(&hash_domains::res_enc(either_shake_or_blake)?)?.into_secret(); + let tki = ck + .mix(&hash_domains::ini_enc(either_shake_or_blake.clone())?)? + .into_secret(); + let tkr = ck + .mix(&hash_domains::res_enc(either_shake_or_blake)?)? + .into_secret(); let created_at = srv.timebase.now(); let (ntx, nrx) = (0, 0); let (mysid, peersid, ktx, krx) = match role { @@ -3458,7 +3521,12 @@ impl CryptoServer { .get(self) .as_ref() .with_context(|| format!("No current session for peer {:?}", peer))?; - Ok(session.ck.mix(&hash_domains::osk(peer.get(self).protocol_version.shake_or_blake())?)?.into_secret()) + Ok(session + .ck + .mix(&hash_domains::osk( + peer.get(self).protocol_version.shake_or_blake(), + )?)? + .into_secret()) } } @@ -3466,7 +3534,10 @@ impl CryptoServer { /// Core cryptographic protocol implementation: Kicks of the handshake /// on the initiator side, producing the InitHello message. pub fn handle_initiation(&mut self, peer: PeerPtr, ih: &mut InitHello) -> Result { - let mut hs = InitiatorHandshake::zero_with_timestamp(self, peer.get(self).protocol_version.shake_or_blake()); + let mut hs = InitiatorHandshake::zero_with_timestamp( + self, + peer.get(self).protocol_version.shake_or_blake(), + ); // IHI1 hs.core.init(peer.get(self).spkt.deref())?; @@ -3490,8 +3561,11 @@ impl CryptoServer { )?; // IHI6 - hs.core - .encrypt_and_mix(ih.pidic.as_mut_slice(), self.pidm(peer.get(self).protocol_version.shake_or_blake())?.as_ref())?; + hs.core.encrypt_and_mix( + ih.pidic.as_mut_slice(), + self.pidm(peer.get(self).protocol_version.shake_or_blake())? + .as_ref(), + )?; // IHI7 hs.core @@ -3510,7 +3584,12 @@ impl CryptoServer { /// Core cryptographic protocol implementation: Parses an [InitHello] message and produces a /// [RespHello] message on the responder side. /// TODO: Document Hash Functon usage - pub fn handle_init_hello(&mut self, ih: &InitHello, rh: &mut RespHello, shake_or_blake: EitherShakeOrBlake) -> Result { + pub fn handle_init_hello( + &mut self, + ih: &InitHello, + rh: &mut RespHello, + shake_or_blake: EitherShakeOrBlake, + ) -> Result { let mut core = HandshakeState::zero(shake_or_blake); core.sidi = SessionId::from_slice(&ih.sidi); @@ -3655,8 +3734,14 @@ impl CryptoServer { // we still need it for InitConf message retransmission to function. // ICI7 - peer.session() - .insert(self, core.enter_live(self, HandshakeRole::Initiator, peer.get(self).protocol_version.shake_or_blake())?)?; + peer.session().insert( + self, + core.enter_live( + self, + HandshakeRole::Initiator, + peer.get(self).protocol_version.shake_or_blake(), + )?, + )?; hs_mut!().core.erase(); hs_mut!().next = HandshakeStateMachine::RespConf; @@ -3669,7 +3754,12 @@ impl CryptoServer { /// This concludes the handshake on the cryptographic level; the [EmptyData] message is just /// an acknowledgement message telling the initiator to stop performing retransmissions. /// TODO: documentation - pub fn handle_init_conf(&mut self, ic: &InitConf, rc: &mut EmptyData, shake_or_blake: EitherShakeOrBlake) -> Result { + pub fn handle_init_conf( + &mut self, + ic: &InitConf, + rc: &mut EmptyData, + shake_or_blake: EitherShakeOrBlake, + ) -> Result { // (peer, bn) ← LoadBiscuit(InitConf.biscuit) // ICR1 let (peer, biscuit_no, mut core) = HandshakeState::load_biscuit( @@ -3702,8 +3792,14 @@ impl CryptoServer { peer.get_mut(self).biscuit_used = biscuit_no; // ICR7 - peer.session() - .insert(self, core.enter_live(self, HandshakeRole::Responder, peer.get(self).protocol_version.shake_or_blake())?)?; + peer.session().insert( + self, + core.enter_live( + self, + HandshakeRole::Responder, + peer.get(self).protocol_version.shake_or_blake(), + )?, + )?; // TODO: This should be part of the protocol specification. // Abort any ongoing handshake from initiator role peer.hs().take(self); @@ -3751,13 +3847,20 @@ impl CryptoServer { /// message then terminates the handshake. /// /// The EmptyData message is just there to tell the initiator to abort retransmissions. - pub fn handle_resp_conf(&mut self, msg_in: &Ref<&[u8], Envelope>, seal_broken: String) -> Result { + pub fn handle_resp_conf( + &mut self, + msg_in: &Ref<&[u8], Envelope>, + seal_broken: String, + ) -> Result { let rc: &EmptyData = &msg_in.payload; let sid = SessionId::from_slice(&rc.sid); let hs = self .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())?, seal_broken); + ensure!( + msg_in.check_seal(self, hs.peer().get(self).protocol_version.shake_or_blake())?, + seal_broken + ); let ses = hs.peer().session(); let exp = hs.get(self).as_ref().map(|h| h.next); @@ -3840,7 +3943,9 @@ impl CryptoServer { }?; let spkt = peer.get(self).spkt.deref(); - let cookie_key = hash_domains::cookie_key(EitherShakeOrBlake::Left(SHAKE256Core))?.mix(spkt)?.into_value(); + let cookie_key = hash_domains::cookie_key(EitherShakeOrBlake::Left(SHAKE256Core))? + .mix(spkt)? + .into_value(); let cookie_value = peer.cv().update_mut(self).unwrap(); xaead::decrypt(cookie_value, &cookie_key, &mac, &cr.inner.cookie_encrypted)?; @@ -3969,7 +4074,6 @@ mod test { handles_incorrect_size_messages(ProtocolVersion::V03) } - /// Ensure that the protocol implementation can deal with truncated /// messages and with overlong messages. /// @@ -4268,20 +4372,21 @@ 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.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(); assert_eq!( PeerPtr(0).cv().get(&a).map(|x| &x.value.secret()[..]), @@ -4331,7 +4436,9 @@ mod test { cookie_reply_mechanism_initiator_bails_on_message_under_load(ProtocolVersion::V03) } - fn cookie_reply_mechanism_initiator_bails_on_message_under_load(protocol_version: ProtocolVersion) { + fn cookie_reply_mechanism_initiator_bails_on_message_under_load( + protocol_version: ProtocolVersion, + ) { setup_logging(); rosenpass_secret_memory::secret_policy_try_use_memfd_secrets(); stacker::grow(8 * 1024 * 1024, || { @@ -4409,10 +4516,7 @@ mod test { Ok((sk, pk)) } - fn proc_initiation( - srv: &mut CryptoServer, - peer: PeerPtr, - ) -> Result> { + fn proc_initiation(srv: &mut CryptoServer, peer: PeerPtr) -> Result> { let mut buf = MsgBuf::zero(); srv.initiate_handshake(peer, buf.as_mut_slice())? .discard_result(); @@ -4482,8 +4586,12 @@ mod test { assert!(res.is_err()); } - // we this as a closure in orer to use the protocol_version variable in it. - let check_retransmission = |srv: &mut CryptoServer, ic: &Envelope, ic_broken: &Envelope, rc: &Envelope| -> Result<()> { + // we this as a closure in orer to use the protocol_version variable in it. + let check_retransmission = |srv: &mut CryptoServer, + ic: &Envelope, + ic_broken: &Envelope, + rc: &Envelope| + -> Result<()> { // Processing the same RespHello package again leads to retransmission (i.e. exactly the // same output) let rc_dup = proc_init_conf(srv, ic)?; @@ -4492,7 +4600,11 @@ mod test { // Though if we directly call handle_resp_hello() we get an error since // retransmission is not being handled by the cryptographic code let mut discard_resp_conf = EmptyData::new_zeroed(); - let res = srv.handle_init_conf(&ic.payload, &mut discard_resp_conf, protocol_version.clone().shake_or_blake()); + let res = srv.handle_init_conf( + &ic.payload, + &mut discard_resp_conf, + protocol_version.clone().shake_or_blake(), + ); assert!(res.is_err()); // Obviously, a broken InitConf message should still be rejected diff --git a/rosenpass/tests/api-integration-tests-api-setup.rs b/rosenpass/tests/api-integration-tests-api-setup.rs index e70e77a..c4f2d22 100644 --- a/rosenpass/tests/api-integration-tests-api-setup.rs +++ b/rosenpass/tests/api-integration-tests-api-setup.rs @@ -14,6 +14,8 @@ use rosenpass::api::{ self, add_listen_socket_response_status, add_psk_broker_response_status, supply_keypair_response_status, }; +use rosenpass::config::ProtocolVersion; +use rosenpass::protocol::SymKey; use rosenpass_util::{ b64::B64Display, file::LoadValueB64, @@ -26,8 +28,6 @@ use rosenpass_util::{ use std::os::fd::{AsFd, AsRawFd}; use tempfile::TempDir; use zerocopy::AsBytes; -use rosenpass::config::ProtocolVersion; -use rosenpass::protocol::SymKey; struct KillChild(std::process::Child); diff --git a/rosenpass/tests/api-integration-tests.rs b/rosenpass/tests/api-integration-tests.rs index 99761e2..de02832 100644 --- a/rosenpass/tests/api-integration-tests.rs +++ b/rosenpass/tests/api-integration-tests.rs @@ -16,8 +16,8 @@ use rosenpass_util::{mem::DiscardResultExt, zerocopy::ZerocopySliceExt}; use tempfile::TempDir; use zerocopy::AsBytes; -use rosenpass::protocol::SymKey; use rosenpass::config::ProtocolVersion; +use rosenpass::protocol::SymKey; struct KillChild(std::process::Child); @@ -46,7 +46,6 @@ fn api_integration_test_v03() -> anyhow::Result<()> { api_integration_test(ProtocolVersion::V03) } - fn api_integration_test(protocol_version: ProtocolVersion) -> anyhow::Result<()> { rosenpass_secret_memory::policy::secret_policy_use_only_malloc_secrets(); diff --git a/rosenpass/tests/app_server_example.rs b/rosenpass/tests/app_server_example.rs index 294898f..31fc78e 100644 --- a/rosenpass/tests/app_server_example.rs +++ b/rosenpass/tests/app_server_example.rs @@ -9,11 +9,11 @@ use std::{ }; use anyhow::ensure; +use rosenpass::config::ProtocolVersion; use rosenpass::{ app_server::{ipv4_any_binding, ipv6_any_binding, AppServer, AppServerTest, MAX_B64_KEY_SIZE}, protocol::{SPk, SSk, SymKey}, }; -use rosenpass::config::ProtocolVersion; use rosenpass_cipher_traits::Kem; use rosenpass_ciphers::kem::StaticKem; use rosenpass_secret_memory::Secret; @@ -66,8 +66,14 @@ fn key_exchange_with_app_server(protocol_version: ProtocolVersion) -> anyhow::Re let outfile = Some(osk); let port = otr_port; let hostname = is_client.then(|| format!("[::1]:{port}")); - srv.app_srv - .add_peer(psk, pk, outfile, broker_peer, hostname, protocol_version.clone())?; + srv.app_srv.add_peer( + psk, + pk, + outfile, + broker_peer, + hostname, + protocol_version.clone(), + )?; srv.app_srv.event_loop() }) diff --git a/rosenpass/tests/poll_example.rs b/rosenpass/tests/poll_example.rs index a7d7eb2..f594c4c 100644 --- a/rosenpass/tests/poll_example.rs +++ b/rosenpass/tests/poll_example.rs @@ -9,7 +9,10 @@ use rosenpass_cipher_traits::Kem; use rosenpass_ciphers::kem::StaticKem; use rosenpass_util::result::OkExt; -use rosenpass::protocol::{testutils::time_travel_forward, CryptoServer, HostIdentification, MsgBuf, PeerPtr, PollResult, ProtocolVersion, SPk, SSk, SymKey, Timing, UNENDING}; +use rosenpass::protocol::{ + testutils::time_travel_forward, CryptoServer, HostIdentification, MsgBuf, PeerPtr, PollResult, + ProtocolVersion, SPk, SSk, SymKey, Timing, UNENDING, +}; // TODO: Most of the utility functions in here should probably be moved to // rosenpass::protocol::testutils; @@ -94,7 +97,9 @@ fn test_successful_exchange_under_packet_loss_v03() -> anyhow::Result<()> { test_successful_exchange_under_packet_loss(ProtocolVersion::V03) } -fn test_successful_exchange_under_packet_loss(protocol_version: ProtocolVersion) -> anyhow::Result<()> { +fn test_successful_exchange_under_packet_loss( + protocol_version: ProtocolVersion, +) -> anyhow::Result<()> { // Set security policy for storing secrets; choose the one that is faster for testing rosenpass_secret_memory::policy::secret_policy_use_only_malloc_secrets();