Begin processing of initation
This commit is contained in:
@@ -8,6 +8,7 @@ use x25519_dalek::PublicKey;
|
|||||||
use x25519_dalek::StaticSecret;
|
use x25519_dalek::StaticSecret;
|
||||||
|
|
||||||
use crate::noise;
|
use crate::noise;
|
||||||
|
use crate::messages;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use crate::peer::Peer;
|
use crate::peer::Peer;
|
||||||
|
|
||||||
@@ -109,9 +110,9 @@ impl Device {
|
|||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `pk` - Public key of peer to initiate handshake for
|
/// * `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.pkmap.get(pk.as_bytes()) {
|
match self.pkmap.get(pk.as_bytes()) {
|
||||||
None => Err(HandshakeError::new()),
|
None => Err(HandshakeError::UnknownPublicKey),
|
||||||
Some(&idx) => {
|
Some(&idx) => {
|
||||||
let peer = &self.peers[idx];
|
let peer = &self.peers[idx];
|
||||||
let id = self.allocate(idx);
|
let id = self.allocate(idx);
|
||||||
@@ -120,15 +121,27 @@ impl Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
/// Process a handshake message.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `msg` - Byte slice containing the message (untrusted input)
|
/// * `msg` - Byte slice containing the message (untrusted input)
|
||||||
pub fn process(&self, msg : &[u8]) -> Result<Output, HandshakeError> {
|
pub fn process(&self, msg : &[u8]) -> Result<Output, HandshakeError> {
|
||||||
// inspect type field
|
|
||||||
match msg.get(0) {
|
match msg.get(0) {
|
||||||
_ => Err(HandshakeError::new())
|
Some(&messages::TYPE_INITIATION) => {
|
||||||
|
noise::process_initiation(self, msg)
|
||||||
|
},
|
||||||
|
Some(&messages::TYPE_RESPONSE) => {
|
||||||
|
Err(HandshakeError::InvalidMessageFormat)
|
||||||
|
},
|
||||||
|
_ => Err(HandshakeError::InvalidMessageFormat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,3 +160,38 @@ impl Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn handshake() {
|
||||||
|
// generate new keypairs
|
||||||
|
|
||||||
|
let mut rng = OsRng::new().unwrap();
|
||||||
|
|
||||||
|
let sk1 = StaticSecret::new(&mut rng);
|
||||||
|
let pk1 = PublicKey::from(&sk1);
|
||||||
|
|
||||||
|
let sk2 = StaticSecret::new(&mut rng);
|
||||||
|
let pk2 = PublicKey::from(&sk2);
|
||||||
|
|
||||||
|
// intialize devices on both ends
|
||||||
|
|
||||||
|
let mut dev1 = Device::new(sk1);
|
||||||
|
let mut dev2 = Device::new(sk2);
|
||||||
|
|
||||||
|
dev1.add(pk2).unwrap();
|
||||||
|
dev2.add(pk1).unwrap();
|
||||||
|
|
||||||
|
// create initiation
|
||||||
|
|
||||||
|
let msg1 = dev1.begin(&pk2).unwrap();
|
||||||
|
|
||||||
|
// process initiation and create response
|
||||||
|
|
||||||
|
let out1 = dev2.process(&msg1).unwrap();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
use crate::types::*;
|
||||||
|
|
||||||
const SIZE_TAG : usize = 16;
|
const SIZE_TAG : usize = 16;
|
||||||
const SIZE_X25519_POINT : usize = 32;
|
const SIZE_X25519_POINT : usize = 32;
|
||||||
const SIZE_TIMESTAMP : usize = 12;
|
const SIZE_TIMESTAMP : usize = 12;
|
||||||
|
|
||||||
pub const TYPE_INITIATION : u32 = 1;
|
pub const TYPE_INITIATION : u8 = 1;
|
||||||
pub const TYPE_RESPONSE : u32 = 2;
|
pub const TYPE_RESPONSE : u8 = 2;
|
||||||
|
|
||||||
|
|
||||||
/* Wireguard handshake (noise) initiation message
|
/* Wireguard handshake (noise) initiation message
|
||||||
* initator -> responder
|
* initator -> responder
|
||||||
@@ -23,22 +27,42 @@ pub struct Initiation {
|
|||||||
pub f_timestamp_tag : [u8; SIZE_TAG],
|
pub f_timestamp_tag : [u8; SIZE_TAG],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&[u8]> for Initiation {
|
impl TryFrom<&[u8]> for Initiation {
|
||||||
fn from(b: &[u8]) -> Self {
|
|
||||||
|
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>() {
|
||||||
|
return Err(HandshakeError::InvalidMessageFormat);
|
||||||
|
}
|
||||||
|
|
||||||
// create owned copy
|
// create owned copy
|
||||||
|
|
||||||
let mut owned = [0u8; mem::size_of::<Self>()];
|
let mut owned = [0u8; mem::size_of::<Self>()];
|
||||||
let mut msg : Self;
|
let mut msg : Self;
|
||||||
owned.copy_from_slice(b);
|
owned.copy_from_slice(value);
|
||||||
|
|
||||||
// cast to Initiation
|
// cast to Initiation
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
msg = mem::transmute::<[u8; mem::size_of::<Self>()], Self>(owned);
|
msg = mem::transmute::<[u8; mem::size_of::<Self>()], Self>(owned);
|
||||||
};
|
};
|
||||||
|
|
||||||
// correct endianness
|
// correct endianness
|
||||||
|
|
||||||
msg.f_type = msg.f_type.to_le();
|
msg.f_type = msg.f_type.to_le();
|
||||||
msg.f_sender = msg.f_sender.to_le();
|
msg.f_sender = msg.f_sender.to_le();
|
||||||
msg
|
|
||||||
|
// check type and reserved fields
|
||||||
|
|
||||||
|
if msg.f_type != (TYPE_INITIATION as u32) {
|
||||||
|
return Err(HandshakeError::InvalidMessageFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +95,7 @@ impl fmt::Debug for Initiation {
|
|||||||
impl Default for Initiation {
|
impl Default for Initiation {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
f_type : TYPE_INITIATION,
|
f_type : TYPE_INITIATION as u32,
|
||||||
f_sender : 0,
|
f_sender : 0,
|
||||||
f_ephemeral : [0u8; SIZE_X25519_POINT],
|
f_ephemeral : [0u8; SIZE_X25519_POINT],
|
||||||
f_static : [0u8; SIZE_X25519_POINT],
|
f_static : [0u8; SIZE_X25519_POINT],
|
||||||
@@ -112,23 +136,43 @@ pub struct Response {
|
|||||||
pub f_empty_tag : [u8; SIZE_TAG],
|
pub f_empty_tag : [u8; SIZE_TAG],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&[u8]> for Response {
|
impl TryFrom<&[u8]> for Response {
|
||||||
fn from(b: &[u8]) -> Self {
|
|
||||||
|
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>() {
|
||||||
|
return Err(HandshakeError::InvalidMessageFormat);
|
||||||
|
}
|
||||||
|
|
||||||
// create owned copy
|
// create owned copy
|
||||||
|
|
||||||
let mut owned = [0u8; mem::size_of::<Self>()];
|
let mut owned = [0u8; mem::size_of::<Self>()];
|
||||||
let mut msg : Self;
|
let mut msg : Self;
|
||||||
owned.copy_from_slice(b);
|
owned.copy_from_slice(value);
|
||||||
|
|
||||||
// cast to MessageResponse
|
// cast to MessageResponse
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
msg = mem::transmute::<[u8; mem::size_of::<Self>()], Self>(owned);
|
msg = mem::transmute::<[u8; mem::size_of::<Self>()], Self>(owned);
|
||||||
};
|
};
|
||||||
|
|
||||||
// correct endianness
|
// correct endianness
|
||||||
|
|
||||||
msg.f_type = msg.f_type.to_le();
|
msg.f_type = msg.f_type.to_le();
|
||||||
msg.f_sender = msg.f_sender.to_le();
|
msg.f_sender = msg.f_sender.to_le();
|
||||||
msg.f_receiver = msg.f_receiver.to_le();
|
msg.f_receiver = msg.f_receiver.to_le();
|
||||||
msg
|
|
||||||
|
// check type and reserved fields
|
||||||
|
|
||||||
|
if msg.f_type != (TYPE_RESPONSE as u32) {
|
||||||
|
return Err(HandshakeError::InvalidMessageFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +221,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn message_response_identity() {
|
fn message_response_identity() {
|
||||||
let msg = Response {
|
let msg = Response {
|
||||||
f_type : TYPE_RESPONSE,
|
f_type : TYPE_RESPONSE as u32,
|
||||||
f_sender : 146252,
|
f_sender : 146252,
|
||||||
f_receiver : 554442,
|
f_receiver : 554442,
|
||||||
f_ephemeral : [
|
f_ephemeral : [
|
||||||
@@ -195,13 +239,14 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let buf : Vec<u8> = msg.into();
|
let buf : Vec<u8> = msg.into();
|
||||||
assert_eq!(msg, Response::from(&buf[..]));
|
let msg_p : Response = Response::try_from(&buf[..]).unwrap();
|
||||||
|
assert_eq!(msg, msg_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn message_initiate_identity() {
|
fn message_initiate_identity() {
|
||||||
let msg = Initiation {
|
let msg = Initiation {
|
||||||
f_type : TYPE_RESPONSE,
|
f_type : TYPE_INITIATION as u32,
|
||||||
f_sender : 575757,
|
f_sender : 575757,
|
||||||
f_ephemeral : [
|
f_ephemeral : [
|
||||||
// ephemeral public key
|
// ephemeral public key
|
||||||
@@ -218,7 +263,7 @@ mod tests {
|
|||||||
0xeb, 0x6a, 0xec, 0xc3, 0x3c, 0xda, 0x47, 0xe1
|
0xeb, 0x6a, 0xec, 0xc3, 0x3c, 0xda, 0x47, 0xe1
|
||||||
],
|
],
|
||||||
f_static_tag : [
|
f_static_tag : [
|
||||||
// tag
|
// poly1305 tag
|
||||||
0x45, 0xac, 0x8d, 0x43, 0xea, 0x1b, 0x2f, 0x02,
|
0x45, 0xac, 0x8d, 0x43, 0xea, 0x1b, 0x2f, 0x02,
|
||||||
0x45, 0x5d, 0x86, 0x37, 0xee, 0x83, 0x6b, 0x42
|
0x45, 0x5d, 0x86, 0x37, 0xee, 0x83, 0x6b, 0x42
|
||||||
],
|
],
|
||||||
@@ -228,13 +273,13 @@ mod tests {
|
|||||||
0x78, 0x28, 0x57, 0x42
|
0x78, 0x28, 0x57, 0x42
|
||||||
],
|
],
|
||||||
f_timestamp_tag : [
|
f_timestamp_tag : [
|
||||||
// tag
|
// poly1305 tag
|
||||||
0x60, 0x0e, 0x1e, 0x95, 0x41, 0x6b, 0x52, 0x05,
|
0x60, 0x0e, 0x1e, 0x95, 0x41, 0x6b, 0x52, 0x05,
|
||||||
0xa2, 0x09, 0xe1, 0xbf, 0x40, 0x05, 0x2f, 0xde
|
0xa2, 0x09, 0xe1, 0xbf, 0x40, 0x05, 0x2f, 0xde
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
let buf : Vec<u8> = msg.into();
|
let buf : Vec<u8> = msg.into();
|
||||||
assert_eq!(msg, Initiation::from(&buf[..]));
|
assert_eq!(msg, Initiation::try_from(&buf[..]).unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
106
src/noise.rs
106
src/noise.rs
@@ -1,3 +1,5 @@
|
|||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
// DH
|
// DH
|
||||||
use x25519_dalek::PublicKey;
|
use x25519_dalek::PublicKey;
|
||||||
use x25519_dalek::StaticSecret;
|
use x25519_dalek::StaticSecret;
|
||||||
@@ -15,7 +17,7 @@ use rand::rngs::OsRng;
|
|||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use crate::peer::{State, Peer};
|
use crate::peer::{State, Peer};
|
||||||
use crate::device::Device;
|
use crate::device::Device;
|
||||||
use crate::messages;
|
use crate::messages::{Initiation, Response};
|
||||||
use crate::timestamp;
|
use crate::timestamp;
|
||||||
|
|
||||||
type HMACBlake2s = Hmac<Blake2s>;
|
type HMACBlake2s = Hmac<Blake2s>;
|
||||||
@@ -129,6 +131,19 @@ macro_rules! SEAL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -156,7 +171,7 @@ pub fn create_initiation(
|
|||||||
id : u32
|
id : u32
|
||||||
) -> Result<Vec<u8>, HandshakeError> {
|
) -> Result<Vec<u8>, HandshakeError> {
|
||||||
let mut rng = OsRng::new().unwrap();
|
let mut rng = OsRng::new().unwrap();
|
||||||
let mut msg : messages::Initiation = Default::default();
|
let mut msg : Initiation = Default::default();
|
||||||
|
|
||||||
// initialize state
|
// initialize state
|
||||||
|
|
||||||
@@ -185,10 +200,7 @@ pub fn create_initiation(
|
|||||||
|
|
||||||
// (C, k) := Kdf2(C, DH(E_priv, S_pub))
|
// (C, k) := Kdf2(C, DH(E_priv, S_pub))
|
||||||
|
|
||||||
let (ck, key) = KDF2!(
|
let (ck, key) = KDF2!(&ck, sk.diffie_hellman(&peer.pk).as_bytes());
|
||||||
&ck,
|
|
||||||
sk.diffie_hellman(&peer.pk).as_bytes()
|
|
||||||
);
|
|
||||||
|
|
||||||
// msg.static := Aead(k, 0, S_pub, H)
|
// msg.static := Aead(k, 0, S_pub, H)
|
||||||
|
|
||||||
@@ -206,10 +218,7 @@ pub fn create_initiation(
|
|||||||
|
|
||||||
// (C, k) := Kdf2(C, DH(S_priv, S_pub))
|
// (C, k) := Kdf2(C, DH(S_priv, S_pub))
|
||||||
|
|
||||||
let (ck, key) = KDF2!(
|
let (ck, key) = KDF2!(&ck, peer.ss.as_bytes());
|
||||||
&ck,
|
|
||||||
peer.ss.as_bytes() // precomputed static-static
|
|
||||||
);
|
|
||||||
|
|
||||||
// msg.timestamp := Aead(k, 0, Timestamp(), H)
|
// msg.timestamp := Aead(k, 0, Timestamp(), H)
|
||||||
|
|
||||||
@@ -236,9 +245,80 @@ pub fn create_initiation(
|
|||||||
|
|
||||||
// return message as vector
|
// return message as vector
|
||||||
|
|
||||||
Ok(messages::Initiation::into(msg))
|
Ok(Initiation::into(msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_initiation(device : &Device, peer : &Peer) -> Result<Output, ()> {
|
pub fn process_initiation(device : &Device, msg : &[u8]) -> Result<Output, HandshakeError> {
|
||||||
Err(())
|
|
||||||
|
// parse message
|
||||||
|
|
||||||
|
let msg = Initiation::try_from(msg)?;
|
||||||
|
|
||||||
|
// initialize state
|
||||||
|
|
||||||
|
let ck = INITIAL_CK;
|
||||||
|
let hs = INITIAL_HS;
|
||||||
|
let hs = HASH!(&hs, device.pk.as_bytes());
|
||||||
|
|
||||||
|
// C := Kdf(C, E_pub)
|
||||||
|
|
||||||
|
let ck = KDF1!(&ck, &msg.f_ephemeral);
|
||||||
|
|
||||||
|
// H := HASH(H, msg.ephemeral)
|
||||||
|
|
||||||
|
let hs = HASH!(&hs, &msg.f_ephemeral);
|
||||||
|
|
||||||
|
// (C, k) := Kdf2(C, DH(E_priv, S_pub))
|
||||||
|
|
||||||
|
let eph = PublicKey::from(msg.f_ephemeral);
|
||||||
|
let (ck, key) = KDF2!(
|
||||||
|
&ck,
|
||||||
|
device.sk.diffie_hellman(&eph).as_bytes()
|
||||||
|
);
|
||||||
|
|
||||||
|
// msg.static := Aead(k, 0, S_pub, H)
|
||||||
|
|
||||||
|
let mut pk = [0u8; 32];
|
||||||
|
|
||||||
|
OPEN!(
|
||||||
|
&key,
|
||||||
|
&hs, // ad
|
||||||
|
&mut pk, // pt
|
||||||
|
&msg.f_static, // ct
|
||||||
|
&msg.f_static_tag // tag
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let peer = device.lookup(&PublicKey::from(pk))?;
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
|
||||||
|
// msg.timestamp := Aead(k, 0, Timestamp(), H)
|
||||||
|
|
||||||
|
let mut ts = timestamp::zero();
|
||||||
|
|
||||||
|
OPEN!(
|
||||||
|
&key,
|
||||||
|
&hs, // ad
|
||||||
|
&mut ts, // pt
|
||||||
|
&msg.f_timestamp, // ct
|
||||||
|
&msg.f_timestamp_tag // tag
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// update state of peer
|
||||||
|
|
||||||
|
peer.set_state_timestamp(
|
||||||
|
State::InitiationSent{
|
||||||
|
hs : hs,
|
||||||
|
ck : ck
|
||||||
|
},
|
||||||
|
&ts
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(Output(None, None))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ impl Peer {
|
|||||||
&self,
|
&self,
|
||||||
state_new : State,
|
state_new : State,
|
||||||
timestamp_new : ×tamp::TAI64N
|
timestamp_new : ×tamp::TAI64N
|
||||||
) -> bool {
|
) -> Result<(), HandshakeError> {
|
||||||
let mut state = self.state.lock().unwrap();
|
let mut state = self.state.lock().unwrap();
|
||||||
let mut timestamp = self.timestamp.lock().unwrap();
|
let mut timestamp = self.timestamp.lock().unwrap();
|
||||||
match *timestamp {
|
match *timestamp {
|
||||||
@@ -84,15 +84,15 @@ impl Peer {
|
|||||||
// no prior timestamp know
|
// no prior timestamp know
|
||||||
*state = state_new;
|
*state = state_new;
|
||||||
*timestamp = Some(*timestamp_new);
|
*timestamp = Some(*timestamp_new);
|
||||||
true
|
Ok(())
|
||||||
},
|
},
|
||||||
Some(timestamp_old) => if timestamp::compare(×tamp_old, ×tamp_new) {
|
Some(timestamp_old) => if timestamp::compare(×tamp_old, ×tamp_new) {
|
||||||
// new timestamp is strictly greater
|
// new timestamp is strictly greater
|
||||||
*state = state_new;
|
*state = state_new;
|
||||||
*timestamp = Some(*timestamp_new);
|
*timestamp = Some(*timestamp_new);
|
||||||
true
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
false
|
Err(HandshakeError::OldTimestamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
pub type TAI64N = [u8; 12];
|
pub type TAI64N = [u8; 12];
|
||||||
|
|
||||||
|
pub fn zero() -> TAI64N {
|
||||||
|
[0u8; 12]
|
||||||
|
}
|
||||||
|
|
||||||
pub fn now() -> TAI64N {
|
pub fn now() -> TAI64N {
|
||||||
[0u8; 12] // TODO
|
[0u8; 12] // TODO, return current timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compare(old : &TAI64N, new : &TAI64N) -> bool {
|
pub fn compare(old : &TAI64N, new : &TAI64N) -> bool {
|
||||||
|
|||||||
15
src/types.rs
15
src/types.rs
@@ -36,12 +36,11 @@ impl Error for ConfigError {
|
|||||||
// handshake error
|
// handshake error
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct HandshakeError {}
|
pub enum HandshakeError {
|
||||||
|
DecryptionFailure,
|
||||||
impl HandshakeError {
|
UnknownPublicKey,
|
||||||
pub fn new() -> Self {
|
InvalidMessageFormat,
|
||||||
HandshakeError{}
|
OldTimestamp
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for HandshakeError {
|
impl fmt::Display for HandshakeError {
|
||||||
@@ -74,8 +73,8 @@ pub struct KeyPair {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Output (
|
pub struct Output (
|
||||||
Option<KeyPair>, // resulting key-pair of successful handshake
|
pub Option<KeyPair>, // resulting key-pair of successful handshake
|
||||||
Option<Vec<u8>> // message to send
|
pub Option<Vec<u8>> // message to send
|
||||||
);
|
);
|
||||||
|
|
||||||
// per-peer state machine
|
// per-peer state machine
|
||||||
|
|||||||
Reference in New Issue
Block a user