Prep for new controller, also reorg header fields in Noise session and move some functions around.

This commit is contained in:
Adam Ierymenko 2022-08-19 11:31:09 -04:00
parent f153d43797
commit a723403fe9
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
5 changed files with 384 additions and 414 deletions

View file

@ -57,6 +57,9 @@ ignored when analyzing the "real" security of the protocol.
/// Minimum packet size / minimum size for work buffers. /// Minimum packet size / minimum size for work buffers.
pub const MIN_BUFFER_SIZE: usize = 1400; pub const MIN_BUFFER_SIZE: usize = 1400;
/// Minimum possible packet size.
pub const MIN_PACKET_SIZE: usize = HEADER_SIZE + 1 + AES_GCM_TAG_SIZE;
/// Start attempting to rekey after a key has been used to send packets this many times. /// Start attempting to rekey after a key has been used to send packets this many times.
const REKEY_AFTER_USES: u64 = 536870912; const REKEY_AFTER_USES: u64 = 536870912;
@ -86,9 +89,7 @@ const E1_TYPE_NONE: u8 = 0;
/// Secondary (hybrid) ephemeral key is Kyber512 /// Secondary (hybrid) ephemeral key is Kyber512
const E1_TYPE_KYBER512: u8 = 1; const E1_TYPE_KYBER512: u8 = 1;
/// Header size; header is: [4] counter | [6] destination session ID | [1] type
const HEADER_SIZE: usize = 11; const HEADER_SIZE: usize = 11;
const AES_GCM_TAG_SIZE: usize = 16; const AES_GCM_TAG_SIZE: usize = 16;
const HMAC_SIZE: usize = 48; // HMAC-SHA384 const HMAC_SIZE: usize = 48; // HMAC-SHA384
const SESSION_ID_SIZE: usize = 6; const SESSION_ID_SIZE: usize = 6;
@ -128,6 +129,9 @@ pub enum Error {
/// Attempt to send using session without established key. /// Attempt to send using session without established key.
SessionNotEstablished, SessionNotEstablished,
/// Packet ignored by rate limiter.
RateLimited,
} }
impl std::fmt::Display for Error { impl std::fmt::Display for Error {
@ -140,6 +144,7 @@ impl std::fmt::Display for Error {
Self::NewSessionRejected => f.write_str("NewSessionRejected"), Self::NewSessionRejected => f.write_str("NewSessionRejected"),
Self::MaxKeyLifetimeExceeded => f.write_str("MaxKeyLifetimeExceeded"), Self::MaxKeyLifetimeExceeded => f.write_str("MaxKeyLifetimeExceeded"),
Self::SessionNotEstablished => f.write_str("SessionNotEstablished"), Self::SessionNotEstablished => f.write_str("SessionNotEstablished"),
Self::RateLimited => f.write_str("RateLimited"),
} }
} }
} }
@ -242,21 +247,61 @@ pub struct Session<O> {
psk: Secret<64>, psk: Secret<64>,
ss: Secret<48>, ss: Secret<48>,
outgoing_obfuscator: Obfuscator, outgoing_obfuscator: Obfuscator,
state: RwLock<State>, state: RwLock<MutableState>,
remote_s_public_p384: [u8; P384_PUBLIC_KEY_SIZE], remote_s_public_p384: [u8; P384_PUBLIC_KEY_SIZE],
/// Arbitrary object associated with this session /// Arbitrary object associated with this session
pub associated_object: O, pub associated_object: O,
} }
/// Mutable inner state of Session (except counter, which is atomic to avoid locks on packet sends) struct MutableState {
struct State {
remote_session_id: Option<SessionId>, remote_session_id: Option<SessionId>,
keys: [Option<SessionKey>; 2], // current, next keys: [Option<SessionKey>; 2], // current, next
offer: Option<EphemeralOffer>, offer: Option<EphemeralOffer>,
} }
impl<O> Session<O> { impl<O> Session<O> {
/// Create a new session and return this plus an outgoing packet to send to the other end.
pub fn new<'a, const MAX_PACKET_SIZE: usize, const STATIC_PUBLIC_SIZE: usize>(
buffer: &'a mut [u8; MAX_PACKET_SIZE],
local_session_id: SessionId,
local_s_public: &[u8; STATIC_PUBLIC_SIZE],
local_s_keypair_p384: &P384KeyPair,
remote_s_public: &[u8; STATIC_PUBLIC_SIZE],
remote_s_public_p384: &P384PublicKey,
psk: &Secret<64>,
associated_object: O,
current_time: i64,
jedi: bool,
) -> Result<(Self, &'a [u8]), Error> {
debug_assert!(MAX_PACKET_SIZE >= MIN_BUFFER_SIZE);
let counter = Counter::new();
if let Some(ss) = local_s_keypair_p384.agree(remote_s_public_p384) {
let outgoing_obfuscator = Obfuscator::new(remote_s_public);
if let Some((offer, psize)) = EphemeralOffer::create_alice_offer(buffer, counter.next(), local_session_id, None, local_s_public, remote_s_public_p384, &ss, &outgoing_obfuscator, current_time, jedi) {
return Ok((
Session::<O> {
id: local_session_id,
send_counter: counter,
remote_s_public_hash: SHA384::hash(remote_s_public),
psk: psk.clone(),
ss,
outgoing_obfuscator,
state: RwLock::new(MutableState {
remote_session_id: None,
keys: [None, None],
offer: Some(offer),
}),
remote_s_public_p384: remote_s_public_p384.as_bytes().clone(),
associated_object,
},
&buffer[..psize],
));
}
}
return Err(Error::InvalidParameter);
}
/// Check whether this session should initiate a re-key, returning a packet to send if true. /// Check whether this session should initiate a re-key, returning a packet to send if true.
/// ///
/// This must be checked often enough to ensure that the hard key usage limit is not reached, which in the /// This must be checked often enough to ensure that the hard key usage limit is not reached, which in the
@ -304,62 +349,19 @@ impl<O> Session<O> {
Err(Error::SessionNotEstablished) Err(Error::SessionNotEstablished)
} }
} }
}
/// Create a new session and return this plus an outgoing packet to send to the other end. /// Receive a packet from the network and take the appropriate action.
pub fn new_session<'a, O, const MAX_PACKET_SIZE: usize, const STATIC_PUBLIC_SIZE: usize>( ///
buffer: &'a mut [u8; MAX_PACKET_SIZE], /// Check ReceiveResult to see if it includes data or a reply packet.
local_session_id: SessionId, pub fn receive<
local_s_public: &[u8; STATIC_PUBLIC_SIZE],
local_s_keypair_p384: &P384KeyPair,
remote_s_public: &[u8; STATIC_PUBLIC_SIZE],
remote_s_public_p384: &P384PublicKey,
psk: &Secret<64>,
associated_object: O,
current_time: i64,
jedi: bool,
) -> Result<(Session<O>, &'a [u8]), Error> {
debug_assert!(MAX_PACKET_SIZE >= MIN_BUFFER_SIZE);
let counter = Counter::new();
if let Some(ss) = local_s_keypair_p384.agree(remote_s_public_p384) {
let outgoing_obfuscator = Obfuscator::new(remote_s_public);
if let Some((offer, psize)) = EphemeralOffer::create_alice_offer(buffer, counter.next(), local_session_id, None, local_s_public, remote_s_public_p384, &ss, &outgoing_obfuscator, current_time, jedi) {
return Ok((
Session::<O> {
id: local_session_id,
send_counter: counter,
remote_s_public_hash: SHA384::hash(remote_s_public),
psk: psk.clone(),
ss,
outgoing_obfuscator,
state: RwLock::new(State {
remote_session_id: None,
keys: [None, None],
offer: Some(offer),
}),
remote_s_public_p384: remote_s_public_p384.as_bytes().clone(),
associated_object,
},
&buffer[..psize],
));
}
}
return Err(Error::InvalidParameter);
}
/// Receive a packet from the network and take the appropriate action.
///
/// Check ReceiveResult to see if it includes data or a reply packet.
pub fn receive<
'a, 'a,
ExtractP384PublicKeyFunction: FnOnce(&[u8; STATIC_PUBLIC_SIZE]) -> Option<P384PublicKey>, ExtractP384PublicKeyFunction: FnOnce(&[u8; STATIC_PUBLIC_SIZE]) -> Option<P384PublicKey>,
SessionLookupFunction: FnOnce(SessionId) -> Option<S>, SessionLookupFunction: FnOnce(SessionId) -> Option<S>,
NewSessionAuthenticatorFunction: FnOnce(&[u8; STATIC_PUBLIC_SIZE]) -> Option<(SessionId, Secret<64>, O)>, NewSessionAuthenticatorFunction: FnOnce(&[u8; STATIC_PUBLIC_SIZE]) -> Option<(SessionId, Secret<64>, O)>,
S: std::ops::Deref<Target = Session<O>>, S: std::ops::Deref<Target = Session<O>>,
O,
const MAX_PACKET_SIZE: usize, const MAX_PACKET_SIZE: usize,
const STATIC_PUBLIC_SIZE: usize, const STATIC_PUBLIC_SIZE: usize,
>( >(
incoming_packet: &[u8], incoming_packet: &[u8],
buffer: &'a mut [u8; MAX_PACKET_SIZE], buffer: &'a mut [u8; MAX_PACKET_SIZE],
local_s_keypair_p384: &P384KeyPair, local_s_keypair_p384: &P384KeyPair,
@ -369,16 +371,16 @@ pub fn receive<
new_session_auth: NewSessionAuthenticatorFunction, new_session_auth: NewSessionAuthenticatorFunction,
current_time: i64, current_time: i64,
jedi: bool, jedi: bool,
) -> Result<ReceiveResult<'a, O>, Error> { ) -> Result<ReceiveResult<'a, O>, Error> {
debug_assert!(MAX_PACKET_SIZE >= MIN_BUFFER_SIZE); debug_assert!(MAX_PACKET_SIZE >= MIN_BUFFER_SIZE);
if incoming_packet.len() > MAX_PACKET_SIZE || incoming_packet.len() <= 16 { if incoming_packet.len() > MAX_PACKET_SIZE || incoming_packet.len() <= MIN_PACKET_SIZE {
unlikely_branch(); unlikely_branch();
return Err(Error::InvalidPacket); return Err(Error::InvalidPacket);
} }
incoming_obfuscator.0.decrypt_block(&incoming_packet[0..16], &mut buffer[0..16]); incoming_obfuscator.0.decrypt_block(&incoming_packet[..16], &mut buffer[..16]);
let local_session_id = SessionId::new_from_bytes(&buffer[4..10]); let packet_type = buffer[0];
let packet_type = buffer[10]; let local_session_id = SessionId::new_from_bytes(&buffer[1..7]);
debug_assert_eq!(PACKET_TYPE_DATA, 0); debug_assert_eq!(PACKET_TYPE_DATA, 0);
debug_assert_eq!(PACKET_TYPE_NOP, 1); debug_assert_eq!(PACKET_TYPE_NOP, 1);
@ -407,7 +409,7 @@ pub fn receive<
} }
if packet_type == PACKET_TYPE_DATA { if packet_type == PACKET_TYPE_DATA {
return Ok(ReceiveResult::OkData(&buffer[HEADER_SIZE..data_len], u32::from_le_bytes(nonce[..4].try_into().unwrap()))); return Ok(ReceiveResult::OkData(&buffer[HEADER_SIZE..data_len], u32::from_le_bytes(nonce[7..11].try_into().unwrap())));
} else { } else {
return Ok(ReceiveResult::Ok); return Ok(ReceiveResult::Ok);
} }
@ -451,6 +453,15 @@ pub fn receive<
PACKET_TYPE_KEY_OFFER => { PACKET_TYPE_KEY_OFFER => {
// alice (remote) -> bob (local) // alice (remote) -> bob (local)
// Check rate limit if this session is known.
if let Some(session) = session.as_ref() {
if let Some(offer) = session.state.read().offer.as_ref() {
if (current_time - offer.creation_time) < OFFER_RATE_LIMIT_MS {
return Err(Error::RateLimited);
}
}
}
let (alice_e0_public, e0s) = P384PublicKey::from_bytes(&buffer[HEADER_SIZE..HEADER_SIZE + P384_PUBLIC_KEY_SIZE]) let (alice_e0_public, e0s) = P384PublicKey::from_bytes(&buffer[HEADER_SIZE..HEADER_SIZE + P384_PUBLIC_KEY_SIZE])
.and_then(|pk| local_s_keypair_p384.agree(&pk).map(move |s| (pk, s))) .and_then(|pk| local_s_keypair_p384.agree(&pk).map(move |s| (pk, s)))
.ok_or(Error::FailedAuthentication)?; .ok_or(Error::FailedAuthentication)?;
@ -468,8 +479,8 @@ pub fn receive<
let (alice_session_id, alice_s_public, alice_e1_public) = parse_KEY_OFFER_after_header(&buffer[(HEADER_SIZE + P384_PUBLIC_KEY_SIZE)..payload_end])?; let (alice_session_id, alice_s_public, alice_e1_public) = parse_KEY_OFFER_after_header(&buffer[(HEADER_SIZE + P384_PUBLIC_KEY_SIZE)..payload_end])?;
// Important! Check to make sure the caller's public identity matches the one for this session.
if let Some(session) = session.as_ref() { if let Some(session) = session.as_ref() {
// If we already have a session for this session ID, make sure this is the same node calling.
if !session.remote_s_public_hash.eq(&SHA384::hash(&alice_s_public)) { if !session.remote_s_public_hash.eq(&SHA384::hash(&alice_s_public)) {
return Err(Error::FailedAuthentication); return Err(Error::FailedAuthentication);
} }
@ -501,7 +512,7 @@ pub fn receive<
psk, psk,
ss, ss,
outgoing_obfuscator: Obfuscator::new(&alice_s_public), outgoing_obfuscator: Obfuscator::new(&alice_s_public),
state: RwLock::new(State { state: RwLock::new(MutableState {
remote_session_id: Some(alice_session_id), remote_session_id: Some(alice_session_id),
keys: [None, None], keys: [None, None],
offer: None, offer: None,
@ -652,6 +663,7 @@ pub fn receive<
_ => return Err(Error::InvalidPacket), _ => return Err(Error::InvalidPacket),
} }
} }
}
} }
#[repr(transparent)] #[repr(transparent)]
@ -845,10 +857,10 @@ impl SessionKey {
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn assemble_and_armor_DATA<const MAX_PACKET_SIZE: usize>(buffer: &mut [u8; MAX_PACKET_SIZE], data: &[u8], packet_type: u8, remote_session_id: u64, counter: CounterValue, key: &SessionKey, outgoing_obfuscator: &Obfuscator) -> Result<usize, Error> { fn assemble_and_armor_DATA<const MAX_PACKET_SIZE: usize>(buffer: &mut [u8; MAX_PACKET_SIZE], data: &[u8], packet_type: u8, remote_session_id: u64, counter: CounterValue, key: &SessionKey, outgoing_obfuscator: &Obfuscator) -> Result<usize, Error> {
buffer[0..4].copy_from_slice(&counter.to_bytes());
buffer[4..10].copy_from_slice(&remote_session_id.to_le_bytes()[..SESSION_ID_SIZE]);
debug_assert!(packet_type == PACKET_TYPE_DATA || packet_type == PACKET_TYPE_NOP); debug_assert!(packet_type == PACKET_TYPE_DATA || packet_type == PACKET_TYPE_NOP);
buffer[10] = packet_type; buffer[0] = packet_type;
buffer[1..7].copy_from_slice(&remote_session_id.to_le_bytes()[..SESSION_ID_SIZE]);
buffer[7..11].copy_from_slice(&counter.to_bytes());
let payload_end = HEADER_SIZE + data.len(); let payload_end = HEADER_SIZE + data.len();
let tag_end = payload_end + AES_GCM_TAG_SIZE; let tag_end = payload_end + AES_GCM_TAG_SIZE;
@ -889,9 +901,9 @@ fn assemble_KEY_OFFER<const MAX_PACKET_SIZE: usize, const STATIC_PUBLIC_SIZE: us
alice_s_public: &[u8; STATIC_PUBLIC_SIZE], alice_s_public: &[u8; STATIC_PUBLIC_SIZE],
alice_e1_public: Option<&[u8; pqc_kyber::KYBER_PUBLICKEYBYTES]>, alice_e1_public: Option<&[u8; pqc_kyber::KYBER_PUBLICKEYBYTES]>,
) -> usize { ) -> usize {
buffer[0..4].copy_from_slice(&counter.to_bytes()); buffer[0] = PACKET_TYPE_KEY_OFFER;
buffer[4..10].copy_from_slice(&bob_session_id.map_or(0_u64, |i| i.into()).to_le_bytes()[..SESSION_ID_SIZE]); buffer[1..7].copy_from_slice(&bob_session_id.map_or(0_u64, |i| i.into()).to_le_bytes()[..SESSION_ID_SIZE]);
buffer[10] = PACKET_TYPE_KEY_OFFER; buffer[7..11].copy_from_slice(&counter.to_bytes());
let mut b = &mut buffer[HEADER_SIZE..]; let mut b = &mut buffer[HEADER_SIZE..];
b[..P384_PUBLIC_KEY_SIZE].copy_from_slice(alice_e0_public.as_bytes()); b[..P384_PUBLIC_KEY_SIZE].copy_from_slice(alice_e0_public.as_bytes());
@ -961,9 +973,9 @@ fn assemble_KEY_COUNTER_OFFER<const MAX_PACKET_SIZE: usize>(
bob_session_id: SessionId, bob_session_id: SessionId,
bob_e1_public: Option<&[u8; pqc_kyber::KYBER_CIPHERTEXTBYTES]>, bob_e1_public: Option<&[u8; pqc_kyber::KYBER_CIPHERTEXTBYTES]>,
) -> usize { ) -> usize {
buffer[0..4].copy_from_slice(&counter.to_bytes()); buffer[0] = PACKET_TYPE_KEY_COUNTER_OFFER;
alice_session_id.copy_to(&mut buffer[4..10]); alice_session_id.copy_to(&mut buffer[1..7]);
buffer[10] = PACKET_TYPE_KEY_COUNTER_OFFER; buffer[7..11].copy_from_slice(&counter.to_bytes());
let mut b = &mut buffer[HEADER_SIZE..]; let mut b = &mut buffer[HEADER_SIZE..];
b[..P384_PUBLIC_KEY_SIZE].copy_from_slice(bob_e0_public.as_bytes()); b[..P384_PUBLIC_KEY_SIZE].copy_from_slice(bob_e0_public.as_bytes());
@ -1053,7 +1065,7 @@ mod tests {
let mut from_bob: Vec<Vec<u8>> = Vec::new(); let mut from_bob: Vec<Vec<u8>> = Vec::new();
// Session TO Bob, on Alice's side. // Session TO Bob, on Alice's side.
let (alice, packet) = new_session( let (alice, packet) = Session::new(
&mut a_buffer, &mut a_buffer,
SessionId::new_random(), SessionId::new_random(),
alice_static_keypair.public_key_bytes(), alice_static_keypair.public_key_bytes(),
@ -1075,7 +1087,7 @@ mod tests {
for _ in 0..256 { for _ in 0..256 {
while !from_alice.is_empty() || !from_bob.is_empty() { while !from_alice.is_empty() || !from_bob.is_empty() {
if let Some(packet) = from_alice.pop() { if let Some(packet) = from_alice.pop() {
let r = receive( let r = Session::receive(
packet.as_slice(), packet.as_slice(),
&mut b_buffer, &mut b_buffer,
&bob_static_keypair, &bob_static_keypair,
@ -1138,7 +1150,7 @@ mod tests {
} }
if let Some(packet) = from_bob.pop() { if let Some(packet) = from_bob.pop() {
let r = receive( let r = Session::receive(
packet.as_slice(), packet.as_slice(),
&mut b_buffer, &mut b_buffer,
&alice_static_keypair, &alice_static_keypair,

View file

@ -102,11 +102,8 @@ pub trait InnerProtocolInterface: Sync + Send + 'static {
/// Handle an OK, returing true if the OK was recognized. /// Handle an OK, returing true if the OK was recognized.
async fn handle_ok<SI: SystemInterface>(&self, source: &Peer<SI>, source_path: &Path<SI>, in_re_verb: u8, in_re_message_id: u64, payload: &PacketBuffer, cursor: &mut usize) -> bool; async fn handle_ok<SI: SystemInterface>(&self, source: &Peer<SI>, source_path: &Path<SI>, in_re_verb: u8, in_re_message_id: u64, payload: &PacketBuffer, cursor: &mut usize) -> bool;
/// Check if this remote peer has a trust relationship with this node. /// Check if this peer should communicate with another at all.
/// fn should_communicate_with(&self, id: &Identity) -> bool;
/// This is checked to determine if we should do things like make direct links or respond to
/// various other VL1 messages.
fn has_trust_relationship(&self, id: &Identity) -> bool;
} }
/// How often to check the root cluster definitions against the root list and update. /// How often to check the root cluster definitions against the root list and update.

View file

@ -75,13 +75,7 @@ pub struct Peer<SI: SystemInterface> {
} }
/// Attempt AEAD packet encryption and MAC validation. Returns message ID on success. /// Attempt AEAD packet encryption and MAC validation. Returns message ID on success.
fn try_aead_decrypt( fn try_aead_decrypt(secret: &SymmetricSecret, packet_frag0_payload_bytes: &[u8], packet_header: &PacketHeader, fragments: &[Option<PooledPacketBuffer>], payload: &mut PacketBuffer) -> Option<MessageId> {
secret: &SymmetricSecret,
packet_frag0_payload_bytes: &[u8],
packet_header: &PacketHeader,
fragments: &[Option<PooledPacketBuffer>],
payload: &mut PacketBuffer,
) -> Option<MessageId> {
let cipher = packet_header.cipher(); let cipher = packet_header.cipher();
match cipher { match cipher {
security_constants::CIPHER_NOCRYPT_POLY1305 | security_constants::CIPHER_SALSA2012_POLY1305 => { security_constants::CIPHER_NOCRYPT_POLY1305 | security_constants::CIPHER_SALSA2012_POLY1305 => {
@ -279,13 +273,7 @@ impl<SI: SystemInterface> Peer<SI> {
match &p.endpoint { match &p.endpoint {
Endpoint::IpUdp(existing_ip) => { Endpoint::IpUdp(existing_ip) => {
if existing_ip.ip_bytes().eq(new_ip.ip_bytes()) { if existing_ip.ip_bytes().eq(new_ip.ip_bytes()) {
debug_event!( debug_event!(si, "[vl1] {} replacing path {} with {} (same IP, different port)", self.identity.address.to_string(), p.endpoint.to_string(), new_path.endpoint.to_string());
si,
"[vl1] {} replacing path {} with {} (same IP, different port)",
self.identity.address.to_string(),
p.endpoint.to_string(),
new_path.endpoint.to_string()
);
pi.path = Arc::downgrade(new_path); pi.path = Arc::downgrade(new_path);
pi.canonical_instance_id = new_path.canonical.canonical_instance_id(); pi.canonical_instance_id = new_path.canonical.canonical_instance_id();
pi.last_receive_time_ticks = time_ticks; pi.last_receive_time_ticks = time_ticks;
@ -332,15 +320,7 @@ impl<SI: SystemInterface> Peer<SI> {
/// ///
/// This does not set the fragmentation field in the packet header, MAC, or encrypt the packet. The sender /// This does not set the fragmentation field in the packet header, MAC, or encrypt the packet. The sender
/// must do that while building the packet. The fragmentation flag must be set if fragmentation will be needed. /// must do that while building the packet. The fragmentation flag must be set if fragmentation will be needed.
async fn internal_send( async fn internal_send(&self, si: &SI, endpoint: &Endpoint, local_socket: Option<&SI::LocalSocket>, local_interface: Option<&SI::LocalInterface>, max_fragment_size: usize, packet: &PacketBuffer) -> bool {
&self,
si: &SI,
endpoint: &Endpoint,
local_socket: Option<&SI::LocalSocket>,
local_interface: Option<&SI::LocalInterface>,
max_fragment_size: usize,
packet: &PacketBuffer,
) -> bool {
let packet_size = packet.len(); let packet_size = packet.len();
if packet_size > max_fragment_size { if packet_size > max_fragment_size {
let bytes = packet.as_bytes(); let bytes = packet.as_bytes();
@ -350,8 +330,7 @@ impl<SI: SystemInterface> Peer<SI> {
let mut pos = UDP_DEFAULT_MTU; let mut pos = UDP_DEFAULT_MTU;
let overrun_size = (packet_size - UDP_DEFAULT_MTU) as u32; let overrun_size = (packet_size - UDP_DEFAULT_MTU) as u32;
let fragment_count = let fragment_count = (overrun_size / (UDP_DEFAULT_MTU - packet_constants::FRAGMENT_HEADER_SIZE) as u32) + (((overrun_size % (UDP_DEFAULT_MTU - packet_constants::FRAGMENT_HEADER_SIZE) as u32) != 0) as u32);
(overrun_size / (UDP_DEFAULT_MTU - packet_constants::FRAGMENT_HEADER_SIZE) as u32) + (((overrun_size % (UDP_DEFAULT_MTU - packet_constants::FRAGMENT_HEADER_SIZE) as u32) != 0) as u32);
debug_assert!(fragment_count <= packet_constants::FRAGMENT_COUNT_MAX as u32); debug_assert!(fragment_count <= packet_constants::FRAGMENT_COUNT_MAX as u32);
let mut header = FragmentHeader { let mut header = FragmentHeader {
@ -400,9 +379,16 @@ impl<SI: SystemInterface> Peer<SI> {
} }
}; };
let max_fragment_size = if path.endpoint.requires_fragmentation() { UDP_DEFAULT_MTU } else { usize::MAX }; let max_fragment_size = if path.endpoint.requires_fragmentation() {
let flags_cipher_hops = UDP_DEFAULT_MTU
if packet.len() > max_fragment_size { packet_constants::HEADER_FLAG_FRAGMENTED | security_constants::CIPHER_AES_GMAC_SIV } else { security_constants::CIPHER_AES_GMAC_SIV }; } else {
usize::MAX
};
let flags_cipher_hops = if packet.len() > max_fragment_size {
packet_constants::HEADER_FLAG_FRAGMENTED | security_constants::CIPHER_AES_GMAC_SIV
} else {
security_constants::CIPHER_AES_GMAC_SIV
};
let mut aes_gmac_siv = self.identity_symmetric_key.aes_gmac_siv.get(); let mut aes_gmac_siv = self.identity_symmetric_key.aes_gmac_siv.get();
aes_gmac_siv.encrypt_init(&self.next_message_id().to_ne_bytes()); aes_gmac_siv.encrypt_init(&self.next_message_id().to_ne_bytes());
@ -481,7 +467,11 @@ impl<SI: SystemInterface> Peer<SI> {
} }
}; };
let max_fragment_size = if destination.requires_fragmentation() { UDP_DEFAULT_MTU } else { usize::MAX }; let max_fragment_size = if destination.requires_fragmentation() {
UDP_DEFAULT_MTU
} else {
usize::MAX
};
let time_ticks = si.time_ticks(); let time_ticks = si.time_ticks();
let mut packet = PacketBuffer::new(); let mut packet = PacketBuffer::new();
@ -532,17 +522,7 @@ impl<SI: SystemInterface> Peer<SI> {
/// those fragments after the main packet header and first chunk. /// those fragments after the main packet header and first chunk.
/// ///
/// This returns true if the packet decrypted and passed authentication. /// This returns true if the packet decrypted and passed authentication.
pub(crate) async fn receive<PH: InnerProtocolInterface>( pub(crate) async fn receive<PH: InnerProtocolInterface>(&self, node: &Node<SI>, si: &SI, ph: &PH, time_ticks: i64, source_path: &Arc<Path<SI>>, packet_header: &PacketHeader, frag0: &PacketBuffer, fragments: &[Option<PooledPacketBuffer>]) -> bool {
&self,
node: &Node<SI>,
si: &SI,
ph: &PH,
time_ticks: i64,
source_path: &Arc<Path<SI>>,
packet_header: &PacketHeader,
frag0: &PacketBuffer,
fragments: &[Option<PooledPacketBuffer>],
) -> bool {
if let Ok(packet_frag0_payload_bytes) = frag0.as_bytes_starting_at(packet_constants::VERB_INDEX) { if let Ok(packet_frag0_payload_bytes) = frag0.as_bytes_starting_at(packet_constants::VERB_INDEX) {
let mut payload = PacketBuffer::new(); let mut payload = PacketBuffer::new();
@ -606,18 +586,8 @@ impl<SI: SystemInterface> Peer<SI> {
return false; return false;
} }
async fn handle_incoming_hello<PH: InnerProtocolInterface>( async fn handle_incoming_hello<PH: InnerProtocolInterface>(&self, si: &SI, ph: &PH, node: &Node<SI>, time_ticks: i64, message_id: MessageId, source_path: &Arc<Path<SI>>, hops: u8, payload: &PacketBuffer) -> bool {
&self, if !(ph.should_communicate_with(&self.identity) || node.this_node_is_root() || node.is_peer_root(self)) {
si: &SI,
ph: &PH,
node: &Node<SI>,
time_ticks: i64,
message_id: MessageId,
source_path: &Arc<Path<SI>>,
hops: u8,
payload: &PacketBuffer,
) -> bool {
if !(ph.has_trust_relationship(&self.identity) || node.this_node_is_root() || node.is_peer_root(self)) {
debug_event!(si, "[vl1] dropping HELLO from {} due to lack of trust relationship", self.identity.address.to_string()); debug_event!(si, "[vl1] dropping HELLO from {} due to lack of trust relationship", self.identity.address.to_string());
return true; // packet wasn't invalid, just ignored return true; // packet wasn't invalid, just ignored
} }
@ -629,9 +599,8 @@ impl<SI: SystemInterface> Peer<SI> {
{ {
let mut remote_node_info = self.remote_node_info.write(); let mut remote_node_info = self.remote_node_info.write();
remote_node_info.remote_protocol_version = hello_fixed_headers.version_proto; remote_node_info.remote_protocol_version = hello_fixed_headers.version_proto;
remote_node_info.remote_version = (hello_fixed_headers.version_major as u64).wrapping_shl(48) remote_node_info.remote_version =
| (hello_fixed_headers.version_minor as u64).wrapping_shl(32) (hello_fixed_headers.version_major as u64).wrapping_shl(48) | (hello_fixed_headers.version_minor as u64).wrapping_shl(32) | (u16::from_be_bytes(hello_fixed_headers.version_revision) as u64).wrapping_shl(16);
| (u16::from_be_bytes(hello_fixed_headers.version_revision) as u64).wrapping_shl(16);
} }
let mut packet = PacketBuffer::new(); let mut packet = PacketBuffer::new();
@ -648,7 +617,14 @@ impl<SI: SystemInterface> Peer<SI> {
f.1.version_revision = VERSION_REVISION.to_be_bytes(); f.1.version_revision = VERSION_REVISION.to_be_bytes();
} }
if hello_fixed_headers.version_proto >= 20 { if hello_fixed_headers.version_proto >= 20 {
let session_metadata = self.create_session_metadata(node, if hops == 0 { Some(&source_path.endpoint) } else { None }); let session_metadata = self.create_session_metadata(
node,
if hops == 0 {
Some(&source_path.endpoint)
} else {
None
},
);
assert!(session_metadata.len() <= 0xffff); // sanity check, should be impossible assert!(session_metadata.len() <= 0xffff); // sanity check, should be impossible
assert!(packet.append_u16(session_metadata.len() as u16).is_ok()); assert!(packet.append_u16(session_metadata.len() as u16).is_ok());
assert!(packet.append_bytes(session_metadata.as_slice()).is_ok()); assert!(packet.append_bytes(session_metadata.as_slice()).is_ok());
@ -676,17 +652,7 @@ impl<SI: SystemInterface> Peer<SI> {
return false; return false;
} }
async fn handle_incoming_ok<PH: InnerProtocolInterface>( async fn handle_incoming_ok<PH: InnerProtocolInterface>(&self, si: &SI, ph: &PH, node: &Node<SI>, time_ticks: i64, source_path: &Arc<Path<SI>>, hops: u8, path_is_known: bool, payload: &PacketBuffer) -> bool {
&self,
si: &SI,
ph: &PH,
node: &Node<SI>,
time_ticks: i64,
source_path: &Arc<Path<SI>>,
hops: u8,
path_is_known: bool,
payload: &PacketBuffer,
) -> bool {
let mut cursor = 0; let mut cursor = 0;
if let Ok(ok_header) = payload.read_struct::<message_component_structs::OkHeader>(&mut cursor) { if let Ok(ok_header) = payload.read_struct::<message_component_structs::OkHeader>(&mut cursor) {
let in_re_message_id: MessageId = u64::from_ne_bytes(ok_header.in_re_message_id); let in_re_message_id: MessageId = u64::from_ne_bytes(ok_header.in_re_message_id);
@ -709,12 +675,7 @@ impl<SI: SystemInterface> Peer<SI> {
let reported_endpoint2 = reported_endpoint.clone(); let reported_endpoint2 = reported_endpoint.clone();
if remote_node_info.reported_local_endpoints.insert(reported_endpoint, time_ticks).is_none() { if remote_node_info.reported_local_endpoints.insert(reported_endpoint, time_ticks).is_none() {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
debug_event!( debug_event!(si, "[vl1] {} reported new remote perspective, local endpoint: {}", self.identity.address.to_string(), reported_endpoint2.to_string());
si,
"[vl1] {} reported new remote perspective, local endpoint: {}",
self.identity.address.to_string(),
reported_endpoint2.to_string()
);
} }
} }
} }
@ -797,7 +758,7 @@ impl<SI: SystemInterface> Peer<SI> {
} }
async fn handle_incoming_whois<PH: InnerProtocolInterface>(&self, si: &SI, ph: &PH, node: &Node<SI>, time_ticks: i64, message_id: MessageId, payload: &PacketBuffer) -> bool { async fn handle_incoming_whois<PH: InnerProtocolInterface>(&self, si: &SI, ph: &PH, node: &Node<SI>, time_ticks: i64, message_id: MessageId, payload: &PacketBuffer) -> bool {
if node.this_node_is_root() || ph.has_trust_relationship(&self.identity) { if node.this_node_is_root() || ph.should_communicate_with(&self.identity) {
let mut packet = PacketBuffer::new(); let mut packet = PacketBuffer::new();
packet.set_size(packet_constants::HEADER_SIZE); packet.set_size(packet_constants::HEADER_SIZE);
{ {
@ -832,7 +793,7 @@ impl<SI: SystemInterface> Peer<SI> {
} }
async fn handle_incoming_echo<PH: InnerProtocolInterface>(&self, si: &SI, ph: &PH, node: &Node<SI>, time_ticks: i64, message_id: MessageId, payload: &PacketBuffer) -> bool { async fn handle_incoming_echo<PH: InnerProtocolInterface>(&self, si: &SI, ph: &PH, node: &Node<SI>, time_ticks: i64, message_id: MessageId, payload: &PacketBuffer) -> bool {
if ph.has_trust_relationship(&self.identity) || node.is_peer_root(self) { if ph.should_communicate_with(&self.identity) || node.is_peer_root(self) {
let mut packet = PacketBuffer::new(); let mut packet = PacketBuffer::new();
packet.set_size(packet_constants::HEADER_SIZE); packet.set_size(packet_constants::HEADER_SIZE);
{ {

View file

@ -39,10 +39,19 @@ impl NetworkId {
pub fn to_bytes(&self) -> [u8; 8] { pub fn to_bytes(&self) -> [u8; 8] {
self.0.get().to_be_bytes() self.0.get().to_be_bytes()
} }
}
impl From<NetworkId> for u64 {
#[inline(always)] #[inline(always)]
pub fn to_u64(&self) -> u64 { fn from(v: NetworkId) -> Self {
self.0.get() v.0.get()
}
}
impl From<&NetworkId> for u64 {
#[inline(always)]
fn from(v: &NetworkId) -> Self {
v.0.get()
} }
} }

View file

@ -18,16 +18,7 @@ impl InnerProtocolInterface for Switch {
} }
#[allow(unused)] #[allow(unused)]
async fn handle_error<SI: SystemInterface>( async fn handle_error<SI: SystemInterface>(&self, peer: &Peer<SI>, source_path: &Path<SI>, in_re_verb: u8, in_re_message_id: u64, error_code: u8, payload: &PacketBuffer, cursor: &mut usize) -> bool {
&self,
peer: &Peer<SI>,
source_path: &Path<SI>,
in_re_verb: u8,
in_re_message_id: u64,
error_code: u8,
payload: &PacketBuffer,
cursor: &mut usize,
) -> bool {
false false
} }
@ -37,7 +28,7 @@ impl InnerProtocolInterface for Switch {
} }
#[allow(unused)] #[allow(unused)]
fn has_trust_relationship(&self, id: &Identity) -> bool { fn should_communicate_with(&self, id: &Identity) -> bool {
true true
} }
} }