Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Post-Quantum Resistant WireGuard #354

Merged
merged 35 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
0bca7b0
feat(qr): include liboqs
jurajhilje May 25, 2023
3324e2b
feat(qr): create KemHelper.swift
jurajhilje May 25, 2023
e1f3b13
feat(qr): update generateKeys method
jurajhilje May 25, 2023
2bacd88
feat(qr): update init in KemHelper.swift
jurajhilje May 25, 2023
b1098bd
feat(qr): update decodeCipher method
jurajhilje May 25, 2023
e1bf9ba
refactor: clean up KemHelper.swift
jurajhilje May 25, 2023
5bdc82f
feat(qr): update setNewKey method in AppKeyManager
jurajhilje May 26, 2023
13b63eb
feat(qr): update setNewKey method in AppKeyManager
jurajhilje May 26, 2023
d2a9d43
feat(qr): update makeWireGuardProtocol method in NETunnelProviderProt…
jurajhilje May 26, 2023
896082b
feat(qr): update KemHelper.swift
jurajhilje May 31, 2023
28ea49c
feat(qr): update KemHelper.swift
jurajhilje May 31, 2023
b3a4703
feat(wireguard): update generatePeerProviderConfiguration method in T…
jurajhilje May 31, 2023
830e6fc
feat(qr): update setNewKey method in AppKeyManager
jurajhilje Jun 1, 2023
5113c3b
feat(qr): update createSession method
jurajhilje Jun 6, 2023
5bbfbd9
feat(qr): link liboqs.a in wireguard-tunnel-provider
jurajhilje Jun 7, 2023
0aac80b
feat(qr): link liboqs.a at build time
jurajhilje Jun 7, 2023
b293878
feat(qr): update ExtensionKeyManager
jurajhilje Jun 7, 2023
4682761
tests: update HEADER_SEARCH_PATHS in UnitTest target
jurajhilje Jun 7, 2023
5ad19f4
feat(qr): add Info view
jurajhilje Jun 12, 2023
fd220bd
feat(qr): update ExtensionKeyManager
jurajhilje Jun 12, 2023
c535147
vendor: upgrade liboqs to version 0.8.0
jurajhilje Jun 12, 2023
b9395a3
fix: update makeWireGuardProtocol method
jurajhilje Jun 13, 2023
447e4de
refactor: update generateKeys method
jurajhilje Jun 13, 2023
a677a4f
feat(qr): update WireGuardSettingsViewController
jurajhilje Jun 14, 2023
0425bf6
Merge branch 'feature/rotate-wireguard-keys-when-connected-with-openv…
jurajhilje Jun 16, 2023
5f9c16d
refactor: update AppKeyManager.swift
jurajhilje Jun 17, 2023
3d0ee44
refactor: remove ExtensionKeyManager.swift
jurajhilje Jun 17, 2023
b2b6461
refactor: fix shorthand_operator warning in AppKeyManager.swift
jurajhilje Jul 6, 2023
fb13779
tests: update AppKeyManagerTests.swift
jurajhilje Jul 6, 2023
99f200a
chore: update project.pbxproj
jurajhilje Jul 6, 2023
f78ed9b
chore: update IVPNClient.xcscheme
jurajhilje Jul 6, 2023
a71491a
ci: update workflows/ci.yml
jurajhilje Jul 7, 2023
7746e15
Merge branch 'feature/rotate-wireguard-keys-when-connected-with-openv…
jurajhilje Jul 12, 2023
37d924c
Merge branch 'feature/rotate-wireguard-keys-when-connected-with-openv…
jurajhilje Jul 12, 2023
0d9a670
ci: update fastlane/Fastfile
jurajhilje Jul 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
name: CI

on:
push:
branches: [ "main", "develop" ]
pull_request:
# This action is disabled until we can run it on Apple Silicon powered macOS runners - https://github.com/github/roadmap/issues/528

jobs:
test:
name: Unit and UI Tests
runs-on: macOS-latest
steps:
- uses: actions/setup-go@v2
with:
go-version: 1.18
- uses: actions/checkout@v2
- name: Set up config files
run: |
cp IVPNClient/Config/staging.template.xcconfig IVPNClient/Config/staging.xcconfig
cp IVPNClient/Config/release.template.xcconfig IVPNClient/Config/release.xcconfig
cp IVPNClient/Config/OpenVPNConf.template.swift IVPNClient/Config/OpenVPNConf.swift
cp fastlane/Appfile.template fastlane/Appfile
- name: Build and test
run: xcodebuild test -scheme IVPNClient -destination 'platform=iOS Simulator,name=iPhone 14'
# on:
# push:
# branches: [ "main", "develop" ]
# pull_request:

# jobs:
# test:
# name: Unit and UI Tests
# runs-on: macOS-latest
# steps:
# - uses: actions/setup-go@v2
# with:
# go-version: 1.18
# - uses: actions/checkout@v2
# - name: Set up config files
# run: |
# cp IVPNClient/Config/staging.template.xcconfig IVPNClient/Config/staging.xcconfig
# cp IVPNClient/Config/release.template.xcconfig IVPNClient/Config/release.xcconfig
# cp IVPNClient/Config/OpenVPNConf.template.swift IVPNClient/Config/OpenVPNConf.swift
# cp fastlane/Appfile.template fastlane/Appfile
# - name: Build and test
# run: xcodebuild test -scheme IVPNClient -destination 'platform=iOS Simulator,name=iPhone 14'
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
build/
DerivedData/

## Static libraries
IVPNClient/liboqs/liboqs-iphoneos.a
IVPNClient/liboqs/liboqs-iphonesimulator.a

## Various settings
*.pbxuser
!default.pbxuser
Expand Down
170 changes: 155 additions & 15 deletions IVPNClient.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

20 changes: 19 additions & 1 deletion IVPNClient.xcodeproj/xcshareddata/xcschemes/IVPNClient.xcscheme
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.3">
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<PreActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Link liboqs"
scriptText = "if [ &quot;${PLATFORM_NAME}&quot; == &quot;iphoneos&quot; ]; then&#10; LIBOQS_LIB=&quot;liboqs-iphoneos.a&quot;&#10;else&#10; LIBOQS_LIB=&quot;liboqs-iphonesimulator.a&quot;&#10;fi&#10;&#10;if test -f &quot;${SRCROOT}/IVPNClient/liboqs/${LIBOQS_LIB}&quot;; then&#10; cp &quot;${SRCROOT}/IVPNClient/liboqs/${LIBOQS_LIB}&quot; &quot;${SRCROOT}/IVPNClient/liboqs/liboqs.a&quot;&#10;fi&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9CDDD5AA1D9D2F9E00D39924"
BuildableName = "IVPNClient.app"
BlueprintName = "IVPNClient"
ReferencedContainer = "container:IVPNClient.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
</PreActions>
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
Expand Down
1 change: 1 addition & 0 deletions IVPNClient/Enums/ApiResults/InterfaceResult.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ import Foundation

struct InterfaceResult: Decodable {
var ipAddress: String
let kemCipher1: String?
}
1 change: 1 addition & 0 deletions IVPNClient/Enums/ApiResults/Session.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct WireGuardResult: Codable {
let status: Int?
let message: String?
let ipAddress: String?
let kemCipher1: String?
}

struct Session: Decodable {
Expand Down
1 change: 1 addition & 0 deletions IVPNClient/IVPNClient-Bridging-Header.h
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#include "../WireGuardKitC/WireGuardKitC.h"
#include "Utilities/Logging/ringlogger.h"
#include "liboqs/include/oqs/oqs.h"
47 changes: 42 additions & 5 deletions IVPNClient/Managers/AppKeyManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class AppKeyManager {
// MARK: - Properties -

weak var delegate: AppKeyManagerDelegate?
static let shared = AppKeyManager()

static var keyTimestamp: Date {
return UserDefaults.shared.wgKeyTimestamp
Expand Down Expand Up @@ -70,8 +71,26 @@ class AppKeyManager {
return true
}

static var isKeyPairRequired: Bool {
return Application.shared.settings.connectionProtocol.tunnelType() == .wireguard
static var regenerationCheckInterval: TimeInterval {
if Config.useDebugWireGuardKeyUpgrade {
return TimeInterval(10)
}

return TimeInterval(60 * 60)
}

static var regenerationInterval: TimeInterval {
var regenerationRate = UserDefaults.shared.wgRegenerationRate

if regenerationRate <= 0 {
regenerationRate = 1
}

if Config.useDebugWireGuardKeyUpgrade {
return TimeInterval(regenerationRate * 60)
}

return TimeInterval(regenerationRate * 60 * 60 * 24)
}

// MARK: - Methods -
Expand All @@ -84,14 +103,15 @@ class AppKeyManager {
KeyChain.wgPublicKey = interface.publicKey
}

func setNewKey() {
func setNewKey(completion: @escaping (String?, String?, String?) -> Void) {
var interface = Interface()
interface.privateKey = Interface.generatePrivateKey()

let params = ApiService.authParams + [
var params = ApiService.authParams + [
URLQueryItem(name: "public_key", value: interface.publicKey ?? "")
]

var kem = KEM()
params += [URLQueryItem(name: "kem_public_key1", value: kem.getPublicKey(algorithm: .Kyber1024))]
let request = ApiRequestDI(method: .post, endpoint: Config.apiSessionWGKeySet, params: params)

delegate?.setKeyStart()
Expand All @@ -103,11 +123,28 @@ class AppKeyManager {
KeyChain.wgPrivateKey = interface.privateKey
KeyChain.wgPublicKey = interface.publicKey
KeyChain.wgIpAddress = model.ipAddress
if let kemCipher1 = model.kemCipher1 {
kem.setCipher(algorithm: .Kyber1024, cipher: kemCipher1)
KeyChain.wgPresharedKey = kem.calculatePresharedKey()
completion(interface.privateKey, model.ipAddress, KeyChain.wgPresharedKey)
} else {
KeyChain.wgPresharedKey = nil
completion(interface.privateKey, model.ipAddress, nil)
}
self.delegate?.setKeySuccess()
case .failure:
self.delegate?.setKeyFail()
completion(nil, nil, nil)
}
}
}

static func needToRegenerate() -> Bool {
guard Date() > UserDefaults.shared.wgKeyTimestamp.addingTimeInterval(regenerationInterval) else {
return false
}

return true
}

}
11 changes: 11 additions & 0 deletions IVPNClient/Managers/KeyChain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class KeyChain {
private static let wgIpAddressKey = "WGIpAddressKey"
private static let wgIpv6HostKey = "WGIPv6HostKey"
private static let wgIpAddressesKey = "WGIpAddressesKey"
private static let wgPresharedKeyKey = "WGPresharedKey"
private static let sessionTokenKey = "session_token"
private static let vpnUsernameKey = "vpn_username"
private static let vpnPasswordKey = "vpn_password"
Expand Down Expand Up @@ -95,6 +96,15 @@ class KeyChain {
}
}

class var wgPresharedKey: String? {
get {
return KeyChain.bundle[wgPresharedKeyKey]
}
set {
KeyChain.bundle[wgPresharedKeyKey] = newValue
}
}

class var wgIpv6Host: String? {
get {
return KeyChain.bundle[wgIpv6HostKey]
Expand Down Expand Up @@ -152,6 +162,7 @@ class KeyChain {
wgPublicKey = nil
wgIpAddress = nil
wgIpAddresses = nil
wgPresharedKey = nil
sessionToken = nil
vpnUsername = nil
vpnPassword = nil
Expand Down
15 changes: 12 additions & 3 deletions IVPNClient/Managers/SessionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,13 @@ class SessionManager {
func createSession(force: Bool = false, connecting: Bool = false, username: String? = nil, confirmation: String? = nil, captcha: String? = nil, captchaId: String? = nil) {
delegate?.createSessionStart()

if AppKeyManager.isKeyPairRequired || connecting {
if Application.isKeyPairRequired || connecting {
AppKeyManager.generateKeyPair()
UserDefaults.shared.set(Date(), forKey: UserDefaults.Key.wgKeyTimestamp)
}

let params = sessionNewParams(force: force, username: username, confirmation: confirmation, captcha: captcha, captchaId: captchaId)
var kem = KEM()
let params = sessionNewParams(force: force, username: username, confirmation: confirmation, captcha: captcha, captchaId: captchaId, kem: kem)
let request = ApiRequestDI(method: .post, endpoint: Config.apiSessionNew, params: params)

ApiService.shared.requestCustomError(request) { (result: ResultCustomError<Session, ErrorResultSessionNew>) in
Expand All @@ -74,6 +75,13 @@ class SessionManager {
Application.shared.serviceStatus = model.serviceStatus
Application.shared.authentication.logIn(session: model)

if let kemCipher1 = model.wireguard?.kemCipher1 {
kem.setCipher(algorithm: .Kyber1024, cipher: kemCipher1)
KeyChain.wgPresharedKey = kem.calculatePresharedKey()
} else {
KeyChain.wgPresharedKey = nil
}

if !model.serviceStatus.isActive {
log(.info, message: "Create session error: createSessionServiceNotActive")
self.delegate?.createSessionServiceNotActive()
Expand Down Expand Up @@ -196,12 +204,13 @@ class SessionManager {

// MARK: - Helper methods -

private func sessionNewParams(force: Bool = false, username: String? = nil, confirmation: String? = nil, captcha: String? = nil, captchaId: String? = nil) -> [URLQueryItem] {
private func sessionNewParams(force: Bool = false, username: String? = nil, confirmation: String? = nil, captcha: String? = nil, captchaId: String? = nil, kem: KEM) -> [URLQueryItem] {
let username = username ?? Application.shared.authentication.getStoredUsername()
var params = [URLQueryItem(name: "username", value: username)]

if let wgPublicKey = KeyChain.wgPublicKey {
params.append(URLQueryItem(name: "wg_public_key", value: wgPublicKey))
params.append(URLQueryItem(name: "kem_public_key1", value: kem.getPublicKey(algorithm: .Kyber1024)))
}

if let confirmation = confirmation {
Expand Down
4 changes: 4 additions & 0 deletions IVPNClient/Models/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ class Application {

var geoLookup = GeoLookup(ipAddress: "", countryCode: "", country: "", city: "", isIvpnServer: false, isp: "", latitude: 0, longitude: 0)

static var isKeyPairRequired: Bool {
return shared.settings.connectionProtocol.tunnelType() == .wireguard
}

// MARK: - Initialize -

private init() {
Expand Down
4 changes: 2 additions & 2 deletions IVPNClient/Models/WireGuard/Tunnel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ struct Tunnel {
settingsString += "public_key=\(hexPublicKey)\n"
}

if let presharedKey = peer.presharedKey {
settingsString += "preshared_key=\(presharedKey)\n"
if let hexPresharedKey = peer.presharedKey?.base64KeyToHex() {
settingsString += "preshared_key=\(hexPresharedKey)\n"
}

if let endpoint = peer.endpoint {
Expand Down
Loading