Move cipher/digest enums to Core
Restrict choice to supported OpenSSL algorithms.
This commit is contained in:
parent
8a9e99e6a9
commit
6d5e9f68a9
|
@ -12,41 +12,6 @@ import SwiftyBeaver
|
||||||
|
|
||||||
private let log = SwiftyBeaver.self
|
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 {
|
extension TunnelKitProvider {
|
||||||
|
|
||||||
// MARK: Configuration
|
// MARK: Configuration
|
||||||
|
@ -152,10 +117,10 @@ extension TunnelKitProvider {
|
||||||
public var endpointProtocols: [EndpointProtocol]
|
public var endpointProtocols: [EndpointProtocol]
|
||||||
|
|
||||||
/// The encryption algorithm.
|
/// The encryption algorithm.
|
||||||
public var cipher: Cipher
|
public var cipher: SessionProxy.Cipher
|
||||||
|
|
||||||
/// The message digest algorithm.
|
/// 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).
|
/// The optional CA certificate to validate server against. Set to `nil` to disable CA validation (default).
|
||||||
public var ca: Certificate?
|
public var ca: Certificate?
|
||||||
|
@ -205,10 +170,10 @@ extension TunnelKitProvider {
|
||||||
guard let appGroup = providerConfiguration[S.appGroup] as? String else {
|
guard let appGroup = providerConfiguration[S.appGroup] as? String else {
|
||||||
throw ProviderError.configuration(field: "protocolConfiguration.providerConfiguration[\(S.appGroup)]")
|
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)]")
|
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)]")
|
throw ProviderError.configuration(field: "protocolConfiguration.providerConfiguration[\(S.digestAlgorithm)]")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,10 +292,10 @@ extension TunnelKitProvider {
|
||||||
public let endpointProtocols: [EndpointProtocol]
|
public let endpointProtocols: [EndpointProtocol]
|
||||||
|
|
||||||
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.cipher`
|
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.cipher`
|
||||||
public let cipher: Cipher
|
public let cipher: SessionProxy.Cipher
|
||||||
|
|
||||||
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.digest`
|
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.digest`
|
||||||
public let digest: Digest
|
public let digest: SessionProxy.Digest
|
||||||
|
|
||||||
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.ca`
|
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.ca`
|
||||||
public let ca: Certificate?
|
public let ca: Certificate?
|
||||||
|
|
|
@ -156,8 +156,8 @@ open class TunnelKitProvider: NEPacketTunnelProvider {
|
||||||
|
|
||||||
// log.info("Temporary CA is stored to: \(caPath)")
|
// log.info("Temporary CA is stored to: \(caPath)")
|
||||||
var sessionConfiguration = SessionProxy.ConfigurationBuilder(username: endpoint.username, password: endpoint.password)
|
var sessionConfiguration = SessionProxy.ConfigurationBuilder(username: endpoint.username, password: endpoint.password)
|
||||||
sessionConfiguration.cipherName = cfg.cipher.rawValue
|
sessionConfiguration.cipher = cfg.cipher
|
||||||
sessionConfiguration.digestName = cfg.digest.rawValue
|
sessionConfiguration.digest = cfg.digest
|
||||||
sessionConfiguration.caPath = caPath
|
sessionConfiguration.caPath = caPath
|
||||||
if let renegotiatesAfterSeconds = cfg.renegotiatesAfterSeconds {
|
if let renegotiatesAfterSeconds = cfg.renegotiatesAfterSeconds {
|
||||||
sessionConfiguration.renegotiatesAfter = Double(renegotiatesAfterSeconds)
|
sessionConfiguration.renegotiatesAfter = Double(renegotiatesAfterSeconds)
|
||||||
|
|
|
@ -96,7 +96,7 @@ public class EncryptionProxy {
|
||||||
return buffer.withOffset(0, count: length)
|
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 {
|
_ sessionId: Data, _ remoteSessionId: Data) throws {
|
||||||
|
|
||||||
guard let serverRandom1 = auth.serverRandom1, let serverRandom2 = auth.serverRandom2 else {
|
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)
|
try self.init(cipher, digest, cipherEncKey, cipherDecKey, hmacEncKey, hmacDecKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
init(_ cipher: String, _ digest: String, _ cipherEncKey: ZeroingData, _ cipherDecKey: ZeroingData, _ hmacEncKey: ZeroingData, _ hmacDecKey: ZeroingData) throws {
|
init(_ cipher: SessionProxy.Cipher, _ digest: SessionProxy.Digest, _ cipherEncKey: ZeroingData, _ cipherDecKey: ZeroingData, _ hmacEncKey: ZeroingData, _ hmacDecKey: ZeroingData) throws {
|
||||||
box = CryptoBox(cipherAlgorithm: cipher, digestAlgorithm: digest)
|
box = CryptoBox(cipherAlgorithm: cipher.rawValue, digestAlgorithm: digest.rawValue)
|
||||||
try box.configure(
|
try box.configure(
|
||||||
withCipherEncKey: cipherEncKey,
|
withCipherEncKey: cipherEncKey,
|
||||||
cipherDecKey: cipherDecKey,
|
cipherDecKey: cipherDecKey,
|
||||||
|
|
|
@ -10,6 +10,36 @@ import Foundation
|
||||||
|
|
||||||
extension SessionProxy {
|
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`.
|
/// The way to create a `SessionProxy.Configuration` object for a `SessionProxy`.
|
||||||
public struct ConfigurationBuilder {
|
public struct ConfigurationBuilder {
|
||||||
|
|
||||||
|
@ -19,11 +49,11 @@ extension SessionProxy {
|
||||||
/// A password.
|
/// A password.
|
||||||
public let password: String
|
public let password: String
|
||||||
|
|
||||||
/// The cipher algorithm for data encryption. Must follow OpenSSL nomenclature, e.g. "AES-128-CBC".
|
/// The cipher algorithm for data encryption.
|
||||||
public var cipherName: String
|
public var cipher: Cipher
|
||||||
|
|
||||||
/// The digest algorithm for HMAC. Must follow OpenSSL nomenclature, e.g. "SHA-1".
|
/// The digest algorithm for HMAC.
|
||||||
public var digestName: String
|
public var digest: Digest
|
||||||
|
|
||||||
/// The path to the optional CA for TLS negotiation (PEM format).
|
/// The path to the optional CA for TLS negotiation (PEM format).
|
||||||
public var caPath: String?
|
public var caPath: String?
|
||||||
|
@ -38,8 +68,8 @@ extension SessionProxy {
|
||||||
public init(username: String, password: String) {
|
public init(username: String, password: String) {
|
||||||
self.username = username
|
self.username = username
|
||||||
self.password = password
|
self.password = password
|
||||||
cipherName = "AES-128-CBC"
|
cipher = .aes128cbc
|
||||||
digestName = "SHA-1"
|
digest = .sha1
|
||||||
caPath = nil
|
caPath = nil
|
||||||
keepAliveInterval = nil
|
keepAliveInterval = nil
|
||||||
renegotiatesAfter = nil
|
renegotiatesAfter = nil
|
||||||
|
@ -54,8 +84,8 @@ extension SessionProxy {
|
||||||
return Configuration(
|
return Configuration(
|
||||||
username: username,
|
username: username,
|
||||||
password: password,
|
password: password,
|
||||||
cipherName: cipherName,
|
cipher: cipher,
|
||||||
digestName: digestName,
|
digest: digest,
|
||||||
caPath: caPath,
|
caPath: caPath,
|
||||||
keepAliveInterval: keepAliveInterval,
|
keepAliveInterval: keepAliveInterval,
|
||||||
renegotiatesAfter: renegotiatesAfter
|
renegotiatesAfter: renegotiatesAfter
|
||||||
|
@ -72,11 +102,11 @@ extension SessionProxy {
|
||||||
/// - Seealso: `SessionProxy.ConfigurationBuilder.password`
|
/// - Seealso: `SessionProxy.ConfigurationBuilder.password`
|
||||||
public let password: String
|
public let password: String
|
||||||
|
|
||||||
/// - Seealso: `SessionProxy.ConfigurationBuilder.cipherName`
|
/// - Seealso: `SessionProxy.ConfigurationBuilder.cipher`
|
||||||
public let cipherName: String
|
public let cipher: Cipher
|
||||||
|
|
||||||
/// - Seealso: `SessionProxy.ConfigurationBuilder.digestName`
|
/// - Seealso: `SessionProxy.ConfigurationBuilder.digest`
|
||||||
public let digestName: String
|
public let digest: Digest
|
||||||
|
|
||||||
/// - Seealso: `SessionProxy.ConfigurationBuilder.caPath`
|
/// - Seealso: `SessionProxy.ConfigurationBuilder.caPath`
|
||||||
public let caPath: String?
|
public let caPath: String?
|
||||||
|
|
|
@ -1010,7 +1010,13 @@ public class SessionProxy {
|
||||||
|
|
||||||
let proxy: EncryptionProxy
|
let proxy: EncryptionProxy
|
||||||
do {
|
do {
|
||||||
proxy = try EncryptionProxy(configuration.cipherName, configuration.digestName, auth, sessionId, remoteSessionId)
|
proxy = try EncryptionProxy(
|
||||||
|
configuration.cipher,
|
||||||
|
configuration.digest,
|
||||||
|
auth,
|
||||||
|
sessionId,
|
||||||
|
remoteSessionId
|
||||||
|
)
|
||||||
} catch let e {
|
} catch let e {
|
||||||
deferStop(.shutdown, e)
|
deferStop(.shutdown, e)
|
||||||
return
|
return
|
||||||
|
|
|
@ -21,7 +21,7 @@ class DataPathPerformanceTests: XCTestCase {
|
||||||
let ck = try! SecureRandom.safeData(length: 32)
|
let ck = try! SecureRandom.safeData(length: 32)
|
||||||
let hk = 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()
|
encrypter = crypto.encrypter()
|
||||||
decrypter = crypto.decrypter()
|
decrypter = crypto.decrypter()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue