Create initiation message
This commit is contained in:
@@ -7,16 +7,15 @@ use rand::rngs::OsRng;
|
||||
use x25519_dalek::PublicKey;
|
||||
use x25519_dalek::StaticSecret;
|
||||
|
||||
|
||||
use crate::noise;
|
||||
use crate::types::*;
|
||||
|
||||
struct Device {
|
||||
sk : StaticSecret, // static secret key
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
/* A mutable reference to the state machine needs to be held,
|
||||
@@ -44,21 +43,17 @@ impl Device {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pk` - The public key to add
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// The call might fail if the public key corresponds to the secret key of the machine
|
||||
pub fn add(&mut self, pk : PublicKey) -> Result<(), ()> {
|
||||
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()) {
|
||||
return Err(());
|
||||
return Err(ConfigError::new("Duplicate public key"));
|
||||
};
|
||||
|
||||
// check that the pk is not that of the device
|
||||
|
||||
if *self.pk.as_bytes() == *pk.as_bytes() {
|
||||
return Err(());
|
||||
return Err(ConfigError::new("Public key corresponds to secret key of interface"));
|
||||
}
|
||||
|
||||
// map : pk -> new index
|
||||
@@ -68,10 +63,10 @@ impl Device {
|
||||
// map : new index -> peer
|
||||
|
||||
self.peers.push(Peer {
|
||||
m : Mutex::new(State::Reset),
|
||||
pk : pk,
|
||||
ss : self.sk.diffie_hellman(&pk),
|
||||
psk : [0u8; 32]
|
||||
state : Mutex::new(State::Reset{ts : None}),
|
||||
pk : pk,
|
||||
ss : self.sk.diffie_hellman(&pk),
|
||||
psk : [0u8; 32]
|
||||
});
|
||||
|
||||
Ok(())
|
||||
@@ -87,7 +82,7 @@ impl Device {
|
||||
/// # Returns
|
||||
///
|
||||
/// The call might fail if the public key is not found
|
||||
pub fn psk(&mut self, pk : PublicKey, psk : Option<[u8; 32]>) -> Result<(), ()> {
|
||||
pub fn psk(&mut self, pk : PublicKey, psk : Option<Psk>) -> Result<(), ConfigError> {
|
||||
match self.pkmap.get(pk.as_bytes()) {
|
||||
Some(&idx) => {
|
||||
let peer = &mut self.peers[idx];
|
||||
@@ -97,7 +92,7 @@ impl Device {
|
||||
};
|
||||
Ok(())
|
||||
},
|
||||
_ => Err(())
|
||||
_ => Err(ConfigError::new("No such public key"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,13 +110,13 @@ impl Device {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pk` - Public key of peer to initiate handshake for
|
||||
pub fn begin(&self, pk : PublicKey) -> Result<Vec<u8>, ()> {
|
||||
pub fn begin(&self, pk : PublicKey) -> Result<Vec<u8>, HandshakeError> {
|
||||
match self.pkmap.get(pk.as_bytes()) {
|
||||
None => Err(()),
|
||||
None => Err(HandshakeError::new()),
|
||||
Some(&idx) => {
|
||||
let peer = &self.peers[idx];
|
||||
let id = self.allocate(idx);
|
||||
noise::create_initiation(peer, id)
|
||||
noise::create_initiation(self, peer, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,10 +126,10 @@ impl Device {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `msg` - Byte slice containing the message (untrusted input)
|
||||
pub fn process(&self, msg : &[u8]) -> Result<Output, ()> {
|
||||
pub fn process(&self, msg : &[u8]) -> Result<Output, HandshakeError> {
|
||||
// inspect type field
|
||||
match msg.get(0) {
|
||||
_ => Err(())
|
||||
_ => Err(HandshakeError::new())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
mod types;
|
||||
mod noise;
|
||||
mod messages;
|
||||
mod machine;
|
||||
mod device;
|
||||
mod timestamp;
|
||||
|
||||
@@ -5,21 +5,22 @@ 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 : u32 = 1;
|
||||
pub const TYPE_RESPONSE : u32 = 2;
|
||||
|
||||
/* Wireguard handshake initiation message
|
||||
/* Wireguard handshake (noise) initiation message
|
||||
* initator -> responder
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Initiation {
|
||||
pub f_type : u8,
|
||||
f_reserved : [u8; 3],
|
||||
pub f_sender : u32,
|
||||
pub f_ephemeral : [u8; SIZE_X25519_POINT],
|
||||
pub f_static : [u8; SIZE_X25519_POINT + SIZE_TAG],
|
||||
pub f_timestamp : [u8; SIZE_TIMESTAMP + 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 From<&[u8]> for Initiation {
|
||||
@@ -70,12 +71,13 @@ impl fmt::Debug for Initiation {
|
||||
impl Default for Initiation {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
f_type : TYPE_INITIATION,
|
||||
f_reserved : [0u8; 3],
|
||||
f_sender : 0,
|
||||
f_ephemeral : [0u8; SIZE_X25519_POINT],
|
||||
f_static : [0u8; SIZE_X25519_POINT + SIZE_TAG],
|
||||
f_timestamp : [0u8; SIZE_TIMESTAMP + SIZE_TAG],
|
||||
f_type : TYPE_INITIATION,
|
||||
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]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,11 +86,12 @@ impl Default for Initiation {
|
||||
impl PartialEq for Initiation {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.f_type == other.f_type &&
|
||||
self.f_reserved == other.f_reserved &&
|
||||
self.f_sender == other.f_sender &&
|
||||
self.f_ephemeral[..] == other.f_ephemeral[..] &&
|
||||
self.f_static[..] == other.f_static[..] &&
|
||||
self.f_timestamp[..] == other.f_timestamp
|
||||
self.f_static_tag[..] == other.f_static_tag[..] &&
|
||||
self.f_timestamp[..] == other.f_timestamp &&
|
||||
self.f_timestamp_tag[..] == other.f_timestamp_tag
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,18 +99,17 @@ impl PartialEq for Initiation {
|
||||
impl Eq for Initiation {}
|
||||
|
||||
|
||||
/* Wireguard handshake responder message
|
||||
/* Wireguard handshake (noise) responder message
|
||||
* responder -> initator
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Response {
|
||||
f_type : u8,
|
||||
f_reserved : [u8; 3],
|
||||
f_sender : u32,
|
||||
f_receiver : u32,
|
||||
f_ephemeral : [u8; SIZE_X25519_POINT],
|
||||
f_empty : [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 From<&[u8]> for Response {
|
||||
@@ -161,11 +163,10 @@ impl fmt::Debug for Response {
|
||||
impl PartialEq for Response {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.f_type == other.f_type &&
|
||||
self.f_reserved == other.f_reserved &&
|
||||
self.f_sender == other.f_sender &&
|
||||
self.f_receiver == other.f_receiver &&
|
||||
self.f_ephemeral == other.f_ephemeral &&
|
||||
self.f_empty == other.f_empty
|
||||
self.f_empty_tag == other.f_empty_tag
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,10 +177,9 @@ mod tests {
|
||||
#[test]
|
||||
fn message_response_identity() {
|
||||
let msg = Response {
|
||||
f_type : TYPE_RESPONSE,
|
||||
f_reserved : [0u8; 3],
|
||||
f_sender : 146252,
|
||||
f_receiver : 554442,
|
||||
f_type : TYPE_RESPONSE,
|
||||
f_sender : 146252,
|
||||
f_receiver : 554442,
|
||||
f_ephemeral : [
|
||||
// ephemeral public key
|
||||
0xc1, 0x66, 0x0a, 0x0c, 0xdc, 0x0f, 0x6c, 0x51,
|
||||
@@ -187,7 +187,7 @@ mod tests {
|
||||
0xf7, 0xf1, 0xca, 0x90, 0x86, 0x72, 0xad, 0x67,
|
||||
0xea, 0x89, 0x45, 0x44, 0x13, 0x56, 0x52, 0x1f
|
||||
],
|
||||
f_empty : [
|
||||
f_empty_tag : [
|
||||
// tag
|
||||
0x60, 0x0e, 0x1e, 0x95, 0x41, 0x6b, 0x52, 0x05,
|
||||
0xa2, 0x09, 0xe1, 0xbf, 0x40, 0x05, 0x2f, 0xde
|
||||
@@ -201,9 +201,8 @@ mod tests {
|
||||
#[test]
|
||||
fn message_initiate_identity() {
|
||||
let msg = Initiation {
|
||||
f_type : TYPE_RESPONSE,
|
||||
f_reserved : [0u8; 3],
|
||||
f_sender : 575757,
|
||||
f_type : TYPE_RESPONSE,
|
||||
f_sender : 575757,
|
||||
f_ephemeral : [
|
||||
// ephemeral public key
|
||||
0xc1, 0x66, 0x0a, 0x0c, 0xdc, 0x0f, 0x6c, 0x51,
|
||||
@@ -211,13 +210,14 @@ mod tests {
|
||||
0xf7, 0xf1, 0xca, 0x90, 0x86, 0x72, 0xad, 0x67,
|
||||
0xea, 0x89, 0x45, 0x44, 0x13, 0x56, 0x52, 0x1f
|
||||
],
|
||||
f_static : [
|
||||
f_static : [
|
||||
// encrypted static public key
|
||||
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,
|
||||
|
||||
0xeb, 0x6a, 0xec, 0xc3, 0x3c, 0xda, 0x47, 0xe1
|
||||
],
|
||||
f_static_tag : [
|
||||
// tag
|
||||
0x45, 0xac, 0x8d, 0x43, 0xea, 0x1b, 0x2f, 0x02,
|
||||
0x45, 0x5d, 0x86, 0x37, 0xee, 0x83, 0x6b, 0x42
|
||||
@@ -225,8 +225,9 @@ mod tests {
|
||||
f_timestamp : [
|
||||
// timestamp
|
||||
0x4f, 0x1c, 0x60, 0xec, 0x0e, 0xf6, 0x36, 0xf0,
|
||||
0x78, 0x28, 0x57, 0x42,
|
||||
|
||||
0x78, 0x28, 0x57, 0x42
|
||||
],
|
||||
f_timestamp_tag : [
|
||||
// tag
|
||||
0x60, 0x0e, 0x1e, 0x95, 0x41, 0x6b, 0x52, 0x05,
|
||||
0xa2, 0x09, 0xe1, 0xbf, 0x40, 0x05, 0x2f, 0xde
|
||||
|
||||
134
src/noise.rs
134
src/noise.rs
@@ -1,16 +1,21 @@
|
||||
// DH
|
||||
use x25519_dalek::PublicKey;
|
||||
use x25519_dalek::StaticSecret;
|
||||
|
||||
// HASH & MAC
|
||||
use hmac::{Mac, Hmac};
|
||||
use blake2::{Blake2s, Digest};
|
||||
|
||||
use x25519_dalek::PublicKey;
|
||||
use x25519_dalek::StaticSecret;
|
||||
use x25519_dalek::SharedSecret;
|
||||
// AEAD
|
||||
use crypto::chacha20poly1305::ChaCha20Poly1305;
|
||||
use crypto::aead::{AeadEncryptor,AeadDecryptor};
|
||||
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use generic_array::*;
|
||||
|
||||
use crate::types::*;
|
||||
use crate::device::Device;
|
||||
use crate::messages;
|
||||
use crate::timestamp;
|
||||
|
||||
type HMACBlake2s = Hmac<Blake2s>;
|
||||
|
||||
@@ -18,6 +23,7 @@ type HMACBlake2s = Hmac<Blake2s>;
|
||||
|
||||
const SIZE_CK : usize = 32;
|
||||
const SIZE_HS : usize = 32;
|
||||
const SIZE_NONCE : usize = 8;
|
||||
|
||||
// C := Hash(Construction)
|
||||
const INITIAL_CK : [u8; SIZE_CK] = [
|
||||
@@ -35,6 +41,10 @@ const INITIAL_HS : [u8; SIZE_HS] = [
|
||||
0x0e, 0xe1, 0x9c, 0x65, 0xba, 0x07, 0x9e, 0xf3
|
||||
];
|
||||
|
||||
const ZERO_NONCE : [u8; SIZE_NONCE] = [
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
];
|
||||
|
||||
macro_rules! HASH {
|
||||
($input1:expr) => {
|
||||
{
|
||||
@@ -52,19 +62,35 @@ macro_rules! HASH {
|
||||
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)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! HMAC {
|
||||
($key:expr, $input:expr) => {
|
||||
($key:expr, $input1:expr) => {
|
||||
{
|
||||
let mut mac = HMACBlake2s::new($key);
|
||||
mac.hash($input);
|
||||
mac.result()
|
||||
// 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) => {
|
||||
HMACBlake2s::new($key).hash($input2).hash($input2).result()
|
||||
{
|
||||
let mut mac = HMACBlake2s::new_varkey($key).unwrap();
|
||||
mac.input($input1);
|
||||
mac.input($input2);
|
||||
mac.result().code()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -72,20 +98,33 @@ macro_rules! KDF1 {
|
||||
($ck:expr, $input:expr) => {
|
||||
{
|
||||
let t0 = HMAC!($ck, $input);
|
||||
t0
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! KDF2 {
|
||||
($ck:expr, $input:expr) => {
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +149,11 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_initiation(peer : &Peer, id : u32) -> Result<Vec<u8>, ()> {
|
||||
pub fn create_initiation(
|
||||
device : &Device,
|
||||
peer : &Peer,
|
||||
id : u32
|
||||
) -> Result<Vec<u8>, HandshakeError> {
|
||||
let mut rng = OsRng::new().unwrap();
|
||||
let mut msg : messages::Initiation = Default::default();
|
||||
|
||||
@@ -122,25 +165,68 @@ pub fn create_initiation(peer : &Peer, id : u32) -> Result<Vec<u8>, ()> {
|
||||
|
||||
msg.f_sender = id;
|
||||
|
||||
// token : e
|
||||
|
||||
// (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();
|
||||
|
||||
// let ck = KDF1!(&ck, pk.as_bytes());
|
||||
// H := HASH(H, msg.ephemeral)
|
||||
let hs = HASH!(&hs, msg.f_ephemeral);
|
||||
|
||||
// token : es
|
||||
// (C, k) := Kdf2(C, DH(E_priv, S_pub))
|
||||
let (ck, key) = KDF2!(
|
||||
&ck,
|
||||
sk.diffie_hellman(&peer.pk).as_bytes()
|
||||
);
|
||||
|
||||
// token : s
|
||||
// msg.static := Aead(k, 0, S_pub, H)
|
||||
SEAL!(
|
||||
&key,
|
||||
&hs, // ad
|
||||
device.pk.as_bytes(), // pt
|
||||
&mut msg.f_static, // ct
|
||||
&mut msg.f_static_tag // tag
|
||||
);
|
||||
|
||||
// token : ss
|
||||
// H := Hash(H || msg.static)
|
||||
let hs = HASH!(&hs, &msg.f_static, &msg.f_static_tag);
|
||||
|
||||
Ok(vec![])
|
||||
// (C, k) := Kdf2(C, DH(S_priv, S_pub))
|
||||
let (ck, key) = KDF2!(
|
||||
&ck,
|
||||
device.sk.diffie_hellman(&peer.pk).as_bytes()
|
||||
);
|
||||
|
||||
// msg.timestamp := Aead(k, 0, Timestamp(), H)
|
||||
SEAL!(
|
||||
&key,
|
||||
&hs, // ad
|
||||
×tamp::new(), // 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
|
||||
|
||||
let mut st = peer.state.lock().unwrap();
|
||||
*st = State::InitiationSent{
|
||||
hs : hs,
|
||||
ck : ck
|
||||
};
|
||||
|
||||
// return message as vector
|
||||
|
||||
Ok(messages::Initiation::into(msg))
|
||||
}
|
||||
|
||||
pub fn process_initiation(peer : &Peer) -> Result<Output, ()> {
|
||||
Err(())
|
||||
}
|
||||
|
||||
|
||||
5
src/timestamp.rs
Normal file
5
src/timestamp.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
pub type TAI64N = [u8; 12];
|
||||
|
||||
pub fn new() -> TAI64N {
|
||||
[0u8; 12] // TODO
|
||||
}
|
||||
84
src/types.rs
84
src/types.rs
@@ -1,8 +1,71 @@
|
||||
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
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConfigError(String);
|
||||
|
||||
impl ConfigError {
|
||||
pub fn new(s : &str) -> Self {
|
||||
ConfigError(s.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ConfigError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "ConfigError({})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ConfigError {
|
||||
fn description(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// handshake error
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HandshakeError {}
|
||||
|
||||
impl HandshakeError {
|
||||
pub fn new() -> Self {
|
||||
HandshakeError{}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for HandshakeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "HandshakeError")
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for HandshakeError {
|
||||
fn description(&self) -> &str {
|
||||
"Generic Handshake Error"
|
||||
}
|
||||
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// types for resulting key-material
|
||||
|
||||
struct Key {
|
||||
key : [u8; 32],
|
||||
id : u32
|
||||
@@ -19,17 +82,26 @@ pub struct Output (
|
||||
Option<Vec<u8>> // message to send
|
||||
);
|
||||
|
||||
// per-peer state machine
|
||||
|
||||
pub type Psk = [u8; 32];
|
||||
|
||||
pub struct Peer {
|
||||
// mutable state
|
||||
pub m : Mutex<State>,
|
||||
pub state : Mutex<State>,
|
||||
|
||||
// constant state
|
||||
pub pk : PublicKey, // public key of peer
|
||||
pub ss : SharedSecret, // precomputed DH(static, static)
|
||||
pub psk : [u8; 32] // psk of peer
|
||||
pub pk : PublicKey, // public key of peer
|
||||
pub ss : SharedSecret, // precomputed DH(static, static)
|
||||
pub psk : Psk // psk of peer
|
||||
}
|
||||
|
||||
pub enum State {
|
||||
Reset,
|
||||
InitiationSent,
|
||||
Reset{
|
||||
ts : Option<timestamp::TAI64N>
|
||||
},
|
||||
InitiationSent{
|
||||
hs : GenericArray<u8, U32>,
|
||||
ck : GenericArray<u8, U32>
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user