aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Hall-Andersen <mathias@hall-andersen.dk>2019-07-25 22:04:35 +0200
committerMathias Hall-Andersen <mathias@hall-andersen.dk>2019-07-25 22:04:35 +0200
commit43b56dfb58b780fef6bccf7e77cd3d2458a94582 (patch)
tree66caaf094a3595dabfb27e479423b3180543e9fb
parentFixed GenericArray version (diff)
downloadwireguard-rs-43b56dfb58b780fef6bccf7e77cd3d2458a94582.tar.xz
wireguard-rs-43b56dfb58b780fef6bccf7e77cd3d2458a94582.zip
Formatting
-rw-r--r--src/device.rs78
-rw-r--r--src/lib.rs6
-rw-r--r--src/messages.rs154
-rw-r--r--src/noise.rs318
-rw-r--r--src/peer.rs101
-rw-r--r--src/timestamp.rs8
-rw-r--r--src/types.rs42
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<T> {
- pub sk : StaticSecret, // static secret key
- pub pk : PublicKey, // static public key
- peers : Vec<Peer<T>>, // peer index -> state
- pk_map : HashMap<[u8; 32], usize>, // public key -> peer index
- id_map : RwLock<HashMap<u32, usize>> // receive ids -> peer index
+ pub sk: StaticSecret, // static secret key
+ pub pk: PublicKey, // static public key
+ peers: Vec<Peer<T>>, // peer index -> state
+ pk_map: HashMap<[u8; 32], usize>, // public key -> peer index
+ id_map: RwLock<HashMap<u32, usize>>, // 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 <T>Device<T> where T : Copy {
+impl<T> Device<T>
+where
+ T: Copy,
+{
/// Initialize a new handshake state machine
///
/// # Arguments
///
/// * `sk` - x25519 scalar representing the local private key
- pub fn new(sk : StaticSecret) -> Device<T> {
+ pub fn new(sk: StaticSecret) -> Device<T> {
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 <T>Device<T> 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 <T>Device<T> 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 <T>Device<T> 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 <T>Device<T> where T : Copy {
/// # Returns
///
/// The call might fail if the public key is not found
- pub fn psk(&mut self, pk : PublicKey, psk : Option<Psk>) -> Result<(), ConfigError> {
+ pub fn psk(&mut self, pk: PublicKey, psk: Option<Psk>) -> Result<(), ConfigError> {
match self.pk_map.get(pk.as_bytes()) {
Some(&idx) => {
let peer = &mut self.peers[idx];
@@ -92,8 +96,8 @@ impl <T>Device<T> 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 <T>Device<T> 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 <T>Device<T> where T : Copy {
/// # Arguments
///
/// * `pk` - Public key of peer to initiate handshake for
- pub fn begin(&self, pk : &PublicKey) -> Result<Vec<u8>, HandshakeError> {
+ pub fn begin(&self, pk: &PublicKey) -> Result<Vec<u8>, HandshakeError> {
match self.pk_map.get(pk.as_bytes()) {
None => Err(HandshakeError::UnknownPublicKey),
Some(&idx) => {
@@ -129,7 +133,7 @@ impl <T>Device<T> where T : Copy {
/// # Arguments
///
/// * `msg` - Byte slice containing the message (untrusted input)
- pub fn process(&self, msg : &[u8]) -> Result<Output<T>, HandshakeError> {
+ pub fn process(&self, msg: &[u8]) -> Result<Output<T>, HandshakeError> {
match msg.get(0) {
Some(&messages::TYPE_INITIATION) => {
// consume the initiation
@@ -143,37 +147,36 @@ impl <T>Device<T> 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<T>, HandshakeError> {
+ pub(crate) fn lookup_pk(&self, pk: &PublicKey) -> Result<&Peer<T>, 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<T>, HandshakeError> {
+ pub(crate) fn lookup_id(&self, id: u32) -> Result<&Peer<T>, 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 <T>Device<T> 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 <T>Device<T> 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<Self, Self::Error> {
-
// check length of slice matches message
if value.len() != mem::size_of::<Self>() {
@@ -44,7 +42,7 @@ impl TryFrom<&[u8]> for Initiation {
// create owned copy
let mut owned = [0u8; mem::size_of::<Self>()];
- let mut msg : Self;
+ let mut msg: Self;
owned.copy_from_slice(value);
// cast to Initiation
@@ -76,10 +74,8 @@ impl Into<Vec<u8>> for Initiation {
msg.f_sender = msg.f_sender.to_le();
// cast to array
- let array : [u8; mem::size_of::<Self>()];
- unsafe {
- array = mem::transmute::<Self, [u8; mem::size_of::<Self>()]>(msg)
- };
+ let array: [u8; mem::size_of::<Self>()];
+ unsafe { array = mem::transmute::<Self, [u8; mem::size_of::<Self>()]>(msg) };
array.to_vec()
}
@@ -88,13 +84,13 @@ impl Into<Vec<u8>> 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<Self, Self::Error> {
-
// check length of slice matches message
if value.len() != mem::size_of::<Self>() {
@@ -155,7 +149,7 @@ impl TryFrom<&[u8]> for Response {
// create owned copy
let mut owned = [0u8; mem::size_of::<Self>()];
- let mut msg : Self;
+ let mut msg: Self;
owned.copy_from_slice(value);
// cast to MessageResponse
@@ -189,10 +183,8 @@ impl Into<Vec<u8>> for Response {
msg.f_receiver = msg.f_receiver.to_le();
// cast to array
- let array : [u8; mem::size_of::<Self>()];
- unsafe {
- array = mem::transmute::<Self, [u8; mem::size_of::<Self>()]>(msg)
- };
+ let array: [u8; mem::size_of::<Self>()];
+ unsafe { array = mem::transmute::<Self, [u8; mem::size_of::<Self>()]>(msg) };
array.to_vec()
}
@@ -201,11 +193,11 @@ 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]
+ 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<u8> = msg.into();
- let msg_p : Response = Response::try_from(&buf[..]).unwrap();
+ let buf: Vec<u8> = 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<u8> = msg.into();
+ 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 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<Blake2s>;
type TemporaryState = (u32, PublicKey, GenericArray<u8, U32>, GenericArray<u8, U32>);
-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 = <Blake2s as Digest>::new();
- Digest::input(&mut hsh, $input1);
- Digest::result(hsh)
- }
- };
-
- ($input1:expr, $input2:expr) => {
- {
- let mut hsh = <Blake2s as Digest>::new();
- Digest::input(&mut hsh, $input1);
- Digest::input(&mut hsh, $input2);
- Digest::result(hsh)
- }
- };
-
- ($input1:expr, $input2:expr, $input3:expr) => {
- {
- let mut hsh = <Blake2s as Digest>::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<T : Copy>(
- device : &Device<T>,
- peer : &Peer<T>,
- sender : u32
+pub fn create_initiation<T: Copy>(
+ device: &Device<T>,
+ peer: &Peer<T>,
+ sender: u32,
) -> Result<Vec<u8>, 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<T : Copy>(
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<T : Copy>(
SEAL!(
&key,
- &hs, // ad
- &timestamp::now(), // pt
- &mut msg.f_timestamp, // ct
- &mut msg.f_timestamp_tag // tag
+ &hs, // ad
+ &timestamp::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<T : Copy>(
// 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<T>,
- msg : &[u8]
+pub fn consume_initiation<'a, T: Copy>(
+ device: &'a Device<T>,
+ msg: &[u8],
) -> Result<(&'a Peer<T>, 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<T : Copy>(
- peer : &Peer<T>,
- sender : u32, // sending identifier
- state : TemporaryState // state from "consume_initiation"
+pub fn create_response<T: Copy>(
+ peer: &Peer<T>,
+ sender: u32, // sending identifier
+ state: TemporaryState, // state from "consume_initiation"
) -> Result<Output<T>, 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<T : Copy>(
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<T : Copy>(
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<T : Copy>(device : &Device<T>, msg : &[u8]) -> Result<Output<T>, HandshakeError> {
-
+pub fn consume_response<T: Copy>(
+ device: &Device<T>,
+ msg: &[u8],
+) -> Result<Output<T>, HandshakeError> {
// parse message
let msg = Response::try_from(msg)?;
@@ -438,7 +389,12 @@ pub fn consume_response<T : Copy>(device : &Device<T>, msg : &[u8]) -> Result<Ou
let peer = device.lookup_id(msg.f_receiver)?;
let (hs, ck, sender, eph_sk) = match peer.get_state() {
State::Reset => 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<T : Copy>(device : &Device<T>, msg : &[u8]) -> Result<Ou
OPEN!(
&key,
- &hs, // ad
- &mut [], // pt
- &[], // ct
- &msg.f_empty_tag // tag
+ &hs, // ad
+ &mut [], // pt
+ &[], // ct
+ &msg.f_empty_tag // tag
)?;
// derive key-pair
@@ -485,16 +441,16 @@ pub fn consume_response<T : Copy>(device : &Device<T>, msg : &[u8]) -> Result<Ou
Ok((
peer.identifier,
None,
- Some(KeyPair{
- confirmed : true,
- send : Key{
- id : sender,
- key : key_send.into()
+ Some(KeyPair {
+ confirmed: true,
+ send: Key {
+ id: sender,
+ key: key_send.into(),
+ },
+ recv: Key {
+ id: msg.f_sender,
+ key: key_recv.into(),
},
- recv : Key{
- id : msg.f_sender,
- key : key_recv.into()
- }
- })
+ }),
))
}
diff --git a/src/peer.rs b/src/peer.rs
index dd7d303..e4dff8b 100644
--- a/src/peer.rs
+++ b/src/peer.rs
@@ -4,12 +4,12 @@ use generic_array::typenum::U32;
use generic_array::GenericArray;
use x25519_dalek::PublicKey;
-use x25519_dalek::StaticSecret;
use x25519_dalek::SharedSecret;
+use x25519_dalek::StaticSecret;
-use crate::types::*;
-use crate::timestamp;
use crate::device::Device;
+use crate::timestamp;
+use crate::types::*;
/* Represents the recomputation and state of a peer.
*
@@ -18,28 +18,28 @@ use crate::device::Device;
pub struct Peer<T> {
// external identifier
- pub(crate) identifier : T,
+ pub(crate) identifier: T,
// internal identifier
- pub(crate) idx : usize,
+ pub(crate) idx: usize,
// mutable state
- state : Mutex<State>,
- timestamp : Mutex<Option<timestamp::TAI64N>>,
+ state: Mutex<State>,
+ timestamp: Mutex<Option<timestamp::TAI64N>>,
// 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<u8, U32>,
- ck : GenericArray<u8, U32>
+ InitiationSent {
+ sender: u32, // assigned sender id
+ eph_sk: StaticSecret,
+ hs: GenericArray<u8, U32>,
+ ck: GenericArray<u8, U32>,
},
}
@@ -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 <T>Peer<T> where T : Copy {
+impl<T> Peer<T>
+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 <T>Peer<T> 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 <T>Peer<T> where T : Copy {
/// * ts_new - The associated timestamp
pub fn check_timestamp(
&self,
- device : &Device<T>,
- timestamp_new : &timestamp::TAI64N
+ device: &Device<T>,
+ timestamp_new: &timestamp::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(&timestamp_old, &timestamp_new) {
- true
- } else {
- false
+ Some(timestamp_old) => {
+ if timestamp::compare(&timestamp_old, &timestamp_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> = (
- 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<Vec<u8>>, // message to send
- Option<KeyPair> // resulting key-pair of successful handshake
+ Option<KeyPair>, // resulting key-pair of successful handshake
);
// preshared key