diff options
| author | Emīls <emils@mullvad.net> | 2024-12-20 09:37:35 +0100 |
|---|---|---|
| committer | Emīls <emils@mullvad.net> | 2024-12-27 13:34:52 +0100 |
| commit | 25381c8d8deadf27d741c232b6fb4d7d06fde40d (patch) | |
| tree | e7f5aafa72e2c1d29fb63375a47dae1dfa207a45 /ios | |
| parent | f9e09b7b22844de577dd3980d5aeaaf24a5ed657 (diff) | |
| download | mullvadvpn-25381c8d8deadf27d741c232b6fb4d7d06fde40d.tar.xz mullvadvpn-25381c8d8deadf27d741c232b6fb4d7d06fde40d.zip | |
Use DAITAv2 on iOS
Diffstat (limited to 'ios')
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() |
