summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBug Magnet <marco.nikic@mullvad.net>2024-02-13 11:34:01 +0100
committerBug Magnet <marco.nikic@mullvad.net>2024-02-13 11:34:01 +0100
commit3a7fdd497202182f28c7eba45fbb9c563f444f6c (patch)
treeef88e4b7d969ff941c1c9d92b88e4f6f2823aebe
parente79f77ad30c938cda9862762a6ad3ad91115415c (diff)
parent0014c3cfcd6108d35909a48148674c789a185ad3 (diff)
downloadmullvadvpn-3a7fdd497202182f28c7eba45fbb9c563f444f6c.tar.xz
mullvadvpn-3a7fdd497202182f28c7eba45fbb9c563f444f6c.zip
Merge branch 'add-quantum-resistant-option-to-settings-ios-459'
-rw-r--r--ios/MullvadVPN/Classes/AccessbilityIdentifier.swift5
-rw-r--r--ios/MullvadVPN/TunnelManager/TunnelManager.swift10
-rw-r--r--ios/MullvadVPN/View controllers/Preferences/PreferencesCellFactory.swift37
-rw-r--r--ios/MullvadVPN/View controllers/Preferences/PreferencesDataSource.swift105
-rw-r--r--ios/MullvadVPN/View controllers/Preferences/PreferencesInfoButtonItem.swift1
-rw-r--r--ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift4
-rw-r--r--ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift13
-rw-r--r--ios/MullvadVPN/View controllers/Preferences/PreferencesViewModel.swift8
8 files changed, 179 insertions, 4 deletions
diff --git a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
index 4f31461e5e..24a87ed14f 100644
--- a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
+++ b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
@@ -84,6 +84,11 @@ public enum AccessibilityIdentifier: String {
case dnsServer
case dnsServerInfo
+ // Quantum resistance
+ case quantumResistanceAutomatic
+ case quantumResistanceOff
+ case quantumResistanceOn
+
// Error
case unknown
}
diff --git a/ios/MullvadVPN/TunnelManager/TunnelManager.swift b/ios/MullvadVPN/TunnelManager/TunnelManager.swift
index 225c25d422..0d9b1e80c2 100644
--- a/ios/MullvadVPN/TunnelManager/TunnelManager.swift
+++ b/ios/MullvadVPN/TunnelManager/TunnelManager.swift
@@ -536,6 +536,16 @@ final class TunnelManager: StorePaymentObserver {
)
}
+ func setQuantumResistance(_ newSetting: TunnelQuantumResistance) {
+ scheduleSettingsUpdate(
+ taskName: "Set quantum resistance",
+ modificationBlock: { settings in
+ settings.tunnelQuantumResistance = newSetting
+ },
+ completionHandler: nil
+ )
+ }
+
func refreshRelayCacheTracker() throws {
try relayCacheTracker.refreshCachedRelays()
}
diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesCellFactory.swift b/ios/MullvadVPN/View controllers/Preferences/PreferencesCellFactory.swift
index bf734b5f83..8e739c33fd 100644
--- a/ios/MullvadVPN/View controllers/Preferences/PreferencesCellFactory.swift
+++ b/ios/MullvadVPN/View controllers/Preferences/PreferencesCellFactory.swift
@@ -155,6 +155,43 @@ final class PreferencesCellFactory: CellFactoryProtocol {
)
cell.accessibilityIdentifier = "\(item.accessibilityIdentifier.rawValue) (\(portString))"
cell.applySubCellStyling()
+
+ #if DEBUG
+ case .quantumResistanceAutomatic:
+ guard let cell = cell as? SelectableSettingsCell else { return }
+
+ cell.titleLabel.text = NSLocalizedString(
+ "QUANTUM_RESISTANCE_AUTOMATIC_LABEL",
+ tableName: "Preferences",
+ value: "Automatic",
+ comment: ""
+ )
+ cell.accessibilityIdentifier = item.accessibilityIdentifier
+ cell.applySubCellStyling()
+
+ case .quantumResistanceOn:
+ guard let cell = cell as? SelectableSettingsCell else { return }
+
+ cell.titleLabel.text = NSLocalizedString(
+ "QUANTUM_RESISTANCE_ON_LABEL",
+ tableName: "Preferences",
+ value: "On",
+ comment: ""
+ )
+ cell.accessibilityIdentifier = item.accessibilityIdentifier
+ cell.applySubCellStyling()
+ case .quantumResistanceOff:
+ guard let cell = cell as? SelectableSettingsCell else { return }
+
+ cell.titleLabel.text = NSLocalizedString(
+ "QUANTUM_RESISTANCE_OFF_LABEL",
+ tableName: "Preferences",
+ value: "Off",
+ comment: ""
+ )
+ cell.accessibilityIdentifier = item.accessibilityIdentifier
+ cell.applySubCellStyling()
+ #endif
}
}
}
diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSource.swift b/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSource.swift
index b726bded69..b984bc1f71 100644
--- a/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSource.swift
+++ b/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSource.swift
@@ -21,6 +21,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
case wireGuardCustomPort
case wireGuardObfuscation
case wireGuardObfuscationPort
+ case quantumResistance
var reusableViewClass: AnyClass {
switch self {
case .dnsSettings:
@@ -33,6 +34,8 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
return SelectableSettingsCell.self
case .wireGuardObfuscationPort:
return SelectableSettingsCell.self
+ case .quantumResistance:
+ return SelectableSettingsCell.self
}
}
}
@@ -50,6 +53,9 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
case wireGuardPorts
case wireGuardObfuscation
case wireGuardObfuscationPort
+ #if DEBUG
+ case quantumResistance
+ #endif
}
enum Item: Hashable {
@@ -60,6 +66,11 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
case wireGuardObfuscationOn
case wireGuardObfuscationOff
case wireGuardObfuscationPort(_ port: UInt16)
+ #if DEBUG
+ case quantumResistanceAutomatic
+ case quantumResistanceOn
+ case quantumResistanceOff
+ #endif
static var wireGuardPorts: [Item] {
let defaultPorts = PreferencesViewModel.defaultWireGuardPorts.map {
@@ -76,6 +87,12 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
[.wireGuardObfuscationPort(0), wireGuardObfuscationPort(80), wireGuardObfuscationPort(5001)]
}
+ #if DEBUG
+ static var quantumResistance: [Item] {
+ [.quantumResistanceAutomatic, .quantumResistanceOn, .quantumResistanceOff]
+ }
+ #endif
+
var accessibilityIdentifier: AccessibilityIdentifier {
switch self {
case .dnsSettings:
@@ -92,6 +109,14 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
return .wireGuardObfuscationOff
case .wireGuardObfuscationPort:
return .wireGuardObfuscationAutomatic
+ #if DEBUG
+ case .quantumResistanceAutomatic:
+ return .quantumResistanceAutomatic
+ case .quantumResistanceOn:
+ return .quantumResistanceOn
+ case .quantumResistanceOff:
+ return .quantumResistanceOff
+ #endif
}
}
@@ -107,6 +132,10 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
return .wireGuardObfuscation
case .wireGuardObfuscationPort:
return .wireGuardObfuscationPort
+ #if DEBUG
+ case .quantumResistanceAutomatic, .quantumResistanceOn, .quantumResistanceOff:
+ return .quantumResistance
+ #endif
}
}
}
@@ -129,14 +158,30 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
case .off: .wireGuardObfuscationOff
case .on: .wireGuardObfuscationOn
}
+ #if DEBUG
+ let quantumResistanceItem: Item = switch viewModel.quantumResistance {
+ case .automatic: .quantumResistanceAutomatic
+ case .off: .quantumResistanceOff
+ case .on: .quantumResistanceOn
+ }
+ #endif
let obfuscationPortItem: Item = .wireGuardObfuscationPort(viewModel.obfuscationPort.portValue)
+ #if DEBUG
+ return [
+ wireGuardPortItem,
+ obfuscationStateItem,
+ obfuscationPortItem,
+ quantumResistanceItem,
+ ].compactMap { indexPath(for: $0) }
+ #else
return [
- indexPath(for: wireGuardPortItem),
- indexPath(for: obfuscationStateItem),
- indexPath(for: obfuscationPortItem),
- ].compactMap { $0 }
+ wireGuardPortItem,
+ obfuscationStateItem,
+ obfuscationPortItem,
+ ].compactMap { indexPath(for: $0) }
+ #endif
}
init(tableView: UITableView) {
@@ -240,6 +285,18 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
case let .wireGuardObfuscationPort(port):
selectObfuscationPort(port)
delegate?.didChangeViewModel(viewModel)
+
+ #if DEBUG
+ case .quantumResistanceAutomatic:
+ selectQuantumResistance(.automatic)
+ delegate?.didChangeViewModel(viewModel)
+ case .quantumResistanceOn:
+ selectQuantumResistance(.on)
+ delegate?.didChangeViewModel(viewModel)
+ case .quantumResistanceOff:
+ selectQuantumResistance(.off)
+ delegate?.didChangeViewModel(viewModel)
+ #endif
default:
break
}
@@ -277,6 +334,12 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
case .wireGuardObfuscationPort:
configureObfuscationPortHeader(view)
return view
+ #if DEBUG
+ case .quantumResistance:
+ configureQuantumResistanceHeader(view)
+ return view
+ #endif
+
default:
return nil
}
@@ -459,6 +522,36 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
}
}
+ #if DEBUG
+ private func configureQuantumResistanceHeader(_ header: SettingsHeaderView) {
+ let title = NSLocalizedString(
+ "QUANTUM_RESISTANCE_HEADER_LABEL",
+ tableName: "Preferences",
+ value: "Quantum-resistant tunnel",
+ comment: ""
+ )
+
+ header.titleLabel.text = title
+ header.accessibilityCustomActionName = title
+ header.didCollapseHandler = { [weak self] header in
+ guard let self else { return }
+
+ var snapshot = snapshot()
+ if header.isExpanded {
+ snapshot.deleteItems(Item.quantumResistance)
+ } else {
+ snapshot.appendItems(Item.quantumResistance, toSection: .quantumResistance)
+ }
+ header.isExpanded.toggle()
+ applySnapshot(snapshot, animated: true)
+ }
+
+ header.infoButtonHandler = { [weak self] in
+ self.map { $0.delegate?.showInfo(for: .quantumResistance) }
+ }
+ }
+ #endif
+
private func selectRow(at indexPath: IndexPath?, animated: Bool = false) {
tableView?.selectRow(at: indexPath, animated: animated, scrollPosition: .none)
}
@@ -505,6 +598,10 @@ extension PreferencesDataSource: PreferencesCellEventHandler {
let selectedPort = WireGuardObfuscationPort(rawValue: port)!
viewModel.setWireGuardObfuscationPort(selectedPort)
}
+
+ func selectQuantumResistance(_ state: TunnelQuantumResistance) {
+ viewModel.setQuantumResistance(state)
+ }
}
// swiftlint:disable:this file_length
diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesInfoButtonItem.swift b/ios/MullvadVPN/View controllers/Preferences/PreferencesInfoButtonItem.swift
index 8323d3311f..a5b5ce5521 100644
--- a/ios/MullvadVPN/View controllers/Preferences/PreferencesInfoButtonItem.swift
+++ b/ios/MullvadVPN/View controllers/Preferences/PreferencesInfoButtonItem.swift
@@ -12,4 +12,5 @@ enum PreferencesInfoButtonItem {
case wireGuardPorts
case wireGuardObfuscation
case wireGuardObfuscationPort
+ case quantumResistance
}
diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift b/ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift
index 96958f2674..8efc309536 100644
--- a/ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift
+++ b/ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift
@@ -55,6 +55,10 @@ final class PreferencesInteractor {
tunnelManager.setRelayConstraints(relayConstraints, completionHandler: completion)
}
+
+ func setQuantumResistance(_ newSetting: TunnelQuantumResistance) {
+ tunnelManager.setQuantumResistance(newSetting)
+ }
}
extension PreferencesInteractor: RelayCacheTrackerObserver {
diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift b/ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift
index 569a091025..7eee1420d7 100644
--- a/ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift
+++ b/ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift
@@ -105,6 +105,7 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel
state: viewModel.obfuscationState,
port: viewModel.obfuscationPort
))
+ interactor.setQuantumResistance(viewModel.quantumResistance)
}
func showInfo(for item: PreferencesInfoButtonItem) {
@@ -152,6 +153,18 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel
comment: ""
)
+ case .quantumResistance:
+ message = NSLocalizedString(
+ "PREFERENCES_QUANTUM_RESISTANCE_GENERAL",
+ tableName: "QuantumResistance",
+ value: """
+ This feature makes the WireGuard tunnel resistant to potential attacks from quantum computers.
+ It does this by performing an extra key exchange using a quantum safe algorithm and mixing the result into WireGuard’s regular encryption.
+ This extra step uses approximately 500 kiB of traffic every time a new tunnel is established.
+ """,
+ comment: ""
+ )
+
default:
assertionFailure("No matching InfoButtonItem")
}
diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesViewModel.swift b/ios/MullvadVPN/View controllers/Preferences/PreferencesViewModel.swift
index cd5345db96..ed8d2b6313 100644
--- a/ios/MullvadVPN/View controllers/Preferences/PreferencesViewModel.swift
+++ b/ios/MullvadVPN/View controllers/Preferences/PreferencesViewModel.swift
@@ -98,6 +98,8 @@ struct PreferencesViewModel: Equatable {
private(set) var obfuscationState: WireGuardObfuscationState
private(set) var obfuscationPort: WireGuardObfuscationPort
+ private(set) var quantumResistance: TunnelQuantumResistance
+
static let defaultWireGuardPorts: [UInt16] = [51820, 53]
mutating func setBlockAdvertising(_ newValue: Bool) {
@@ -148,6 +150,10 @@ struct PreferencesViewModel: Equatable {
obfuscationPort = newPort
}
+ mutating func setQuantumResistance(_ newState: TunnelQuantumResistance) {
+ quantumResistance = newState
+ }
+
/// Precondition for enabling Custom DNS.
var customDNSPrecondition: CustomDNSPrecondition {
if blockAdvertising || blockTracking || blockMalware ||
@@ -193,6 +199,8 @@ struct PreferencesViewModel: Equatable {
obfuscationState = tunnelSettings.wireGuardObfuscation.state
obfuscationPort = tunnelSettings.wireGuardObfuscation.port
+
+ quantumResistance = tunnelSettings.tunnelQuantumResistance
}
/// Produce merged view model keeping entry `identifier` for matching DNS entries.