summaryrefslogtreecommitdiffhomepage
path: root/ios
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2024-12-20 09:37:35 +0100
committerEmīls <emils@mullvad.net>2024-12-27 13:34:52 +0100
commit25381c8d8deadf27d741c232b6fb4d7d06fde40d (patch)
treee7f5aafa72e2c1d29fb63375a47dae1dfa207a45 /ios
parentf9e09b7b22844de577dd3980d5aeaaf24a5ed657 (diff)
downloadmullvadvpn-25381c8d8deadf27d741c232b6fb4d7d06fde40d.tar.xz
mullvadvpn-25381c8d8deadf27d741c232b6fb4d7d06fde40d.zip
Use DAITAv2 on iOS
Diffstat (limited to 'ios')
-rw-r--r--ios/CHANGELOG.md5
-rw-r--r--ios/MullvadRustRuntime/EphemeralPeerReceiver.swift27
-rw-r--r--ios/MullvadRustRuntime/include/mullvad_rust_runtime.h43
-rw-r--r--ios/MullvadTypes/Protocols/DaitaV2Parameters.swift31
-rw-r--r--ios/MullvadTypes/Protocols/EphemeralPeerReceiver.swift15
-rw-r--r--ios/MullvadTypes/Protocols/EphemeralPeerReceiving.swift9
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift22
-rw-r--r--ios/PacketTunnel/PostQuantum/EphemeralPeerExchangingPipeline.swift23
-rw-r--r--ios/PacketTunnel/PostQuantum/MultiHopEphemeralPeerExchanger.swift26
-rw-r--r--ios/PacketTunnel/PostQuantum/SingleHopEphemeralPeerExchanger.swift14
-rw-r--r--ios/PacketTunnelCore/Actor/EphemeralPeerNegotiationState.swift10
-rw-r--r--ios/PacketTunnelCore/Actor/PacketTunnelActor+PostQuantum.swift28
-rw-r--r--ios/PacketTunnelCore/Actor/PacketTunnelActor.swift13
-rw-r--r--ios/PacketTunnelCore/Actor/Protocols/EphemeralPeerExchangingProtocol.swift9
-rw-r--r--ios/PacketTunnelCore/Daita/Maybenot.swift6
-rw-r--r--ios/PacketTunnelCoreTests/EphemeralPeerExchangingPipelineTests.swift36
-rw-r--r--ios/PacketTunnelCoreTests/Mocks/EphemeralPeerExchangeActorStub.swift17
-rw-r--r--ios/PacketTunnelCoreTests/Mocks/KeyExchangingResultStub.swift19
-rw-r--r--ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift15
-rw-r--r--ios/PacketTunnelCoreTests/SingleHopEphemeralPeerExchangerTests.swift15
20 files changed, 283 insertions, 100 deletions
diff --git a/ios/CHANGELOG.md b/ios/CHANGELOG.md
index 80ffcf9643..e074727922 100644
--- a/ios/CHANGELOG.md
+++ b/ios/CHANGELOG.md
@@ -21,6 +21,11 @@ Line wrap the file at 100 chars. Th
* **Fixed**: for any bug fixes.
* **Security**: in case of vulnerabilities.
+## Unreleased
+### Added
+- Update to DAITA v2 - now machines are provided by relays dynamically instead
+ of using bundled ones.
+
## [2024.11 - 2024-12-12]
### Added
- Add WireGuard over Shadowsocks obfuscation. It can be enabled in "VPN settings". This will
diff --git a/ios/MullvadRustRuntime/EphemeralPeerReceiver.swift b/ios/MullvadRustRuntime/EphemeralPeerReceiver.swift
index 2b1b4adac5..6752ec3e51 100644
--- a/ios/MullvadRustRuntime/EphemeralPeerReceiver.swift
+++ b/ios/MullvadRustRuntime/EphemeralPeerReceiver.swift
@@ -24,11 +24,13 @@ import WireGuardKitTypes
/// - rawEphemeralPeerReceiver: A raw pointer to the running instance of `NEPacketTunnelProvider`
/// - rawPresharedKey: A raw pointer to the quantum-secure pre shared key
/// - rawEphemeralKey: A raw pointer to the ephemeral private key of the device
-@_cdecl("swift_ephemeral_peer_ready")
+/// - rawDaitaParameters: A raw pointer to negotiated DAITA parameters
+@_silgen_name("swift_ephemeral_peer_ready")
func receivePostQuantumKey(
rawEphemeralPeerReceiver: UnsafeMutableRawPointer?,
rawPresharedKey: UnsafeMutableRawPointer?,
- rawEphemeralKey: UnsafeMutableRawPointer?
+ rawEphemeralKey: UnsafeMutableRawPointer?,
+ rawDaitaParameters: UnsafePointer<DaitaV2Parameters>?
) {
guard let rawEphemeralPeerReceiver else { return }
let ephemeralPeerReceiver = Unmanaged<EphemeralPeerReceiver>.fromOpaque(rawEphemeralPeerReceiver)
@@ -41,12 +43,29 @@ func receivePostQuantumKey(
return
}
+ let maybeNot = Maybenot()
+ let daitaParameters: DaitaV2Parameters? = rawDaitaParameters?.withMemoryRebound(
+ to: DaitaParameters.self,
+ capacity: 1
+ ) { body in
+ let params = body.pointee
+ guard params.machines != nil else { return nil }
+ let machines = String(cString: params.machines)
+ return DaitaV2Parameters(
+ machines: machines,
+ maximumEvents: maybeNot.maximumEvents,
+ maximumActions: maybeNot.maximumActions,
+ maximumPadding: params.max_padding_frac,
+ maximumBlocking: params.max_blocking_frac
+ )
+ }
+
// If there is a pre-shared key, an ephemeral peer was negotiated with Post Quantum options
// Otherwise, a Daita enabled ephemeral peer was requested
if let rawPresharedKey, let key = PreSharedKey(rawValue: Data(bytes: rawPresharedKey, count: 32)) {
- ephemeralPeerReceiver.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
+ ephemeralPeerReceiver.receivePostQuantumKey(key, ephemeralKey: ephemeralKey, daitaParameters: daitaParameters)
} else {
- ephemeralPeerReceiver.receiveEphemeralPeerPrivateKey(ephemeralKey)
+ ephemeralPeerReceiver.receiveEphemeralPeerPrivateKey(ephemeralKey, daitaParameters: daitaParameters)
}
return
}
diff --git a/ios/MullvadRustRuntime/include/mullvad_rust_runtime.h b/ios/MullvadRustRuntime/include/mullvad_rust_runtime.h
index 93c04587f1..b10f4f81f2 100644
--- a/ios/MullvadRustRuntime/include/mullvad_rust_runtime.h
+++ b/ios/MullvadRustRuntime/include/mullvad_rust_runtime.h
@@ -27,6 +27,12 @@ typedef struct ProxyHandle {
uint16_t port;
} ProxyHandle;
+typedef struct DaitaParameters {
+ uint8_t *machines;
+ double max_padding_frac;
+ double max_blocking_frac;
+} DaitaParameters;
+
typedef struct WgTcpConnectionFunctions {
int32_t (*open_fn)(int32_t tunnelHandle, const char *address, uint64_t timeout);
int32_t (*close_fn)(int32_t tunnelHandle, int32_t socketHandle);
@@ -89,6 +95,22 @@ int32_t encrypted_dns_proxy_start(struct EncryptedDnsProxyState *encrypted_dns_p
int32_t encrypted_dns_proxy_stop(struct ProxyHandle *proxy_config);
/**
+ * To be called when ephemeral peer exchange has finished. All parameters except
+ * `raw_packet_tunnel` are optional.
+ *
+ * # Safety:
+ * If the key exchange failed, all pointers except `raw_packet_tunnel` must be null. If the
+ * key exchange was successful, `raw_ephemeral_private_key` must be a valid pointer to 32
+ * bytes for the lifetime of this call. If PQ was enabled, `raw_preshared_key` must be a valid
+ * pointer to 32 bytes for the lifetime of this call. If DAITA was requested, the
+ * `daita_prameters` must point to a valid instance of `DaitaParameters`.
+ */
+extern void swift_ephemeral_peer_ready(const void *raw_packet_tunnel,
+ const uint8_t *raw_preshared_key,
+ const uint8_t *raw_ephemeral_private_key,
+ const struct DaitaParameters *daita_parameters);
+
+/**
* Called by the Swift side to signal that the ephemeral peer exchange should be cancelled.
* After this call, the cancel token is no longer valid.
*
@@ -112,11 +134,11 @@ void drop_ephemeral_peer_exchange_token(struct ExchangeCancelToken *sender);
* Entry point for requesting ephemeral peers on iOS.
* The TCP connection must be created to go through the tunnel.
* # Safety
- * `public_key` and `ephemeral_key` must be valid respective `PublicKey` and `PrivateKey` types.
- * They will not be valid after this function is called, and thus must be copied here.
- * `packet_tunnel` must be valid pointers to a packet tunnel, the packet tunnel pointer must
- * outlive the ephemeral peer exchange. `cancel_token` should be owned by the caller of this
- * function.
+ * `public_key` and `ephemeral_key` must be valid respective `PublicKey` and `PrivateKey` types,
+ * specifically, they must be valid pointers to 32 bytes. They will not be valid after this
+ * function is called, and thus must be copied here. `packet_tunnel` must be valid pointers to a
+ * packet tunnel, the packet tunnel pointer must outlive the ephemeral peer exchange.
+ * `cancel_token` should be owned by the caller of this function.
*/
struct ExchangeCancelToken *request_ephemeral_peer(const uint8_t *public_key,
const uint8_t *ephemeral_key,
@@ -125,17 +147,6 @@ struct ExchangeCancelToken *request_ephemeral_peer(const uint8_t *public_key,
struct EphemeralPeerParameters peer_parameters);
/**
- * Called when the preshared post quantum key is ready,
- * or when a Daita peer has been successfully requested.
- * `raw_preshared_key` will be NULL if:
- * - The post quantum key negotiation failed
- * - A Daita peer has been requested without enabling post quantum keys.
- */
-extern void swift_ephemeral_peer_ready(const void *raw_packet_tunnel,
- const uint8_t *raw_preshared_key,
- const uint8_t *raw_ephemeral_private_key);
-
-/**
* # Safety
* `addr`, `password`, `cipher` must be valid for the lifetime of this function call and they must
* be backed by the amount of bytes as stored in the respective `*_len` parameters.
diff --git a/ios/MullvadTypes/Protocols/DaitaV2Parameters.swift b/ios/MullvadTypes/Protocols/DaitaV2Parameters.swift
new file mode 100644
index 0000000000..53ab61ada4
--- /dev/null
+++ b/ios/MullvadTypes/Protocols/DaitaV2Parameters.swift
@@ -0,0 +1,31 @@
+//
+// DaitaV2Parameters.swift
+// MullvadTypes
+//
+// Created by Marco Nikic on 2024-11-12.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+
+public struct DaitaV2Parameters: Equatable {
+ public let machines: String
+ public let maximumEvents: UInt32
+ public let maximumActions: UInt32
+ public let maximumPadding: Double
+ public let maximumBlocking: Double
+
+ public init(
+ machines: String,
+ maximumEvents: UInt32,
+ maximumActions: UInt32,
+ maximumPadding: Double,
+ maximumBlocking: Double
+ ) {
+ self.machines = machines
+ self.maximumEvents = maximumEvents
+ self.maximumActions = maximumActions
+ self.maximumPadding = maximumPadding
+ self.maximumBlocking = maximumBlocking
+ }
+}
diff --git a/ios/MullvadTypes/Protocols/EphemeralPeerReceiver.swift b/ios/MullvadTypes/Protocols/EphemeralPeerReceiver.swift
index 7f45669468..91519c746c 100644
--- a/ios/MullvadTypes/Protocols/EphemeralPeerReceiver.swift
+++ b/ios/MullvadTypes/Protocols/EphemeralPeerReceiver.swift
@@ -29,19 +29,26 @@ public class EphemeralPeerReceiver: EphemeralPeerReceiving, TunnelProvider {
// MARK: - EphemeralPeerReceiving
- public func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) {
+ public func receivePostQuantumKey(
+ _ key: PreSharedKey,
+ ephemeralKey: PrivateKey,
+ daitaParameters: DaitaV2Parameters?
+ ) {
let semaphore = DispatchSemaphore(value: 0)
Task {
- await keyReceiver.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
+ await keyReceiver.receivePostQuantumKey(key, ephemeralKey: ephemeralKey, daitaParameters: daitaParameters)
semaphore.signal()
}
semaphore.wait()
}
- public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) {
+ public func receiveEphemeralPeerPrivateKey(
+ _ ephemeralPeerPrivateKey: PrivateKey,
+ daitaParameters: DaitaV2Parameters?
+ ) {
let semaphore = DispatchSemaphore(value: 0)
Task {
- await keyReceiver.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
+ await keyReceiver.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey, daitaParameters: daitaParameters)
semaphore.signal()
}
semaphore.wait()
diff --git a/ios/MullvadTypes/Protocols/EphemeralPeerReceiving.swift b/ios/MullvadTypes/Protocols/EphemeralPeerReceiving.swift
index cc1c8f0f8a..d799dd646c 100644
--- a/ios/MullvadTypes/Protocols/EphemeralPeerReceiving.swift
+++ b/ios/MullvadTypes/Protocols/EphemeralPeerReceiving.swift
@@ -15,11 +15,14 @@ public protocol EphemeralPeerReceiving {
/// - Parameters:
/// - key: The preshared key used by the Ephemeral Peer
/// - ephemeralKey: The private key used by the Ephemeral Peer
- func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) async
+ /// - daitaParameters: DAITA parameters
+ func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey, daitaParameters: DaitaV2Parameters?) async
/// Called when successfully requesting an ephemeral peer with Daita enabled, and Post Quantum PSK disabled
- /// - Parameter _:_ The private key used by the Ephemeral Peer
- func receiveEphemeralPeerPrivateKey(_: PrivateKey) async
+ /// - Parameters:
+ /// - _: The private key used by the Ephemeral Peer
+ /// - daitaParameters: DAITA parameters
+ func receiveEphemeralPeerPrivateKey(_: PrivateKey, daitaParameters: DaitaV2Parameters?) async
/// Called when an ephemeral peer could not be successfully negotiated
func ephemeralPeerExchangeFailed()
diff --git a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift
index 75678417ef..133ba93b8a 100644
--- a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift
@@ -376,12 +376,26 @@ extension PacketTunnelProvider {
}
extension PacketTunnelProvider: EphemeralPeerReceiving {
- func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) async {
- await ephemeralPeerExchangingPipeline.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
+ func receivePostQuantumKey(
+ _ key: PreSharedKey,
+ ephemeralKey: PrivateKey,
+ daitaParameters: MullvadTypes.DaitaV2Parameters?
+ ) async {
+ await ephemeralPeerExchangingPipeline.receivePostQuantumKey(
+ key,
+ ephemeralKey: ephemeralKey,
+ daitaParameters: daitaParameters
+ )
}
- public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) async {
- await ephemeralPeerExchangingPipeline.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
+ public func receiveEphemeralPeerPrivateKey(
+ _ ephemeralPeerPrivateKey: PrivateKey,
+ daitaParameters: MullvadTypes.DaitaV2Parameters?
+ ) async {
+ await ephemeralPeerExchangingPipeline.receiveEphemeralPeerPrivateKey(
+ ephemeralPeerPrivateKey,
+ daitaParameters: daitaParameters
+ )
}
func ephemeralPeerExchangeFailed() {
diff --git a/ios/PacketTunnel/PostQuantum/EphemeralPeerExchangingPipeline.swift b/ios/PacketTunnel/PostQuantum/EphemeralPeerExchangingPipeline.swift
index 1619889003..387c41213a 100644
--- a/ios/PacketTunnel/PostQuantum/EphemeralPeerExchangingPipeline.swift
+++ b/ios/PacketTunnel/PostQuantum/EphemeralPeerExchangingPipeline.swift
@@ -8,6 +8,7 @@
import MullvadRustRuntime
import MullvadSettings
+import MullvadTypes
import PacketTunnelCore
import WireGuardKitTypes
@@ -59,11 +60,25 @@ final public class EphemeralPeerExchangingPipeline {
await ephemeralPeerExchanger.start()
}
- public func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) async {
- await ephemeralPeerExchanger.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
+ public func receivePostQuantumKey(
+ _ key: PreSharedKey,
+ ephemeralKey: PrivateKey,
+ daitaParameters: DaitaV2Parameters?
+ ) async {
+ await ephemeralPeerExchanger.receivePostQuantumKey(
+ key,
+ ephemeralKey: ephemeralKey,
+ daitaParameters: daitaParameters
+ )
}
- public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) async {
- await ephemeralPeerExchanger.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
+ public func receiveEphemeralPeerPrivateKey(
+ _ ephemeralPeerPrivateKey: PrivateKey,
+ daitaParameters: DaitaV2Parameters?
+ ) async {
+ await ephemeralPeerExchanger.receiveEphemeralPeerPrivateKey(
+ ephemeralPeerPrivateKey,
+ daitaParameters: daitaParameters
+ )
}
}
diff --git a/ios/PacketTunnel/PostQuantum/MultiHopEphemeralPeerExchanger.swift b/ios/PacketTunnel/PostQuantum/MultiHopEphemeralPeerExchanger.swift
index 0e2bc97778..91e3db3bda 100644
--- a/ios/PacketTunnel/PostQuantum/MultiHopEphemeralPeerExchanger.swift
+++ b/ios/PacketTunnel/PostQuantum/MultiHopEphemeralPeerExchanger.swift
@@ -25,6 +25,7 @@ final class MultiHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
private var entryPeerKey: EphemeralPeerKey!
private var exitPeerKey: EphemeralPeerKey!
+ private var daitaParameters: DaitaV2Parameters?
private let defaultGatewayAddressRange = [IPAddressRange(from: "\(LocalNetworkIPs.gatewayAddress.rawValue)/32")!]
private let allTrafficRange = [
@@ -66,7 +67,11 @@ final class MultiHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
await negotiateWithEntry()
}
- public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) async {
+ public func receiveEphemeralPeerPrivateKey(
+ _ ephemeralPeerPrivateKey: PrivateKey,
+ daitaParameters: DaitaV2Parameters?
+ ) async {
+ self.daitaParameters = daitaParameters
if state == .negotiatingWithEntry {
entryPeerKey = EphemeralPeerKey(ephemeralKey: ephemeralPeerPrivateKey)
await negotiateBetweenEntryAndExit()
@@ -78,8 +83,10 @@ final class MultiHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
func receivePostQuantumKey(
_ preSharedKey: PreSharedKey,
- ephemeralKey: PrivateKey
+ ephemeralKey: PrivateKey,
+ daitaParameters: DaitaV2Parameters?
) async {
+ self.daitaParameters = daitaParameters
if state == .negotiatingWithEntry {
entryPeerKey = EphemeralPeerKey(preSharedKey: preSharedKey, ephemeralKey: ephemeralKey)
await negotiateBetweenEntryAndExit()
@@ -95,7 +102,8 @@ final class MultiHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
relay: entry,
configuration: EphemeralPeerConfiguration(
privateKey: devicePrivateKey,
- allowedIPs: defaultGatewayAddressRange
+ allowedIPs: defaultGatewayAddressRange,
+ daitaParameters: daitaParameters
)
)))
keyExchanger.startNegotiation(
@@ -113,14 +121,16 @@ final class MultiHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
configuration: EphemeralPeerConfiguration(
privateKey: entryPeerKey.ephemeralKey,
preSharedKey: entryPeerKey.preSharedKey,
- allowedIPs: [IPAddressRange(from: "\(exit.endpoint.ipv4Relay.ip)/32")!]
+ allowedIPs: [IPAddressRange(from: "\(exit.endpoint.ipv4Relay.ip)/32")!],
+ daitaParameters: self.daitaParameters
)
),
exit: EphemeralPeerRelayConfiguration(
relay: exit,
configuration: EphemeralPeerConfiguration(
privateKey: devicePrivateKey,
- allowedIPs: defaultGatewayAddressRange
+ allowedIPs: defaultGatewayAddressRange,
+ daitaParameters: self.daitaParameters
)
)
))
@@ -140,7 +150,8 @@ final class MultiHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
configuration: EphemeralPeerConfiguration(
privateKey: entryPeerKey.ephemeralKey,
preSharedKey: entryPeerKey.preSharedKey,
- allowedIPs: [IPAddressRange(from: "\(exit.endpoint.ipv4Relay.ip)/32")!]
+ allowedIPs: [IPAddressRange(from: "\(exit.endpoint.ipv4Relay.ip)/32")!],
+ daitaParameters: self.daitaParameters
)
),
exit: EphemeralPeerRelayConfiguration(
@@ -148,7 +159,8 @@ final class MultiHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
configuration: EphemeralPeerConfiguration(
privateKey: exitPeerKey.ephemeralKey,
preSharedKey: exitPeerKey.preSharedKey,
- allowedIPs: allTrafficRange
+ allowedIPs: allTrafficRange,
+ daitaParameters: self.daitaParameters
)
)
))
diff --git a/ios/PacketTunnel/PostQuantum/SingleHopEphemeralPeerExchanger.swift b/ios/PacketTunnel/PostQuantum/SingleHopEphemeralPeerExchanger.swift
index 3c6ab5631a..fc9a08f989 100644
--- a/ios/PacketTunnel/PostQuantum/SingleHopEphemeralPeerExchanger.swift
+++ b/ios/PacketTunnel/PostQuantum/SingleHopEphemeralPeerExchanger.swift
@@ -45,7 +45,8 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
relay: exit,
configuration: EphemeralPeerConfiguration(
privateKey: devicePrivateKey,
- allowedIPs: [IPAddressRange(from: "\(LocalNetworkIPs.gatewayAddress.rawValue)/32")!]
+ allowedIPs: [IPAddressRange(from: "\(LocalNetworkIPs.gatewayAddress.rawValue)/32")!],
+ daitaParameters: nil
)
)))
keyExchanger.startNegotiation(
@@ -55,7 +56,7 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
)
}
- public func receiveEphemeralPeerPrivateKey(_ ephemeralKey: PrivateKey) async {
+ public func receiveEphemeralPeerPrivateKey(_ ephemeralKey: PrivateKey, daitaParameters: DaitaV2Parameters?) async {
await onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
relay: exit,
configuration: EphemeralPeerConfiguration(
@@ -64,7 +65,8 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
allowedIPs: [
IPAddressRange(from: "\(LocalNetworkIPs.defaultRouteIpV4.rawValue)/0")!,
IPAddressRange(from: "\(LocalNetworkIPs.defaultRouteIpV6.rawValue)/0")!,
- ]
+ ],
+ daitaParameters: daitaParameters
)
)))
self.onFinish()
@@ -72,7 +74,8 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
func receivePostQuantumKey(
_ preSharedKey: WireGuardKitTypes.PreSharedKey,
- ephemeralKey: WireGuardKitTypes.PrivateKey
+ ephemeralKey: WireGuardKitTypes.PrivateKey,
+ daitaParameters: DaitaV2Parameters?
) async {
await onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
relay: exit,
@@ -82,7 +85,8 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
allowedIPs: [
IPAddressRange(from: "\(LocalNetworkIPs.defaultRouteIpV4.rawValue)/0")!,
IPAddressRange(from: "\(LocalNetworkIPs.defaultRouteIpV6.rawValue)/0")!,
- ]
+ ],
+ daitaParameters: daitaParameters
)
)))
self.onFinish()
diff --git a/ios/PacketTunnelCore/Actor/EphemeralPeerNegotiationState.swift b/ios/PacketTunnelCore/Actor/EphemeralPeerNegotiationState.swift
index 339e458ce2..18eee61f3b 100644
--- a/ios/PacketTunnelCore/Actor/EphemeralPeerNegotiationState.swift
+++ b/ios/PacketTunnelCore/Actor/EphemeralPeerNegotiationState.swift
@@ -7,6 +7,7 @@
//
import MullvadREST
+import MullvadTypes
import WireGuardKitTypes
public enum EphemeralPeerNegotiationState: Equatable {
@@ -43,11 +44,18 @@ public struct EphemeralPeerConfiguration: Equatable, CustomDebugStringConvertibl
public let privateKey: PrivateKey
public let preSharedKey: PreSharedKey?
public let allowedIPs: [IPAddressRange]
+ public let daitaParameters: DaitaV2Parameters?
- public init(privateKey: PrivateKey, preSharedKey: PreSharedKey? = nil, allowedIPs: [IPAddressRange]) {
+ public init(
+ privateKey: PrivateKey,
+ preSharedKey: PreSharedKey? = nil,
+ allowedIPs: [IPAddressRange],
+ daitaParameters: DaitaV2Parameters?
+ ) {
self.privateKey = privateKey
self.preSharedKey = preSharedKey
self.allowedIPs = allowedIPs
+ self.daitaParameters = daitaParameters
}
public var debugDescription: String {
diff --git a/ios/PacketTunnelCore/Actor/PacketTunnelActor+PostQuantum.swift b/ios/PacketTunnelCore/Actor/PacketTunnelActor+PostQuantum.swift
index f35677c846..ced44e3a3d 100644
--- a/ios/PacketTunnelCore/Actor/PacketTunnelActor+PostQuantum.swift
+++ b/ios/PacketTunnelCore/Actor/PacketTunnelActor+PostQuantum.swift
@@ -7,6 +7,7 @@
//
import Foundation
+import MullvadTypes
import WireGuardKitTypes
extension PacketTunnelActor {
@@ -65,14 +66,6 @@ extension PacketTunnelActor {
}
var daitaConfiguration: DaitaConfiguration?
- if settings.daita.daitaState.isEnabled {
- let maybeNot = Maybenot()
- daitaConfiguration = DaitaConfiguration(
- machines: maybeNot.machines,
- maxEvents: maybeNot.maximumEvents,
- maxActions: maybeNot.maximumActions
- )
- }
switch configuration {
case let .single(hop):
@@ -81,6 +74,9 @@ extension PacketTunnelActor {
settings: settings,
connectionData: connectionData
).make().exitConfiguration
+ if settings.daita.daitaState.isEnabled, let daitaSettings = hop.configuration.daitaParameters {
+ daitaConfiguration = DaitaConfiguration(daita: daitaSettings)
+ }
try await tunnelAdapter.start(configuration: exitConfiguration, daita: daitaConfiguration)
case let .multi(firstHop, secondHop):
@@ -90,6 +86,10 @@ extension PacketTunnelActor {
connectionData: connectionData
).make()
+ if settings.daita.daitaState.isEnabled, let daitaSettings = firstHop.configuration.daitaParameters {
+ daitaConfiguration = DaitaConfiguration(daita: daitaSettings)
+ }
+
try await tunnelAdapter.startMultihop(
entryConfiguration: connectionConfiguration.entryConfiguration,
exitConfiguration: connectionConfiguration.exitConfiguration, daita: daitaConfiguration
@@ -97,3 +97,15 @@ extension PacketTunnelActor {
}
}
}
+
+extension DaitaConfiguration {
+ init(daita: DaitaV2Parameters) {
+ self = DaitaConfiguration(
+ machines: daita.machines,
+ maxEvents: daita.maximumEvents,
+ maxActions: daita.maximumActions,
+ maxPadding: daita.maximumPadding,
+ maxBlocking: daita.maximumBlocking
+ )
+ }
+}
diff --git a/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift b/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift
index d9cce79f57..469bf0fa20 100644
--- a/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift
+++ b/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift
@@ -307,20 +307,11 @@ extension PacketTunnelActor {
startDefaultPathObserver(notifyObserverWithCurrentPath: true)
}
- var daitaConfiguration: DaitaConfiguration?
- if settings.daita.daitaState.isEnabled {
- let maybeNot = Maybenot()
- daitaConfiguration = DaitaConfiguration(
- machines: maybeNot.machines,
- maxEvents: maybeNot.maximumEvents,
- maxActions: maybeNot.maximumActions
- )
- }
-
+ // Daita parameters are gotten from an ephemeral peer
try await tunnelAdapter.startMultihop(
entryConfiguration: configuration.entryConfiguration,
exitConfiguration: configuration.exitConfiguration,
- daita: daitaConfiguration
+ daita: nil
)
// Resume tunnel monitoring and use IPv4 gateway as a probe address.
diff --git a/ios/PacketTunnelCore/Actor/Protocols/EphemeralPeerExchangingProtocol.swift b/ios/PacketTunnelCore/Actor/Protocols/EphemeralPeerExchangingProtocol.swift
index a0d596fd9e..1155f516e2 100644
--- a/ios/PacketTunnelCore/Actor/Protocols/EphemeralPeerExchangingProtocol.swift
+++ b/ios/PacketTunnelCore/Actor/Protocols/EphemeralPeerExchangingProtocol.swift
@@ -6,10 +6,15 @@
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
//
+import MullvadTypes
import WireGuardKitTypes
public protocol EphemeralPeerExchangingProtocol {
func start() async
- func receivePostQuantumKey(_ preSharedKey: PreSharedKey, ephemeralKey: PrivateKey) async
- func receiveEphemeralPeerPrivateKey(_: PrivateKey) async
+ func receivePostQuantumKey(
+ _ preSharedKey: PreSharedKey,
+ ephemeralKey: PrivateKey,
+ daitaParameters: DaitaV2Parameters?
+ ) async
+ func receiveEphemeralPeerPrivateKey(_: PrivateKey, daitaParameters: DaitaV2Parameters?) async
}
diff --git a/ios/PacketTunnelCore/Daita/Maybenot.swift b/ios/PacketTunnelCore/Daita/Maybenot.swift
index fc5b0bd75c..0bc682af75 100644
--- a/ios/PacketTunnelCore/Daita/Maybenot.swift
+++ b/ios/PacketTunnelCore/Daita/Maybenot.swift
@@ -7,7 +7,9 @@ public struct Maybenot {
02eNqFjDkOgDAMBL056PkEJTVdvsY/+URKmojDmwiBUDyStbJ35DLuy5anWRrlqLTDcA0AkTXVkDt01ZAHwLFwludZeMsLLILlRRax4+lKcnrnl/8HJzqIIG0=
02eNpdjr0LQVEYxt9zGES5o4myKVksFM45lEHKx0LJYDAZ5C+QRTHIaGETViYDKYPp3ijFYLj3KkmGK2WwuVwiv3rrrafnA1Jm16ijKBQ+6NRDGPJ2E0Xe6YnAD0hFD9nm/ObIHumlv4imZ3Mm8DwvtaxB0Jy1IUex0pYIIB30lhuCYkYvwW6nQFSV41R1L8vkmwlgEOONVvEaYt1SwLhdhxn8gdBgEfXU7RFmzeR9YtPPxrbqOVkLsd29XJhIJfbqRomGheLcYUWeFgxQodrq9wcP1E88/w==
"""
- public let maximumEvents: UInt32 = 1000
- public let maximumActions: UInt32 = 1000
+ public let maximumEvents: UInt32 = 2048
+ public let maximumActions: UInt32 = 1024
+ public let maximumPadding: Double = 1.0
+ public let maximumBlocking: Double = 1.0
}
// swiftlint:enable line_length
diff --git a/ios/PacketTunnelCoreTests/EphemeralPeerExchangingPipelineTests.swift b/ios/PacketTunnelCoreTests/EphemeralPeerExchangingPipelineTests.swift
index bbce8c8b44..e0ce35f2bf 100644
--- a/ios/PacketTunnelCoreTests/EphemeralPeerExchangingPipelineTests.swift
+++ b/ios/PacketTunnelCoreTests/EphemeralPeerExchangingPipelineTests.swift
@@ -77,9 +77,14 @@ final class EphemeralPeerExchangingPipelineTests: XCTestCase {
negotiationSuccessful.fulfill()
}
- keyExchangeActor.delegate = KeyExchangingResultStub(onReceivePostQuantumKey: { preSharedKey, privateKey in
- await postQuantumKeyExchangingPipeline.receivePostQuantumKey(preSharedKey, ephemeralKey: privateKey)
- })
+ keyExchangeActor
+ .delegate = KeyExchangingResultStub(onReceivePostQuantumKey: { preSharedKey, privateKey, daita in
+ await postQuantumKeyExchangingPipeline.receivePostQuantumKey(
+ preSharedKey,
+ ephemeralKey: privateKey,
+ daitaParameters: daita
+ )
+ })
let connectionState = stubConnectionState(enableMultiHop: false, enablePostQuantum: true, enableDaita: false)
await postQuantumKeyExchangingPipeline.startNegotiation(connectionState, privateKey: PrivateKey())
@@ -107,9 +112,13 @@ final class EphemeralPeerExchangingPipelineTests: XCTestCase {
negotiationSuccessful.fulfill()
}
- keyExchangeActor.delegate = KeyExchangingResultStub(onReceiveEphemeralPeerPrivateKey: { privateKey in
- await postQuantumKeyExchangingPipeline.receiveEphemeralPeerPrivateKey(privateKey)
- })
+ keyExchangeActor
+ .delegate = KeyExchangingResultStub(onReceiveEphemeralPeerPrivateKey: { privateKey, daitaParameters in
+ await postQuantumKeyExchangingPipeline.receiveEphemeralPeerPrivateKey(
+ privateKey,
+ daitaParameters: daitaParameters
+ )
+ })
let connectionState = stubConnectionState(enableMultiHop: false, enablePostQuantum: false, enableDaita: true)
await postQuantumKeyExchangingPipeline.startNegotiation(connectionState, privateKey: PrivateKey())
@@ -137,9 +146,14 @@ final class EphemeralPeerExchangingPipelineTests: XCTestCase {
negotiationSuccessful.fulfill()
}
- keyExchangeActor.delegate = KeyExchangingResultStub(onReceivePostQuantumKey: { preSharedKey, privateKey in
- await postQuantumKeyExchangingPipeline.receivePostQuantumKey(preSharedKey, ephemeralKey: privateKey)
- })
+ keyExchangeActor
+ .delegate = KeyExchangingResultStub(onReceivePostQuantumKey: { preSharedKey, privateKey, daita in
+ await postQuantumKeyExchangingPipeline.receivePostQuantumKey(
+ preSharedKey,
+ ephemeralKey: privateKey,
+ daitaParameters: daita
+ )
+ })
let connectionState = stubConnectionState(enableMultiHop: true, enablePostQuantum: true, enableDaita: false)
await postQuantumKeyExchangingPipeline.startNegotiation(connectionState, privateKey: PrivateKey())
@@ -167,8 +181,8 @@ final class EphemeralPeerExchangingPipelineTests: XCTestCase {
negotiationSuccessful.fulfill()
}
- keyExchangeActor.delegate = KeyExchangingResultStub(onReceiveEphemeralPeerPrivateKey: { privateKey in
- await postQuantumKeyExchangingPipeline.receiveEphemeralPeerPrivateKey(privateKey)
+ keyExchangeActor.delegate = KeyExchangingResultStub(onReceiveEphemeralPeerPrivateKey: { privateKey, daita in
+ await postQuantumKeyExchangingPipeline.receiveEphemeralPeerPrivateKey(privateKey, daitaParameters: daita)
})
let connectionState = stubConnectionState(enableMultiHop: true, enablePostQuantum: false, enableDaita: true)
diff --git a/ios/PacketTunnelCoreTests/Mocks/EphemeralPeerExchangeActorStub.swift b/ios/PacketTunnelCoreTests/Mocks/EphemeralPeerExchangeActorStub.swift
index 2f21748820..f3e00135e8 100644
--- a/ios/PacketTunnelCoreTests/Mocks/EphemeralPeerExchangeActorStub.swift
+++ b/ios/PacketTunnelCoreTests/Mocks/EphemeralPeerExchangeActorStub.swift
@@ -19,12 +19,25 @@ final class EphemeralPeerExchangeActorStub: EphemeralPeerExchangeActorProtocol {
var delegate: EphemeralPeerReceiving?
func startNegotiation(with privateKey: PrivateKey, enablePostQuantum: Bool, enableDaita: Bool) {
+ let daita = enableDaita
+ ? DaitaV2Parameters(
+ machines: "test",
+ maximumEvents: 1,
+ maximumActions: 1,
+ maximumPadding: 1.0,
+ maximumBlocking: 1.0
+ )
+ : nil
switch result {
case let .success((preSharedKey, ephemeralKey)):
if enablePostQuantum {
- Task { await delegate?.receivePostQuantumKey(preSharedKey, ephemeralKey: ephemeralKey) }
+ Task { await delegate?.receivePostQuantumKey(
+ preSharedKey,
+ ephemeralKey: ephemeralKey,
+ daitaParameters: daita
+ ) }
} else {
- Task { await delegate?.receiveEphemeralPeerPrivateKey(ephemeralKey) }
+ Task { await delegate?.receiveEphemeralPeerPrivateKey(ephemeralKey, daitaParameters: daita) }
}
case .failure:
delegate?.ephemeralPeerExchangeFailed()
diff --git a/ios/PacketTunnelCoreTests/Mocks/KeyExchangingResultStub.swift b/ios/PacketTunnelCoreTests/Mocks/KeyExchangingResultStub.swift
index 250524ec06..197ef54d3a 100644
--- a/ios/PacketTunnelCoreTests/Mocks/KeyExchangingResultStub.swift
+++ b/ios/PacketTunnelCoreTests/Mocks/KeyExchangingResultStub.swift
@@ -12,15 +12,22 @@
struct KeyExchangingResultStub: EphemeralPeerReceiving {
var onFailure: (() -> Void)?
- var onReceivePostQuantumKey: ((PreSharedKey, PrivateKey) async -> Void)?
- var onReceiveEphemeralPeerPrivateKey: ((PrivateKey) async -> Void)?
+ var onReceivePostQuantumKey: ((PreSharedKey, PrivateKey, DaitaV2Parameters?) async -> Void)?
+ var onReceiveEphemeralPeerPrivateKey: ((PrivateKey, DaitaV2Parameters?) async -> Void)?
- func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) async {
- await onReceivePostQuantumKey?(key, ephemeralKey)
+ func receivePostQuantumKey(
+ _ key: PreSharedKey,
+ ephemeralKey: PrivateKey,
+ daitaParameters: DaitaV2Parameters?
+ ) async {
+ await onReceivePostQuantumKey?(key, ephemeralKey, daitaParameters)
}
- public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) async {
- await onReceiveEphemeralPeerPrivateKey?(ephemeralPeerPrivateKey)
+ public func receiveEphemeralPeerPrivateKey(
+ _ ephemeralPeerPrivateKey: PrivateKey,
+ daitaParameters daitaParamters: MullvadTypes.DaitaV2Parameters?
+ ) async {
+ await onReceiveEphemeralPeerPrivateKey?(ephemeralPeerPrivateKey, daitaParamters)
}
func ephemeralPeerExchangeFailed() {
diff --git a/ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift b/ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift
index c55f5b4d65..245d2d71b7 100644
--- a/ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift
+++ b/ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift
@@ -123,9 +123,14 @@ final class MultiHopEphemeralPeerExchangerTests: XCTestCase {
negotiationSuccessful.fulfill()
}
- peerExchangeActor.delegate = KeyExchangingResultStub(onReceivePostQuantumKey: { preSharedKey, ephemeralKey in
- await multiHopPeerExchanger.receivePostQuantumKey(preSharedKey, ephemeralKey: ephemeralKey)
- })
+ peerExchangeActor
+ .delegate = KeyExchangingResultStub(onReceivePostQuantumKey: { preSharedKey, ephemeralKey, daita in
+ await multiHopPeerExchanger.receivePostQuantumKey(
+ preSharedKey,
+ ephemeralKey: ephemeralKey,
+ daitaParameters: daita
+ )
+ })
await multiHopPeerExchanger.start()
wait(
@@ -161,8 +166,8 @@ final class MultiHopEphemeralPeerExchangerTests: XCTestCase {
negotiationSuccessful.fulfill()
}
- peerExchangeActor.delegate = KeyExchangingResultStub(onReceiveEphemeralPeerPrivateKey: { ephemeralKey in
- await multiHopPeerExchanger.receiveEphemeralPeerPrivateKey(ephemeralKey)
+ peerExchangeActor.delegate = KeyExchangingResultStub(onReceiveEphemeralPeerPrivateKey: { ephemeralKey, daita in
+ await multiHopPeerExchanger.receiveEphemeralPeerPrivateKey(ephemeralKey, daitaParameters: daita)
})
await multiHopPeerExchanger.start()
diff --git a/ios/PacketTunnelCoreTests/SingleHopEphemeralPeerExchangerTests.swift b/ios/PacketTunnelCoreTests/SingleHopEphemeralPeerExchangerTests.swift
index deb402abeb..6b7b8da2bb 100644
--- a/ios/PacketTunnelCoreTests/SingleHopEphemeralPeerExchangerTests.swift
+++ b/ios/PacketTunnelCoreTests/SingleHopEphemeralPeerExchangerTests.swift
@@ -100,9 +100,14 @@ final class SingleHopEphemeralPeerExchangerTests: XCTestCase {
negotiationSuccessful.fulfill()
}
- keyExchangeActor.delegate = KeyExchangingResultStub(onReceivePostQuantumKey: { preSharedKey, ephemeralKey in
- await singleHopPostQuantumKeyExchanging.receivePostQuantumKey(preSharedKey, ephemeralKey: ephemeralKey)
- })
+ keyExchangeActor
+ .delegate = KeyExchangingResultStub(onReceivePostQuantumKey: { preSharedKey, ephemeralKey, daita in
+ await singleHopPostQuantumKeyExchanging.receivePostQuantumKey(
+ preSharedKey,
+ ephemeralKey: ephemeralKey,
+ daitaParameters: daita
+ )
+ })
await singleHopPostQuantumKeyExchanging.start()
wait(
@@ -137,8 +142,8 @@ final class SingleHopEphemeralPeerExchangerTests: XCTestCase {
negotiationSuccessful.fulfill()
}
- peerExchangeActor.delegate = KeyExchangingResultStub(onReceiveEphemeralPeerPrivateKey: { ephemeralKey in
- await multiHopPeerExchanger.receiveEphemeralPeerPrivateKey(ephemeralKey)
+ peerExchangeActor.delegate = KeyExchangingResultStub(onReceiveEphemeralPeerPrivateKey: { ephemeralKey, daita in
+ await multiHopPeerExchanger.receiveEphemeralPeerPrivateKey(ephemeralKey, daitaParameters: daita)
})
await multiHopPeerExchanger.start()