Move cipher/digest enums to Core

Restrict choice to supported OpenSSL algorithms.
This commit is contained in:
Davide De Rosa 2018-08-23 15:44:31 +02:00
parent 8a9e99e6a9
commit 6d5e9f68a9
6 changed files with 61 additions and 60 deletions

View File

@ -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?

View File

@ -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)

View File

@ -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,

View File

@ -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?

View File

@ -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

View File

@ -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()