Skip to content

Commit

Permalink
Add quantum resistance items to preferences view, Disable quantum res…
Browse files Browse the repository at this point in the history
…istance preferences UI options if DEBUG is not set
  • Loading branch information
acb-mv authored and buggmagnet committed Feb 13, 2024
1 parent e79f77a commit 0014c3c
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 4 deletions.
5 changes: 5 additions & 0 deletions ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ public enum AccessibilityIdentifier: String {
case dnsServer
case dnsServerInfo

// Quantum resistance
case quantumResistanceAutomatic
case quantumResistanceOff
case quantumResistanceOn

// Error
case unknown
}
Expand Down
10 changes: 10 additions & 0 deletions ios/MullvadVPN/TunnelManager/TunnelManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
case wireGuardCustomPort
case wireGuardObfuscation
case wireGuardObfuscationPort
case quantumResistance
var reusableViewClass: AnyClass {
switch self {
case .dnsSettings:
Expand All @@ -33,6 +34,8 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
return SelectableSettingsCell.self
case .wireGuardObfuscationPort:
return SelectableSettingsCell.self
case .quantumResistance:
return SelectableSettingsCell.self
}
}
}
Expand All @@ -50,6 +53,9 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
case wireGuardPorts
case wireGuardObfuscation
case wireGuardObfuscationPort
#if DEBUG
case quantumResistance
#endif
}

enum Item: Hashable {
Expand All @@ -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 {
Expand All @@ -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:
Expand All @@ -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
}
}

Expand All @@ -107,6 +132,10 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
return .wireGuardObfuscation
case .wireGuardObfuscationPort:
return .wireGuardObfuscationPort
#if DEBUG
case .quantumResistanceAutomatic, .quantumResistanceOn, .quantumResistanceOff:
return .quantumResistance
#endif
}
}
}
Expand All @@ -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) {
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ enum PreferencesInfoButtonItem {
case wireGuardPorts
case wireGuardObfuscation
case wireGuardObfuscationPort
case quantumResistance
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ final class PreferencesInteractor {

tunnelManager.setRelayConstraints(relayConstraints, completionHandler: completion)
}

func setQuantumResistance(_ newSetting: TunnelQuantumResistance) {
tunnelManager.setQuantumResistance(newSetting)
}
}

extension PreferencesInteractor: RelayCacheTrackerObserver {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel
state: viewModel.obfuscationState,
port: viewModel.obfuscationPort
))
interactor.setQuantumResistance(viewModel.quantumResistance)
}

func showInfo(for item: PreferencesInfoButtonItem) {
Expand Down Expand Up @@ -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")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 ||
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 0014c3c

Please sign in to comment.