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

View File

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

View File

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

View File

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

View File

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

View File

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