Skip to content

Commit

Permalink
Change key exchange to be asynchronous
Browse files Browse the repository at this point in the history
  • Loading branch information
pinkisemils committed Dec 17, 2024
1 parent e3acff5 commit 4761d26
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 41 deletions.
26 changes: 17 additions & 9 deletions ios/MullvadTypes/Promise.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,26 @@ public final class Promise<Success, Failure: Error> {
}
}


public struct OneshotChannel {
private let semaphore = DispatchSemaphore(value: 0)

private var continuation: AsyncStream<Void>.Continuation?
private var stream: AsyncStream<Void>

public init() {
var ownedContinuation: AsyncStream<Void>.Continuation?
stream = AsyncStream { continuation in
ownedContinuation = continuation
}
self.continuation = ownedContinuation
}

public mutating func send() {
semaphore.signal()

public func send() {
continuation?.yield()
continuation?.finish()
}

public func receive() {
semaphore.wait()

public func receive() async {
for await _ in stream {
return
}
}
}
16 changes: 12 additions & 4 deletions ios/MullvadTypes/Protocols/EphemeralPeerReceiver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,21 @@ public class EphemeralPeerReceiver: EphemeralPeerReceiving, TunnelProvider {
// MARK: - EphemeralPeerReceiving

public func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) {
guard let receiver = tunnelProvider as? EphemeralPeerReceiving else { return }
receiver.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
let semaphore = DispatchSemaphore(value: 0)
Task {
await keyReceiver.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
semaphore.signal()
}
semaphore.wait()
}

public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) {
guard let receiver = tunnelProvider as? EphemeralPeerReceiving else { return }
receiver.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
let semaphore = DispatchSemaphore(value: 0)
Task {
await keyReceiver.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
semaphore.signal()
}
semaphore.wait()
}

public func ephemeralPeerExchangeFailed() {
Expand Down
4 changes: 2 additions & 2 deletions ios/MullvadTypes/Protocols/EphemeralPeerReceiving.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ 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)
func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) 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)
func receiveEphemeralPeerPrivateKey(_: PrivateKey) async

/// Called when an ephemeral peer could not be successfully negotiated
func ephemeralPeerExchangeFailed()
Expand Down
20 changes: 13 additions & 7 deletions ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,11 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
),
onUpdateConfiguration: { [unowned self] configuration in
let channel = OneshotChannel()
actor.changeEphemeralPeerNegotiationState(configuration: configuration, reconfigurationSemaphore: channel)
channel.receive()
actor.changeEphemeralPeerNegotiationState(
configuration: configuration,
reconfigurationSemaphore: channel
)
await channel.receive()
}, onFinish: { [unowned self] in
actor.notifyEphemeralPeerNegotiated()
}
Expand Down Expand Up @@ -313,7 +316,10 @@ extension PacketTunnelProvider {
lastConnectionAttempt = connectionAttempt

case let .negotiatingEphemeralPeer(observedConnectionState, privateKey):
ephemeralPeerExchangingPipeline.startNegotiation(observedConnectionState, privateKey: privateKey)
await ephemeralPeerExchangingPipeline.startNegotiation(
observedConnectionState,
privateKey: privateKey
)
case .initial, .connected, .disconnecting, .disconnected, .error:
break
}
Expand Down Expand Up @@ -370,12 +376,12 @@ extension PacketTunnelProvider {
}

extension PacketTunnelProvider: EphemeralPeerReceiving {
func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) {
ephemeralPeerExchangingPipeline.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) async {
await ephemeralPeerExchangingPipeline.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
}

public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) {
ephemeralPeerExchangingPipeline.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) async {
await ephemeralPeerExchangingPipeline.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
}

func ephemeralPeerExchangeFailed() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@ import WireGuardKitTypes

final public class EphemeralPeerExchangingPipeline {
let keyExchanger: EphemeralPeerExchangeActorProtocol
let onUpdateConfiguration: (EphemeralPeerNegotiationState) -> Void
let onUpdateConfiguration: (EphemeralPeerNegotiationState) async -> Void
let onFinish: () -> Void

private var ephemeralPeerExchanger: EphemeralPeerExchangingProtocol!

public init(
_ keyExchanger: EphemeralPeerExchangeActorProtocol,
onUpdateConfiguration: @escaping (EphemeralPeerNegotiationState) -> Void,
onUpdateConfiguration: @escaping (EphemeralPeerNegotiationState) async -> Void,
onFinish: @escaping () -> Void
) {
self.keyExchanger = keyExchanger
self.onUpdateConfiguration = onUpdateConfiguration
self.onFinish = onFinish
}

public func startNegotiation(_ connectionState: ObservedConnectionState, privateKey: PrivateKey) {
public func startNegotiation(_ connectionState: ObservedConnectionState, privateKey: PrivateKey) async {
keyExchanger.reset()
let entryPeer = connectionState.selectedRelays.entry
let exitPeer = connectionState.selectedRelays.exit
Expand Down Expand Up @@ -56,14 +56,14 @@ final public class EphemeralPeerExchangingPipeline {
onFinish: onFinish
)
}
ephemeralPeerExchanger.start()
await ephemeralPeerExchanger.start()
}

public func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) {
ephemeralPeerExchanger.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
public func receivePostQuantumKey(_ key: PreSharedKey, ephemeralKey: PrivateKey) async {
await ephemeralPeerExchanger.receivePostQuantumKey(key, ephemeralKey: ephemeralKey)
}

public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) {
ephemeralPeerExchanger.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
public func receiveEphemeralPeerPrivateKey(_ ephemeralPeerPrivateKey: PrivateKey) async {
await ephemeralPeerExchanger.receiveEphemeralPeerPrivateKey(ephemeralPeerPrivateKey)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
let keyExchanger: EphemeralPeerExchangeActorProtocol
let devicePrivateKey: PrivateKey
let onFinish: () -> Void
let onUpdateConfiguration: (EphemeralPeerNegotiationState) -> Void
let onUpdateConfiguration: (EphemeralPeerNegotiationState) async -> Void
let enablePostQuantum: Bool
let enableDaita: Bool

Expand All @@ -28,7 +28,7 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
keyExchanger: EphemeralPeerExchangeActorProtocol,
enablePostQuantum: Bool,
enableDaita: Bool,
onUpdateConfiguration: @escaping (EphemeralPeerNegotiationState) -> Void,
onUpdateConfiguration: @escaping (EphemeralPeerNegotiationState) async -> Void,
onFinish: @escaping () -> Void
) {
self.devicePrivateKey = devicePrivateKey
Expand All @@ -40,8 +40,8 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
self.onFinish = onFinish
}

func start() {
onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
func start() async {
await onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
relay: exit,
configuration: EphemeralPeerConfiguration(
privateKey: devicePrivateKey,
Expand All @@ -55,8 +55,8 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
)
}

public func receiveEphemeralPeerPrivateKey(_ ephemeralKey: PrivateKey) {
onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
public func receiveEphemeralPeerPrivateKey(_ ephemeralKey: PrivateKey) async {
await onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
relay: exit,
configuration: EphemeralPeerConfiguration(
privateKey: ephemeralKey,
Expand All @@ -73,8 +73,8 @@ struct SingleHopEphemeralPeerExchanger: EphemeralPeerExchangingProtocol {
func receivePostQuantumKey(
_ preSharedKey: WireGuardKitTypes.PreSharedKey,
ephemeralKey: WireGuardKitTypes.PrivateKey
) {
onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
) async {
await onUpdateConfiguration(.single(EphemeralPeerRelayConfiguration(
relay: exit,
configuration: EphemeralPeerConfiguration(
privateKey: ephemeralKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import WireGuardKitTypes

public protocol EphemeralPeerExchangingProtocol {
func start()
func receivePostQuantumKey(_ preSharedKey: PreSharedKey, ephemeralKey: PrivateKey)
func receiveEphemeralPeerPrivateKey(_: PrivateKey)
func start() async
func receivePostQuantumKey(_ preSharedKey: PreSharedKey, ephemeralKey: PrivateKey) async
func receiveEphemeralPeerPrivateKey(_: PrivateKey) async
}

0 comments on commit 4761d26

Please sign in to comment.