diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift index 3acc3fb..60806a8 100644 --- a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift +++ b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift @@ -12,41 +12,6 @@ import SwiftyBeaver private let log = SwiftyBeaver.self -extension TunnelKitProvider { - - // MARK: Cryptography - - /// The available encryption algorithms. - public enum Cipher: String { - - // WARNING: must match OpenSSL algorithm names - - /// AES encryption with 128-bit key size and CBC. - case aes128cbc = "AES-128-CBC" - - /// AES encryption with 256-bit key size and CBC. - case aes256cbc = "AES-256-CBC" - - /// AES encryption with 128-bit key size and GCM. - case aes128gcm = "AES-128-GCM" - - /// AES encryption with 256-bit key size and GCM. - case aes256gcm = "AES-256-GCM" - } - - /// The available message digest algorithms. - public enum Digest: String { - - // WARNING: must match OpenSSL algorithm names - - /// SHA1 message digest. - case sha1 = "SHA1" - - /// SHA256 message digest. - case sha256 = "SHA256" - } -} - extension TunnelKitProvider { // MARK: Configuration @@ -152,10 +117,10 @@ extension TunnelKitProvider { public var endpointProtocols: [EndpointProtocol] /// The encryption algorithm. - public var cipher: Cipher + public var cipher: SessionProxy.Cipher /// The message digest algorithm. - public var digest: Digest + public var digest: SessionProxy.Digest /// The optional CA certificate to validate server against. Set to `nil` to disable CA validation (default). public var ca: Certificate? @@ -205,10 +170,10 @@ extension TunnelKitProvider { guard let appGroup = providerConfiguration[S.appGroup] as? String else { throw ProviderError.configuration(field: "protocolConfiguration.providerConfiguration[\(S.appGroup)]") } - guard let cipherAlgorithm = providerConfiguration[S.cipherAlgorithm] as? String, let cipher = Cipher(rawValue: cipherAlgorithm) else { + guard let cipherAlgorithm = providerConfiguration[S.cipherAlgorithm] as? String, let cipher = SessionProxy.Cipher(rawValue: cipherAlgorithm) else { throw ProviderError.configuration(field: "protocolConfiguration.providerConfiguration[\(S.cipherAlgorithm)]") } - guard let digestAlgorithm = providerConfiguration[S.digestAlgorithm] as? String, let digest = Digest(rawValue: digestAlgorithm) else { + guard let digestAlgorithm = providerConfiguration[S.digestAlgorithm] as? String, let digest = SessionProxy.Digest(rawValue: digestAlgorithm) else { throw ProviderError.configuration(field: "protocolConfiguration.providerConfiguration[\(S.digestAlgorithm)]") } @@ -327,10 +292,10 @@ extension TunnelKitProvider { public let endpointProtocols: [EndpointProtocol] /// - Seealso: `TunnelKitProvider.ConfigurationBuilder.cipher` - public let cipher: Cipher + public let cipher: SessionProxy.Cipher /// - Seealso: `TunnelKitProvider.ConfigurationBuilder.digest` - public let digest: Digest + public let digest: SessionProxy.Digest /// - Seealso: `TunnelKitProvider.ConfigurationBuilder.ca` public let ca: Certificate? diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift index 5ab8970..84ba6f9 100644 --- a/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift +++ b/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift @@ -156,8 +156,8 @@ open class TunnelKitProvider: NEPacketTunnelProvider { // log.info("Temporary CA is stored to: \(caPath)") var sessionConfiguration = SessionProxy.ConfigurationBuilder(username: endpoint.username, password: endpoint.password) - sessionConfiguration.cipherName = cfg.cipher.rawValue - sessionConfiguration.digestName = cfg.digest.rawValue + sessionConfiguration.cipher = cfg.cipher + sessionConfiguration.digest = cfg.digest sessionConfiguration.caPath = caPath if let renegotiatesAfterSeconds = cfg.renegotiatesAfterSeconds { sessionConfiguration.renegotiatesAfter = Double(renegotiatesAfterSeconds) diff --git a/TunnelKit/Sources/Core/EncryptionProxy.swift b/TunnelKit/Sources/Core/EncryptionProxy.swift index b832c37..fb7b8ed 100644 --- a/TunnelKit/Sources/Core/EncryptionProxy.swift +++ b/TunnelKit/Sources/Core/EncryptionProxy.swift @@ -96,7 +96,7 @@ public class EncryptionProxy { return buffer.withOffset(0, count: length) } - convenience init(_ cipher: String, _ digest: String, _ auth: Authenticator, + convenience init(_ cipher: SessionProxy.Cipher, _ digest: SessionProxy.Digest, _ auth: Authenticator, _ sessionId: Data, _ remoteSessionId: Data) throws { guard let serverRandom1 = auth.serverRandom1, let serverRandom2 = auth.serverRandom2 else { @@ -130,8 +130,8 @@ public class EncryptionProxy { try self.init(cipher, digest, cipherEncKey, cipherDecKey, hmacEncKey, hmacDecKey) } - init(_ cipher: String, _ digest: String, _ cipherEncKey: ZeroingData, _ cipherDecKey: ZeroingData, _ hmacEncKey: ZeroingData, _ hmacDecKey: ZeroingData) throws { - box = CryptoBox(cipherAlgorithm: cipher, digestAlgorithm: digest) + init(_ cipher: SessionProxy.Cipher, _ digest: SessionProxy.Digest, _ cipherEncKey: ZeroingData, _ cipherDecKey: ZeroingData, _ hmacEncKey: ZeroingData, _ hmacDecKey: ZeroingData) throws { + box = CryptoBox(cipherAlgorithm: cipher.rawValue, digestAlgorithm: digest.rawValue) try box.configure( withCipherEncKey: cipherEncKey, cipherDecKey: cipherDecKey, diff --git a/TunnelKit/Sources/Core/SessionProxy+Configuration.swift b/TunnelKit/Sources/Core/SessionProxy+Configuration.swift index ebc8b2c..a35a50e 100644 --- a/TunnelKit/Sources/Core/SessionProxy+Configuration.swift +++ b/TunnelKit/Sources/Core/SessionProxy+Configuration.swift @@ -10,6 +10,36 @@ import Foundation extension SessionProxy { + /// The available encryption algorithms. + public enum Cipher: String { + + // WARNING: must match OpenSSL algorithm names + + /// AES encryption with 128-bit key size and CBC. + case aes128cbc = "AES-128-CBC" + + /// AES encryption with 256-bit key size and CBC. + case aes256cbc = "AES-256-CBC" + + /// AES encryption with 128-bit key size and GCM. + case aes128gcm = "AES-128-GCM" + + /// AES encryption with 256-bit key size and GCM. + case aes256gcm = "AES-256-GCM" + } + + /// The available message digest algorithms. + public enum Digest: String { + + // WARNING: must match OpenSSL algorithm names + + /// SHA1 message digest. + case sha1 = "SHA1" + + /// SHA256 message digest. + case sha256 = "SHA256" + } + /// The way to create a `SessionProxy.Configuration` object for a `SessionProxy`. public struct ConfigurationBuilder { @@ -19,11 +49,11 @@ extension SessionProxy { /// A password. public let password: String - /// The cipher algorithm for data encryption. Must follow OpenSSL nomenclature, e.g. "AES-128-CBC". - public var cipherName: String + /// The cipher algorithm for data encryption. + public var cipher: Cipher - /// The digest algorithm for HMAC. Must follow OpenSSL nomenclature, e.g. "SHA-1". - public var digestName: String + /// The digest algorithm for HMAC. + public var digest: Digest /// The path to the optional CA for TLS negotiation (PEM format). public var caPath: String? @@ -38,8 +68,8 @@ extension SessionProxy { public init(username: String, password: String) { self.username = username self.password = password - cipherName = "AES-128-CBC" - digestName = "SHA-1" + cipher = .aes128cbc + digest = .sha1 caPath = nil keepAliveInterval = nil renegotiatesAfter = nil @@ -54,8 +84,8 @@ extension SessionProxy { return Configuration( username: username, password: password, - cipherName: cipherName, - digestName: digestName, + cipher: cipher, + digest: digest, caPath: caPath, keepAliveInterval: keepAliveInterval, renegotiatesAfter: renegotiatesAfter @@ -72,11 +102,11 @@ extension SessionProxy { /// - Seealso: `SessionProxy.ConfigurationBuilder.password` public let password: String - /// - Seealso: `SessionProxy.ConfigurationBuilder.cipherName` - public let cipherName: String + /// - Seealso: `SessionProxy.ConfigurationBuilder.cipher` + public let cipher: Cipher - /// - Seealso: `SessionProxy.ConfigurationBuilder.digestName` - public let digestName: String + /// - Seealso: `SessionProxy.ConfigurationBuilder.digest` + public let digest: Digest /// - Seealso: `SessionProxy.ConfigurationBuilder.caPath` public let caPath: String? diff --git a/TunnelKit/Sources/Core/SessionProxy.swift b/TunnelKit/Sources/Core/SessionProxy.swift index fc8439d..6300a25 100644 --- a/TunnelKit/Sources/Core/SessionProxy.swift +++ b/TunnelKit/Sources/Core/SessionProxy.swift @@ -1010,7 +1010,13 @@ public class SessionProxy { let proxy: EncryptionProxy do { - proxy = try EncryptionProxy(configuration.cipherName, configuration.digestName, auth, sessionId, remoteSessionId) + proxy = try EncryptionProxy( + configuration.cipher, + configuration.digest, + auth, + sessionId, + remoteSessionId + ) } catch let e { deferStop(.shutdown, e) return diff --git a/TunnelKitTests/DataPathPerformanceTests.swift b/TunnelKitTests/DataPathPerformanceTests.swift index e5b43fa..664077d 100644 --- a/TunnelKitTests/DataPathPerformanceTests.swift +++ b/TunnelKitTests/DataPathPerformanceTests.swift @@ -21,7 +21,7 @@ class DataPathPerformanceTests: XCTestCase { let ck = try! SecureRandom.safeData(length: 32) let hk = try! SecureRandom.safeData(length: 32) - let crypto = try! EncryptionProxy("aes-128-cbc", "sha1", ck, ck, hk, hk) + let crypto = try! EncryptionProxy(.aes128cbc, .sha1, ck, ck, hk, hk) encrypter = crypto.encrypter() decrypter = crypto.decrypter()