summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2022-05-20 11:40:32 +0200
committerDavid Lönnhager <david.l@mullvad.net>2022-06-14 12:37:04 +0200
commitad0fdb6d5dc0c0e7c1eb1183784d994d44b459be (patch)
treecad8267f22d8567c0f36785c78b48e438bd3f1ff
parentd8e1e030af2d8a1f900a83c6f8f6f23a6d736be6 (diff)
downloadmullvadvpn-ad0fdb6d5dc0c0e7c1eb1183784d994d44b459be.tar.xz
mullvadvpn-ad0fdb6d5dc0c0e7c1eb1183784d994d44b459be.zip
Add option for enabling PQ PSK exchange to CLI and gRPC service
-rw-r--r--mullvad-cli/src/cmds/relay.rs19
-rw-r--r--mullvad-cli/src/cmds/tunnel.rs56
-rw-r--r--mullvad-daemon/src/lib.rs35
-rw-r--r--mullvad-daemon/src/management_interface.rs11
-rw-r--r--mullvad-daemon/src/settings.rs16
-rw-r--r--mullvad-management-interface/proto/management_interface.proto1
6 files changed, 137 insertions, 1 deletions
diff --git a/mullvad-cli/src/cmds/relay.rs b/mullvad-cli/src/cmds/relay.rs
index c624c2a25b..ac7bd74c63 100644
--- a/mullvad-cli/src/cmds/relay.rs
+++ b/mullvad-cli/src/cmds/relay.rs
@@ -573,7 +573,24 @@ impl Relay {
}
if let Some(entry) = matches.values_of("entry location") {
wireguard_constraints.entry_location = parse_entry_location_constraint(entry);
- wireguard_constraints.use_multihop = wireguard_constraints.entry_location.is_some();
+ let use_multihop = wireguard_constraints.entry_location.is_some();
+ if use_multihop {
+ let use_pq = rpc
+ .get_settings(())
+ .await?
+ .into_inner()
+ .tunnel_options
+ .unwrap()
+ .wireguard
+ .unwrap()
+ .use_pq_safe_psk;
+ if use_pq {
+ return Err(Error::CommandFailed(
+ "PQ PSK exchange does not work when multihop is enabled",
+ ));
+ }
+ }
+ wireguard_constraints.use_multihop = use_multihop;
}
self.update_constraints(types::RelaySettingsUpdate {
diff --git a/mullvad-cli/src/cmds/tunnel.rs b/mullvad-cli/src/cmds/tunnel.rs
index f01452a925..7856cc849c 100644
--- a/mullvad-cli/src/cmds/tunnel.rs
+++ b/mullvad-cli/src/cmds/tunnel.rs
@@ -37,6 +37,7 @@ fn create_wireguard_subcommand() -> clap::App<'static> {
.about("Manage options for Wireguard tunnels")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(create_wireguard_mtu_subcommand())
+ .subcommand(create_wireguard_quantum_resistant_tunnel_subcommand())
.subcommand(create_wireguard_keys_subcommand());
#[cfg(windows)]
{
@@ -57,6 +58,14 @@ fn create_wireguard_mtu_subcommand() -> clap::App<'static> {
.subcommand(clap::App::new("set").arg(clap::Arg::new("mtu").required(true)))
}
+fn create_wireguard_quantum_resistant_tunnel_subcommand() -> clap::App<'static> {
+ clap::App::new("quantum-resistant-tunnel")
+ .about("EXPERIMENTAL: Enables quantum-resistant PSK exchange in the tunnel")
+ .setting(clap::AppSettings::SubcommandRequiredElseHelp)
+ .subcommand(clap::App::new("get"))
+ .subcommand(clap::App::new("set").arg(clap::Arg::new("policy").required(true)))
+}
+
fn create_wireguard_keys_subcommand() -> clap::App<'static> {
clap::App::new("key")
.about("Manage your wireguard key")
@@ -163,6 +172,14 @@ impl Tunnel {
_ => unreachable!("unhandled command"),
},
+ Some(("quantum-resistant-tunnel", matches)) => match matches.subcommand() {
+ Some(("get", _)) => Self::process_wireguard_quantum_resistant_tunnel_get().await,
+ Some(("set", matches)) => {
+ Self::process_wireguard_quantum_resistant_tunnel_set(matches).await
+ }
+ _ => unreachable!("unhandled command"),
+ },
+
#[cfg(windows)]
Some(("use-wireguard-nt", matches)) => match matches.subcommand() {
Some(("get", _)) => Self::process_wireguard_use_wg_nt_get().await,
@@ -203,6 +220,45 @@ impl Tunnel {
Ok(())
}
+ async fn process_wireguard_quantum_resistant_tunnel_get() -> Result<()> {
+ let tunnel_options = Self::get_tunnel_options().await?;
+ if tunnel_options.wireguard.unwrap().use_pq_safe_psk {
+ println!("enabled");
+ } else {
+ println!("disabled");
+ }
+ Ok(())
+ }
+
+ async fn process_wireguard_quantum_resistant_tunnel_set(
+ matches: &clap::ArgMatches,
+ ) -> Result<()> {
+ let new_state = matches.value_of("policy").unwrap() == "on";
+ let mut rpc = new_rpc_client().await?;
+ let settings = rpc.get_settings(()).await?;
+ let multihop_is_enabled = settings
+ .into_inner()
+ .relay_settings
+ .unwrap()
+ .endpoint
+ .and_then(|endpoint| {
+ if let types::relay_settings::Endpoint::Normal(settings) = endpoint {
+ Some(settings.wireguard_constraints.unwrap().use_multihop)
+ } else {
+ None
+ }
+ })
+ .unwrap_or(false);
+ if multihop_is_enabled {
+ return Err(Error::CommandFailed(
+ "PQ PSK exchange does not work when multihop is enabled",
+ ));
+ }
+ rpc.set_quantum_resistant_tunnel(new_state).await?;
+ println!("Updated quantum resistant tunnel setting");
+ Ok(())
+ }
+
#[cfg(windows)]
async fn process_wireguard_use_wg_nt_get() -> Result<()> {
let tunnel_options = Self::get_tunnel_options().await?;
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index b75ad9121c..9b82470bab 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -220,6 +220,8 @@ pub enum DaemonCommand {
SetBridgeState(ResponseTx<(), settings::Error>, BridgeState),
/// Set if IPv6 should be enabled in the tunnel
SetEnableIpv6(ResponseTx<(), settings::Error>, bool),
+ /// Set whether to enable PQ PSK exchange in the tunnel
+ SetQuantumResistantTunnel(ResponseTx<(), settings::Error>, bool),
/// Set DNS options or servers to use
SetDnsOptions(ResponseTx<(), settings::Error>, DnsOptions),
/// Toggle macOS network check leak
@@ -979,6 +981,9 @@ where
}
SetBridgeState(tx, bridge_state) => self.on_set_bridge_state(tx, bridge_state).await,
SetEnableIpv6(tx, enable_ipv6) => self.on_set_enable_ipv6(tx, enable_ipv6).await,
+ SetQuantumResistantTunnel(tx, enable_pq) => {
+ self.on_set_quantum_resistant_tunnel(tx, enable_pq).await
+ }
SetDnsOptions(tx, dns_servers) => self.on_set_dns_options(tx, dns_servers).await,
SetWireguardMtu(tx, mtu) => self.on_set_wireguard_mtu(tx, mtu).await,
SetWireguardRotationInterval(tx, interval) => {
@@ -1954,6 +1959,36 @@ where
}
}
+ async fn on_set_quantum_resistant_tunnel(
+ &mut self,
+ tx: ResponseTx<(), settings::Error>,
+ use_pq_safe_psk: bool,
+ ) {
+ let save_result = self
+ .settings
+ .set_quantum_resistant_tunnel(use_pq_safe_psk)
+ .await;
+ match save_result {
+ Ok(settings_changed) => {
+ Self::oneshot_send(tx, Ok(()), "set_quantum_resistant_tunnel response");
+ if settings_changed {
+ self.parameters_generator
+ .set_tunnel_options(&self.settings.tunnel_options);
+ self.event_listener
+ .notify_settings(self.settings.to_settings());
+ if self.get_connected_tunnel_type() == Some(TunnelType::Wireguard) {
+ log::info!("Reconnecting because the PQ safety setting changed");
+ self.reconnect_tunnel();
+ }
+ }
+ }
+ Err(e) => {
+ log::error!("{}", e.display_chain_with_msg("Unable to save settings"));
+ Self::oneshot_send(tx, Err(e), "set_quantum_resistant_tunnel response");
+ }
+ }
+ }
+
async fn on_set_dns_options(
&mut self,
tx: ResponseTx<(), settings::Error>,
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index 2264159fc8..a7478eb048 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -373,6 +373,17 @@ impl ManagementService for ManagementServiceImpl {
.map_err(map_settings_error)
}
+ async fn set_quantum_resistant_tunnel(&self, request: Request<bool>) -> ServiceResult<()> {
+ let enable = request.into_inner();
+ log::debug!("set_quantum_resistant_tunnel({})", enable);
+ let (tx, rx) = oneshot::channel();
+ self.send_command_to_daemon(DaemonCommand::SetQuantumResistantTunnel(tx, enable))?;
+ self.wait_for_result(rx)
+ .await?
+ .map(Response::new)
+ .map_err(map_settings_error)
+ }
+
#[cfg(not(target_os = "android"))]
async fn set_dns_options(&self, request: Request<types::DnsOptions>) -> ServiceResult<()> {
let options = DnsOptions::try_from(request.into_inner()).map_err(map_protobuf_type_err)?;
diff --git a/mullvad-daemon/src/settings.rs b/mullvad-daemon/src/settings.rs
index 52800028cc..e69ca8316f 100644
--- a/mullvad-daemon/src/settings.rs
+++ b/mullvad-daemon/src/settings.rs
@@ -236,6 +236,22 @@ impl SettingsPersister {
self.update(should_save).await
}
+ pub async fn set_quantum_resistant_tunnel(
+ &mut self,
+ use_pq_safe_psk: bool,
+ ) -> Result<bool, Error> {
+ let should_save = Self::update_field(
+ &mut self
+ .settings
+ .tunnel_options
+ .wireguard
+ .options
+ .use_pq_safe_psk,
+ use_pq_safe_psk,
+ );
+ self.update(should_save).await
+ }
+
pub async fn set_dns_options(&mut self, options: DnsOptions) -> Result<bool, Error> {
let should_save =
Self::update_field(&mut self.settings.tunnel_options.dns_options, options);
diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto
index eb132b2a52..9d53ccf837 100644
--- a/mullvad-management-interface/proto/management_interface.proto
+++ b/mullvad-management-interface/proto/management_interface.proto
@@ -43,6 +43,7 @@ service ManagementService {
rpc SetOpenvpnMssfix(google.protobuf.UInt32Value) returns (google.protobuf.Empty) {}
rpc SetWireguardMtu(google.protobuf.UInt32Value) returns (google.protobuf.Empty) {}
rpc SetEnableIpv6(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
+ rpc SetQuantumResistantTunnel(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
rpc SetDnsOptions(DnsOptions) returns (google.protobuf.Empty) {}
// Account management