diff options
author | Mathias Hall-Andersen <mathias@hall-andersen.dk> | 2019-07-17 16:28:21 +0200 |
---|---|---|
committer | Mathias Hall-Andersen <mathias@hall-andersen.dk> | 2019-07-17 16:28:21 +0200 |
commit | 4817ca79060eb303452730aed4f4ad7ca44b8579 (patch) | |
tree | 8790b0c4e80613bd393b6a435b4866bde5fa03f0 /src | |
parent | Use precomputed static-static (diff) | |
download | wireguard-rs-4817ca79060eb303452730aed4f4ad7ca44b8579.tar.xz wireguard-rs-4817ca79060eb303452730aed4f4ad7ca44b8579.zip |
Better seperation and introduction of timestamp
Diffstat (limited to 'src')
-rw-r--r-- | src/device.rs | 11 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/noise.rs | 30 | ||||
-rw-r--r-- | src/peer.rs | 99 | ||||
-rw-r--r-- | src/timestamp.rs | 11 | ||||
-rw-r--r-- | src/types.rs | 23 |
6 files changed, 136 insertions, 39 deletions
diff --git a/src/device.rs b/src/device.rs index 6107e34..928863a 100644 --- a/src/device.rs +++ b/src/device.rs @@ -9,6 +9,7 @@ use x25519_dalek::StaticSecret; use crate::noise; use crate::types::*; +use crate::peer::Peer; pub struct Device { pub sk : StaticSecret, // static secret key @@ -62,12 +63,10 @@ impl Device { // map : new index -> peer - self.peers.push(Peer { - state : Mutex::new(State::Reset{ts : None}), - pk : pk, - ss : self.sk.diffie_hellman(&pk), - psk : [0u8; 32] - }); + self.peers.push(Peer::new( + pk, + self.sk.diffie_hellman(&pk) + )); Ok(()) } @@ -1,5 +1,6 @@ mod types; mod noise; mod messages; +mod peer; mod device; mod timestamp; diff --git a/src/noise.rs b/src/noise.rs index 702f084..7cc5f6c 100644 --- a/src/noise.rs +++ b/src/noise.rs @@ -13,6 +13,7 @@ use crypto::aead::{AeadEncryptor,AeadDecryptor}; use rand::rngs::OsRng; use crate::types::*; +use crate::peer::{State, Peer}; use crate::device::Device; use crate::messages; use crate::timestamp; @@ -166,25 +167,31 @@ pub fn create_initiation( msg.f_sender = id; // (E_priv, E_pub) := DH-Generate() + let sk = StaticSecret::new(&mut rng); let pk = PublicKey::from(&sk); // C := Kdf(C, E_pub) + let ck = KDF1!(&ck, pk.as_bytes()); // msg.ephemeral := E_pub + msg.f_ephemeral = *pk.as_bytes(); // H := HASH(H, msg.ephemeral) + let hs = HASH!(&hs, msg.f_ephemeral); // (C, k) := Kdf2(C, DH(E_priv, S_pub)) + let (ck, key) = KDF2!( &ck, sk.diffie_hellman(&peer.pk).as_bytes() ); // msg.static := Aead(k, 0, S_pub, H) + SEAL!( &key, &hs, // ad @@ -194,39 +201,44 @@ pub fn create_initiation( ); // H := Hash(H || msg.static) + let hs = HASH!(&hs, &msg.f_static, &msg.f_static_tag); // (C, k) := Kdf2(C, DH(S_priv, S_pub)) + let (ck, key) = KDF2!( &ck, - peer.ss.as_bytes() // precomputed + peer.ss.as_bytes() // precomputed static-static ); // msg.timestamp := Aead(k, 0, Timestamp(), H) + SEAL!( &key, &hs, // ad - ×tamp::new(), // pt + ×tamp::now(), // pt &mut msg.f_timestamp, // ct &mut msg.f_timestamp_tag // tag ); // H := Hash(H || msg.timestamp) + let hs = HASH!(&hs, &msg.f_timestamp, &msg.f_timestamp_tag); - // mutate state of peer + // update state of peer - let mut st = peer.state.lock().unwrap(); - *st = State::InitiationSent{ - hs : hs, - ck : ck - }; + peer.set_state( + State::InitiationSent{ + hs : hs, + ck : ck + } + ); // return message as vector Ok(messages::Initiation::into(msg)) } -pub fn process_initiation(peer : &Peer) -> Result<Output, ()> { +pub fn process_initiation(device : &Device, peer : &Peer) -> Result<Output, ()> { Err(()) } diff --git a/src/peer.rs b/src/peer.rs new file mode 100644 index 0000000..3c81f32 --- /dev/null +++ b/src/peer.rs @@ -0,0 +1,99 @@ +use std::sync::Mutex; + +use generic_array::typenum::U32; +use generic_array::GenericArray; + +use x25519_dalek::PublicKey; +use x25519_dalek::SharedSecret; + +use crate::types::*; +use crate::timestamp; + +pub struct Peer { + // mutable state + state : Mutex<State>, + timestamp : Mutex<Option<timestamp::TAI64N>>, + + // constant state + pub pk : PublicKey, // public key of peer + pub ss : SharedSecret, // precomputed DH(static, static) + pub psk : Psk // psk of peer +} + +#[derive(Debug, Copy, Clone)] +pub enum State { + Reset, + InitiationSent{ + hs : GenericArray<u8, U32>, + ck : GenericArray<u8, U32> + }, +} + +impl Peer { + pub fn new( + pk : PublicKey, // public key of peer + ss : SharedSecret // precomputed DH(static, static) + ) -> Self { + Self { + state : Mutex::new(State::Reset), + timestamp : Mutex::new(None), + pk : pk, + ss : ss, + psk : [0u8; 32] + } + } + + /// Return the state of the peer + /// + /// # Arguments + pub fn get_state(&self) -> State { + *self.state.lock().unwrap() + } + + /// Set the state of the peer unconditionally + /// + /// # Arguments + /// + pub fn set_state( + &self, + state_new : State + ) { + let mut state = self.state.lock().unwrap(); + *state = state_new; + } + + /// Set the mutable state of the peer conditioned on the timestamp being newer + /// + /// # Arguments + /// + /// * st_new - The updated state of the peer + /// * ts_new - The associated timestamp + /// + /// # Returns + /// + /// A Boolean indicating if the state was updated + pub fn set_state_timestamp( + &self, + state_new : State, + timestamp_new : ×tamp::TAI64N + ) -> bool { + let mut state = self.state.lock().unwrap(); + let mut timestamp = self.timestamp.lock().unwrap(); + match *timestamp { + None => { + // no prior timestamp know + *state = state_new; + *timestamp = Some(*timestamp_new); + true + }, + Some(timestamp_old) => if timestamp::compare(×tamp_old, ×tamp_new) { + // new timestamp is strictly greater + *state = state_new; + *timestamp = Some(*timestamp_new); + true + } else { + false + } + } + } +} diff --git a/src/timestamp.rs b/src/timestamp.rs index ba5c2f1..6ac20b8 100644 --- a/src/timestamp.rs +++ b/src/timestamp.rs @@ -1,5 +1,14 @@ pub type TAI64N = [u8; 12]; -pub fn new() -> TAI64N { +pub fn now() -> TAI64N { [0u8; 12] // TODO } + +pub fn compare(old : &TAI64N, new : &TAI64N) -> bool { + for i in 0..12 { + if new[i] > old[i] { + return true; + } + } + return false; +} diff --git a/src/types.rs b/src/types.rs index 54f4801..81c1dc7 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,13 +1,9 @@ use std::fmt; -use std::sync::Mutex; use std::error::Error; use x25519_dalek::PublicKey; use x25519_dalek::SharedSecret; -use generic_array::typenum::U32; -use generic_array::GenericArray; - use crate::timestamp; // config error @@ -86,22 +82,3 @@ pub struct Output ( pub type Psk = [u8; 32]; -pub struct Peer { - // mutable state - pub state : Mutex<State>, - - // constant state - pub pk : PublicKey, // public key of peer - pub ss : SharedSecret, // precomputed DH(static, static) - pub psk : Psk // psk of peer -} - -pub enum State { - Reset{ - ts : Option<timestamp::TAI64N> - }, - InitiationSent{ - hs : GenericArray<u8, U32>, - ck : GenericArray<u8, U32> - }, -} |