Better seperation and introduction of timestamp

This commit is contained in:
Mathias Hall-Andersen
2019-07-17 16:28:21 +02:00
parent 55418344ae
commit 4817ca7906
6 changed files with 136 additions and 39 deletions

View File

@@ -9,6 +9,7 @@ use x25519_dalek::StaticSecret;
use crate::noise; use crate::noise;
use crate::types::*; use crate::types::*;
use crate::peer::Peer;
pub struct Device { pub struct Device {
pub sk : StaticSecret, // static secret key pub sk : StaticSecret, // static secret key
@@ -62,12 +63,10 @@ impl Device {
// map : new index -> peer // map : new index -> peer
self.peers.push(Peer { self.peers.push(Peer::new(
state : Mutex::new(State::Reset{ts : None}), pk,
pk : pk, self.sk.diffie_hellman(&pk)
ss : self.sk.diffie_hellman(&pk), ));
psk : [0u8; 32]
});
Ok(()) Ok(())
} }

View File

@@ -1,5 +1,6 @@
mod types; mod types;
mod noise; mod noise;
mod messages; mod messages;
mod peer;
mod device; mod device;
mod timestamp; mod timestamp;

View File

@@ -13,6 +13,7 @@ use crypto::aead::{AeadEncryptor,AeadDecryptor};
use rand::rngs::OsRng; use rand::rngs::OsRng;
use crate::types::*; use crate::types::*;
use crate::peer::{State, Peer};
use crate::device::Device; use crate::device::Device;
use crate::messages; use crate::messages;
use crate::timestamp; use crate::timestamp;
@@ -166,25 +167,31 @@ pub fn create_initiation(
msg.f_sender = id; msg.f_sender = id;
// (E_priv, E_pub) := DH-Generate() // (E_priv, E_pub) := DH-Generate()
let sk = StaticSecret::new(&mut rng); let sk = StaticSecret::new(&mut rng);
let pk = PublicKey::from(&sk); let pk = PublicKey::from(&sk);
// C := Kdf(C, E_pub) // C := Kdf(C, E_pub)
let ck = KDF1!(&ck, pk.as_bytes()); let ck = KDF1!(&ck, pk.as_bytes());
// msg.ephemeral := E_pub // msg.ephemeral := E_pub
msg.f_ephemeral = *pk.as_bytes(); msg.f_ephemeral = *pk.as_bytes();
// H := HASH(H, msg.ephemeral) // H := HASH(H, msg.ephemeral)
let hs = HASH!(&hs, msg.f_ephemeral); let hs = HASH!(&hs, msg.f_ephemeral);
// (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, &ck,
sk.diffie_hellman(&peer.pk).as_bytes() sk.diffie_hellman(&peer.pk).as_bytes()
); );
// msg.static := Aead(k, 0, S_pub, H) // msg.static := Aead(k, 0, S_pub, H)
SEAL!( SEAL!(
&key, &key,
&hs, // ad &hs, // ad
@@ -194,39 +201,44 @@ pub fn create_initiation(
); );
// H := Hash(H || msg.static) // H := Hash(H || msg.static)
let hs = HASH!(&hs, &msg.f_static, &msg.f_static_tag); let hs = HASH!(&hs, &msg.f_static, &msg.f_static_tag);
// (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, &ck,
peer.ss.as_bytes() // precomputed peer.ss.as_bytes() // precomputed static-static
); );
// msg.timestamp := Aead(k, 0, Timestamp(), H) // msg.timestamp := Aead(k, 0, Timestamp(), H)
SEAL!( SEAL!(
&key, &key,
&hs, // ad &hs, // ad
&timestamp::new(), // pt &timestamp::now(), // pt
&mut msg.f_timestamp, // ct &mut msg.f_timestamp, // ct
&mut msg.f_timestamp_tag // tag &mut msg.f_timestamp_tag // tag
); );
// H := Hash(H || msg.timestamp) // H := Hash(H || msg.timestamp)
let hs = HASH!(&hs, &msg.f_timestamp, &msg.f_timestamp_tag); 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(); peer.set_state(
*st = State::InitiationSent{ State::InitiationSent{
hs : hs, hs : hs,
ck : ck ck : ck
}; }
);
// return message as vector // return message as vector
Ok(messages::Initiation::into(msg)) Ok(messages::Initiation::into(msg))
} }
pub fn process_initiation(peer : &Peer) -> Result<Output, ()> { pub fn process_initiation(device : &Device, peer : &Peer) -> Result<Output, ()> {
Err(()) Err(())
} }

99
src/peer.rs Normal file
View 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 : &timestamp::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(&timestamp_old, &timestamp_new) {
// new timestamp is strictly greater
*state = state_new;
*timestamp = Some(*timestamp_new);
true
} else {
false
}
}
}
}

View File

@@ -1,5 +1,14 @@
pub type TAI64N = [u8; 12]; pub type TAI64N = [u8; 12];
pub fn new() -> TAI64N { pub fn now() -> TAI64N {
[0u8; 12] // TODO [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;
}

View File

@@ -1,13 +1,9 @@
use std::fmt; use std::fmt;
use std::sync::Mutex;
use std::error::Error; use std::error::Error;
use x25519_dalek::PublicKey; use x25519_dalek::PublicKey;
use x25519_dalek::SharedSecret; use x25519_dalek::SharedSecret;
use generic_array::typenum::U32;
use generic_array::GenericArray;
use crate::timestamp; use crate::timestamp;
// config error // config error
@@ -86,22 +82,3 @@ pub struct Output (
pub type Psk = [u8; 32]; 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>
},
}