Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
jurajhilje committed Aug 8, 2023
2 parents 4ce562e + 6538d26 commit 6c29dd1
Show file tree
Hide file tree
Showing 66 changed files with 3,435 additions and 494 deletions.
48 changes: 23 additions & 25 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,28 +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.16
- 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 wireguard-tunnel-provider/Config/wg-staging.template.xcconfig wireguard-tunnel-provider/Config/wg-staging.xcconfig
cp wireguard-tunnel-provider/Config/wg-release.template.xcconfig wireguard-tunnel-provider/Config/wg-release.xcconfig
cp IVPNWidget/Config/widget-staging.template.xcconfig IVPNWidget/Config/widget-staging.xcconfig
cp IVPNWidget/Config/widget-release.template.xcconfig IVPNWidget/Config/widget-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'
8 changes: 4 additions & 4 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 Expand Up @@ -58,10 +62,6 @@ Carthage/Build
# Rules for .xcconfig files
staging.xcconfig
release.xcconfig
wg-staging.xcconfig
wg-release.xcconfig
widget-staging.xcconfig
widget-release.xcconfig

# Rules for .swift files
OpenVPNConf.swift
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

All notable changes to this project will be documented in this file.

## 2.10.0 - 2023-08-08

[NEW] Post-Quantum Resistant WireGuard Connections
[NEW] AntiTracker Plus additional block lists
[IMPROVED] WireGuard keys rotation when connected with OpenVPN
[NOTE] Kill Switch is removed for iOS 16+ devices; Disable Kill Switch before upgrading to avoid connection issues

## 2.9.1 - 2023-06-29

[NOTE] Removed references to Port Forwarding
Expand Down
282 changes: 225 additions & 57 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"
2 changes: 1 addition & 1 deletion IVPNClient/Managers/APIClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ class APIClient: NSObject {

do {
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
} catch let error {
} catch {

}

Expand Down
14 changes: 0 additions & 14 deletions IVPNClient/Managers/ApiService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,12 @@ class ApiService {
// MARK: - Methods -

func request<T>(_ requestDI: ApiRequestDI, completion: @escaping (Result<T>) -> Void) {
let requestName = "\(requestDI.method.description) \(requestDI.endpoint)"
let request = APIRequest(method: requestDI.method, path: requestDI.endpoint, contentType: requestDI.contentType, addressType: requestDI.addressType)

if let params = requestDI.params {
request.queryItems = params
}

log(.info, message: "\(requestName) started")

APIClient().perform(request) { result in
DispatchQueue.main.async {
switch result {
Expand All @@ -60,39 +57,32 @@ class ApiService {
do {
let successResponse = try decoder.decode(T.self, from: data)
completion(.success(successResponse))
log(.info, message: "\(requestName) success")
return
} catch {}

do {
let errorResponse = try decoder.decode(ErrorResult.self, from: data)
let error = self.getServiceError(message: errorResponse.message, code: errorResponse.status)
completion(.failure(error))
log(.info, message: "\(requestName) error response")
return
} catch {}
}

completion(.failure(nil))
log(.info, message: "\(requestName) parse error")
case .failure(let error):
log(.info, message: "\(requestName) failure")
completion(.failure(error))
}
}
}
}

func requestCustomError<T, E>(_ requestDI: ApiRequestDI, completion: @escaping (ResultCustomError<T, E>) -> Void) {
let requestName = "\(requestDI.method.description) \(requestDI.endpoint)"
let request = APIRequest(method: requestDI.method, path: requestDI.endpoint, contentType: requestDI.contentType, addressType: requestDI.addressType)

if let params = requestDI.params {
request.queryItems = params
}

log(.info, message: "\(requestName) started")

APIClient().perform(request) { result in
DispatchQueue.main.async {
switch result {
Expand All @@ -104,22 +94,18 @@ class ApiService {
do {
let successResponse = try decoder.decode(T.self, from: data)
completion(.success(successResponse))
log(.info, message: "\(requestName) success")
return
} catch {}

do {
let errorResponse = try decoder.decode(E.self, from: data)
completion(.failure(errorResponse))
log(.info, message: "\(requestName) error response")
return
} catch {}
}

completion(.failure(nil))
log(.info, message: "\(requestName) parse error")
case .failure:
log(.info, message: "\(requestName) failure")
completion(.failure(nil))
}
}
Expand Down
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
Loading

0 comments on commit 6c29dd1

Please sign in to comment.