From 5ced547a075188de5d53fe4b5b0b3260cd3d8bc8 Mon Sep 17 00:00:00 2001 From: Karolin Varner Date: Sun, 1 Jun 2025 20:52:21 +0200 Subject: [PATCH] chore: PeerIndex split from protocol.rs --- rosenpass/src/protocol/constants.rs | 2 +- rosenpass/src/protocol/index.rs | 45 ++++++++++++++++++ rosenpass/src/protocol/mod.rs | 1 + rosenpass/src/protocol/protocol.rs | 72 +++++++++-------------------- 4 files changed, 70 insertions(+), 50 deletions(-) create mode 100644 rosenpass/src/protocol/index.rs diff --git a/rosenpass/src/protocol/constants.rs b/rosenpass/src/protocol/constants.rs index c497e0e..8478cdd 100644 --- a/rosenpass/src/protocol/constants.rs +++ b/rosenpass/src/protocol/constants.rs @@ -20,9 +20,9 @@ pub const REKEY_AFTER_TIME_INITIATOR: Timing = 130.0; /// Time after which either party rejects the current key. /// /// At this point a new key should have been negotiated. +/// /// Rejection happens 50-60 seconds after key renegotiation /// to allow for a graceful handover. -/// /// From the wireguard paper: rekey every two minutes, /// discard the key if no rekey is achieved within three pub const REJECT_AFTER_TIME: Timing = 180.0; diff --git a/rosenpass/src/protocol/index.rs b/rosenpass/src/protocol/index.rs new file mode 100644 index 0000000..9f3556b --- /dev/null +++ b/rosenpass/src/protocol/index.rs @@ -0,0 +1,45 @@ +//! Quick lookup of values in [super::CryptoServer] + +use std::collections::HashMap; + +use super::basic_types::{PeerId, PeerNo, SessionId}; +use super::KnownResponseHash; + +/// Maps various keys to peer (numbers). +/// +/// See: +/// - [super::CryptoServer::index] +/// - [super::CryptoServer::peers] +/// - [PeerNo] +/// - [super::PeerPtr] +/// - [super::Peer] +pub type PeerIndex = HashMap; + +/// We maintain various indices in [super::CryptoServer::index], mapping some key to a particular +/// [PeerNo], i.e. to an index in [super::CryptoServer::peers]. These are the possible index key. +#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug)] +pub enum PeerIndexKey { + /// Lookup of a particular peer given the [PeerId], i.e. a value derived from the peers public + /// key as created by [super::CryptoServer::pidm] or [super::Peer::pidt]. + /// + /// The peer id is used by the initiator to tell the responder about its identity in + /// [crate::msgs::InitHello]. + /// + /// See also the pointer types [super::PeerPtr]. + Peer(PeerId), + /// Lookup of a particular session id. + /// + /// This is used to look up both established sessions (see + /// [super::CryptoServer::lookup_session]) and ongoing handshakes (see [super::CryptoServer::lookup_handshake]). + /// + /// Lookup of a peer to get an established session or a handshake is sufficient, because a peer + /// contains a limited number of sessions and handshakes ([super::Peer::session] and [super::Peer::handshake] respectively). + /// + /// See also the pointer types [super::IniHsPtr] and [super::SessionPtr]. + Sid(SessionId), + /// Lookup of a cached response ([crate::msgs::Envelope]<[crate::msgs::EmptyData]>) to an [crate::msgs::InitConf] (i.e. + /// [crate::msgs::Envelope]<[crate::msgs::InitConf]>) message. + /// + /// See [super::KnownInitConfResponsePtr] on how this value is maintained. + KnownInitConfResponse(KnownResponseHash), +} diff --git a/rosenpass/src/protocol/mod.rs b/rosenpass/src/protocol/mod.rs index f7865f1..cb14c3b 100644 --- a/rosenpass/src/protocol/mod.rs +++ b/rosenpass/src/protocol/mod.rs @@ -80,6 +80,7 @@ pub use build_crypto_server::*; pub mod basic_types; pub mod constants; pub mod cookies; +pub mod index; pub mod testutils; pub mod timing; pub mod zerocopy; diff --git a/rosenpass/src/protocol/protocol.rs b/rosenpass/src/protocol/protocol.rs index 2155b31..8300be6 100644 --- a/rosenpass/src/protocol/protocol.rs +++ b/rosenpass/src/protocol/protocol.rs @@ -41,6 +41,7 @@ use super::constants::{ REKEY_AFTER_TIME_RESPONDER, RETRANSMIT_DELAY_BEGIN, RETRANSMIT_DELAY_END, RETRANSMIT_DELAY_GROWTH, RETRANSMIT_DELAY_JITTER, }; +use super::index::{PeerIndex, PeerIndexKey}; use super::timing::{has_happened, Timing, BCE, UNENDING}; use super::zerocopy::{truncating_cast_into, truncating_cast_into_nomut}; use super::{ @@ -105,12 +106,12 @@ pub struct CryptoServer { /// List of peers and their session and handshake states pub peers: Vec, - /// Index into the list of peers. See [IndexKey] for details. - pub index: HashMap, + /// Index into the list of peers. See [PeerIndexKey] for details. + pub index: PeerIndex, /// Hash key for known responder confirmation responses. /// /// These hashes are then used for lookups in [Self::index] using - /// the [IndexKey::KnownInitConfResponse] enum case. + /// the [PeerIndexKey::KnownInitConfResponse] enum case. /// /// This is used to allow for retransmission of responder confirmation (i.e. /// [Envelope]<[EmptyData]>) messages in response to [Envelope]<[InitConf]> @@ -139,35 +140,6 @@ pub struct CryptoServer { pub cookie_secrets: [CookieSecret; 2], } -/// We maintain various indices in [CryptoServer::index], mapping some key to a particular -/// [PeerNo], i.e. to an index in [CryptoServer::peers]. These are the possible index key. -#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug)] -pub enum IndexKey { - /// Lookup of a particular peer given the [PeerId], i.e. a value derived from the peers public - /// key as created by [CryptoServer::pidm] or [Peer::pidt]. - /// - /// The peer id is used by the initiator to tell the responder about its identity in - /// [crate::msgs::InitHello]. - /// - /// See also the pointer types [PeerPtr]. - Peer(PeerId), - /// Lookup of a particular session id. - /// - /// This is used to look up both established sessions (see - /// [CryptoServer::lookup_session]) and ongoing handshakes (see [CryptoServer::lookup_handshake]). - /// - /// Lookup of a peer to get an established session or a handshake is sufficient, because a peer - /// contains a limited number of sessions and handshakes ([Peer::session] and [Peer::handshake] respectively). - /// - /// See also the pointer types [IniHsPtr] and [SessionPtr]. - Sid(SessionId), - /// Lookup of a cached response ([Envelope]<[EmptyData]>) to an [InitConf] (i.e. - /// [Envelope]<[InitConf]>) message. - /// - /// See [KnownInitConfResponsePtr] on how this value is maintained. - KnownInitConfResponse(KnownResponseHash), -} - /// Specifies the protocol version used by a peer. #[derive(Debug, Clone)] pub enum ProtocolVersion { @@ -199,7 +171,7 @@ impl From for ProtocolVersion { /// Peers generally live in [CryptoServer::peers]. [PeerNo] captures an array /// into this field and [PeerPtr] is a wrapper around a [PeerNo] imbued with /// peer specific functionality. [CryptoServer::index] contains a list of lookup-keys -/// for retrieving peers using various keys (see [IndexKey]). +/// for retrieving peers using various keys (see [PeerIndexKey]). /// /// # Examples /// @@ -257,7 +229,7 @@ pub struct Peer { pub biscuit_used: BiscuitId, /// The last established session /// - /// This is indexed though [IndexKey::Sid]. + /// This is indexed though [PeerIndexKey::Sid]. pub session: Option, /// Ongoing handshake, in initiator mode. /// @@ -265,7 +237,7 @@ pub struct Peer { /// because the state is stored inside a [Biscuit] to make sure the responder /// is stateless. /// - /// This is indexed though [IndexKey::Sid]. + /// This is indexed though [PeerIndexKey::Sid]. pub handshake: Option, /// Used to make sure that the same [PollResult::SendInitiation] event is never issued twice. /// @@ -277,7 +249,7 @@ pub struct Peer { /// [Envelope]<[EmptyData]>. /// /// Upon reception of an InitConf message, [CryptoServer::handle_msg] first checks - /// if a cached response exists through [IndexKey::KnownInitConfResponse]. If one exists, + /// if a cached response exists through [PeerIndexKey::KnownInitConfResponse]. If one exists, /// then this field must be set to [Option::Some] and the cached response is returned. /// /// This allows us to perform retransmission for the purpose of dealing with packet loss @@ -472,14 +444,14 @@ fn known_response_format() { pub type KnownInitConfResponse = KnownResponse; /// The type used to represent the hash of a known response -/// in the context of [KnownResponse]/[IndexKey::KnownInitConfResponse] +/// in the context of [KnownResponse]/[PeerIndexKey::KnownInitConfResponse] pub type KnownResponseHash = Public<16>; /// Object that produces [KnownResponseHash]. /// /// Merely a key plus some utility functions. /// -/// See [IndexKey::KnownInitConfResponse] and [KnownResponse::request_mac] +/// See [PeerIndexKey::KnownInitConfResponse] and [KnownResponse::request_mac] /// /// # Examples /// @@ -1051,7 +1023,7 @@ impl KnownInitConfResponsePtr { pub fn remove(&self, srv: &mut CryptoServer) -> Option { let peer = self.peer(); let val = peer.get_mut(srv).known_init_conf_response.take()?; - let lookup_key = IndexKey::KnownInitConfResponse(val.request_mac); + let lookup_key = PeerIndexKey::KnownInitConfResponse(val.request_mac); srv.index.remove(&lookup_key).unwrap(); Some(val) } @@ -1070,7 +1042,7 @@ impl KnownInitConfResponsePtr { pub fn insert(&self, srv: &mut CryptoServer, known_response: KnownInitConfResponse) { self.remove(srv).discard_result(); - let index_key = IndexKey::KnownInitConfResponse(known_response.request_mac); + let index_key = PeerIndexKey::KnownInitConfResponse(known_response.request_mac); self.peer().get_mut(srv).known_init_conf_response = Some(known_response); // There is a question here whether we should just discard the result…or panic if the @@ -1171,9 +1143,9 @@ impl KnownInitConfResponsePtr { /// Calculate an appropriate index key for `req` /// - /// Merely forwards [Self::index_key_for_msg] and wraps the result in [IndexKey::KnownInitConfResponse] - pub fn index_key_for_msg(srv: &CryptoServer, req: &Envelope) -> IndexKey { - Self::index_key_hash_for_msg(srv, req).apply(IndexKey::KnownInitConfResponse) + /// Merely forwards [Self::index_key_for_msg] and wraps the result in [PeerIndexKey::KnownInitConfResponse] + pub fn index_key_for_msg(srv: &CryptoServer, req: &Envelope) -> PeerIndexKey { + Self::index_key_hash_for_msg(srv, req).apply(PeerIndexKey::KnownInitConfResponse) } } @@ -1291,7 +1263,7 @@ impl CryptoServer { }; let peerid = peer.pidt()?; let peerno = self.peers.len(); - match self.index.entry(IndexKey::Peer(peerid)) { + match self.index.entry(PeerIndexKey::Peer(peerid)) { Occupied(_) => bail!( "Cannot insert peer with id {:?}; peer with this id already registered.", peerid @@ -1315,7 +1287,7 @@ impl CryptoServer { /// To rgister a session, you should generally use [SessionPtr::insert] or [IniHsPtr::insert] /// instead of this, more lower level function. pub fn register_session(&mut self, id: SessionId, peer: PeerPtr) -> Result<()> { - match self.index.entry(IndexKey::Sid(id)) { + match self.index.entry(PeerIndexKey::Sid(id)) { Occupied(p) if PeerPtr(*p.get()) == peer => {} // Already registered Occupied(_) => bail!("Cannot insert session with id {:?}; id is in use.", id), Vacant(e) => { @@ -1334,7 +1306,7 @@ impl CryptoServer { /// To unregister a session, you should generally use [SessionPtr::take] or [IniHsPtr::take] /// instead of this, more lower level function. pub fn unregister_session(&mut self, id: SessionId) { - self.index.remove(&IndexKey::Sid(id)); + self.index.remove(&PeerIndexKey::Sid(id)); } /// Unregister a session previously registered using [Self::register_session], @@ -1363,7 +1335,9 @@ impl CryptoServer { /// This function is used in cryptographic message processing /// [CryptoServer::handle_init_hello], and [HandshakeState::load_biscuit] pub fn find_peer(&self, id: PeerId) -> Option { - self.index.get(&IndexKey::Peer(id)).map(|no| PeerPtr(*no)) + self.index + .get(&PeerIndexKey::Peer(id)) + .map(|no| PeerPtr(*no)) } /// Look up a handshake given its session id [HandshakeState::sidi] @@ -1371,7 +1345,7 @@ impl CryptoServer { /// This is called `lookup_session` in [whitepaper](https://rosenpass.eu/whitepaper.pdf). pub fn lookup_handshake(&self, id: SessionId) -> Option { self.index - .get(&IndexKey::Sid(id)) // lookup the session in the index + .get(&PeerIndexKey::Sid(id)) // lookup the session in the index .map(|no| IniHsPtr(*no)) // convert to peer pointer .filter(|hsptr| { hsptr @@ -1387,7 +1361,7 @@ impl CryptoServer { /// This is called `lookup_session` in [whitepaper](https://rosenpass.eu/whitepaper.pdf). pub fn lookup_session(&self, id: SessionId) -> Option { self.index - .get(&IndexKey::Sid(id)) + .get(&PeerIndexKey::Sid(id)) .map(|no| SessionPtr(*no)) .filter(|sptr| { sptr.get(self)