Make unit tests pass

This commit is contained in:
Mathias Hall-Andersen
2019-08-01 11:12:30 +02:00
parent 1cfd5aea1a
commit ab98d9dced
5 changed files with 83 additions and 64 deletions

View File

@@ -1,5 +1,6 @@
use spin::RwLock;
use std::collections::HashMap;
use zerocopy::AsBytes;
use rand::prelude::*;
use rand::rngs::OsRng;
@@ -159,7 +160,16 @@ where
None => Err(HandshakeError::UnknownPublicKey),
Some(peer) => {
let sender = self.allocate(peer);
noise::create_initiation(self, peer, sender)
let mut msg = Initiation::default();
noise::create_initiation(self, peer, sender, &mut msg.noise)?;
// add macs to initation
peer.macs.generate(msg.noise.as_bytes(), &mut msg.macs);
Ok(msg.as_bytes().to_owned())
}
}
}
@@ -174,7 +184,7 @@ where
Some(&TYPE_INITIATION) => {
let msg = Initiation::parse(msg)?;
// check mac footer and ratelimiter
// check mac footer and ratelimiter for initiation
// consume the initiation
let (peer, st) = noise::consume_initiation(self, &msg.noise)?;
@@ -182,12 +192,25 @@ where
// allocate new index for response
let sender = self.allocate(peer);
// create response (release id on error), TODO: take slice
// prepare memory for response, TODO: take slice for zero allocation
let mut resp = Response::default();
noise::create_response(peer, sender, st, &mut resp.noise).map_err(|e| {
self.release(sender);
e
})
// create response (release id on error)
let keys =
noise::create_response(peer, sender, st, &mut resp.noise).map_err(|e| {
self.release(sender);
e
})?;
// add macs to response
resp.macs.f_mac1 = [8u8; 16];
Ok((
peer.identifier,
Some(resp.as_bytes().to_owned()),
Some(keys),
))
}
Some(&TYPE_RESPONSE) => {
let msg = Response::parse(msg)?;
@@ -297,7 +320,7 @@ mod tests {
let msg1 = dev1.begin(&pk2).unwrap();
println!("msg1 = {}", hex::encode(&msg1[..]));
println!("msg1 = {} : {} bytes", hex::encode(&msg1[..]), msg1.len());
println!("msg1 = {:?}", Initiation::parse(&msg1[..]).unwrap());
// process initiation and create response
@@ -307,7 +330,7 @@ mod tests {
let ks_r = ks_r.unwrap();
let msg2 = msg2.unwrap();
println!("msg2 = {}", hex::encode(&msg2[..]));
println!("msg2 = {} : {} bytes", hex::encode(&msg2[..]), msg2.len());
println!("msg2 = {:?}", Response::parse(&msg2[..]).unwrap());
assert!(!ks_r.confirmed, "Responders key-pair is confirmed");

View File

@@ -38,14 +38,14 @@ macro_rules! MAC {
}};
}
struct Generator {
pub struct Generator {
mac1_key: [u8; 32],
cookie_value: [u8; 16],
cookie_birth: Option<Instant>, // when was the cookie set?
}
impl Generator {
fn new(pk: PublicKey) -> Generator {
pub fn new(pk: PublicKey) -> Generator {
Generator {
mac1_key: HASH!(LABEL_MAC1, pk.as_bytes()).into(),
cookie_value: [0u8; SIZE_COOKIE],
@@ -66,14 +66,11 @@ impl Generator {
self.cookie_value = *cookie;
}
pub fn generate(&self, msg: &[u8]) -> MacsFooter {
MacsFooter {
f_mac1: self.mac1(msg),
f_mac2: self.mac2(msg),
}
pub fn generate(&self, inner: &[u8], macs : &mut MacsFooter) {
}
}
struct Validator {}
pub struct Validator {}
impl Validator {}

View File

@@ -11,7 +11,7 @@ use zerocopy::{AsBytes, ByteSlice, FromBytes, LayoutVerified};
use super::timestamp;
use super::types::*;
const SIZE_MAC: usize = 16;
const SIZE_MAC: usize = 16;
const SIZE_TAG: usize = 16; // poly1305 tag
const SIZE_NONCE: usize = 16; // xchacha20 nonce
const SIZE_COOKIE: usize = 16; //
@@ -23,21 +23,21 @@ pub const TYPE_COOKIEREPLY: u8 = 3;
/* Handshake messsages */
#[repr(C)]
#[repr(packed)]
#[derive(Copy, Clone, FromBytes, AsBytes)]
pub struct Response {
pub noise: NoiseResponse, // inner message covered by macs
pub macs: MacsFooter,
}
#[repr(C)]
#[repr(packed)]
#[derive(Copy, Clone, FromBytes, AsBytes)]
pub struct Initiation {
pub noise: NoiseInitiation, // inner message covered by macs
pub macs: MacsFooter,
}
#[repr(C)]
#[repr(packed)]
#[derive(Copy, Clone, FromBytes, AsBytes)]
pub struct CookieReply {
f_type: U32<LittleEndian>,
@@ -49,14 +49,14 @@ pub struct CookieReply {
/* Inner sub-messages */
#[repr(C)]
#[repr(packed)]
#[derive(Copy, Clone, FromBytes, AsBytes)]
pub struct MacsFooter {
pub f_mac1: [u8; SIZE_MAC],
pub f_mac2: [u8; SIZE_MAC],
}
#[repr(C)]
#[repr(packed)]
#[derive(Copy, Clone, FromBytes, AsBytes)]
pub struct NoiseInitiation {
f_type: U32<LittleEndian>,
@@ -65,17 +65,17 @@ pub struct NoiseInitiation {
pub f_static: [u8; SIZE_X25519_POINT],
pub f_static_tag: [u8; SIZE_TAG],
pub f_timestamp: timestamp::TAI64N,
pub f_timestamp_tag: [u8; SIZE_TAG]
pub f_timestamp_tag: [u8; SIZE_TAG],
}
#[repr(C)]
#[repr(packed)]
#[derive(Copy, Clone, FromBytes, AsBytes)]
pub struct NoiseResponse {
f_type: U32<LittleEndian>,
pub f_sender: U32<LittleEndian>,
pub f_receiver: U32<LittleEndian>,
pub f_ephemeral: [u8; SIZE_X25519_POINT],
pub f_empty_tag: [u8; SIZE_TAG]
pub f_empty_tag: [u8; SIZE_TAG],
}
/* Zero copy parsing of handshake messages */
@@ -124,8 +124,8 @@ impl CookieReply {
impl Default for Response {
fn default() -> Self {
Self {
noise: Default::default(),
macs: Default::default(),
noise: Default::default(),
macs: Default::default(),
}
}
}
@@ -133,8 +133,8 @@ impl Default for Response {
impl Default for Initiation {
fn default() -> Self {
Self {
noise: Default::default(),
macs: Default::default(),
noise: Default::default(),
macs: Default::default(),
}
}
}
@@ -142,11 +142,11 @@ impl Default for Initiation {
impl Default for CookieReply {
fn default() -> Self {
Self {
f_type: <U32<LittleEndian>>::new(TYPE_COOKIEREPLY as u32),
f_receiver: <U32<LittleEndian>>::ZERO,
f_nonce: [0u8; SIZE_NONCE],
f_cookie: [0u8; SIZE_COOKIE],
f_cookie_tag: [0u8; SIZE_TAG],
f_type: <U32<LittleEndian>>::new(TYPE_COOKIEREPLY as u32),
f_receiver: <U32<LittleEndian>>::ZERO,
f_nonce: [0u8; SIZE_NONCE],
f_cookie: [0u8; SIZE_COOKIE],
f_cookie_tag: [0u8; SIZE_TAG],
}
}
}
@@ -161,7 +161,7 @@ impl Default for MacsFooter {
}
impl Default for NoiseInitiation {
fn default() -> Self {
fn default() -> Self {
Self {
f_type: <U32<LittleEndian>>::new(TYPE_INITIATION as u32),
@@ -170,7 +170,7 @@ impl Default for NoiseInitiation {
f_static: [0u8; SIZE_X25519_POINT],
f_static_tag: [0u8; SIZE_TAG],
f_timestamp: timestamp::ZERO,
f_timestamp_tag: [0u8; SIZE_TAG]
f_timestamp_tag: [0u8; SIZE_TAG],
}
}
}
@@ -206,7 +206,8 @@ impl fmt::Debug for Response {
#[cfg(test)]
impl fmt::Debug for CookieReply {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f,
write!(
f,
"CookieReply {{ type = {}, receiver = {}, nonce = {}, cookie = {}|{} }}",
self.f_type,
self.f_receiver,
@@ -250,7 +251,8 @@ impl fmt::Debug for NoiseResponse {
#[cfg(test)]
impl fmt::Debug for MacsFooter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f,
write!(
f,
"Macs {{ mac1 = {}, mac2 = {} }}",
hex::encode(self.f_mac1),
hex::encode(self.f_mac2)
@@ -268,7 +270,7 @@ macro_rules! eq_as_bytes {
}
}
impl Eq for $type {}
}
};
}
#[cfg(test)]

View File

@@ -15,8 +15,6 @@ use rand::rngs::OsRng;
use generic_array::typenum::*;
use generic_array::GenericArray;
use zerocopy::AsBytes;
use super::device::Device;
use super::messages::{NoiseInitiation, NoiseResponse};
use super::peer::{Peer, State};
@@ -140,9 +138,9 @@ pub fn create_initiation<T: Copy>(
device: &Device<T>,
peer: &Peer<T>,
sender: u32,
) -> Result<Vec<u8>, HandshakeError> {
msg: &mut NoiseInitiation,
) -> Result<(), HandshakeError> {
let mut rng = OsRng::new().unwrap();
let mut msg: NoiseInitiation = Default::default();
// initialize state
@@ -214,9 +212,7 @@ pub fn create_initiation<T: Copy>(
sender,
});
// return message as vector
Ok(msg.as_bytes().to_vec())
Ok(())
}
pub fn consume_initiation<'a, T: Copy>(
@@ -294,7 +290,7 @@ pub fn create_response<T: Copy>(
sender: u32, // sending identifier
state: TemporaryState, // state from "consume_initiation"
msg: &mut NoiseResponse, // resulting response
) -> Result<Output<T>, HandshakeError> {
) -> Result<KeyPair, HandshakeError> {
let mut rng = OsRng::new().unwrap();
let (receiver, eph_r_pk, hs, ck) = state;
@@ -354,23 +350,19 @@ pub fn create_response<T: Copy>(
let (key_recv, key_send) = KDF2!(&ck, &[]);
// return response and unconfirmed key-pair
// return unconfirmed key-pair
Ok((
peer.identifier,
Some(msg.as_bytes().to_vec()),
Some(KeyPair {
confirmed: false,
send: Key {
id: sender,
key: key_send.into(),
},
recv: Key {
id: receiver,
key: key_recv.into(),
},
}),
))
Ok(KeyPair {
confirmed: false,
send: Key {
id: sender,
key: key_send.into(),
},
recv: Key {
id: receiver,
key: key_recv.into(),
},
})
}
pub fn consume_response<T: Copy>(

View File

@@ -10,6 +10,7 @@ use x25519_dalek::StaticSecret;
use super::device::Device;
use super::timestamp;
use super::types::*;
use super::macs;
/* Represents the recomputation and state of a peer.
*
@@ -24,6 +25,9 @@ pub struct Peer<T> {
state: Mutex<State>,
timestamp: Mutex<Option<timestamp::TAI64N>>,
// state related to DoS mitigation fields
pub(crate) macs: macs::Generator,
// constant state
pub(crate) pk: PublicKey, // public key of peer
pub(crate) ss: SharedSecret, // precomputed DH(static, static)
@@ -69,6 +73,7 @@ where
ss: SharedSecret, // precomputed DH(static, static)
) -> Self {
Self {
macs: macs::Generator::new(pk),
identifier: identifier,
state: Mutex::new(State::Reset),
timestamp: Mutex::new(None),