summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Hall-Andersen <mathias@hall-andersen.dk>2019-07-18 19:52:23 +0200
committerMathias Hall-Andersen <mathias@hall-andersen.dk>2019-07-18 19:52:23 +0200
commite0e95d9679e4cb0eb905d9f0910a49fe86586982 (patch)
tree290fe613430ea4a30fa7ee947cf95d0dbab0ccab
parentBegin processing of initation (diff)
downloadwireguard-rs-e0e95d9679e4cb0eb905d9f0910a49fe86586982.tar.xz
wireguard-rs-e0e95d9679e4cb0eb905d9f0910a49fe86586982.zip
Begin creation of response
-rw-r--r--Cargo.toml1
-rw-r--r--src/device.rs36
-rw-r--r--src/lib.rs4
-rw-r--r--src/messages.rs134
-rw-r--r--src/noise.rs36
-rw-r--r--src/peer.rs31
-rw-r--r--src/types.rs16
7 files changed, 164 insertions, 94 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 354f8aa..2d27e3d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,6 +3,7 @@ name = "wg-handshake"
version = "0.1.0"
authors = ["Mathias Hall-Andersen <mathias@hall-andersen.dk>"]
edition = "2018"
+license = "GPL-3.0"
[dependencies]
rand = "0.6.5"
diff --git a/src/device.rs b/src/device.rs
index 85adc69..0635a5e 100644
--- a/src/device.rs
+++ b/src/device.rs
@@ -60,13 +60,13 @@ impl Device {
// map : pk -> new index
- self.pkmap.insert(*pk.as_bytes(), self.peers.len());
+ let idx = self.peers.len();
+ self.pkmap.insert(*pk.as_bytes(), idx);
// map : new index -> peer
self.peers.push(Peer::new(
- pk,
- self.sk.diffie_hellman(&pk)
+ idx, pk, self.sk.diffie_hellman(&pk)
));
Ok(())
@@ -115,19 +115,12 @@ impl Device {
None => Err(HandshakeError::UnknownPublicKey),
Some(&idx) => {
let peer = &self.peers[idx];
- let id = self.allocate(idx);
- noise::create_initiation(self, peer, id)
+ let sender = self.allocate(idx);
+ noise::create_initiation(self, peer, sender)
}
}
}
- pub fn lookup(&self, pk : &PublicKey) -> Result<&Peer, HandshakeError> {
- match self.pkmap.get(pk.as_bytes()) {
- Some(&idx) => Ok(&self.peers[idx]),
- _ => Err(HandshakeError::UnknownPublicKey)
- }
- }
-
/// Process a handshake message.
///
/// # Arguments
@@ -136,7 +129,17 @@ impl Device {
pub fn process(&self, msg : &[u8]) -> Result<Output, HandshakeError> {
match msg.get(0) {
Some(&messages::TYPE_INITIATION) => {
- noise::process_initiation(self, msg)
+ // consume the initiation
+ let (peer, receiver, hs, ck) = noise::consume_initiation(self, msg)?;
+
+ // allocate index for response
+ let sender = self.allocate(peer.idx);
+
+ // create response
+ noise::create_response(self, peer, sender, receiver, hs, ck).map_err(|e| {
+ self.release(sender);
+ e
+ })
},
Some(&messages::TYPE_RESPONSE) => {
Err(HandshakeError::InvalidMessageFormat)
@@ -144,6 +147,13 @@ impl Device {
_ => Err(HandshakeError::InvalidMessageFormat)
}
}
+
+ pub fn lookup(&self, pk : &PublicKey) -> Result<&Peer, HandshakeError> {
+ match self.pkmap.get(pk.as_bytes()) {
+ Some(&idx) => Ok(&self.peers[idx]),
+ _ => Err(HandshakeError::UnknownPublicKey)
+ }
+ }
}
impl Device {
diff --git a/src/lib.rs b/src/lib.rs
index ee22a9b..e2d9b8d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,3 +4,7 @@ mod messages;
mod peer;
mod device;
mod timestamp;
+
+// publicly exposed interface
+
+pub use device::Device;
diff --git a/src/messages.rs b/src/messages.rs
index da26e48..52a3393 100644
--- a/src/messages.rs
+++ b/src/messages.rs
@@ -11,10 +11,12 @@ const SIZE_TIMESTAMP : usize = 12;
pub const TYPE_INITIATION : u8 = 1;
pub const TYPE_RESPONSE : u8 = 2;
-
-/* Wireguard handshake (noise) initiation message
- * initator -> responder
+/* Functions related to the packing / unpacking of
+ * the fixed-sized noise handshake messages.
+ *
+ * The unpacked types are unexposed implementation details.
*/
+
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Initiation {
@@ -83,15 +85,6 @@ impl Into<Vec<u8>> for Initiation {
}
}
-impl fmt::Debug for Initiation {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f,
- "MessageInitiation {{ type = {} }}",
- self.f_type
- )
- }
-}
-
impl Default for Initiation {
fn default() -> Self {
Self {
@@ -106,6 +99,15 @@ impl Default for Initiation {
}
}
+impl fmt::Debug for Initiation {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f,
+ "MessageInitiation {{ type = {} }}",
+ self.f_type
+ )
+ }
+}
+
#[cfg(test)]
impl PartialEq for Initiation {
fn eq(&self, other: &Self) -> bool {
@@ -122,10 +124,6 @@ impl PartialEq for Initiation {
#[cfg(test)]
impl Eq for Initiation {}
-
-/* Wireguard handshake (noise) responder message
- * responder -> initator
- */
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Response {
@@ -194,6 +192,19 @@ impl Into<Vec<u8>> 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]
+ }
+ }
+}
+
+
impl fmt::Debug for Response {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f,
@@ -220,23 +231,20 @@ mod tests {
#[test]
fn message_response_identity() {
- let msg = Response {
- f_type : TYPE_RESPONSE as u32,
- f_sender : 146252,
- f_receiver : 554442,
- f_ephemeral : [
- // ephemeral public key
- 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
- ],
- f_empty_tag : [
- // tag
- 0x60, 0x0e, 0x1e, 0x95, 0x41, 0x6b, 0x52, 0x05,
- 0xa2, 0x09, 0xe1, 0xbf, 0x40, 0x05, 0x2f, 0xde
- ]
- };
+ 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
+ ];
+ msg.f_empty_tag = [
+ 0x60, 0x0e, 0x1e, 0x95, 0x41, 0x6b, 0x52, 0x05,
+ 0xa2, 0x09, 0xe1, 0xbf, 0x40, 0x05, 0x2f, 0xde
+ ];
let buf : Vec<u8> = msg.into();
let msg_p : Response = Response::try_from(&buf[..]).unwrap();
@@ -245,39 +253,33 @@ mod tests {
#[test]
fn message_initiate_identity() {
- let msg = Initiation {
- f_type : TYPE_INITIATION as u32,
- f_sender : 575757,
- f_ephemeral : [
- // ephemeral public key
- 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
- ],
- f_static : [
- // encrypted static public key
- 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
- ],
- f_static_tag : [
- // poly1305 tag
- 0x45, 0xac, 0x8d, 0x43, 0xea, 0x1b, 0x2f, 0x02,
- 0x45, 0x5d, 0x86, 0x37, 0xee, 0x83, 0x6b, 0x42
- ],
- f_timestamp : [
- // timestamp
- 0x4f, 0x1c, 0x60, 0xec, 0x0e, 0xf6, 0x36, 0xf0,
- 0x78, 0x28, 0x57, 0x42
- ],
- f_timestamp_tag : [
- // poly1305 tag
- 0x60, 0x0e, 0x1e, 0x95, 0x41, 0x6b, 0x52, 0x05,
- 0xa2, 0x09, 0xe1, 0xbf, 0x40, 0x05, 0x2f, 0xde
- ]
- };
+ 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
+ ];
+ 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
+ ];
+ msg.f_static_tag = [
+ 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
+ ];
+ msg.f_timestamp_tag = [
+ 0x60, 0x0e, 0x1e, 0x95, 0x41, 0x6b, 0x52, 0x05,
+ 0xa2, 0x09, 0xe1, 0xbf, 0x40, 0x05, 0x2f, 0xde
+ ];
let buf : Vec<u8> = msg.into();
assert_eq!(msg, Initiation::try_from(&buf[..]).unwrap());
diff --git a/src/noise.rs b/src/noise.rs
index 9de03cd..9f127e8 100644
--- a/src/noise.rs
+++ b/src/noise.rs
@@ -14,6 +14,9 @@ use crypto::aead::{AeadEncryptor,AeadDecryptor};
use rand::rngs::OsRng;
+use generic_array::typenum::U32;
+use generic_array::GenericArray;
+
use crate::types::*;
use crate::peer::{State, Peer};
use crate::device::Device;
@@ -248,7 +251,10 @@ pub fn create_initiation(
Ok(Initiation::into(msg))
}
-pub fn process_initiation(device : &Device, msg : &[u8]) -> Result<Output, HandshakeError> {
+pub fn consume_initiation<'a>(
+ device : &'a Device,
+ msg : &[u8]
+) -> Result<(&'a Peer, u32, GenericArray<u8, U32>, GenericArray<u8, U32>), HandshakeError> {
// parse message
@@ -310,15 +316,27 @@ pub fn process_initiation(device : &Device, msg : &[u8]) -> Result<Output, Hands
&msg.f_timestamp_tag // tag
)?;
- // update state of peer
+ // check and update timestamp
- peer.set_state_timestamp(
- State::InitiationSent{
- hs : hs,
- ck : ck
- },
- &ts
- )?;
+ peer.check_timestamp(&ts)?;
+
+ // return state (to create response)
+
+ Ok((peer, msg.f_sender, hs, ck))
+}
+
+pub fn create_response(
+ device : &Device,
+ peer : &Peer,
+ sender : u32,
+ receiver : u32,
+ hs : GenericArray<u8, U32>,
+ ck : GenericArray<u8, U32>
+) -> Result<Output, HandshakeError> {
+
+ let mut msg : Response = Default::default();
+
+ // parse message
Ok(Output(None, None))
}
diff --git a/src/peer.rs b/src/peer.rs
index 6c4bb3c..e656d56 100644
--- a/src/peer.rs
+++ b/src/peer.rs
@@ -9,7 +9,14 @@ use x25519_dalek::SharedSecret;
use crate::types::*;
use crate::timestamp;
+/* Represents the recomputation and state of a peer.
+ *
+ * This type is only for internal use and not exposed.
+ */
+
pub struct Peer {
+ pub idx : usize,
+
// mutable state
state : Mutex<State>,
timestamp : Mutex<Option<timestamp::TAI64N>>,
@@ -31,10 +38,12 @@ pub enum State {
impl Peer {
pub fn new(
+ idx : usize,
pk : PublicKey, // public key of peer
ss : SharedSecret // precomputed DH(static, static)
) -> Self {
Self {
+ idx : idx,
state : Mutex::new(State::Reset),
timestamp : Mutex::new(None),
pk : pk,
@@ -62,6 +71,28 @@ impl Peer {
*state = state_new;
}
+ /// # Arguments
+ ///
+ /// * ts_new - The timestamp
+ ///
+ /// # Returns
+ ///
+ /// A Boolean indicating if the state was updated
+ pub fn check_timestamp(&self,
+ timestamp_new : &timestamp::TAI64N) -> Result<(), HandshakeError> {
+
+ let mut timestamp = self.timestamp.lock().unwrap();
+ match *timestamp {
+ None => Ok(()),
+ Some(timestamp_old) => if timestamp::compare(&timestamp_old, &timestamp_new) {
+ *timestamp = Some(*timestamp_new);
+ Ok(())
+ } else {
+ Err(HandshakeError::OldTimestamp)
+ }
+ }
+ }
+
/// Set the mutable state of the peer conditioned on the timestamp being newer
///
/// # Arguments
diff --git a/src/types.rs b/src/types.rs
index 464ad81..a2a7cdd 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -1,11 +1,6 @@
use std::fmt;
use std::error::Error;
-use x25519_dalek::PublicKey;
-use x25519_dalek::SharedSecret;
-
-use crate::timestamp;
-
// config error
#[derive(Debug)]
@@ -45,7 +40,16 @@ pub enum HandshakeError {
impl fmt::Display for HandshakeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "HandshakeError")
+ match self {
+ HandshakeError::DecryptionFailure =>
+ write!(f, "Failed to AEAD:OPEN"),
+ HandshakeError::UnknownPublicKey =>
+ write!(f, "Unknown public key"),
+ HandshakeError::InvalidMessageFormat =>
+ write!(f, "Invalid handshake message format"),
+ HandshakeError::OldTimestamp =>
+ write!(f, "Timestamp is less/equal to the newest")
+ }
}
}