diff options
| author | David Lönnhager <david.l@mullvad.net> | 2020-02-07 09:31:54 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2020-02-07 09:31:54 +0100 |
| commit | a6c3608e710503ac29cf51f721f1dc4e8c7e2724 (patch) | |
| tree | 5e9358332ff6af88e3eb05ff3c512a24328b522d | |
| parent | db8ea63ffaa671df27dc404b75a9ee92fda0312c (diff) | |
| parent | 1839efc29694a0dd32fcf07753cec71603cfc455 (diff) | |
| download | mullvadvpn-a6c3608e710503ac29cf51f721f1dc4e8c7e2724.tar.xz mullvadvpn-a6c3608e710503ac29cf51f721f1dc4e8c7e2724.zip | |
Merge branch 'x25519-update'
| -rw-r--r-- | Cargo.lock | 44 | ||||
| -rw-r--r-- | mullvad-daemon/src/wireguard.rs | 21 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/config.rs | 2 | ||||
| -rw-r--r-- | talpid-types/Cargo.toml | 2 | ||||
| -rw-r--r-- | talpid-types/src/net/wireguard.rs | 92 |
5 files changed, 93 insertions, 68 deletions
diff --git a/Cargo.lock b/Cargo.lock index 8e6b03aa4e..a77b00b0d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -232,14 +232,6 @@ dependencies = [ ] [[package]] -name = "clear_on_drop" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -337,14 +329,14 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "1.2.3" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2522,7 +2514,7 @@ dependencies = [ "jnix 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "x25519-dalek 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3132,18 +3124,32 @@ dependencies = [ [[package]] name = "x25519-dalek" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "zeroize" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "zeroize_derive 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zeroize_derive" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [metadata] "checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" @@ -3177,7 +3183,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c" "checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"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 colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cdb90b60f2927f8d76139c72dbde7e10c3a2bc47c8594c9c7a66529f2687c03" "checksum combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" @@ -3189,7 +3194,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7dfd2d8b4c82121dfdff120f818e09fc4380b0b7e17a742081a89b94853e87f" -"checksum curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d" +"checksum curve25519-dalek 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26778518a7f6cffa1d25a44b602b62b979bd88adb9e99ffec546998cf3404839" "checksum darling 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfbcb0c5961907597a7d1148e3af036268f2b773886b8bb3eeb1e1281d3d3d6" "checksum darling_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6afc018370c3bff3eb51f89256a6bdb18b4fdcda72d577982a14954a7a0b402c" "checksum darling_macro 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6d8dac1c6f1d29a41c4712b4400f878cb4fcc4c7628f298dd75038e024998d1" @@ -3465,5 +3470,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" "checksum winres 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ff4fb510bbfe5b8992ff15f77a2e6fe6cf062878f0eda00c0f44963a807ca5dc" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee1585dc1484373cbc1cee7aafda26634665cf449436fd6e24bfd1fad230538" +"checksum x25519-dalek 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "637ff90c9540fa3073bb577e65033069e4bae7c79d49d74aa3ffdf5342a53217" "checksum zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8" +"checksum zeroize_derive 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2" diff --git a/mullvad-daemon/src/wireguard.rs b/mullvad-daemon/src/wireguard.rs index 7bd98cee52..1cad231548 100644 --- a/mullvad-daemon/src/wireguard.rs +++ b/mullvad-daemon/src/wireguard.rs @@ -1,7 +1,7 @@ use crate::{account_history::AccountHistory, InternalDaemonEvent}; use chrono::offset::Utc; use futures::{ - future::{Executor, IntoFuture}, + future::Executor, sync::{mpsc::UnboundedSender, oneshot}, Async, Future, Poll, }; @@ -30,11 +30,8 @@ const AUTOMATIC_ROTATION_RETRY_DELAY: Duration = Duration::from_secs(5); /// A short interval is used in case the computer is ever suspended. const KEY_CHECK_INTERVAL: Duration = Duration::from_secs(60); - #[derive(err_derive::Error, Debug)] pub enum Error { - #[error(display = "Failed to generate private key")] - GenerationError(#[error(source)] rand::Error), #[error(display = "Failed to spawn future")] ExectuionError, #[error(display = "Unexpected RPC error")] @@ -123,7 +120,7 @@ impl KeyManager { /// Generate a new private key pub fn generate_key_sync(&mut self, account: AccountToken) -> Result<WireguardData> { self.reset(); - let private_key = PrivateKey::new_from_random().map_err(Error::GenerationError)?; + let private_key = PrivateKey::new_from_random(); self.run_future_sync(self.push_future_generator(account, private_key)()) .map_err(Self::map_rpc_error) @@ -149,7 +146,7 @@ impl KeyManager { old_key: PublicKey, ) -> Result<WireguardData> { self.reset(); - let new_key = PrivateKey::new_from_random().map_err(Error::GenerationError)?; + let new_key = PrivateKey::new_from_random(); self.run_future_sync(Self::replace_key_rpc( self.http_handle.clone(), account, @@ -163,7 +160,7 @@ impl KeyManager { /// Generate a new private key asyncronously. The new keys will be sent to the daemon channel. pub fn generate_key_async(&mut self, account: AccountToken) -> Result<()> { self.reset(); - let private_key = PrivateKey::new_from_random().map_err(Error::GenerationError)?; + let private_key = PrivateKey::new_from_random(); let future_generator = self.push_future_generator(account.clone(), private_key); let retry_strategy = ExponentialBackoff::from_millis(300) @@ -321,13 +318,9 @@ impl KeyManager { .and_then(move |_| { log::info!("Replacing WireGuard key"); - let private_key = PrivateKey::new_from_random() - .map_err(Error::GenerationError) - .into_future(); - private_key.and_then(move |private_key| { - Self::replace_key_rpc(http_handle, account_token, public_key, private_key) - .map_err(Self::map_rpc_error) - }) + let private_key = PrivateKey::new_from_random(); + Self::replace_key_rpc(http_handle, account_token, public_key, private_key) + .map_err(Self::map_rpc_error) }) .then(move |rpc_result| { match rpc_result { diff --git a/talpid-core/src/tunnel/wireguard/config.rs b/talpid-core/src/tunnel/wireguard/config.rs index 76107a2a63..e433483a55 100644 --- a/talpid-core/src/tunnel/wireguard/config.rs +++ b/talpid-core/src/tunnel/wireguard/config.rs @@ -95,7 +95,7 @@ impl Config { // the order of insertion matters, public key entry denotes a new peer entry let mut wg_conf = WgConfigBuffer::new(); wg_conf - .add("private_key", self.tunnel.private_key.as_bytes().as_ref()) + .add("private_key", self.tunnel.private_key.to_bytes().as_ref()) .add("listen_port", "0"); wg_conf.add("replace_peers", "true"); diff --git a/talpid-types/Cargo.toml b/talpid-types/Cargo.toml index 5e9354847c..a75af01062 100644 --- a/talpid-types/Cargo.toml +++ b/talpid-types/Cargo.toml @@ -11,7 +11,7 @@ publish = false serde = { version = "1.0", features = ["derive"] } ipnetwork = "0.15" base64 = "0.10" -x25519-dalek = { version = "0.5", features = [ "std", "u64_backend" ], default-features = false } +x25519-dalek = { version = "0.6", features = [ "std", "u64_backend" ], default-features = false } rand = "0.7" err-derive = "0.2.1" diff --git a/talpid-types/src/net/wireguard.rs b/talpid-types/src/net/wireguard.rs index 805d1884ba..767687dd6b 100644 --- a/talpid-types/src/net/wireguard.rs +++ b/talpid-types/src/net/wireguard.rs @@ -1,9 +1,10 @@ use crate::net::{Endpoint, GenericTunnelOptions, TransportProtocol}; use ipnetwork::IpNetwork; -use rand::{rngs::OsRng, RngCore}; +use rand::rngs::OsRng; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::{ - fmt, + cmp, fmt, + hash::{Hash, Hasher}, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, }; @@ -56,41 +57,48 @@ pub struct TunnelOptions { } /// Wireguard x25519 private key -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct PrivateKey([u8; 32]); +#[derive(Clone)] +pub struct PrivateKey(x25519_dalek::StaticSecret); impl PrivateKey { /// Get private key as bytes - pub fn as_bytes(&self) -> &[u8; 32] { - &self.0 - } - - /// Normalizing a private key as per the specification - https://cr.yp.to/ecdh.html - fn normalize_key(bytes: &mut [u8; 32]) { - bytes[0] &= 248; - bytes[31] &= 127; - bytes[31] |= 64; + pub fn to_bytes(&self) -> [u8; 32] { + self.0.to_bytes() } - pub fn new_from_random() -> Result<Self, rand::Error> { - let mut bytes = [0u8; 32]; - OsRng.fill_bytes(&mut bytes); - Ok(Self::from(bytes)) + pub fn new_from_random() -> Self { + PrivateKey(x25519_dalek::StaticSecret::new(&mut OsRng)) } /// Generate public key from private key pub fn public_key(&self) -> PublicKey { - PublicKey::from(x25519_dalek::x25519( - self.0, - x25519_dalek::X25519_BASEPOINT_BYTES, - )) + PublicKey::from(&self.0) } } impl From<[u8; 32]> for PrivateKey { - fn from(mut private_key: [u8; 32]) -> PrivateKey { - Self::normalize_key(&mut private_key); - PrivateKey(private_key) + fn from(bytes: [u8; 32]) -> Self { + Self(x25519_dalek::StaticSecret::from(bytes)) + } +} + +impl cmp::PartialEq for PrivateKey { + fn eq(&self, other: &PrivateKey) -> bool { + self.0.to_bytes() == other.0.to_bytes() + } +} + +impl cmp::Eq for PrivateKey {} + +impl fmt::Debug for PrivateKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", &self) + } +} + +impl fmt::Display for PrivateKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", &base64::encode(&(self.0).to_bytes())) } } @@ -99,11 +107,10 @@ impl Serialize for PrivateKey { where S: Serializer, { - serialize_key(&self.0, serializer) + serialize_key(&self.0.to_bytes(), serializer) } } - impl<'de> Deserialize<'de> for PrivateKey { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where @@ -114,20 +121,26 @@ impl<'de> Deserialize<'de> for PrivateKey { } /// Wireguard x25519 public key -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct PublicKey([u8; 32]); +#[derive(Clone)] +pub struct PublicKey(x25519_dalek::PublicKey); impl PublicKey { /// Get the public key as bytes pub fn as_bytes(&self) -> &[u8; 32] { - &self.0 + self.0.as_bytes() } } +impl<'a> From<&'a x25519_dalek::StaticSecret> for PublicKey { + fn from(private_key: &'a x25519_dalek::StaticSecret) -> PublicKey { + PublicKey(x25519_dalek::PublicKey::from(private_key)) + } +} + impl From<[u8; 32]> for PublicKey { fn from(public_key: [u8; 32]) -> PublicKey { - PublicKey(public_key) + PublicKey(x25519_dalek::PublicKey::from(public_key)) } } @@ -136,11 +149,10 @@ impl Serialize for PublicKey { where S: Serializer, { - serialize_key(&self.0, serializer) + serialize_key(&self.0.as_bytes(), serializer) } } - impl<'de> Deserialize<'de> for PublicKey { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where @@ -150,6 +162,20 @@ impl<'de> Deserialize<'de> for PublicKey { } } +impl Hash for PublicKey { + fn hash<H: Hasher>(&self, state: &mut H) { + self.0.as_bytes().hash(state); + } +} + +impl cmp::PartialEq for PublicKey { + fn eq(&self, other: &PublicKey) -> bool { + self.0.as_bytes() == other.0.as_bytes() + } +} + +impl cmp::Eq for PublicKey {} + impl fmt::Debug for PublicKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", &self) @@ -158,7 +184,7 @@ impl fmt::Debug for PublicKey { impl fmt::Display for PublicKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", &base64::encode(&self.0)) + write!(f, "{}", &base64::encode(self.0.as_bytes())) } } |
