86 lines
No EOL
2.8 KiB
Rust
86 lines
No EOL
2.8 KiB
Rust
//! `Noise_IKpsk2` handshake, specifically the way WireGuard defines it
|
|
use std::fmt::{Debug, Formatter};
|
|
use tai64::Tai64N;
|
|
use x25519_dalek::{EphemeralSecret, PublicKey, StaticSecret};
|
|
use crate::qcrypto::timestamp;
|
|
|
|
pub mod initiator;
|
|
pub mod response;
|
|
|
|
#[cfg(test)]
|
|
pub mod tests;
|
|
|
|
/// The Blake2s hash of the construction
|
|
pub const HANDSHAKE_INITIATOR_CHAIN_KEY: [u8; 32] = [
|
|
96, 226, 109, 174, 243, 39, 239, 192, 46, 195, 53, 226, 160, 37, 210, 208, 22, 235, 66, 6, 248,
|
|
114, 119, 245, 45, 56, 209, 152, 139, 120, 205, 54,
|
|
];
|
|
|
|
/// The hashed chaining key
|
|
pub const HANDSHAKE_INITIATOR_CHAIN_KEY_HASH: [u8; 32] = [
|
|
34, 17, 179, 97, 8, 26, 197, 102, 105, 18, 67, 219, 69, 138, 213, 50, 45, 156, 108, 102, 34,
|
|
147, 232, 183, 14, 225, 156, 101, 186, 7, 158, 243,
|
|
];
|
|
|
|
/// Represents a cookie we got from the other peer
|
|
#[derive(Debug)]
|
|
pub struct Cookie {
|
|
time: Tai64N,
|
|
cookie: [u8; 16]
|
|
}
|
|
|
|
/// Represents the internal handshake state. This does not really need to be messed with by outside users
|
|
#[allow(missing_docs)]
|
|
#[allow(clippy::module_name_repetitions)]
|
|
pub struct HandshakeState {
|
|
pub h: [u8; 32],
|
|
pub ck: [u8; 32],
|
|
|
|
pub e_pub_i: PublicKey,
|
|
|
|
pub s_pub_i: PublicKey,
|
|
pub s_pub_r: PublicKey,
|
|
|
|
pub e_priv_me: EphemeralSecret,
|
|
pub s_priv_me: StaticSecret,
|
|
pub s_pub_them: PublicKey,
|
|
|
|
pub i_i: u32,
|
|
pub i_r: u32,
|
|
|
|
pub cookies: Vec<Cookie>
|
|
}
|
|
impl HandshakeState {
|
|
/// Determines if the state variables of this `HandshakeState` are the same as another
|
|
#[allow(clippy::suspicious_operation_groupings)]
|
|
pub fn is_eq(&self, other: &HandshakeState) -> bool {
|
|
self.h == other.h && self.ck == other.ck && self.e_pub_i == other.e_pub_i && self.s_pub_i == other.s_pub_i && self.s_pub_r == other.s_pub_r && self.i_i == other.i_i && self.i_r == other.i_r
|
|
}
|
|
}
|
|
impl Debug for HandshakeState {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
f.debug_struct("HandshakeState")
|
|
.field("h", &self.h)
|
|
.field("ck", &self.ck)
|
|
.field("e_pub_i", &self.e_pub_i)
|
|
.field("s_pub_i", &self.s_pub_i)
|
|
.field("s_pub_r", &self.s_pub_r)
|
|
.field("e_priv_me", &"<redacted>")
|
|
.field("s_priv_me", &"<redacted>")
|
|
.field("s_pub_them", &self.s_pub_them)
|
|
.field("i_i", &self.i_i)
|
|
.field("i_r", &self.i_r)
|
|
.field("cookies", &self.cookies).finish()
|
|
}
|
|
}
|
|
|
|
/// Determines if a cookie MAC needs to be added to the packet being sent
|
|
pub fn needs_cookie(session: &HandshakeState) -> bool {
|
|
if !session.cookies.is_empty() {
|
|
let past_cookie_timeout = session.cookies[session.cookies.len()-1].time.duration_since(×tamp()).map_or(true, |t| t.as_secs() >= 120);
|
|
if !past_cookie_timeout {
|
|
return true;
|
|
}
|
|
}
|
|
false
|
|
} |