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,13 +7,12 @@ 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
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
@@ -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,7 +63,7 @@ impl Device {
// map : new index -> peer
self.peers.push(Peer {
m : Mutex::new(State::Reset),
state : Mutex::new(State::Reset{ts : None}),
pk : pk,
ss : self.sk.diffie_hellman(&pk),
psk : [0u8; 32]
@@ -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],
f_type : u32,
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],
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 {
@@ -71,11 +72,12 @@ 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_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
}
}
@@ -177,7 +178,6 @@ mod tests {
fn message_response_identity() {
let msg = Response {
f_type : TYPE_RESPONSE,
f_reserved : [0u8; 3],
f_sender : 146252,
f_receiver : 554442,
f_ephemeral : [
@@ -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
@@ -202,7 +202,6 @@ mod tests {
fn message_initiate_identity() {
let msg = Initiation {
f_type : TYPE_RESPONSE,
f_reserved : [0u8; 3],
f_sender : 575757,
f_ephemeral : [
// ephemeral public key
@@ -216,8 +215,9 @@ mod tests {
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 psk : Psk // psk of peer
}
pub enum State {
Reset,
InitiationSent,
Reset{
ts : Option<timestamp::TAI64N>
},
InitiationSent{
hs : GenericArray<u8, U32>,
ck : GenericArray<u8, U32>
},
}