summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMathias Hall-Andersen <mathias@hall-andersen.dk>2019-07-17 16:28:21 +0200
committerMathias Hall-Andersen <mathias@hall-andersen.dk>2019-07-17 16:28:21 +0200
commit4817ca79060eb303452730aed4f4ad7ca44b8579 (patch)
tree8790b0c4e80613bd393b6a435b4866bde5fa03f0 /src
parentUse precomputed static-static (diff)
downloadwireguard-rs-4817ca79060eb303452730aed4f4ad7ca44b8579.tar.xz
wireguard-rs-4817ca79060eb303452730aed4f4ad7ca44b8579.zip
Better seperation and introduction of timestamp
Diffstat (limited to 'src')
-rw-r--r--src/device.rs11
-rw-r--r--src/lib.rs1
-rw-r--r--src/noise.rs30
-rw-r--r--src/peer.rs99
-rw-r--r--src/timestamp.rs11
-rw-r--r--src/types.rs23
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(())
}
diff --git a/src/lib.rs b/src/lib.rs
index 2edf0fd..ee22a9b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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
- &timestamp::new(), // pt
+ &timestamp::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 : &timestamp::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(&timestamp_old, &timestamp_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>
- },
-}