diff --git a/ios/CHANGELOG.md b/ios/CHANGELOG.md index 80ffcf9643fe..e07472792269 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 2b1b4adac53b..6752ec3e51fc 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? ) { guard let rawEphemeralPeerReceiver else { return } let ephemeralPeerReceiver = Unmanaged.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 93c04587f16a..b10f4f81f25a 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); @@ -88,6 +94,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, @@ -124,17 +146,6 @@ struct ExchangeCancelToken *request_ephemeral_peer(const uint8_t *public_key, int32_t tunnel_handle, 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 diff --git a/ios/MullvadTypes/Protocols/DaitaV2Parameters.swift b/ios/MullvadTypes/Protocols/DaitaV2Parameters.swift new file mode 100644 index 000000000000..53ab61ada42f --- /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 7f4566946802..91519c746cdc 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 cc1c8f0f8aae..d799dd646c35 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/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 4efca4ee9de9..1e8521cd2a6c 100644 --- a/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,4 @@ { - "originHash" : "c15149b2d59d9e9c72375f65339c04f41a19943e1117e682df27fc9f943fdc56", "pins" : [ { "identity" : "swift-log", @@ -19,5 +18,5 @@ } } ], - "version" : 3 + "version" : 2 } diff --git a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift index 75678417ef51..133ba93b8aca 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 1619889003ab..387c41213a4c 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 0e2bc97778a1..91e3db3bda0b 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 3c6ab5631ac4..fc9a08f98978 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 339e458ce266..18eee61f3b0a 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 f35677c84622..3b549b08d0d4 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,13 @@ extension PacketTunnelActor { } } } + +extension DaitaConfiguration { + init(daita: DaitaV2Parameters) { + self = DaitaConfiguration( + machines: daita.machines, + maxEvents: daita.maximumEvents, + maxActions: daita.maximumActions + ) + } +} diff --git a/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift b/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift index d9cce79f576d..469bf0fa20d9 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 a0d596fd9e18..1155f516e25d 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 fc5b0bd75cda..0bc682af753f 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 bbce8c8b44f7..e0ce35f2bfe7 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 2f217488200e..f3e00135e887 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 250524ec0677..197ef54d3a9f 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 c55f5b4d6566..245d2d71b7e7 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 deb402abeb4a..6b7b8da2bb19 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() diff --git a/mullvad-ios/src/ephemeral_peer_proxy/ios_tcp_connection.rs b/mullvad-ios/src/ephemeral_peer_proxy/ios_tcp_connection.rs index 3244e5f2d95c..1be9a18bf339 100644 --- a/mullvad-ios/src/ephemeral_peer_proxy/ios_tcp_connection.rs +++ b/mullvad-ios/src/ephemeral_peer_proxy/ios_tcp_connection.rs @@ -1,4 +1,3 @@ -use libc::c_void; use std::{ ffi::CStr, future::Future, @@ -71,20 +70,6 @@ impl WgTcpConnectionFunctions { } } -extern "C" { - /// 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. - pub fn swift_ephemeral_peer_ready( - raw_packet_tunnel: *const c_void, - raw_preshared_key: *const u8, - raw_ephemeral_private_key: *const u8, - ); - -} - #[derive(Clone)] pub struct IosTcpProvider { tunnel_handle: i32, diff --git a/mullvad-ios/src/ephemeral_peer_proxy/mod.rs b/mullvad-ios/src/ephemeral_peer_proxy/mod.rs index 70d9347ad7a1..6d598c5e4048 100644 --- a/mullvad-ios/src/ephemeral_peer_proxy/mod.rs +++ b/mullvad-ios/src/ephemeral_peer_proxy/mod.rs @@ -2,11 +2,11 @@ pub mod ios_tcp_connection; pub mod peer_exchange; -use ios_tcp_connection::swift_ephemeral_peer_ready; use libc::c_void; use peer_exchange::EphemeralPeerExchange; -use std::{ptr, sync::Once}; +use std::{ffi::CString, ptr, sync::Once}; +use talpid_tunnel_config_client::DaitaSettings; static INIT_LOGGING: Once = Once::new(); #[derive(Clone)] @@ -17,17 +17,39 @@ pub struct PacketTunnelBridge { impl PacketTunnelBridge { fn fail_exchange(self) { - unsafe { swift_ephemeral_peer_ready(self.packet_tunnel, ptr::null(), ptr::null()) }; + // # Safety + // Call is safe as long as the `packet_tunnel` pointer is valid. Since a valid instance of + // `PacketTunnelBridge` requires the packet tunnel pointer to be valid, it is assumed this + // call is safe. + unsafe { + swift_ephemeral_peer_ready(self.packet_tunnel, ptr::null(), ptr::null(), ptr::null()) + }; } - fn succeed_exchange(self, ephemeral_key: [u8; 32], preshared_key: Option<[u8; 32]>) { + fn succeed_exchange( + self, + ephemeral_key: [u8; 32], + preshared_key: Option<[u8; 32]>, + daita: Option, + ) { let ephemeral_ptr = ephemeral_key.as_ptr(); let preshared_ptr = preshared_key .as_ref() .map(|key| key.as_ptr()) .unwrap_or(ptr::null()); - unsafe { swift_ephemeral_peer_ready(self.packet_tunnel, preshared_ptr, ephemeral_ptr) }; + let daita_ptr = daita + .as_ref() + .map(|params| params as *const _) + .unwrap_or(ptr::null()); + // # Safety + // The `packet_tunnel` pointer must be valid, much like the call in `fail_exchange`, but + // since the other arguments here are non-null, these pointers (`preshared_ptr`, + // `ephmerela_ptr` and `daita_ptr`) have to be valid too. Since they point to local + // variables or are null, the pointer values will be valid for the lifetime of the call. + unsafe { + swift_ephemeral_peer_ready(self.packet_tunnel, preshared_ptr, ephemeral_ptr, daita_ptr) + }; } } @@ -42,6 +64,54 @@ pub struct EphemeralPeerParameters { pub funcs: ios_tcp_connection::WgTcpConnectionFunctions, } +#[repr(C)] +pub struct DaitaParameters { + pub machines: *mut u8, + pub max_padding_frac: f64, + pub max_blocking_frac: f64, +} + +impl DaitaParameters { + fn new(settings: DaitaSettings) -> Option { + let machines_string = settings.client_machines.join("\n"); + let machines = CString::new(machines_string).ok()?.into_raw().cast(); + Some(Self { + machines, + max_padding_frac: settings.max_padding_frac, + max_blocking_frac: settings.max_blocking_frac, + }) + } +} + +impl Drop for DaitaParameters { + fn drop(&mut self) { + // # Safety + // `machines` pointer must be a valid pointer to a CString. This can be achieved by + // ensuring that `DaitaParameters` are constructed via `DaitaParameters::new` and the + // `machines` pointer is never written to. + let _ = unsafe { CString::from_raw(self.machines.cast()) }; + } +} + +extern "C" { + /// 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`. + pub fn swift_ephemeral_peer_ready( + raw_packet_tunnel: *const c_void, + raw_preshared_key: *const u8, + raw_ephemeral_private_key: *const u8, + daita_parameters: *const DaitaParameters, + ); + +} + /// 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. /// @@ -73,11 +143,11 @@ pub unsafe extern "C" fn drop_ephemeral_peer_exchange_token( /// 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. #[no_mangle] pub unsafe extern "C" fn request_ephemeral_peer( public_key: *const u8, @@ -92,7 +162,11 @@ pub unsafe extern "C" fn request_ephemeral_peer( .init(); }); + // # Safety + // `public_key` pointer must be a valid pointer to 32 unsigned bytes. let pub_key: [u8; 32] = unsafe { ptr::read(public_key as *const [u8; 32]) }; + // # Safety + // `ephemeral_key` pointer must be a valid pointer to 32 unsigned bytes. let eph_key: [u8; 32] = unsafe { ptr::read(ephemeral_key as *const [u8; 32]) }; let handle = match crate::mullvad_ios_runtime() { diff --git a/mullvad-ios/src/ephemeral_peer_proxy/peer_exchange.rs b/mullvad-ios/src/ephemeral_peer_proxy/peer_exchange.rs index ee9a512777e8..f65ccd016610 100644 --- a/mullvad-ios/src/ephemeral_peer_proxy/peer_exchange.rs +++ b/mullvad-ios/src/ephemeral_peer_proxy/peer_exchange.rs @@ -1,6 +1,8 @@ -use super::{ios_tcp_connection::*, EphemeralPeerParameters, PacketTunnelBridge}; +use super::{ios_tcp_connection::*, DaitaParameters, EphemeralPeerParameters, PacketTunnelBridge}; use std::{ffi::CStr, sync::Mutex, thread}; -use talpid_tunnel_config_client::{request_ephemeral_peer_with, Error, RelayConfigService}; +use talpid_tunnel_config_client::{ + request_ephemeral_peer_with, EphemeralPeer, Error, RelayConfigService, +}; use talpid_types::net::wireguard::{PrivateKey, PublicKey}; use tokio::{runtime::Handle as TokioHandle, task::JoinHandle}; use tonic::transport::channel::Endpoint; @@ -139,24 +141,15 @@ impl EphemeralPeerExchange { self.peer_parameters.enable_daita, ) => { match ephemeral_peer { - Ok(peer) => { - match peer.psk { - Some(preshared_key) => { - let preshared_key_bytes = *preshared_key.as_bytes(); - thread::spawn(move || { - let Self{ ephemeral_key, packet_tunnel, .. } = self; - packet_tunnel.succeed_exchange(ephemeral_key, Some(preshared_key_bytes)); - }); - - }, - None => { - // Daita peer was requested, but without enabling post quantum keys - thread::spawn(move || { - let Self{ ephemeral_key, packet_tunnel, .. } = self; - packet_tunnel.succeed_exchange(ephemeral_key, None); - }); - } - } + Ok(EphemeralPeer { psk, daita }) => { + thread::spawn(move || { + let Self{ ephemeral_key, packet_tunnel, .. } = self; + packet_tunnel.succeed_exchange( + ephemeral_key, + psk.map(|psk| *psk.as_bytes()), + daita.and_then(DaitaParameters::new) + ); + }); }, Err(error) => { log::error!("Key exchange failed {}", error); diff --git a/talpid-tunnel-config-client/src/lib.rs b/talpid-tunnel-config-client/src/lib.rs index f13832fa609b..bfa3deb29277 100644 --- a/talpid-tunnel-config-client/src/lib.rs +++ b/talpid-tunnel-config-client/src/lib.rs @@ -22,7 +22,7 @@ mod proto { tonic::include_proto!("ephemeralpeer"); } -#[cfg(all(unix, not(target_os = "ios")))] +#[cfg(unix)] const DAITA_VERSION: u32 = 2; #[derive(Debug)] @@ -88,7 +88,7 @@ pub const CONFIG_SERVICE_PORT: u16 = 1337; pub struct EphemeralPeer { pub psk: Option, - #[cfg(all(unix, not(target_os = "ios")))] + #[cfg(unix)] pub daita: Option, } @@ -141,15 +141,15 @@ pub async fn request_ephemeral_peer_with( wg_parent_pubkey: parent_pubkey.as_bytes().to_vec(), wg_ephemeral_peer_pubkey: ephemeral_pubkey.as_bytes().to_vec(), post_quantum: pq_request, - #[cfg(any(windows, target_os = "ios"))] + #[cfg(windows)] daita: Some(proto::DaitaRequestV1 { activate_daita: enable_daita, }), - #[cfg(any(windows, target_os = "ios"))] + #[cfg(windows)] daita_v2: None, - #[cfg(all(unix, not(target_os = "ios")))] + #[cfg(unix)] daita: None, - #[cfg(all(unix, not(target_os = "ios")))] + #[cfg(unix)] daita_v2: enable_daita.then(|| proto::DaitaRequestV2 { level: i32::from(proto::DaitaLevel::LevelDefault), platform: i32::from(get_platform()), @@ -204,7 +204,7 @@ pub async fn request_ephemeral_peer_with( None }; - #[cfg(all(unix, not(target_os = "ios")))] + #[cfg(unix)] { let daita = response.daita.map(|daita| DaitaSettings { client_machines: daita.client_machines, @@ -217,13 +217,13 @@ pub async fn request_ephemeral_peer_with( Ok(EphemeralPeer { psk, daita }) } - #[cfg(any(windows, target_os = "ios"))] + #[cfg(windows)] { Ok(EphemeralPeer { psk }) } } -#[cfg(all(unix, not(target_os = "ios")))] +#[cfg(unix)] const fn get_platform() -> proto::DaitaPlatform { use proto::DaitaPlatform; const PLATFORM: DaitaPlatform = if cfg!(target_os = "windows") {