diff options
author | Mathias Hall-Andersen <mathias@hall-andersen.dk> | 2019-07-28 17:09:27 +0200 |
---|---|---|
committer | Mathias Hall-Andersen <mathias@hall-andersen.dk> | 2019-07-28 17:09:27 +0200 |
commit | 2c81abbe7973dfbe6113d66f9d92b6b4ad3b0afa (patch) | |
tree | 62f32c732564544edf1ca5456cbd84e87385ae38 /src/noise/peer.rs | |
parent | Added ability to remove peer from device (diff) | |
download | wireguard-rs-2c81abbe7973dfbe6113d66f9d92b6b4ad3b0afa.tar.xz wireguard-rs-2c81abbe7973dfbe6113d66f9d92b6b4ad3b0afa.zip |
Restructured for wireguard-rs
Diffstat (limited to 'src/noise/peer.rs')
-rw-r--r-- | src/noise/peer.rs | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/noise/peer.rs b/src/noise/peer.rs new file mode 100644 index 0000000..5b01d75 --- /dev/null +++ b/src/noise/peer.rs @@ -0,0 +1,136 @@ +use spin::Mutex; + +use generic_array::typenum::U32; +use generic_array::GenericArray; + +use x25519_dalek::PublicKey; +use x25519_dalek::SharedSecret; +use x25519_dalek::StaticSecret; + +use super::device::Device; +use super::timestamp; +use super::types::*; + +/* Represents the recomputation and state of a peer. + * + * This type is only for internal use and not exposed. + */ + +pub struct Peer<T> { + // external identifier + pub(crate) identifier: T, + + // mutable state + state: Mutex<State>, + timestamp: Mutex<Option<timestamp::TAI64N>>, + + // constant state + pub(crate) pk: PublicKey, // public key of peer + pub(crate) ss: SharedSecret, // precomputed DH(static, static) + pub(crate) psk: Psk, // psk of peer +} + +pub enum State { + Reset, + InitiationSent { + sender: u32, // assigned sender id + eph_sk: StaticSecret, + hs: GenericArray<u8, U32>, + ck: GenericArray<u8, U32>, + }, +} + +impl Clone for State { + fn clone(&self) -> State { + match self { + State::Reset => State::Reset, + State::InitiationSent { + sender, + eph_sk, + hs, + ck, + } => State::InitiationSent { + sender: *sender, + eph_sk: StaticSecret::from(eph_sk.to_bytes()), + hs: *hs, + ck: *ck, + }, + } + } +} + +impl<T> Peer<T> +where + T: Copy, +{ + pub fn new( + identifier: T, // external identifier + pk: PublicKey, // public key of peer + ss: SharedSecret, // precomputed DH(static, static) + ) -> Self { + Self { + identifier: identifier, + state: Mutex::new(State::Reset), + timestamp: Mutex::new(None), + pk: pk, + ss: ss, + psk: [0u8; 32], + } + } + + /// Return the state of the peer + /// + /// # Arguments + pub fn get_state(&self) -> State { + self.state.lock().clone() + } + + /// Set the state of the peer unconditionally + /// + /// # Arguments + /// + pub fn set_state(&self, state_new: State) { + *self.state.lock() = state_new; + } + + /// Set the mutable state of the peer conditioned on the timestamp being newer + /// + /// # Arguments + /// + /// * st_new - The updated state of the peer + /// * ts_new - The associated timestamp + pub fn check_timestamp( + &self, + device: &Device<T>, + timestamp_new: ×tamp::TAI64N, + ) -> Result<(), HandshakeError> { + let mut state = self.state.lock(); + let mut timestamp = self.timestamp.lock(); + + let update = match *timestamp { + None => true, + Some(timestamp_old) => { + if timestamp::compare(×tamp_old, ×tamp_new) { + true + } else { + false + } + } + }; + + if update { + // release existing identifier + match *state { + State::InitiationSent { sender, .. } => device.release(sender), + _ => (), + } + + // reset state and update timestamp + *state = State::Reset; + *timestamp = Some(*timestamp_new); + Ok(()) + } else { + Err(HandshakeError::OldTimestamp) + } + } +} |