Skip to content

Commit ee5c10b

Browse files
committed
Change key exchange to be asynchronous
1 parent f1df6d5 commit ee5c10b

File tree

7 files changed

+67
-41
lines changed

7 files changed

+67
-41
lines changed

ios/MullvadTypes/Promise.swift

+21-9
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,30 @@ public final class Promise<Success, Failure: Error> {
4848
}
4949
}
5050

51-
51+
// This object can be used like an async semaphore with exactly 1 writer. It
52+
// allows the waiter to wait to `receive()` from another operation
53+
// asynchronously. It is important not to forget to call `send`, otherwise this
54+
// operation will block indefinitely.
5255
public struct OneshotChannel {
53-
private let semaphore = DispatchSemaphore(value: 0)
54-
56+
private var continuation: AsyncStream<Void>.Continuation?
57+
private var stream: AsyncStream<Void>
58+
5559
public init() {
60+
var ownedContinuation: AsyncStream<Void>.Continuation?
61+
stream = AsyncStream { continuation in
62+
ownedContinuation = continuation
63+
}
64+
self.continuation = ownedContinuation
5665
}
57-
58-
public mutating func send() {
59-
semaphore.signal()
66+
67+
public func send() {
68+
continuation?.yield()
69+
continuation?.finish()
6070
}
61-
62-
public func receive() {
63-
semaphore.wait()
71+
72+
public func receive() async {
73+
for await _ in stream {
74+
return
75+
}
6476
}
6577
}

ios/MullvadTypes/Protocols/EphemeralPeerReceiver.swift

+12-4
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,21 @@ public class EphemeralPeerReceiver: EphemeralPeerReceiving, TunnelProvider {
3030
// MARK: - EphemeralPeerReceiving
3131

3232
public func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) {
33-
guard let receiver = tunnelProvider as? EphemeralPeerReceiving else { return }
34-
receiver.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
33+
let semaphore = DispatchSemaphore(value: 0)
34+
Task {
35+
await keyReceiver.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
36+
semaphore.signal()
37+
}
38+
semaphore.wait()
3539
}
3640

3741
public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) {
38-
guard let receiver = tunnelProvider as? EphemeralPeerReceiving else { return }
39-
receiver.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
42+
let semaphore = DispatchSemaphore(value: 0)
43+
Task {
44+
await keyReceiver.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
45+
semaphore.signal()
46+
}
47+
semaphore.wait()
4048
}
4149

4250
public func ephemeralPeerExchangeFailed() {

ios/MullvadTypes/Protocols/EphemeralPeerReceiving.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ public protocol EphemeralPeerReceiving {
1515
/// - Parameters:
1616
/// - key: The preshared key used by the Ephemeral Peer
1717
/// - ephemeralKey: The private key used by the Ephemeral Peer
18-
func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey)
18+
func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) async
1919

2020
/// Called when successfully requesting an ephemeral peer with Daita enabled, and Post Quantum PSK disabled
2121
/// - Parameter _:_ The private key used by the Ephemeral Peer
22-
func receiveEphemeralPeerPrivateKey(_: PrivateKey)
22+
func receiveEphemeralPeerPrivateKey(_: PrivateKey) async
2323

2424
/// Called when an ephemeral peer could not be successfully negotiated
2525
func ephemeralPeerExchangeFailed()

ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift

+13-7
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,11 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
111111
),
112112
onUpdateConfiguration: { [unowned self] configuration in
113113
let channel = OneshotChannel()
114-
actor.changeEphemeralPeerNegotiationState(configuration: configuration, reconfigurationSemaphore: channel)
115-
channel.receive()
114+
actor.changeEphemeralPeerNegotiationState(
115+
configuration: configuration,
116+
reconfigurationSemaphore: channel
117+
)
118+
await channel.receive()
116119
}, onFinish: { [unowned self] in
117120
actor.notifyEphemeralPeerNegotiated()
118121
}
@@ -313,7 +316,10 @@ extension PacketTunnelProvider {
313316
lastConnectionAttempt = connectionAttempt
314317

315318
case let .negotiatingEphemeralPeer(observedConnectionState, privateKey):
316-
ephemeralPeerExchangingPipeline.startNegotiation(observedConnectionState, privateKey: privateKey)
319+
await ephemeralPeerExchangingPipeline.startNegotiation(
320+
observedConnectionState,
321+
privateKey: privateKey
322+
)
317323
case .initial, .connected, .disconnecting, .disconnected, .error:
318324
break
319325
}
@@ -370,12 +376,12 @@ extension PacketTunnelProvider {
370376
}
371377

372378
extension PacketTunnelProvider: EphemeralPeerReceiving {
373-
func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) {
374-
ephemeralPeerExchangingPipeline.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
379+
func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) async {
380+
await ephemeralPeerExchangingPipeline.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
375381
}
376382

377-
public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) {
378-
ephemeralPeerExchangingPipeline.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
383+
public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) async {
384+
await ephemeralPeerExchangingPipeline.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
379385
}
380386

381387
func ephemeralPeerExchangeFailed() {

ios/PacketTunnel/PostQuantum/EphemeralPeerExchangingPipeline.swift

+8-8
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,22 @@ import WireGuardKitTypes
1313

1414
final public class EphemeralPeerExchangingPipeline {
1515
let keyExchanger: EphemeralPeerExchangeActorProtocol
16-
let onUpdateConfiguration: (EphemeralPeerNegotiationState) -> Void
16+
let onUpdateConfiguration: (EphemeralPeerNegotiationState) async -> Void
1717
let onFinish: () -> Void
1818

1919
private var ephemeralPeerExchanger: EphemeralPeerExchangingProtocol!
2020

2121
public init(
2222
_ keyExchanger: EphemeralPeerExchangeActorProtocol,
23-
onUpdateConfiguration: @escaping (EphemeralPeerNegotiationState) -> Void,
23+
onUpdateConfiguration: @escaping (EphemeralPeerNegotiationState) async -> Void,
2424
onFinish: @escaping () -> Void
2525
) {
2626
self.keyExchanger = keyExchanger
2727
self.onUpdateConfiguration = onUpdateConfiguration
2828
self.onFinish = onFinish
2929
}
3030

31-
public func startNegotiation(_ connectionState: ObservedConnectionState, privateKey: PrivateKey) {
31+
public func startNegotiation(_ connectionState: ObservedConnectionState, privateKey: PrivateKey) async {
3232
keyExchanger.reset()
3333
let entryPeer = connectionState.selectedRelays.entry
3434
let exitPeer = connectionState.selectedRelays.exit
@@ -56,14 +56,14 @@ final public class EphemeralPeerExchangingPipeline {
5656
onFinish: onFinish
5757
)
5858
}
59-
ephemeralPeerExchanger.start()
59+
await ephemeralPeerExchanger.start()
6060
}
6161

62-
public func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) {
63-
ephemeralPeerExchanger.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
62+
public func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) async {
63+
await ephemeralPeerExchanger.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
6464
}
6565

66-
public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) {
67-
ephemeralPeerExchanger.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
66+
public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) async {
67+
await ephemeralPeerExchanger.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
6868
}
6969
}

ios/PacketTunnel/PostQuantum/SingleHopEphemeralPeerExchanger.swift

+8-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
1818
let keyExchanger: EphemeralPeerExchangeActorProtocol
1919
let devicePrivateKey: PrivateKey
2020
let onFinish: () -> Void
21-
let onUpdateConfiguration: (EphemeralPeerNegotiationState) -> Void
21+
let onUpdateConfiguration: (EphemeralPeerNegotiationState) async -> Void
2222
let enablePostQuantum: Bool
2323
let enableDaita: Bool
2424

@@ -28,7 +28,7 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
2828
keyExchanger: EphemeralPeerExchangeActorProtocol,
2929
enablePostQuantum: Bool,
3030
enableDaita: Bool,
31-
onUpdateConfiguration: @escaping (EphemeralPeerNegotiationState) -> Void,
31+
onUpdateConfiguration: @escaping (EphemeralPeerNegotiationState) async -> Void,
3232
onFinish: @escaping () -> Void
3333
) {
3434
self.devicePrivateKey = devicePrivateKey
@@ -40,8 +40,8 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
4040
self.onFinish = onFinish
4141
}
4242

43-
func start() {
44-
onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
43+
func start() async {
44+
await onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
4545
relay: exit,
4646
configuration: EphemeralPeerConfiguration(
4747
privateKey: devicePrivateKey,
@@ -55,8 +55,8 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
5555
)
5656
}
5757

58-
public func receiveEphemeralPeerPrivateKey(_ ephemeralKey: PrivateKey) {
59-
onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
58+
public func receiveEphemeralPeerPrivateKey(_ ephemeralKey: PrivateKey) async {
59+
await onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
6060
relay: exit,
6161
configuration: EphemeralPeerConfiguration(
6262
privateKey: ephemeralKey,
@@ -73,8 +73,8 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
7373
func receivePostQuantumKey(
7474
_ preSharedKey: WireGuardKitTypes.PreSharedKey,
7575
ephemeralKey: WireGuardKitTypes.PrivateKey
76-
) {
77-
onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
76+
) async {
77+
await onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
7878
relay: exit,
7979
configuration: EphemeralPeerConfiguration(
8080
privateKey: ephemeralKey,

ios/PacketTunnelCore/Actor/Protocols/EphemeralPeerExchangingProtocol.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import WireGuardKitTypes
1010

1111
public protocol EphemeralPeerExchangingProtocol {
12-
func start()
13-
func receivePostQuantumKey(_ preSharedKey: PreSharedKey, ephemeralKey: PrivateKey)
14-
func receiveEphemeralPeerPrivateKey(_: PrivateKey)
12+
func start() async
13+
func receivePostQuantumKey(_ preSharedKey: PreSharedKey, ephemeralKey: PrivateKey) async
14+
func receiveEphemeralPeerPrivateKey(_: PrivateKey) async
1515
}

0 commit comments

Comments
 (0)