Skip to content

Commit

Permalink
Merge branch 'add-daita-v2-functionality-ios-971'
Browse files Browse the repository at this point in the history
  • Loading branch information
pinkisemils committed Dec 27, 2024
2 parents 740ae68 + 25381c8 commit de998f8
Show file tree
Hide file tree
Showing 26 changed files with 400 additions and 161 deletions.
5 changes: 5 additions & 0 deletions ios/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 23 additions & 4 deletions ios/MullvadRustRuntime/EphemeralPeerReceiver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
}
43 changes: 27 additions & 16 deletions ios/MullvadRustRuntime/include/mullvad_rust_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -112,29 +134,18 @@ 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,
const void *packet_tunnel,
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
Expand Down
31 changes: 31 additions & 0 deletions ios/MullvadTypes/Protocols/DaitaV2Parameters.swift
Original file line number Diff line number Diff line change
@@ -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
}
}
15 changes: 11 additions & 4 deletions ios/MullvadTypes/Protocols/EphemeralPeerReceiver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
9 changes: 6 additions & 3 deletions ios/MullvadTypes/Protocols/EphemeralPeerReceiving.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
16 changes: 10 additions & 6 deletions ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -739,18 +739,19 @@
A932D9F52B5EBB9D00999395 /* RESTTransportStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = A932D9F42B5EBB9D00999395 /* RESTTransportStub.swift */; };
A935594C2B4C2DA900D5D524 /* APIAvailabilityTestRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A935594B2B4C2DA900D5D524 /* APIAvailabilityTestRequest.swift */; };
A939661B2CAE6CE1008128CA /* MigrationManagerMultiProcessUpgradeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A939661A2CAE6CE1008128CA /* MigrationManagerMultiProcessUpgradeTests.swift */; };
A93969812CE606190032A7A0 /* Maybenot.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9840BB32C69F78A0030F05E /* Maybenot.swift */; };
A94D691A2ABAD66700413DD4 /* WireGuardKitTypes in Frameworks */ = {isa = PBXBuildFile; productRef = 58FE25E22AA72AE9003D1918 /* WireGuardKitTypes */; };
A94D691B2ABAD66700413DD4 /* WireGuardKitTypes in Frameworks */ = {isa = PBXBuildFile; productRef = 58FE25E72AA7399D003D1918 /* WireGuardKitTypes */; };
A95EEE362B722CD600A8A39B /* TunnelMonitorState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A95EEE352B722CD600A8A39B /* TunnelMonitorState.swift */; };
A95EEE382B722DFC00A8A39B /* PingStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = A95EEE372B722DFC00A8A39B /* PingStats.swift */; };
A970C89D2B29E38C000A7684 /* Socks5UsernamePasswordCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = A970C89C2B29E38C000A7684 /* Socks5UsernamePasswordCommand.swift */; };
A97275562CE36CAE00029F15 /* DaitaV2Parameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97275552CE36CAE00029F15 /* DaitaV2Parameters.swift */; };
A97D25AE2B0BB18100946B2D /* ProtocolObfuscator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97D25AD2B0BB18100946B2D /* ProtocolObfuscator.swift */; };
A97D25B02B0BB5C400946B2D /* ProtocolObfuscationStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97D25AF2B0BB5C400946B2D /* ProtocolObfuscationStub.swift */; };
A97D25B22B0CB02D00946B2D /* ProtocolObfuscatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97D25B12B0CB02D00946B2D /* ProtocolObfuscatorTests.swift */; };
A97D25B42B0CB59300946B2D /* TunnelObfuscationStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97D25B32B0CB59300946B2D /* TunnelObfuscationStub.swift */; };
A97D30172AE6B5E90045C0E4 /* StoredWgKeyData.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97D30162AE6B5E90045C0E4 /* StoredWgKeyData.swift */; };
A97FF5502A0D2FFC00900996 /* NSFileCoordinator+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97FF54F2A0D2FFC00900996 /* NSFileCoordinator+Extensions.swift */; };
A9840BB42C69F78A0030F05E /* Maybenot.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9840BB32C69F78A0030F05E /* Maybenot.swift */; };
A98502032B627B120061901E /* LocalNetworkProbe.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98502022B627B120061901E /* LocalNetworkProbe.swift */; };
A988A3E22AFE54AC0008D2C7 /* AccountExpiry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6F2FA62AFBB9AE006D0856 /* AccountExpiry.swift */; };
A988DF272ADE86ED00D807EF /* WireGuardObfuscationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = A988DF252ADE86ED00D807EF /* WireGuardObfuscationSettings.swift */; };
Expand Down Expand Up @@ -2120,6 +2121,7 @@
A95EEE352B722CD600A8A39B /* TunnelMonitorState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelMonitorState.swift; sourceTree = "<group>"; };
A95EEE372B722DFC00A8A39B /* PingStats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PingStats.swift; sourceTree = "<group>"; };
A970C89C2B29E38C000A7684 /* Socks5UsernamePasswordCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Socks5UsernamePasswordCommand.swift; sourceTree = "<group>"; };
A97275552CE36CAE00029F15 /* DaitaV2Parameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DaitaV2Parameters.swift; sourceTree = "<group>"; };
A97D25AD2B0BB18100946B2D /* ProtocolObfuscator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtocolObfuscator.swift; sourceTree = "<group>"; };
A97D25AF2B0BB5C400946B2D /* ProtocolObfuscationStub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtocolObfuscationStub.swift; sourceTree = "<group>"; };
A97D25B12B0CB02D00946B2D /* ProtocolObfuscatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtocolObfuscatorTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2714,6 +2716,7 @@
449EBA252B975B9700DFA4EB /* EphemeralPeerReceiving.swift */,
A90C48662C36BC2600DCB94C /* EphemeralPeerReceiver.swift */,
A90C48682C36BF3900DCB94C /* TunnelProvider.swift */,
A97275552CE36CAE00029F15 /* DaitaV2Parameters.swift */,
);
path = Protocols;
sourceTree = "<group>";
Expand Down Expand Up @@ -4721,7 +4724,6 @@
isa = PBXNativeTarget;
buildConfigurationList = 58C7A44B2A863F4A0060C66F /* Build configuration list for PBXNativeTarget "PacketTunnelCore" */;
buildPhases = (
A9840BB22C69F7290030F05E /* Import maybenot_machines */,
58C7A4312A863F440060C66F /* Headers */,
58C7A4322A863F440060C66F /* Sources */,
58C7A4332A863F440060C66F /* Frameworks */,
Expand Down Expand Up @@ -4973,6 +4975,7 @@
isa = PBXNativeTarget;
buildConfigurationList = A992DA252C24709F00DE7CE5 /* Build configuration list for PBXNativeTarget "MullvadRustRuntime" */;
buildPhases = (
A93969802CE603110032A7A0 /* Import maybenot_machines */,
A992DA2A2C2470B300DE7CE5 /* Build MullvadRustRuntime */,
A992DA182C24709F00DE7CE5 /* Headers */,
A992DA192C24709F00DE7CE5 /* Sources */,
Expand Down Expand Up @@ -5351,7 +5354,7 @@
shellPath = /bin/sh;
shellScript = "if [[ \"$(uname -m)\" == arm64 ]]; then\n export PATH=\"/opt/homebrew/bin:$PATH\"\nfi\n\nif which swiftlint > /dev/null; then\n swiftlint PacketTunnel/**/*.swift\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
A9840BB22C69F7290030F05E /* Import maybenot_machines */ = {
A93969802CE603110032A7A0 /* Import maybenot_machines */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
Expand All @@ -5367,7 +5370,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "MAYBENOT_MACHINES=`cat ${SRCROOT}/../dist-assets/maybenot_machines`\ncat > ${SRCROOT}/PacketTunnelCore/Daita/Maybenot.swift << EOF\n// swiftlint:disable line_length\n// This is an autogenerated file, do not edit\npublic struct Maybenot {\n public let machines=\"\"\"\n$MAYBENOT_MACHINES\n\"\"\"\n public let maximumEvents: UInt32 = 1000\n public let maximumActions: UInt32 = 1000\n}\n// swiftlint:enable line_length\nEOF\n";
shellScript = "MAYBENOT_MACHINES=`cat ${SRCROOT}/../dist-assets/maybenot_machines`\ncat > ${SRCROOT}/PacketTunnelCore/Daita/Maybenot.swift << EOF\n// swiftlint:disable line_length\n// This is an autogenerated file, do not edit\npublic struct Maybenot {\n public let machines=\"\"\"\n$MAYBENOT_MACHINES\n\"\"\"\n public let maximumEvents: UInt32 = 2048\n public let maximumActions: UInt32 = 1024\n public let maximumPadding: Double = 1.0\n public let maximumBlocking: Double = 1.0\n}\n// swiftlint:enable line_length\nEOF\n";
};
A992DA2A2C2470B300DE7CE5 /* Build MullvadRustRuntime */ = {
isa = PBXShellScriptBuildPhase;
Expand Down Expand Up @@ -5775,7 +5778,6 @@
583832272AC3193600EA2071 /* PacketTunnelActor+SleepCycle.swift in Sources */,
58FE25DC2AA72A8F003D1918 /* AnyTask.swift in Sources */,
F04AF92D2C466013004A8314 /* EphemeralPeerNegotiationState.swift in Sources */,
A9840BB42C69F78A0030F05E /* Maybenot.swift in Sources */,
58FE25D92AA72A8F003D1918 /* AutoCancellingTask.swift in Sources */,
58FE25E12AA72A9B003D1918 /* SettingsReaderProtocol.swift in Sources */,
58C7A4582A863FB90060C66F /* TunnelMonitorProtocol.swift in Sources */,
Expand Down Expand Up @@ -6313,6 +6315,7 @@
58D22412294C90210029F5F8 /* RelayConstraint.swift in Sources */,
7A7AD14F2BF21EF200B30B3C /* NameInputFormatter.swift in Sources */,
58D22413294C90210029F5F8 /* RelayConstraints.swift in Sources */,
A97275562CE36CAE00029F15 /* DaitaV2Parameters.swift in Sources */,
7AF9BE8C2A321D1F00DBFEDB /* RelayFilter.swift in Sources */,
58D22414294C90210029F5F8 /* RelayLocation.swift in Sources */,
581DA2732A1E227D0046ED47 /* RESTTypes.swift in Sources */,
Expand Down Expand Up @@ -6447,6 +6450,7 @@
A9D9A4BB2C36D397004088DD /* EphemeralPeerNegotiator.swift in Sources */,
A9D9A4B22C36D12D004088DD /* TunnelObfuscator.swift in Sources */,
A9173C322C36CCDD00F6A08C /* EphemeralPeerReceiver.swift in Sources */,
A93969812CE606190032A7A0 /* Maybenot.swift in Sources */,
F05919802C45515200C301F3 /* EphemeralPeerExchangeActor.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -9512,7 +9516,7 @@
repositoryURL = "https://github.com/mullvad/wireguard-apple.git";
requirement = {
kind = revision;
revision = 4499596651b4fe8a162e587c75a01615168f29a6;
revision = f6c6af02d3a9168589b8c109b4826b7f224fcf73;
};
};
/* End XCRemoteSwiftPackageReference section */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/mullvad/wireguard-apple.git",
"state" : {
"revision" : "4499596651b4fe8a162e587c75a01615168f29a6"
"revision" : "f6c6af02d3a9168589b8c109b4826b7f224fcf73"
}
}
],
Expand Down
Loading

0 comments on commit de998f8

Please sign in to comment.