Finish handshake exchange
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -265,6 +265,11 @@ name = "rustc-serialize"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "1.0.0"
|
||||
@@ -299,6 +304,7 @@ dependencies = [
|
||||
"hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x25519-dalek 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -365,6 +371,7 @@ dependencies = [
|
||||
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
|
||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55"
|
||||
"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
|
||||
"checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926"
|
||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||
|
||||
@@ -6,6 +6,7 @@ edition = "2018"
|
||||
license = "GPL-3.0"
|
||||
|
||||
[dependencies]
|
||||
spin = "0.5.0"
|
||||
rand = "0.6.5"
|
||||
blake2 = "0.8.0"
|
||||
hmac = "0.7.1"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::sync::Mutex;
|
||||
use spin::RwLock;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use rand::prelude::*;
|
||||
@@ -16,8 +16,8 @@ pub struct Device {
|
||||
pub sk : StaticSecret, // static secret key
|
||||
pub pk : PublicKey, // static public key
|
||||
peers : Vec<Peer>, // peer index -> state
|
||||
pkmap : HashMap<[u8; 32], usize>, // public key -> peer index
|
||||
ids : Mutex<HashMap<u32, usize>> // receive ids -> peer index
|
||||
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 state machine needs to be held,
|
||||
@@ -34,8 +34,8 @@ impl Device {
|
||||
pk : PublicKey::from(&sk),
|
||||
sk : sk,
|
||||
peers : vec![],
|
||||
pkmap : HashMap::new(),
|
||||
ids : Mutex::new(HashMap::new())
|
||||
pk_map : HashMap::new(),
|
||||
id_map : RwLock::new(HashMap::new())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ impl Device {
|
||||
pub fn add(&mut self, pk : PublicKey) -> Result<(), ConfigError> {
|
||||
// check that the pk is not added twice
|
||||
|
||||
if let Some(_) = self.pkmap.get(pk.as_bytes()) {
|
||||
if let Some(_) = self.pk_map.get(pk.as_bytes()) {
|
||||
return Err(ConfigError::new("Duplicate public key"));
|
||||
};
|
||||
|
||||
@@ -61,7 +61,7 @@ impl Device {
|
||||
// map : pk -> new index
|
||||
|
||||
let idx = self.peers.len();
|
||||
self.pkmap.insert(*pk.as_bytes(), idx);
|
||||
self.pk_map.insert(*pk.as_bytes(), idx);
|
||||
|
||||
// map : new index -> peer
|
||||
|
||||
@@ -83,7 +83,7 @@ impl Device {
|
||||
///
|
||||
/// The call might fail if the public key is not found
|
||||
pub fn psk(&mut self, pk : PublicKey, psk : Option<Psk>) -> Result<(), ConfigError> {
|
||||
match self.pkmap.get(pk.as_bytes()) {
|
||||
match self.pk_map.get(pk.as_bytes()) {
|
||||
Some(&idx) => {
|
||||
let peer = &mut self.peers[idx];
|
||||
peer.psk = match psk {
|
||||
@@ -102,7 +102,7 @@ impl Device {
|
||||
///
|
||||
/// * `id` - The (sender) id to release
|
||||
pub fn release(&self, id : u32) {
|
||||
self.ids.lock().unwrap().remove(&id);
|
||||
self.id_map.write().remove(&id);
|
||||
}
|
||||
|
||||
/// Begin a new handshake
|
||||
@@ -111,7 +111,7 @@ impl Device {
|
||||
///
|
||||
/// * `pk` - Public key of peer to initiate handshake for
|
||||
pub fn begin(&self, pk : &PublicKey) -> Result<Vec<u8>, HandshakeError> {
|
||||
match self.pkmap.get(pk.as_bytes()) {
|
||||
match self.pk_map.get(pk.as_bytes()) {
|
||||
None => Err(HandshakeError::UnknownPublicKey),
|
||||
Some(&idx) => {
|
||||
let peer = &self.peers[idx];
|
||||
@@ -130,41 +130,42 @@ impl Device {
|
||||
match msg.get(0) {
|
||||
Some(&messages::TYPE_INITIATION) => {
|
||||
// consume the initiation
|
||||
let (peer, receiver, hs, ck) = noise::consume_initiation(self, msg)?;
|
||||
let (peer, st) = noise::consume_initiation(self, msg)?;
|
||||
|
||||
// allocate index for response
|
||||
// allocate new index for response
|
||||
let sender = self.allocate(peer.idx);
|
||||
|
||||
// create response
|
||||
noise::create_response(self, peer, sender, receiver, hs, ck).map_err(|e| {
|
||||
noise::create_response(self, peer, sender, st).map_err(|e| {
|
||||
self.release(sender);
|
||||
e
|
||||
})
|
||||
},
|
||||
Some(&messages::TYPE_RESPONSE) => {
|
||||
Err(HandshakeError::InvalidMessageFormat)
|
||||
},
|
||||
Some(&messages::TYPE_RESPONSE) => noise::consume_response(self, msg),
|
||||
_ => Err(HandshakeError::InvalidMessageFormat)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lookup(&self, pk : &PublicKey) -> Result<&Peer, HandshakeError> {
|
||||
match self.pkmap.get(pk.as_bytes()) {
|
||||
pub(crate) fn lookup_pk(&self, pk : &PublicKey) -> Result<&Peer, HandshakeError> {
|
||||
match self.pk_map.get(pk.as_bytes()) {
|
||||
Some(&idx) => Ok(&self.peers[idx]),
|
||||
_ => Err(HandshakeError::UnknownPublicKey)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn lookup_id(&self, id : u32) -> Result<&Peer, HandshakeError> {
|
||||
match self.id_map.read().get(&id) {
|
||||
Some(&idx) => Ok(&self.peers[idx]),
|
||||
_ => Err(HandshakeError::UnknownReceiverId)
|
||||
}
|
||||
}
|
||||
|
||||
impl Device {
|
||||
// allocate a new index (id), for peer with idx
|
||||
fn allocate(&self, idx : usize) -> u32 {
|
||||
let mut rng = OsRng::new().unwrap();
|
||||
let mut table = self.ids.lock().unwrap();
|
||||
loop {
|
||||
let id = rng.gen();
|
||||
if !table.contains_key(&id) {
|
||||
table.insert(id, idx);
|
||||
if !self.id_map.read().contains_key(&id) {
|
||||
self.id_map.write().insert(id, idx);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
171
src/noise.rs
171
src/noise.rs
@@ -23,9 +23,13 @@ use crate::device::Device;
|
||||
use crate::messages::{Initiation, Response};
|
||||
use crate::timestamp;
|
||||
|
||||
// HMAC hasher (generic construction)
|
||||
|
||||
type HMACBlake2s = Hmac<Blake2s>;
|
||||
|
||||
/* Internal functions for processing and creating noise messages */
|
||||
// convenient alias to pass state temporarily into device.rs and back
|
||||
|
||||
type TemporaryState = (u32, PublicKey, GenericArray<u8, U32>, GenericArray<u8, U32>);
|
||||
|
||||
const SIZE_CK : usize = 32;
|
||||
const SIZE_HS : usize = 32;
|
||||
@@ -121,6 +125,18 @@ macro_rules! KDF2 {
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! SEAL {
|
||||
($key:expr, $aead:expr, $pt:expr, $ct:expr, $tag:expr) => {
|
||||
{
|
||||
@@ -171,8 +187,9 @@ mod tests {
|
||||
pub fn create_initiation(
|
||||
device : &Device,
|
||||
peer : &Peer,
|
||||
id : u32
|
||||
sender : u32
|
||||
) -> Result<Vec<u8>, HandshakeError> {
|
||||
|
||||
let mut rng = OsRng::new().unwrap();
|
||||
let mut msg : Initiation = Default::default();
|
||||
|
||||
@@ -182,20 +199,20 @@ pub fn create_initiation(
|
||||
let hs = INITIAL_HS;
|
||||
let hs = HASH!(&hs, peer.pk.as_bytes());
|
||||
|
||||
msg.f_sender = id;
|
||||
msg.f_sender = sender;
|
||||
|
||||
// (E_priv, E_pub) := DH-Generate()
|
||||
|
||||
let sk = StaticSecret::new(&mut rng);
|
||||
let pk = PublicKey::from(&sk);
|
||||
let eph_sk = StaticSecret::new(&mut rng);
|
||||
let eph_pk = PublicKey::from(&eph_sk);
|
||||
|
||||
// C := Kdf(C, E_pub)
|
||||
|
||||
let ck = KDF1!(&ck, pk.as_bytes());
|
||||
let ck = KDF1!(&ck, eph_pk.as_bytes());
|
||||
|
||||
// msg.ephemeral := E_pub
|
||||
|
||||
msg.f_ephemeral = *pk.as_bytes();
|
||||
msg.f_ephemeral = *eph_pk.as_bytes();
|
||||
|
||||
// H := HASH(H, msg.ephemeral)
|
||||
|
||||
@@ -203,7 +220,7 @@ pub fn create_initiation(
|
||||
|
||||
// (C, k) := Kdf2(C, DH(E_priv, S_pub))
|
||||
|
||||
let (ck, key) = KDF2!(&ck, sk.diffie_hellman(&peer.pk).as_bytes());
|
||||
let (ck, key) = KDF2!(&ck, eph_sk.diffie_hellman(&peer.pk).as_bytes());
|
||||
|
||||
// msg.static := Aead(k, 0, S_pub, H)
|
||||
|
||||
@@ -239,12 +256,7 @@ pub fn create_initiation(
|
||||
|
||||
// update state of peer
|
||||
|
||||
peer.set_state(
|
||||
State::InitiationSent{
|
||||
hs : hs,
|
||||
ck : ck
|
||||
}
|
||||
);
|
||||
peer.set_state(State::InitiationSent{hs, ck, eph_sk, sender});
|
||||
|
||||
// return message as vector
|
||||
|
||||
@@ -254,7 +266,7 @@ pub fn create_initiation(
|
||||
pub fn consume_initiation<'a>(
|
||||
device : &'a Device,
|
||||
msg : &[u8]
|
||||
) -> Result<(&'a Peer, u32, GenericArray<u8, U32>, GenericArray<u8, U32>), HandshakeError> {
|
||||
) -> Result<(&'a Peer, TemporaryState), HandshakeError> {
|
||||
|
||||
// parse message
|
||||
|
||||
@@ -276,10 +288,10 @@ pub fn consume_initiation<'a>(
|
||||
|
||||
// (C, k) := Kdf2(C, DH(E_priv, S_pub))
|
||||
|
||||
let eph = PublicKey::from(msg.f_ephemeral);
|
||||
let eph_r_pk = PublicKey::from(msg.f_ephemeral);
|
||||
let (ck, key) = KDF2!(
|
||||
&ck,
|
||||
device.sk.diffie_hellman(&eph).as_bytes()
|
||||
device.sk.diffie_hellman(&eph_r_pk).as_bytes()
|
||||
);
|
||||
|
||||
// msg.static := Aead(k, 0, S_pub, H)
|
||||
@@ -294,7 +306,7 @@ pub fn consume_initiation<'a>(
|
||||
&msg.f_static_tag // tag
|
||||
)?;
|
||||
|
||||
let peer = device.lookup(&PublicKey::from(pk))?;
|
||||
let peer = device.lookup_pk(&PublicKey::from(pk))?;
|
||||
|
||||
// H := Hash(H || msg.static)
|
||||
|
||||
@@ -318,25 +330,134 @@ pub fn consume_initiation<'a>(
|
||||
|
||||
// check and update timestamp
|
||||
|
||||
peer.check_timestamp(&ts)?;
|
||||
peer.check_timestamp(device, &ts)?;
|
||||
|
||||
// return state (to create response)
|
||||
|
||||
Ok((peer, msg.f_sender, hs, ck))
|
||||
Ok((peer, (msg.f_sender, eph_r_pk, hs, ck)))
|
||||
}
|
||||
|
||||
pub fn create_response(
|
||||
device : &Device,
|
||||
peer : &Peer,
|
||||
sender : u32,
|
||||
receiver : u32,
|
||||
hs : GenericArray<u8, U32>,
|
||||
ck : GenericArray<u8, U32>
|
||||
sender : u32, // sending identifier
|
||||
state : TemporaryState // state from "consume_initiation"
|
||||
) -> Result<Output, HandshakeError> {
|
||||
|
||||
let mut rng = OsRng::new().unwrap();
|
||||
let mut msg : Response = Default::default();
|
||||
|
||||
// parse message
|
||||
let (receiver, eph_r_pk, hs, ck) = state;
|
||||
|
||||
// (E_priv, E_pub) := DH-Generate()
|
||||
|
||||
let eph_sk = StaticSecret::new(&mut rng);
|
||||
let eph_pk = PublicKey::from(&eph_sk);
|
||||
|
||||
// C := Kdf1(C, E_pub)
|
||||
|
||||
let ck = KDF1!(&ck, eph_pk.as_bytes());
|
||||
|
||||
// msg.ephemeral := E_pub
|
||||
|
||||
msg.f_ephemeral = *eph_pk.as_bytes();
|
||||
|
||||
// H := Hash(H || msg.ephemeral)
|
||||
|
||||
let hs = HASH!(&hs, &msg.f_ephemeral);
|
||||
|
||||
// C := Kdf1(C, DH(E_priv, E_pub))
|
||||
|
||||
let ck = KDF1!(&ck, eph_sk.diffie_hellman(&eph_r_pk).as_bytes());
|
||||
|
||||
// C := Kdf1(C, DH(E_priv, S_pub))
|
||||
|
||||
let ck = KDF1!(&ck, eph_sk.diffie_hellman(&peer.pk).as_bytes());
|
||||
|
||||
// (C, tau, k) := Kdf3(C, Q)
|
||||
|
||||
let (ck, tau, key) = KDF3!(&ck, &peer.psk);
|
||||
|
||||
// H := Hash(H || tau)
|
||||
|
||||
let hs = HASH!(&hs, tau);
|
||||
|
||||
// msg.empty := Aead(k, 0, [], H)
|
||||
|
||||
SEAL!(
|
||||
&key,
|
||||
&hs, // ad
|
||||
&[], // pt
|
||||
&mut [], // ct
|
||||
&mut msg.f_empty_tag // tag
|
||||
);
|
||||
|
||||
// H := Hash(H || msg.empty)
|
||||
|
||||
// let hs = HASH!(&hs, &msg.f_empty_tag); // not strictly needed
|
||||
|
||||
// derive key-pair
|
||||
|
||||
let (key_recv, key_send) = KDF2!(&ck, &[]);
|
||||
|
||||
Ok(Output(None, None))
|
||||
}
|
||||
|
||||
pub fn consume_response(
|
||||
device : &Device,
|
||||
msg : &[u8]
|
||||
) -> Result<Output, HandshakeError> {
|
||||
|
||||
// parse message
|
||||
|
||||
let msg = Response::try_from(msg)?;
|
||||
|
||||
// retrieve peer and associated state
|
||||
|
||||
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))
|
||||
}?;
|
||||
|
||||
// C := Kdf1(C, E_pub)
|
||||
|
||||
let ck = KDF1!(&ck, &msg.f_ephemeral);
|
||||
|
||||
// H := Hash(H || msg.ephemeral)
|
||||
|
||||
let hs = HASH!(&hs, &msg.f_ephemeral);
|
||||
|
||||
// C := Kdf1(C, DH(E_priv, E_pub))
|
||||
|
||||
let eph_r_pk = PublicKey::from(msg.f_ephemeral);
|
||||
let ck = KDF1!(&ck, eph_sk.diffie_hellman(&eph_r_pk).as_bytes());
|
||||
|
||||
// C := Kdf1(C, DH(E_priv, S_pub))
|
||||
|
||||
let ck = KDF1!(&ck, eph_sk.diffie_hellman(&peer.pk).as_bytes());
|
||||
|
||||
// (C, tau, k) := Kdf3(C, Q)
|
||||
|
||||
let (ck, tau, key) = KDF3!(&ck, &peer.psk);
|
||||
|
||||
// H := Hash(H || tau)
|
||||
|
||||
let hs = HASH!(&hs, tau);
|
||||
|
||||
// msg.empty := Aead(k, 0, [], H)
|
||||
|
||||
OPEN!(
|
||||
&key,
|
||||
&hs, // ad
|
||||
&mut [], // pt
|
||||
&[], // ct
|
||||
&msg.f_empty_tag // tag
|
||||
);
|
||||
|
||||
// derive key-pair
|
||||
|
||||
let (key_send, key_recv) = KDF2!(&ck, &[]);
|
||||
|
||||
Ok(Output(None, None))
|
||||
}
|
||||
|
||||
92
src/peer.rs
92
src/peer.rs
@@ -4,10 +4,12 @@ use generic_array::typenum::U32;
|
||||
use generic_array::GenericArray;
|
||||
|
||||
use x25519_dalek::PublicKey;
|
||||
use x25519_dalek::StaticSecret;
|
||||
use x25519_dalek::SharedSecret;
|
||||
|
||||
use crate::types::*;
|
||||
use crate::timestamp;
|
||||
use crate::device::Device;
|
||||
|
||||
/* Represents the recomputation and state of a peer.
|
||||
*
|
||||
@@ -15,27 +17,44 @@ use crate::timestamp;
|
||||
*/
|
||||
|
||||
pub struct Peer {
|
||||
pub idx : usize,
|
||||
// internal identifier
|
||||
pub(crate) idx : usize,
|
||||
|
||||
// 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
|
||||
pub(crate) pk : PublicKey, // public key of peer
|
||||
pub(crate) ss : SharedSecret, // precomputed DH(static, static)
|
||||
pub(crate) psk : Psk // psk of peer
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum State {
|
||||
Reset,
|
||||
InitiationSent{
|
||||
sender : u32, // assigned sender id
|
||||
eph_sk : StaticSecret,
|
||||
hs : GenericArray<u8, U32>,
|
||||
ck : GenericArray<u8, U32>
|
||||
},
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Peer {
|
||||
pub fn new(
|
||||
idx : usize,
|
||||
@@ -56,7 +75,7 @@ impl Peer {
|
||||
///
|
||||
/// # Arguments
|
||||
pub fn get_state(&self) -> State {
|
||||
*self.state.lock().unwrap()
|
||||
self.state.lock().unwrap().clone()
|
||||
}
|
||||
|
||||
/// Set the state of the peer unconditionally
|
||||
@@ -71,55 +90,41 @@ 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 : ×tamp::TAI64N) -> Result<(), HandshakeError> {
|
||||
|
||||
let mut timestamp = self.timestamp.lock().unwrap();
|
||||
match *timestamp {
|
||||
None => Ok(()),
|
||||
Some(timestamp_old) => if timestamp::compare(×tamp_old, ×tamp_new) {
|
||||
*timestamp = Some(*timestamp_new);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(HandshakeError::OldTimestamp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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(
|
||||
pub fn check_timestamp(
|
||||
&self,
|
||||
state_new : State,
|
||||
device : &Device,
|
||||
timestamp_new : ×tamp::TAI64N
|
||||
) -> Result<(), HandshakeError> {
|
||||
|
||||
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);
|
||||
Ok(())
|
||||
},
|
||||
|
||||
let update = match *timestamp {
|
||||
None => true,
|
||||
Some(timestamp_old) => if timestamp::compare(×tamp_old, ×tamp_new) {
|
||||
// new timestamp is strictly greater
|
||||
*state = state_new;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
if update {
|
||||
// release existing identifier
|
||||
match *state {
|
||||
State::InitiationSent{sender, ..} => {
|
||||
device.release(sender)
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
|
||||
// reset state and update timestamp
|
||||
*state = State::Reset;
|
||||
*timestamp = Some(*timestamp_new);
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -127,4 +132,3 @@ impl Peer {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
src/types.rs
10
src/types.rs
@@ -34,8 +34,10 @@ impl Error for ConfigError {
|
||||
pub enum HandshakeError {
|
||||
DecryptionFailure,
|
||||
UnknownPublicKey,
|
||||
UnknownReceiverId,
|
||||
InvalidMessageFormat,
|
||||
OldTimestamp
|
||||
OldTimestamp,
|
||||
InvalidState
|
||||
}
|
||||
|
||||
impl fmt::Display for HandshakeError {
|
||||
@@ -45,10 +47,14 @@ impl fmt::Display for HandshakeError {
|
||||
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")
|
||||
write!(f, "Timestamp is less/equal to the newest"),
|
||||
HandshakeError::InvalidState =>
|
||||
write!(f, "Message does not apply to handshake state")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user