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
|
||||
|
||||
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?
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
Loading…
Reference in New Issue