From 43b56dfb58b780fef6bccf7e77cd3d2458a94582 Mon Sep 17 00:00:00 2001 From: Mathias Hall-Andersen Date: Thu, 25 Jul 2019 22:04:35 +0200 Subject: Formatting --- src/device.rs | 78 +++++++------- src/lib.rs | 6 +- src/messages.rs | 154 +++++++++++++-------------- src/noise.rs | 318 ++++++++++++++++++++++++------------------------------- src/peer.rs | 101 +++++++++--------- src/timestamp.rs | 8 +- src/types.rs | 42 ++++---- 7 files changed, 326 insertions(+), 381 deletions(-) diff --git a/src/device.rs b/src/device.rs index 66d5644..838ae63 100644 --- a/src/device.rs +++ b/src/device.rs @@ -7,35 +7,38 @@ use rand::rngs::OsRng; use x25519_dalek::PublicKey; use x25519_dalek::StaticSecret; -use crate::noise; use crate::messages; -use crate::types::*; +use crate::noise; use crate::peer::Peer; +use crate::types::*; pub struct Device { - pub sk : StaticSecret, // static secret key - pub pk : PublicKey, // static public key - peers : Vec>, // peer index -> state - pk_map : HashMap<[u8; 32], usize>, // public key -> peer index - id_map : RwLock> // receive ids -> peer index + pub sk: StaticSecret, // static secret key + pub pk: PublicKey, // static public key + peers: Vec>, // peer index -> state + pk_map: HashMap<[u8; 32], usize>, // public key -> peer index + id_map: RwLock>, // receive ids -> peer index } /* A mutable reference to the device needs to be held during configuration. * Wrapping the device in a RwLock enables peer config after "configuration time" */ -impl Device where T : Copy { +impl Device +where + T: Copy, +{ /// Initialize a new handshake state machine /// /// # Arguments /// /// * `sk` - x25519 scalar representing the local private key - pub fn new(sk : StaticSecret) -> Device { + pub fn new(sk: StaticSecret) -> Device { Device { - pk : PublicKey::from(&sk), - sk : sk, - peers : vec![], - pk_map : HashMap::new(), - id_map : RwLock::new(HashMap::new()) + pk: PublicKey::from(&sk), + sk: sk, + peers: vec![], + pk_map: HashMap::new(), + id_map: RwLock::new(HashMap::new()), } } @@ -46,7 +49,7 @@ impl Device where T : Copy { /// /// * `pk` - The public key to add /// * `identifier` - Associated identifier which can be used to distinguish the peers - pub fn add(&mut self, pk : PublicKey, identifier : T) -> Result<(), ConfigError> { + pub fn add(&mut self, pk: PublicKey, identifier: T) -> Result<(), ConfigError> { // check that the pk is not added twice if let Some(_) = self.pk_map.get(pk.as_bytes()) { @@ -56,7 +59,9 @@ impl Device where T : Copy { // check that the pk is not that of the device if *self.pk.as_bytes() == *pk.as_bytes() { - return Err(ConfigError::new("Public key corresponds to secret key of interface")); + return Err(ConfigError::new( + "Public key corresponds to secret key of interface", + )); } // map : pk -> new index @@ -66,9 +71,8 @@ impl Device where T : Copy { // map : new index -> peer - self.peers.push(Peer::new( - idx, identifier, pk, self.sk.diffie_hellman(&pk) - )); + self.peers + .push(Peer::new(idx, identifier, pk, self.sk.diffie_hellman(&pk))); Ok(()) } @@ -83,7 +87,7 @@ impl Device where T : Copy { /// # Returns /// /// The call might fail if the public key is not found - pub fn psk(&mut self, pk : PublicKey, psk : Option) -> Result<(), ConfigError> { + pub fn psk(&mut self, pk: PublicKey, psk: Option) -> Result<(), ConfigError> { match self.pk_map.get(pk.as_bytes()) { Some(&idx) => { let peer = &mut self.peers[idx]; @@ -92,8 +96,8 @@ impl Device where T : Copy { None => [0u8; 32], }; Ok(()) - }, - _ => Err(ConfigError::new("No such public key")) + } + _ => Err(ConfigError::new("No such public key")), } } @@ -102,8 +106,8 @@ impl Device where T : Copy { /// # Arguments /// /// * `id` - The (sender) id to release - pub fn release(&self, id : u32) { - let mut m =self.id_map.write(); + pub fn release(&self, id: u32) { + let mut m = self.id_map.write(); debug_assert!(m.contains_key(&id), "Releasing id not allocated"); m.remove(&id); } @@ -113,7 +117,7 @@ impl Device where T : Copy { /// # Arguments /// /// * `pk` - Public key of peer to initiate handshake for - pub fn begin(&self, pk : &PublicKey) -> Result, HandshakeError> { + pub fn begin(&self, pk: &PublicKey) -> Result, HandshakeError> { match self.pk_map.get(pk.as_bytes()) { None => Err(HandshakeError::UnknownPublicKey), Some(&idx) => { @@ -129,7 +133,7 @@ impl Device where T : Copy { /// # Arguments /// /// * `msg` - Byte slice containing the message (untrusted input) - pub fn process(&self, msg : &[u8]) -> Result, HandshakeError> { + pub fn process(&self, msg: &[u8]) -> Result, HandshakeError> { match msg.get(0) { Some(&messages::TYPE_INITIATION) => { // consume the initiation @@ -143,37 +147,36 @@ impl Device where T : Copy { self.release(sender); e }) - }, - Some(&messages::TYPE_RESPONSE) => - noise::consume_response(self, msg), - _ => Err(HandshakeError::InvalidMessageFormat) + } + Some(&messages::TYPE_RESPONSE) => noise::consume_response(self, msg), + _ => Err(HandshakeError::InvalidMessageFormat), } } // Internal function // // Return the peer associated with the public key - pub(crate) fn lookup_pk(&self, pk : &PublicKey) -> Result<&Peer, HandshakeError> { + pub(crate) fn lookup_pk(&self, pk: &PublicKey) -> Result<&Peer, HandshakeError> { match self.pk_map.get(pk.as_bytes()) { Some(&idx) => Ok(&self.peers[idx]), - _ => Err(HandshakeError::UnknownPublicKey) + _ => Err(HandshakeError::UnknownPublicKey), } } // Internal function // // Return the peer currently associated with the receiver identifier - pub(crate) fn lookup_id(&self, id : u32) -> Result<&Peer, HandshakeError> { + pub(crate) fn lookup_id(&self, id: u32) -> Result<&Peer, HandshakeError> { match self.id_map.read().get(&id) { Some(&idx) => Ok(&self.peers[idx]), - _ => Err(HandshakeError::UnknownReceiverId) + _ => Err(HandshakeError::UnknownReceiverId), } } // Internal function // // Allocated a new receiver identifier for the peer index - fn allocate(&self, idx : usize) -> u32 { + fn allocate(&self, idx: usize) -> u32 { let mut rng = OsRng::new().unwrap(); loop { @@ -181,7 +184,7 @@ impl Device where T : Copy { // check membership with read lock if self.id_map.read().contains_key(&id) { - continue + continue; } // take write lock and add index @@ -196,8 +199,8 @@ impl Device where T : Copy { #[cfg(test)] mod tests { - use hex; use super::*; + use hex; use messages::*; use std::convert::TryFrom; @@ -224,7 +227,6 @@ mod tests { // do a few handshakes for i in 0..10 { - println!("handshake : {}", i); // create initiation diff --git a/src/lib.rs b/src/lib.rs index e2d9b8d..d5a9c31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,9 @@ -mod types; -mod noise; +mod device; mod messages; +mod noise; mod peer; -mod device; mod timestamp; +mod types; // publicly exposed interface diff --git a/src/messages.rs b/src/messages.rs index b1d1659..136c899 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -1,15 +1,15 @@ +use crate::types::*; use hex; -use std::mem; -use std::fmt; use std::convert::TryFrom; -use crate::types::*; +use std::fmt; +use std::mem; -const SIZE_TAG : usize = 16; -const SIZE_X25519_POINT : usize = 32; -const SIZE_TIMESTAMP : usize = 12; +const SIZE_TAG: usize = 16; +const SIZE_X25519_POINT: usize = 32; +const SIZE_TIMESTAMP: usize = 12; -pub const TYPE_INITIATION : u8 = 1; -pub const TYPE_RESPONSE : u8 = 2; +pub const TYPE_INITIATION: u8 = 1; +pub const TYPE_RESPONSE: u8 = 2; /* Functions related to the packing / unpacking of * the fixed-sized noise handshake messages. @@ -20,21 +20,19 @@ pub const TYPE_RESPONSE : u8 = 2; #[repr(C)] #[derive(Copy, Clone)] pub struct Initiation { - f_type : u32, - pub f_sender : u32, - pub f_ephemeral : [u8; SIZE_X25519_POINT], - pub f_static : [u8; SIZE_X25519_POINT], - pub f_static_tag : [u8; SIZE_TAG], - pub f_timestamp : [u8; SIZE_TIMESTAMP], - pub f_timestamp_tag : [u8; SIZE_TAG], + f_type: u32, + pub f_sender: u32, + pub f_ephemeral: [u8; SIZE_X25519_POINT], + pub f_static: [u8; SIZE_X25519_POINT], + pub f_static_tag: [u8; SIZE_TAG], + pub f_timestamp: [u8; SIZE_TIMESTAMP], + pub f_timestamp_tag: [u8; SIZE_TAG], } impl TryFrom<&[u8]> for Initiation { - type Error = HandshakeError; fn try_from(value: &[u8]) -> Result { - // check length of slice matches message if value.len() != mem::size_of::() { @@ -44,7 +42,7 @@ impl TryFrom<&[u8]> for Initiation { // create owned copy let mut owned = [0u8; mem::size_of::()]; - let mut msg : Self; + let mut msg: Self; owned.copy_from_slice(value); // cast to Initiation @@ -76,10 +74,8 @@ impl Into> for Initiation { msg.f_sender = msg.f_sender.to_le(); // cast to array - let array : [u8; mem::size_of::()]; - unsafe { - array = mem::transmute::()]>(msg) - }; + let array: [u8; mem::size_of::()]; + unsafe { array = mem::transmute::()]>(msg) }; array.to_vec() } @@ -88,13 +84,13 @@ impl Into> for Initiation { impl Default for Initiation { fn default() -> Self { Self { - f_type : TYPE_INITIATION as u32, - f_sender : 0, - f_ephemeral : [0u8; SIZE_X25519_POINT], - f_static : [0u8; SIZE_X25519_POINT], - f_static_tag : [0u8; SIZE_TAG], - f_timestamp : [0u8; SIZE_TIMESTAMP], - f_timestamp_tag : [0u8; SIZE_TAG] + f_type: TYPE_INITIATION as u32, + f_sender: 0, + f_ephemeral: [0u8; SIZE_X25519_POINT], + f_static: [0u8; SIZE_X25519_POINT], + f_static_tag: [0u8; SIZE_TAG], + f_timestamp: [0u8; SIZE_TIMESTAMP], + f_timestamp_tag: [0u8; SIZE_TAG], } } } @@ -117,13 +113,13 @@ impl fmt::Debug for Initiation { #[cfg(test)] impl PartialEq for Initiation { fn eq(&self, other: &Self) -> bool { - self.f_type == other.f_type && - self.f_sender == other.f_sender && - self.f_ephemeral[..] == other.f_ephemeral[..] && - self.f_static[..] == other.f_static[..] && - self.f_static_tag[..] == other.f_static_tag[..] && - self.f_timestamp[..] == other.f_timestamp && - self.f_timestamp_tag[..] == other.f_timestamp_tag + self.f_type == other.f_type + && self.f_sender == other.f_sender + && self.f_ephemeral[..] == other.f_ephemeral[..] + && self.f_static[..] == other.f_static[..] + && self.f_static_tag[..] == other.f_static_tag[..] + && self.f_timestamp[..] == other.f_timestamp + && self.f_timestamp_tag[..] == other.f_timestamp_tag } } @@ -133,19 +129,17 @@ impl Eq for Initiation {} #[repr(C)] #[derive(Copy, Clone)] pub struct Response { - f_type : u32, - pub f_sender : u32, - pub f_receiver : u32, - pub f_ephemeral : [u8; SIZE_X25519_POINT], - pub f_empty_tag : [u8; SIZE_TAG], + f_type: u32, + pub f_sender: u32, + pub f_receiver: u32, + pub f_ephemeral: [u8; SIZE_X25519_POINT], + pub f_empty_tag: [u8; SIZE_TAG], } impl TryFrom<&[u8]> for Response { - type Error = HandshakeError; fn try_from(value: &[u8]) -> Result { - // check length of slice matches message if value.len() != mem::size_of::() { @@ -155,7 +149,7 @@ impl TryFrom<&[u8]> for Response { // create owned copy let mut owned = [0u8; mem::size_of::()]; - let mut msg : Self; + let mut msg: Self; owned.copy_from_slice(value); // cast to MessageResponse @@ -189,10 +183,8 @@ impl Into> for Response { msg.f_receiver = msg.f_receiver.to_le(); // cast to array - let array : [u8; mem::size_of::()]; - unsafe { - array = mem::transmute::()]>(msg) - }; + let array: [u8; mem::size_of::()]; + unsafe { array = mem::transmute::()]>(msg) }; array.to_vec() } @@ -201,11 +193,11 @@ impl Into> for Response { impl Default for Response { fn default() -> Self { Self { - f_type : TYPE_RESPONSE as u32, - f_sender : 0, - f_receiver : 0, - f_ephemeral : [0u8; SIZE_X25519_POINT], - f_empty_tag : [0u8; SIZE_TAG] + f_type: TYPE_RESPONSE as u32, + f_sender: 0, + f_receiver: 0, + f_ephemeral: [0u8; SIZE_X25519_POINT], + f_empty_tag: [0u8; SIZE_TAG], } } } @@ -226,11 +218,11 @@ impl fmt::Debug for Response { #[cfg(test)] impl PartialEq for Response { fn eq(&self, other: &Self) -> bool { - self.f_type == other.f_type && - self.f_sender == other.f_sender && - self.f_receiver == other.f_receiver && - self.f_ephemeral == other.f_ephemeral && - self.f_empty_tag == other.f_empty_tag + self.f_type == other.f_type + && self.f_sender == other.f_sender + && self.f_receiver == other.f_receiver + && self.f_ephemeral == other.f_ephemeral + && self.f_empty_tag == other.f_empty_tag } } @@ -240,57 +232,53 @@ mod tests { #[test] fn message_response_identity() { - let mut msg : Response = Default::default(); + let mut msg: Response = Default::default(); msg.f_sender = 146252; msg.f_receiver = 554442; msg.f_ephemeral = [ - 0xc1, 0x66, 0x0a, 0x0c, 0xdc, 0x0f, 0x6c, 0x51, - 0x0f, 0xc2, 0xcc, 0x51, 0x52, 0x0c, 0xde, 0x1e, - 0xf7, 0xf1, 0xca, 0x90, 0x86, 0x72, 0xad, 0x67, - 0xea, 0x89, 0x45, 0x44, 0x13, 0x56, 0x52, 0x1f + 0xc1, 0x66, 0x0a, 0x0c, 0xdc, 0x0f, 0x6c, 0x51, 0x0f, 0xc2, 0xcc, 0x51, 0x52, 0x0c, + 0xde, 0x1e, 0xf7, 0xf1, 0xca, 0x90, 0x86, 0x72, 0xad, 0x67, 0xea, 0x89, 0x45, 0x44, + 0x13, 0x56, 0x52, 0x1f, ]; msg.f_empty_tag = [ - 0x60, 0x0e, 0x1e, 0x95, 0x41, 0x6b, 0x52, 0x05, - 0xa2, 0x09, 0xe1, 0xbf, 0x40, 0x05, 0x2f, 0xde + 0x60, 0x0e, 0x1e, 0x95, 0x41, 0x6b, 0x52, 0x05, 0xa2, 0x09, 0xe1, 0xbf, 0x40, 0x05, + 0x2f, 0xde, ]; - let buf : Vec = msg.into(); - let msg_p : Response = Response::try_from(&buf[..]).unwrap(); + let buf: Vec = msg.into(); + let msg_p: Response = Response::try_from(&buf[..]).unwrap(); assert_eq!(msg, msg_p); } #[test] fn message_initiate_identity() { - let mut msg : Initiation = Default::default(); + let mut msg: Initiation = Default::default(); msg.f_sender = 575757; msg.f_ephemeral = [ - 0xc1, 0x66, 0x0a, 0x0c, 0xdc, 0x0f, 0x6c, 0x51, - 0x0f, 0xc2, 0xcc, 0x51, 0x52, 0x0c, 0xde, 0x1e, - 0xf7, 0xf1, 0xca, 0x90, 0x86, 0x72, 0xad, 0x67, - 0xea, 0x89, 0x45, 0x44, 0x13, 0x56, 0x52, 0x1f + 0xc1, 0x66, 0x0a, 0x0c, 0xdc, 0x0f, 0x6c, 0x51, 0x0f, 0xc2, 0xcc, 0x51, 0x52, 0x0c, + 0xde, 0x1e, 0xf7, 0xf1, 0xca, 0x90, 0x86, 0x72, 0xad, 0x67, 0xea, 0x89, 0x45, 0x44, + 0x13, 0x56, 0x52, 0x1f, ]; msg.f_static = [ - 0xdc, 0x33, 0x90, 0x15, 0x8f, 0x82, 0x3e, 0x06, - 0x44, 0xa0, 0xde, 0x4c, 0x15, 0x6c, 0x5d, 0xa4, - 0x65, 0x99, 0xf6, 0x6c, 0xa1, 0x14, 0x77, 0xf9, - 0xeb, 0x6a, 0xec, 0xc3, 0x3c, 0xda, 0x47, 0xe1 + 0xdc, 0x33, 0x90, 0x15, 0x8f, 0x82, 0x3e, 0x06, 0x44, 0xa0, 0xde, 0x4c, 0x15, 0x6c, + 0x5d, 0xa4, 0x65, 0x99, 0xf6, 0x6c, 0xa1, 0x14, 0x77, 0xf9, 0xeb, 0x6a, 0xec, 0xc3, + 0x3c, 0xda, 0x47, 0xe1, ]; msg.f_static_tag = [ - 0x45, 0xac, 0x8d, 0x43, 0xea, 0x1b, 0x2f, 0x02, - 0x45, 0x5d, 0x86, 0x37, 0xee, 0x83, 0x6b, 0x42 + 0x45, 0xac, 0x8d, 0x43, 0xea, 0x1b, 0x2f, 0x02, 0x45, 0x5d, 0x86, 0x37, 0xee, 0x83, + 0x6b, 0x42, ]; msg.f_timestamp = [ - 0x4f, 0x1c, 0x60, 0xec, 0x0e, 0xf6, 0x36, 0xf0, - 0x78, 0x28, 0x57, 0x42 + 0x4f, 0x1c, 0x60, 0xec, 0x0e, 0xf6, 0x36, 0xf0, 0x78, 0x28, 0x57, 0x42, ]; msg.f_timestamp_tag = [ - 0x60, 0x0e, 0x1e, 0x95, 0x41, 0x6b, 0x52, 0x05, - 0xa2, 0x09, 0xe1, 0xbf, 0x40, 0x05, 0x2f, 0xde + 0x60, 0x0e, 0x1e, 0x95, 0x41, 0x6b, 0x52, 0x05, 0xa2, 0x09, 0xe1, 0xbf, 0x40, 0x05, + 0x2f, 0xde, ]; - let buf : Vec = msg.into(); + let buf: Vec = msg.into(); assert_eq!(msg, Initiation::try_from(&buf[..]).unwrap()); } } diff --git a/src/noise.rs b/src/noise.rs index 6327776..b45b690 100644 --- a/src/noise.rs +++ b/src/noise.rs @@ -5,23 +5,23 @@ use x25519_dalek::PublicKey; use x25519_dalek::StaticSecret; // HASH & MAC -use hmac::{Mac, Hmac}; -use blake2::{Blake2s, Digest}; +use blake2::Blake2s; +use hmac::Hmac; // AEAD +use crypto::aead::{AeadDecryptor, AeadEncryptor}; use crypto::chacha20poly1305::ChaCha20Poly1305; -use crypto::aead::{AeadEncryptor,AeadDecryptor}; use rand::rngs::OsRng; use generic_array::typenum::*; use generic_array::GenericArray; -use crate::types::*; -use crate::peer::{State, Peer}; use crate::device::Device; use crate::messages::{Initiation, Response}; +use crate::peer::{Peer, State}; use crate::timestamp; +use crate::types::*; // HMAC hasher (generic construction) @@ -31,144 +31,97 @@ type HMACBlake2s = Hmac; type TemporaryState = (u32, PublicKey, GenericArray, GenericArray); -const SIZE_CK : usize = 32; -const SIZE_HS : usize = 32; -const SIZE_NONCE : usize = 8; +const SIZE_CK: usize = 32; +const SIZE_HS: usize = 32; +const SIZE_NONCE: usize = 8; // C := Hash(Construction) -const INITIAL_CK : [u8; SIZE_CK] = [ - 0x60, 0xe2, 0x6d, 0xae, 0xf3, 0x27, 0xef, 0xc0, - 0x2e, 0xc3, 0x35, 0xe2, 0xa0, 0x25, 0xd2, 0xd0, - 0x16, 0xeb, 0x42, 0x06, 0xf8, 0x72, 0x77, 0xf5, - 0x2d, 0x38, 0xd1, 0x98, 0x8b, 0x78, 0xcd, 0x36 +const INITIAL_CK: [u8; SIZE_CK] = [ + 0x60, 0xe2, 0x6d, 0xae, 0xf3, 0x27, 0xef, 0xc0, 0x2e, 0xc3, 0x35, 0xe2, 0xa0, 0x25, 0xd2, 0xd0, + 0x16, 0xeb, 0x42, 0x06, 0xf8, 0x72, 0x77, 0xf5, 0x2d, 0x38, 0xd1, 0x98, 0x8b, 0x78, 0xcd, 0x36, ]; // H := Hash(C || Identifier) -const INITIAL_HS : [u8; SIZE_HS] = [ - 0x22, 0x11, 0xb3, 0x61, 0x08, 0x1a, 0xc5, 0x66, - 0x69, 0x12, 0x43, 0xdb, 0x45, 0x8a, 0xd5, 0x32, - 0x2d, 0x9c, 0x6c, 0x66, 0x22, 0x93, 0xe8, 0xb7, - 0x0e, 0xe1, 0x9c, 0x65, 0xba, 0x07, 0x9e, 0xf3 +const INITIAL_HS: [u8; SIZE_HS] = [ + 0x22, 0x11, 0xb3, 0x61, 0x08, 0x1a, 0xc5, 0x66, 0x69, 0x12, 0x43, 0xdb, 0x45, 0x8a, 0xd5, 0x32, + 0x2d, 0x9c, 0x6c, 0x66, 0x22, 0x93, 0xe8, 0xb7, 0x0e, 0xe1, 0x9c, 0x65, 0xba, 0x07, 0x9e, 0xf3, ]; -const ZERO_NONCE : [u8; SIZE_NONCE] = [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -]; +const ZERO_NONCE: [u8; SIZE_NONCE] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; macro_rules! HASH { - ($input1:expr) => { - { - let mut hsh = ::new(); - Digest::input(&mut hsh, $input1); - Digest::result(hsh) - } - }; - - ($input1:expr, $input2:expr) => { - { - let mut hsh = ::new(); - Digest::input(&mut hsh, $input1); - Digest::input(&mut hsh, $input2); - Digest::result(hsh) - } - }; - - ($input1:expr, $input2:expr, $input3:expr) => { - { - let mut hsh = ::new(); - Digest::input(&mut hsh, $input1); - Digest::input(&mut hsh, $input2); - Digest::input(&mut hsh, $input3); - Digest::result(hsh) - } - }; + ( $($input:expr),* ) => {{ + use blake2::Digest; + let mut hsh = Blake2s::new(); + $( + hsh.input($input); + )* + hsh.result() + }}; } macro_rules! HMAC { - ($key:expr, $input1:expr) => { - { - // let mut mac = HMACBlake2s::new($key); - let mut mac = HMACBlake2s::new_varkey($key).unwrap(); - mac.input($input1); - mac.result().code() - } - }; - - ($key:expr, $input1:expr, $input2:expr) => { - { - let mut mac = HMACBlake2s::new_varkey($key).unwrap(); - mac.input($input1); - mac.input($input2); - mac.result().code() - } - }; + ($key:expr, $($input:expr),*) => {{ + use hmac::Mac; + let mut mac = HMACBlake2s::new_varkey($key).unwrap(); + $( + mac.input($input); + )* + mac.result().code() + }}; } macro_rules! KDF1 { - ($ck:expr, $input:expr) => { - { - let t0 = HMAC!($ck, $input); - let t1 = HMAC!(&t0, &[0x1]); - t1 - } - } + ($ck:expr, $input:expr) => {{ + let t0 = HMAC!($ck, $input); + let t1 = HMAC!(&t0, &[0x1]); + t1 + }}; } macro_rules! KDF2 { - ($ck:expr, $input:expr) => { - { - let t0 = HMAC!($ck, $input); - let t1 = HMAC!(&t0, &[0x1]); - let t2 = HMAC!(&t0, &t1, &[0x2]); - (t1, t2) - } - } + ($ck:expr, $input:expr) => {{ + let t0 = HMAC!($ck, $input); + let t1 = HMAC!(&t0, &[0x1]); + let t2 = HMAC!(&t0, &t1, &[0x2]); + (t1, t2) + }}; } macro_rules! KDF3 { - ($ck:expr, $input:expr) => { - { - let t0 = HMAC!($ck, $input); - let t1 = HMAC!(&t0, &[0x1]); - let t2 = HMAC!(&t0, &t1, &[0x2]); - let t3 = HMAC!(&t0, &t2, &[0x3]); - (t1, t2, t3) - } - } + ($ck:expr, $input:expr) => {{ + let t0 = HMAC!($ck, $input); + let t1 = HMAC!(&t0, &[0x1]); + let t2 = HMAC!(&t0, &t1, &[0x2]); + let t3 = HMAC!(&t0, &t2, &[0x3]); + (t1, t2, t3) + }}; } macro_rules! SEAL { - ($key:expr, $aead:expr, $pt:expr, $ct:expr, $tag:expr) => { - { - let mut aead = ChaCha20Poly1305::new($key, &ZERO_NONCE, $aead); - aead.encrypt( - $pt, - $ct, - $tag - ); - } - } + ($key:expr, $aead:expr, $pt:expr, $ct:expr, $tag:expr) => {{ + let mut aead = ChaCha20Poly1305::new($key, &ZERO_NONCE, $aead); + aead.encrypt($pt, $ct, $tag); + }}; } macro_rules! OPEN { - ($key:expr, $aead:expr, $pt:expr, $ct:expr, $tag:expr) => { - { - let mut aead = ChaCha20Poly1305::new($key, &ZERO_NONCE, $aead); - if !aead.decrypt($ct, $pt, $tag) { - Err(HandshakeError::DecryptionFailure) - } else { - Ok(()) - } + ($key:expr, $aead:expr, $pt:expr, $ct:expr, $tag:expr) => {{ + let mut aead = ChaCha20Poly1305::new($key, &ZERO_NONCE, $aead); + if !aead.decrypt($ct, $pt, $tag) { + Err(HandshakeError::DecryptionFailure) + } else { + Ok(()) } - } + }}; } #[cfg(test)] mod tests { use super::*; - const IDENTIFIER : &[u8] = b"WireGuard v1 zx2c4 Jason@zx2c4.com"; - const CONSTRUCTION : &[u8] = b"Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"; + const IDENTIFIER: &[u8] = b"WireGuard v1 zx2c4 Jason@zx2c4.com"; + const CONSTRUCTION: &[u8] = b"Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"; #[test] fn precomputed_chain_key() { @@ -177,21 +130,17 @@ mod tests { #[test] fn precomputed_hash() { - assert_eq!( - INITIAL_HS[..], - HASH!(INITIAL_CK, IDENTIFIER)[..] - ); + assert_eq!(INITIAL_HS[..], HASH!(INITIAL_CK, IDENTIFIER)[..]); } } -pub fn create_initiation( - device : &Device, - peer : &Peer, - sender : u32 +pub fn create_initiation( + device: &Device, + peer: &Peer, + sender: u32, ) -> Result, HandshakeError> { - let mut rng = OsRng::new().unwrap(); - let mut msg : Initiation = Default::default(); + let mut msg: Initiation = Default::default(); // initialize state @@ -226,10 +175,10 @@ pub fn create_initiation( SEAL!( &key, - &hs, // ad - device.pk.as_bytes(), // pt - &mut msg.f_static, // ct - &mut msg.f_static_tag // tag + &hs, // ad + device.pk.as_bytes(), // pt + &mut msg.f_static, // ct + &mut msg.f_static_tag // tag ); // H := Hash(H || msg.static) @@ -244,10 +193,10 @@ pub fn create_initiation( SEAL!( &key, - &hs, // ad - ×tamp::now(), // pt - &mut msg.f_timestamp, // ct - &mut msg.f_timestamp_tag // tag + &hs, // ad + ×tamp::now(), // pt + &mut msg.f_timestamp, // ct + &mut msg.f_timestamp_tag // tag ); // H := Hash(H || msg.timestamp) @@ -256,18 +205,22 @@ pub fn create_initiation( // update state of peer - peer.set_state(State::InitiationSent{hs, ck, eph_sk, sender}); + peer.set_state(State::InitiationSent { + hs, + ck, + eph_sk, + sender, + }); // return message as vector Ok(Initiation::into(msg)) } -pub fn consume_initiation<'a, T : Copy>( - device : &'a Device, - msg : &[u8] +pub fn consume_initiation<'a, T: Copy>( + device: &'a Device, + msg: &[u8], ) -> Result<(&'a Peer, TemporaryState), HandshakeError> { - // parse message let msg = Initiation::try_from(msg)?; @@ -289,10 +242,7 @@ pub fn consume_initiation<'a, T : Copy>( // (C, k) := Kdf2(C, DH(E_priv, S_pub)) let eph_r_pk = PublicKey::from(msg.f_ephemeral); - let (ck, key) = KDF2!( - &ck, - device.sk.diffie_hellman(&eph_r_pk).as_bytes() - ); + let (ck, key) = KDF2!(&ck, device.sk.diffie_hellman(&eph_r_pk).as_bytes()); // msg.static := Aead(k, 0, S_pub, H) @@ -300,10 +250,10 @@ pub fn consume_initiation<'a, T : Copy>( OPEN!( &key, - &hs, // ad - &mut pk, // pt - &msg.f_static, // ct - &msg.f_static_tag // tag + &hs, // ad + &mut pk, // pt + &msg.f_static, // ct + &msg.f_static_tag // tag )?; let peer = device.lookup_pk(&PublicKey::from(pk))?; @@ -322,10 +272,10 @@ pub fn consume_initiation<'a, T : Copy>( OPEN!( &key, - &hs, // ad - &mut ts, // pt - &msg.f_timestamp, // ct - &msg.f_timestamp_tag // tag + &hs, // ad + &mut ts, // pt + &msg.f_timestamp, // ct + &msg.f_timestamp_tag // tag )?; // check and update timestamp @@ -341,14 +291,13 @@ pub fn consume_initiation<'a, T : Copy>( Ok((peer, (msg.f_sender, eph_r_pk, hs, ck))) } -pub fn create_response( - peer : &Peer, - sender : u32, // sending identifier - state : TemporaryState // state from "consume_initiation" +pub fn create_response( + peer: &Peer, + sender: u32, // sending identifier + state: TemporaryState, // state from "consume_initiation" ) -> Result, HandshakeError> { - let mut rng = OsRng::new().unwrap(); - let mut msg : Response = Default::default(); + let mut msg: Response = Default::default(); let (receiver, eph_r_pk, hs, ck) = state; @@ -392,10 +341,10 @@ pub fn create_response( SEAL!( &key, - &hs, // ad - &[], // pt - &mut [], // ct - &mut msg.f_empty_tag // tag + &hs, // ad + &[], // pt + &mut [], // ct + &mut msg.f_empty_tag // tag ); /* not strictly needed @@ -413,22 +362,24 @@ pub fn create_response( Ok(( peer.identifier, Some(Response::into(msg)), - Some(KeyPair{ - confirmed : false, - send : Key{ - id : sender, - key : key_send.into() + Some(KeyPair { + confirmed: false, + send: Key { + id: sender, + key: key_send.into(), }, - recv : Key{ - id : receiver, - key : key_recv.into() - } - }) + recv: Key { + id: receiver, + key: key_recv.into(), + }, + }), )) } -pub fn consume_response(device : &Device, msg : &[u8]) -> Result, HandshakeError> { - +pub fn consume_response( + device: &Device, + msg: &[u8], +) -> Result, HandshakeError> { // parse message let msg = Response::try_from(msg)?; @@ -438,7 +389,12 @@ pub fn consume_response(device : &Device, msg : &[u8]) -> Result Err(HandshakeError::InvalidState), - State::InitiationSent{hs, ck, sender, eph_sk} => Ok((hs, ck, sender, eph_sk)) + State::InitiationSent { + hs, + ck, + sender, + eph_sk, + } => Ok((hs, ck, sender, eph_sk)), }?; // C := Kdf1(C, E_pub) @@ -470,10 +426,10 @@ pub fn consume_response(device : &Device, msg : &[u8]) -> Result(device : &Device, msg : &[u8]) -> Result { // external identifier - pub(crate) identifier : T, + pub(crate) identifier: T, // internal identifier - pub(crate) idx : usize, + pub(crate) idx: usize, // mutable state - state : Mutex, - timestamp : Mutex>, + state: Mutex, + timestamp: Mutex>, // constant state - pub(crate) pk : PublicKey, // public key of peer - pub(crate) ss : SharedSecret, // precomputed DH(static, static) - pub(crate) psk : Psk // psk of peer + pub(crate) pk: PublicKey, // public key of peer + pub(crate) ss: SharedSecret, // precomputed DH(static, static) + pub(crate) psk: Psk, // psk of peer } pub enum State { Reset, - InitiationSent{ - sender : u32, // assigned sender id - eph_sk : StaticSecret, - hs : GenericArray, - ck : GenericArray + InitiationSent { + sender: u32, // assigned sender id + eph_sk: StaticSecret, + hs: GenericArray, + ck: GenericArray, }, } @@ -47,32 +47,39 @@ impl Clone for State { fn clone(&self) -> State { match self { State::Reset => State::Reset, - State::InitiationSent{sender, eph_sk, hs, ck} => - State::InitiationSent{ - sender : *sender, - eph_sk : StaticSecret::from(eph_sk.to_bytes()), - hs : *hs, - ck : *ck - } + State::InitiationSent { + sender, + eph_sk, + hs, + ck, + } => State::InitiationSent { + sender: *sender, + eph_sk: StaticSecret::from(eph_sk.to_bytes()), + hs: *hs, + ck: *ck, + }, } } } -impl Peer where T : Copy { +impl Peer +where + T: Copy, +{ pub fn new( - idx : usize, - identifier : T, // external identifier - pk : PublicKey, // public key of peer - ss : SharedSecret // precomputed DH(static, static) + idx: usize, + identifier: T, // external identifier + pk: PublicKey, // public key of peer + ss: SharedSecret, // precomputed DH(static, static) ) -> Self { Self { - idx : idx, - identifier : identifier, - state : Mutex::new(State::Reset), - timestamp : Mutex::new(None), - pk : pk, - ss : ss, - psk : [0u8; 32] + idx: idx, + identifier: identifier, + state: Mutex::new(State::Reset), + timestamp: Mutex::new(None), + pk: pk, + ss: ss, + psk: [0u8; 32], } } @@ -87,10 +94,7 @@ impl Peer where T : Copy { /// /// # Arguments /// - pub fn set_state( - &self, - state_new : State - ) { + pub fn set_state(&self, state_new: State) { *self.state.lock() = state_new; } @@ -102,29 +106,28 @@ impl Peer where T : Copy { /// * ts_new - The associated timestamp pub fn check_timestamp( &self, - device : &Device, - timestamp_new : ×tamp::TAI64N + device: &Device, + timestamp_new: ×tamp::TAI64N, ) -> Result<(), HandshakeError> { - let mut state = self.state.lock(); let mut timestamp = self.timestamp.lock(); let update = match *timestamp { None => true, - Some(timestamp_old) => if timestamp::compare(×tamp_old, ×tamp_new) { - true - } else { - false + Some(timestamp_old) => { + if timestamp::compare(×tamp_old, ×tamp_new) { + true + } else { + false + } } }; if update { // release existing identifier match *state { - State::InitiationSent{sender, ..} => { - device.release(sender) - }, - _ => () + State::InitiationSent { sender, .. } => device.release(sender), + _ => (), } // reset state and update timestamp diff --git a/src/timestamp.rs b/src/timestamp.rs index e8447b1..0996f8b 100644 --- a/src/timestamp.rs +++ b/src/timestamp.rs @@ -1,6 +1,6 @@ use std::time::{SystemTime, UNIX_EPOCH}; -const TAI64_EPOCH : u64 = 0x4000000000000000; +const TAI64_EPOCH: u64 = 0x4000000000000000; pub type TAI64N = [u8; 12]; @@ -10,8 +10,8 @@ pub fn zero() -> TAI64N { pub fn now() -> TAI64N { // get system time as duration - let sysnow = SystemTime::now(); - let delta = sysnow.duration_since(UNIX_EPOCH).unwrap(); + let sysnow = SystemTime::now(); + let delta = sysnow.duration_since(UNIX_EPOCH).unwrap(); // convert to tai64n let tai64_secs = delta.as_secs() + TAI64_EPOCH; @@ -24,7 +24,7 @@ pub fn now() -> TAI64N { res } -pub fn compare(old : &TAI64N, new : &TAI64N) -> bool { +pub fn compare(old: &TAI64N, new: &TAI64N) -> bool { for i in 0..12 { if new[i] > old[i] { return true; diff --git a/src/types.rs b/src/types.rs index 593500f..a18057f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,5 +1,5 @@ -use std::fmt; use std::error::Error; +use std::fmt; // config error @@ -7,7 +7,7 @@ use std::error::Error; pub struct ConfigError(String); impl ConfigError { - pub fn new(s : &str) -> Self { + pub fn new(s: &str) -> Self { ConfigError(s.to_string()) } } @@ -37,24 +37,20 @@ pub enum HandshakeError { UnknownReceiverId, InvalidMessageFormat, OldTimestamp, - InvalidState + InvalidState, } impl fmt::Display for HandshakeError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - HandshakeError::DecryptionFailure => - write!(f, "Failed to AEAD:OPEN"), - HandshakeError::UnknownPublicKey => - write!(f, "Unknown public key"), - HandshakeError::UnknownReceiverId => - write!(f, "Receiver id not allocated to any handshake"), - HandshakeError::InvalidMessageFormat => - write!(f, "Invalid handshake message format"), - HandshakeError::OldTimestamp => - write!(f, "Timestamp is less/equal to the newest"), - HandshakeError::InvalidState => - write!(f, "Message does not apply to handshake state") + HandshakeError::DecryptionFailure => write!(f, "Failed to AEAD:OPEN"), + HandshakeError::UnknownPublicKey => write!(f, "Unknown public key"), + HandshakeError::UnknownReceiverId => { + write!(f, "Receiver id not allocated to any handshake") + } + HandshakeError::InvalidMessageFormat => write!(f, "Invalid handshake message format"), + HandshakeError::OldTimestamp => write!(f, "Timestamp is less/equal to the newest"), + HandshakeError::InvalidState => write!(f, "Message does not apply to handshake state"), } } } @@ -73,8 +69,8 @@ impl Error for HandshakeError { #[derive(Debug)] pub struct Key { - pub key : [u8; 32], - pub id : u32 + pub key: [u8; 32], + pub id: u32, } #[cfg(test)] @@ -86,16 +82,16 @@ impl PartialEq for Key { #[derive(Debug)] pub struct KeyPair { - pub confirmed : bool, // has the key-pair been confirmed? - pub send : Key, // key for outbound messages - pub recv : Key // key for inbound messages + pub confirmed: bool, // has the key-pair been confirmed? + pub send: Key, // key for outbound messages + pub recv: Key, // key for inbound messages } pub type Output = ( - T, // external identifier associated with peer - // (e.g. a reference or vector index) + T, // external identifier associated with peer + // (e.g. a reference or vector index) Option>, // message to send - Option // resulting key-pair of successful handshake + Option, // resulting key-pair of successful handshake ); // preshared key -- cgit v1.2.3-59-g8ed1b