diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/handshake/device.rs | 41 | ||||
-rw-r--r-- | src/handshake/macs.rs | 13 | ||||
-rw-r--r-- | src/handshake/messages.rs | 48 | ||||
-rw-r--r-- | src/handshake/noise.rs | 42 | ||||
-rw-r--r-- | src/handshake/peer.rs | 5 |
5 files changed, 84 insertions, 65 deletions
diff --git a/src/handshake/device.rs b/src/handshake/device.rs index b28613a..f3458ae 100644 --- a/src/handshake/device.rs +++ b/src/handshake/device.rs @@ -1,5 +1,6 @@ use spin::RwLock; use std::collections::HashMap; +use zerocopy::AsBytes; use rand::prelude::*; use rand::rngs::OsRng; @@ -159,7 +160,16 @@ where None => Err(HandshakeError::UnknownPublicKey), Some(peer) => { let sender = self.allocate(peer); - noise::create_initiation(self, peer, sender) + + let mut msg = Initiation::default(); + + noise::create_initiation(self, peer, sender, &mut msg.noise)?; + + // add macs to initation + + peer.macs.generate(msg.noise.as_bytes(), &mut msg.macs); + + Ok(msg.as_bytes().to_owned()) } } } @@ -174,7 +184,7 @@ where Some(&TYPE_INITIATION) => { let msg = Initiation::parse(msg)?; - // check mac footer and ratelimiter + // check mac footer and ratelimiter for initiation // consume the initiation let (peer, st) = noise::consume_initiation(self, &msg.noise)?; @@ -182,12 +192,25 @@ where // allocate new index for response let sender = self.allocate(peer); - // create response (release id on error), TODO: take slice + // prepare memory for response, TODO: take slice for zero allocation let mut resp = Response::default(); - noise::create_response(peer, sender, st, &mut resp.noise).map_err(|e| { - self.release(sender); - e - }) + + // create response (release id on error) + let keys = + noise::create_response(peer, sender, st, &mut resp.noise).map_err(|e| { + self.release(sender); + e + })?; + + // add macs to response + + resp.macs.f_mac1 = [8u8; 16]; + + Ok(( + peer.identifier, + Some(resp.as_bytes().to_owned()), + Some(keys), + )) } Some(&TYPE_RESPONSE) => { let msg = Response::parse(msg)?; @@ -297,7 +320,7 @@ mod tests { let msg1 = dev1.begin(&pk2).unwrap(); - println!("msg1 = {}", hex::encode(&msg1[..])); + println!("msg1 = {} : {} bytes", hex::encode(&msg1[..]), msg1.len()); println!("msg1 = {:?}", Initiation::parse(&msg1[..]).unwrap()); // process initiation and create response @@ -307,7 +330,7 @@ mod tests { let ks_r = ks_r.unwrap(); let msg2 = msg2.unwrap(); - println!("msg2 = {}", hex::encode(&msg2[..])); + println!("msg2 = {} : {} bytes", hex::encode(&msg2[..]), msg2.len()); println!("msg2 = {:?}", Response::parse(&msg2[..]).unwrap()); assert!(!ks_r.confirmed, "Responders key-pair is confirmed"); diff --git a/src/handshake/macs.rs b/src/handshake/macs.rs index 05546a7..9092daa 100644 --- a/src/handshake/macs.rs +++ b/src/handshake/macs.rs @@ -38,14 +38,14 @@ macro_rules! MAC { }}; } -struct Generator { +pub struct Generator { mac1_key: [u8; 32], cookie_value: [u8; 16], cookie_birth: Option<Instant>, // when was the cookie set? } impl Generator { - fn new(pk: PublicKey) -> Generator { + pub fn new(pk: PublicKey) -> Generator { Generator { mac1_key: HASH!(LABEL_MAC1, pk.as_bytes()).into(), cookie_value: [0u8; SIZE_COOKIE], @@ -66,14 +66,11 @@ impl Generator { self.cookie_value = *cookie; } - pub fn generate(&self, msg: &[u8]) -> MacsFooter { - MacsFooter { - f_mac1: self.mac1(msg), - f_mac2: self.mac2(msg), - } + pub fn generate(&self, inner: &[u8], macs : &mut MacsFooter) { + } } -struct Validator {} +pub struct Validator {} impl Validator {} diff --git a/src/handshake/messages.rs b/src/handshake/messages.rs index a2ff19a..004e059 100644 --- a/src/handshake/messages.rs +++ b/src/handshake/messages.rs @@ -11,7 +11,7 @@ use zerocopy::{AsBytes, ByteSlice, FromBytes, LayoutVerified}; use super::timestamp; use super::types::*; -const SIZE_MAC: usize = 16; +const SIZE_MAC: usize = 16; const SIZE_TAG: usize = 16; // poly1305 tag const SIZE_NONCE: usize = 16; // xchacha20 nonce const SIZE_COOKIE: usize = 16; // @@ -23,21 +23,21 @@ pub const TYPE_COOKIEREPLY: u8 = 3; /* Handshake messsages */ -#[repr(C)] +#[repr(packed)] #[derive(Copy, Clone, FromBytes, AsBytes)] pub struct Response { pub noise: NoiseResponse, // inner message covered by macs pub macs: MacsFooter, } -#[repr(C)] +#[repr(packed)] #[derive(Copy, Clone, FromBytes, AsBytes)] pub struct Initiation { pub noise: NoiseInitiation, // inner message covered by macs pub macs: MacsFooter, } -#[repr(C)] +#[repr(packed)] #[derive(Copy, Clone, FromBytes, AsBytes)] pub struct CookieReply { f_type: U32<LittleEndian>, @@ -49,14 +49,14 @@ pub struct CookieReply { /* Inner sub-messages */ -#[repr(C)] +#[repr(packed)] #[derive(Copy, Clone, FromBytes, AsBytes)] pub struct MacsFooter { pub f_mac1: [u8; SIZE_MAC], pub f_mac2: [u8; SIZE_MAC], } -#[repr(C)] +#[repr(packed)] #[derive(Copy, Clone, FromBytes, AsBytes)] pub struct NoiseInitiation { f_type: U32<LittleEndian>, @@ -65,17 +65,17 @@ pub struct NoiseInitiation { pub f_static: [u8; SIZE_X25519_POINT], pub f_static_tag: [u8; SIZE_TAG], pub f_timestamp: timestamp::TAI64N, - pub f_timestamp_tag: [u8; SIZE_TAG] + pub f_timestamp_tag: [u8; SIZE_TAG], } -#[repr(C)] +#[repr(packed)] #[derive(Copy, Clone, FromBytes, AsBytes)] pub struct NoiseResponse { f_type: U32<LittleEndian>, pub f_sender: U32<LittleEndian>, pub f_receiver: U32<LittleEndian>, pub f_ephemeral: [u8; SIZE_X25519_POINT], - pub f_empty_tag: [u8; SIZE_TAG] + pub f_empty_tag: [u8; SIZE_TAG], } /* Zero copy parsing of handshake messages */ @@ -124,8 +124,8 @@ impl CookieReply { impl Default for Response { fn default() -> Self { Self { - noise: Default::default(), - macs: Default::default(), + noise: Default::default(), + macs: Default::default(), } } } @@ -133,8 +133,8 @@ impl Default for Response { impl Default for Initiation { fn default() -> Self { Self { - noise: Default::default(), - macs: Default::default(), + noise: Default::default(), + macs: Default::default(), } } } @@ -142,11 +142,11 @@ impl Default for Initiation { impl Default for CookieReply { fn default() -> Self { Self { - f_type: <U32<LittleEndian>>::new(TYPE_COOKIEREPLY as u32), - f_receiver: <U32<LittleEndian>>::ZERO, - f_nonce: [0u8; SIZE_NONCE], - f_cookie: [0u8; SIZE_COOKIE], - f_cookie_tag: [0u8; SIZE_TAG], + f_type: <U32<LittleEndian>>::new(TYPE_COOKIEREPLY as u32), + f_receiver: <U32<LittleEndian>>::ZERO, + f_nonce: [0u8; SIZE_NONCE], + f_cookie: [0u8; SIZE_COOKIE], + f_cookie_tag: [0u8; SIZE_TAG], } } } @@ -161,7 +161,7 @@ impl Default for MacsFooter { } impl Default for NoiseInitiation { - fn default() -> Self { + fn default() -> Self { Self { f_type: <U32<LittleEndian>>::new(TYPE_INITIATION as u32), @@ -170,7 +170,7 @@ impl Default for NoiseInitiation { f_static: [0u8; SIZE_X25519_POINT], f_static_tag: [0u8; SIZE_TAG], f_timestamp: timestamp::ZERO, - f_timestamp_tag: [0u8; SIZE_TAG] + f_timestamp_tag: [0u8; SIZE_TAG], } } } @@ -206,7 +206,8 @@ impl fmt::Debug for Response { #[cfg(test)] impl fmt::Debug for CookieReply { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, + write!( + f, "CookieReply {{ type = {}, receiver = {}, nonce = {}, cookie = {}|{} }}", self.f_type, self.f_receiver, @@ -250,7 +251,8 @@ impl fmt::Debug for NoiseResponse { #[cfg(test)] impl fmt::Debug for MacsFooter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, + write!( + f, "Macs {{ mac1 = {}, mac2 = {} }}", hex::encode(self.f_mac1), hex::encode(self.f_mac2) @@ -268,7 +270,7 @@ macro_rules! eq_as_bytes { } } impl Eq for $type {} - } + }; } #[cfg(test)] diff --git a/src/handshake/noise.rs b/src/handshake/noise.rs index 72e0f47..b0d492c 100644 --- a/src/handshake/noise.rs +++ b/src/handshake/noise.rs @@ -15,8 +15,6 @@ use rand::rngs::OsRng; use generic_array::typenum::*; use generic_array::GenericArray; -use zerocopy::AsBytes; - use super::device::Device; use super::messages::{NoiseInitiation, NoiseResponse}; use super::peer::{Peer, State}; @@ -140,9 +138,9 @@ pub fn create_initiation<T: Copy>( device: &Device<T>, peer: &Peer<T>, sender: u32, -) -> Result<Vec<u8>, HandshakeError> { + msg: &mut NoiseInitiation, +) -> Result<(), HandshakeError> { let mut rng = OsRng::new().unwrap(); - let mut msg: NoiseInitiation = Default::default(); // initialize state @@ -214,9 +212,7 @@ pub fn create_initiation<T: Copy>( sender, }); - // return message as vector - - Ok(msg.as_bytes().to_vec()) + Ok(()) } pub fn consume_initiation<'a, T: Copy>( @@ -294,7 +290,7 @@ pub fn create_response<T: Copy>( sender: u32, // sending identifier state: TemporaryState, // state from "consume_initiation" msg: &mut NoiseResponse, // resulting response -) -> Result<Output<T>, HandshakeError> { +) -> Result<KeyPair, HandshakeError> { let mut rng = OsRng::new().unwrap(); let (receiver, eph_r_pk, hs, ck) = state; @@ -354,23 +350,19 @@ pub fn create_response<T: Copy>( let (key_recv, key_send) = KDF2!(&ck, &[]); - // return response and unconfirmed key-pair - - Ok(( - peer.identifier, - Some(msg.as_bytes().to_vec()), - Some(KeyPair { - confirmed: false, - send: Key { - id: sender, - key: key_send.into(), - }, - recv: Key { - id: receiver, - key: key_recv.into(), - }, - }), - )) + // return unconfirmed key-pair + + Ok(KeyPair { + confirmed: false, + send: Key { + id: sender, + key: key_send.into(), + }, + recv: Key { + id: receiver, + key: key_recv.into(), + }, + }) } pub fn consume_response<T: Copy>( diff --git a/src/handshake/peer.rs b/src/handshake/peer.rs index 5b01d75..309a9cf 100644 --- a/src/handshake/peer.rs +++ b/src/handshake/peer.rs @@ -10,6 +10,7 @@ use x25519_dalek::StaticSecret; use super::device::Device; use super::timestamp; use super::types::*; +use super::macs; /* Represents the recomputation and state of a peer. * @@ -24,6 +25,9 @@ pub struct Peer<T> { state: Mutex<State>, timestamp: Mutex<Option<timestamp::TAI64N>>, + // state related to DoS mitigation fields + pub(crate) macs: macs::Generator, + // constant state pub(crate) pk: PublicKey, // public key of peer pub(crate) ss: SharedSecret, // precomputed DH(static, static) @@ -69,6 +73,7 @@ where ss: SharedSecret, // precomputed DH(static, static) ) -> Self { Self { + macs: macs::Generator::new(pk), identifier: identifier, state: Mutex::new(State::Reset), timestamp: Mutex::new(None), |