Create initiation message

This commit is contained in:
Mathias Hall-Andersen
2019-07-16 23:37:25 +02:00
parent abf502f73c
commit 5a5d09bb41
8 changed files with 322 additions and 121 deletions

89
Cargo.lock generated
View File

@@ -36,14 +36,6 @@ name = "cc"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "chacha20-poly1305-aead"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clear_on_drop"
version = "0.2.3"
@@ -60,11 +52,6 @@ dependencies = [
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "constant_time_eq"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "crypto-mac"
version = "0.7.0"
@@ -100,16 +87,13 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "generic-array"
version = "0.12.0"
name = "gcc"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "generic-array"
version = "0.13.2"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -134,6 +118,27 @@ name = "opaque-debug"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.6.5"
@@ -238,6 +243,28 @@ dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rust-crypto"
version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "subtle"
version = "1.0.0"
@@ -248,6 +275,16 @@ name = "subtle"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "time"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "typenum"
version = "1.10.0"
@@ -258,10 +295,10 @@ name = "wg-handshake"
version = "0.1.0"
dependencies = [
"blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"chacha20-poly1305-aead 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
"generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"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)",
"x25519-dalek 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -301,19 +338,19 @@ dependencies = [
"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
"checksum cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ad0daef304fa0b4238f5f7ed7178774b43b06f6a9b6509f6642bef4ff1f7b9b2"
"checksum chacha20-poly1305-aead 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77d2058ba29594f69c75e8a9018e0485e3914ca5084e3613cd64529042f5423b"
"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
"checksum curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1f8a6fc0376eb52dc18af94915cc04dfdf8353746c0e8c550ae683a0815e5c1"
"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592"
"checksum generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd"
"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695"
"checksum libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "3262021842bf00fe07dbd6cf34ff25c99d7a7ebef8deea84db72be3ea3bb0aff"
"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409"
"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
@@ -325,8 +362,12 @@ dependencies = [
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
"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 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"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"

View File

@@ -8,8 +8,8 @@ edition = "2018"
rand = "0.6.5"
blake2 = "0.8.0"
hmac = "0.7.1"
chacha20-poly1305-aead = "0.1.2"
generic-array = "0.13"
rust-crypto = "^0.2"
generic-array = "0.12"
[dependencies.x25519-dalek]
version = "^0.5"

View File

@@ -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())
}
}
}

View File

@@ -1,4 +1,5 @@
mod types;
mod noise;
mod messages;
mod machine;
mod device;
mod timestamp;

View File

@@ -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

View File

@@ -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
&timestamp::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
View File

@@ -0,0 +1,5 @@
pub type TAI64N = [u8; 12];
pub fn new() -> TAI64N {
[0u8; 12] // TODO
}

View File

@@ -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>
},
}