Better seperation and introduction of timestamp
This commit is contained in:
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
mod types;
|
||||
mod noise;
|
||||
mod messages;
|
||||
mod peer;
|
||||
mod device;
|
||||
mod timestamp;
|
||||
|
||||
26
src/noise.rs
26
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
|
||||
×tamp::new(), // pt
|
||||
×tamp::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{
|
||||
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(())
|
||||
}
|
||||
|
||||
99
src/peer.rs
Normal file
99
src/peer.rs
Normal file
@@ -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 : ×tamp::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(×tamp_old, ×tamp_new) {
|
||||
// new timestamp is strictly greater
|
||||
*state = state_new;
|
||||
*timestamp = Some(*timestamp_new);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
23
src/types.rs
23
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>
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user