From 0f92468f6978c7ce13b33558e5bc36f94a2b7e4e Mon Sep 17 00:00:00 2001 From: Mathias Hall-Andersen Date: Thu, 1 Aug 2019 13:25:50 +0200 Subject: Successfully validate mac1 field --- src/handshake/macs.rs | 93 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 75 insertions(+), 18 deletions(-) (limited to 'src/handshake/macs.rs') diff --git a/src/handshake/macs.rs b/src/handshake/macs.rs index 9092daa..f558362 100644 --- a/src/handshake/macs.rs +++ b/src/handshake/macs.rs @@ -1,10 +1,11 @@ -use std::time::Instant; +use std::time::{Duration, Instant}; use blake2::Blake2s; use subtle::ConstantTimeEq; use x25519_dalek::PublicKey; use super::messages::{CookieReply, MacsFooter}; +use super::types::HandshakeError; const LABEL_MAC1: &[u8] = b"mac1----"; const LABEL_COOKIE: &[u8] = b"cookie--"; @@ -12,6 +13,8 @@ const LABEL_COOKIE: &[u8] = b"cookie--"; const SIZE_COOKIE: usize = 16; const SIZE_MAC: usize = 16; // blake2s-mac128 +const SECS_COOKIE_UPDATE: u64 = 120; + macro_rules! HASH { ( $($input:expr),* ) => {{ use blake2::Digest; @@ -38,39 +41,93 @@ macro_rules! MAC { }}; } +struct Cookie { + value: [u8; 16], + birth: Instant, +} + pub struct Generator { mac1_key: [u8; 32], - cookie_value: [u8; 16], - cookie_birth: Option, // when was the cookie set? + last_mac1: Option<[u8; 16]>, + cookie: Option, } impl Generator { + /// Initalize a new mac field generator + /// + /// # Arguments + /// + /// - pk: The public key of the peer to which the generator is associated + /// + /// # Returns + /// + /// A freshly initated generator pub fn new(pk: PublicKey) -> Generator { Generator { mac1_key: HASH!(LABEL_MAC1, pk.as_bytes()).into(), - cookie_value: [0u8; SIZE_COOKIE], - cookie_birth: None, + last_mac1: None, + cookie: None, } } - fn mac1(&self, msg: &[u8]) -> [u8; SIZE_MAC] { - MAC!(&self.mac1_key, msg) + /// Process a CookieReply message + /// + /// # Arguments + /// + /// - reply: CookieReply to process + /// + /// # Returns + /// + /// Can fail if the cookie reply fails to validate + /// (either indicating that it is outdated or malformed) + pub fn process(&mut self, reply: &CookieReply) -> Option { + self.cookie = Some(Cookie { + birth: Instant::now(), + value: reply.f_cookie, + }); + None } - fn mac2(&self, msg: &[u8]) -> [u8; SIZE_MAC] { - MAC!(&self.cookie_value, msg) + /// Generate both mac fields for an inner message + /// + /// # Arguments + /// + /// - inner: A byteslice representing the inner message to be covered + /// - macs: The destination mac footer for the resulting macs + pub fn generate(&mut self, inner: &[u8], macs: &mut MacsFooter) { + macs.f_mac1 = MAC!(&self.mac1_key, inner); + macs.f_mac2 = match &self.cookie { + Some(cookie) => { + if cookie.birth.elapsed() > Duration::from_secs(SECS_COOKIE_UPDATE) { + self.cookie = None; + [0u8; SIZE_MAC] + } else { + MAC!(&cookie.value, inner, macs.f_mac1) + } + } + None => [0u8; SIZE_MAC], + }; + self.last_mac1 = Some(macs.f_mac1); } +} - pub fn set_cookie(&mut self, cookie: &[u8; SIZE_COOKIE]) { - self.cookie_birth = Some(Instant::now()); - self.cookie_value = *cookie; - } +pub struct Validator { + mac1_key: [u8; 32], +} - pub fn generate(&self, inner: &[u8], macs : &mut MacsFooter) { +impl Validator { + pub fn new(pk: PublicKey) -> Validator { + Validator { + mac1_key: HASH!(LABEL_MAC1, pk.as_bytes()).into(), + } + } + pub fn check_mac1(&self, inner: &[u8], macs: &MacsFooter) -> Result<(), HandshakeError> { + let valid_mac1: bool = MAC!(&self.mac1_key, inner).ct_eq(&macs.f_mac1).into(); + if !valid_mac1 { + Err(HandshakeError::InvalidMac1) + } else { + Ok(()) + } } } - -pub struct Validator {} - -impl Validator {} -- cgit v1.2.3-59-g8ed1b