From 82f043130322a2e10c70ca4365ea89951e14cbf6 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Wed, 8 May 2019 15:54:05 +0200 Subject: [PATCH 1/3] Take optional securityLevel field in TLSBox --- TunnelKit/Sources/Core/TLSBox.h | 4 ++++ TunnelKit/Sources/Core/TLSBox.m | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/TunnelKit/Sources/Core/TLSBox.h b/TunnelKit/Sources/Core/TLSBox.h index d162e11..9780c67 100644 --- a/TunnelKit/Sources/Core/TLSBox.h +++ b/TunnelKit/Sources/Core/TLSBox.h @@ -43,6 +43,8 @@ extern const NSInteger TLSBoxMaxBufferLength; extern NSString *const TLSBoxPeerVerificationErrorNotification; +extern const NSInteger TLSBoxDefaultSecurityLevel; + // // cipher text is safe within NSData // plain text might be sensitive and must avoid NSData @@ -51,6 +53,8 @@ extern NSString *const TLSBoxPeerVerificationErrorNotification; // @interface TLSBox : NSObject +@property (nonatomic, assign) NSInteger securityLevel; // TLSBoxDefaultSecurityLevel for default + + (nullable NSString *)md5ForCertificatePath:(NSString *)path error:(NSError **)error; + (nullable NSString *)decryptedPrivateKeyFromPath:(NSString *)path passphrase:(NSString *)passphrase error:(NSError **)error; + (nullable NSString *)decryptedPrivateKeyFromPEM:(NSString *)pem passphrase:(NSString *)passphrase error:(NSError **)error; diff --git a/TunnelKit/Sources/Core/TLSBox.m b/TunnelKit/Sources/Core/TLSBox.m index 029a527..3a57596 100644 --- a/TunnelKit/Sources/Core/TLSBox.m +++ b/TunnelKit/Sources/Core/TLSBox.m @@ -62,6 +62,8 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) { return ok; } +const NSInteger TLSBoxDefaultSecurityLevel = -1; + @interface TLSBox () @property (nonatomic, strong) NSString *caPath; @@ -180,6 +182,7 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) { self.clientKeyPath = clientKeyPath; self.checksEKU = checksEKU; self.bufferCipherText = allocate_safely(TLSBoxMaxBufferLength); + self.securityLevel = TLSBoxDefaultSecurityLevel; } return self; } @@ -205,7 +208,9 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) { self.ctx = SSL_CTX_new(TLS_client_method()); SSL_CTX_set_options(self.ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION); SSL_CTX_set_verify(self.ctx, SSL_VERIFY_PEER, TLSBoxVerifyPeer); - SSL_CTX_set_security_level(self.ctx, 0); + if (self.securityLevel != TLSBoxDefaultSecurityLevel) { + SSL_CTX_set_security_level(self.ctx, (int)self.securityLevel); + } if (!SSL_CTX_load_verify_locations(self.ctx, [self.caPath cStringUsingEncoding:NSASCIIStringEncoding], NULL)) { ERR_print_errors_fp(stdout); if (error) { From 3a136bdce9f188499a57dc5f3215e5ad8777ee09 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Wed, 8 May 2019 15:58:29 +0200 Subject: [PATCH 2/3] Make TLS security level an option Default level by default. --- TunnelKit/Sources/Core/SessionProxy+Configuration.swift | 8 ++++++++ TunnelKit/Sources/Core/SessionProxy.swift | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/TunnelKit/Sources/Core/SessionProxy+Configuration.swift b/TunnelKit/Sources/Core/SessionProxy+Configuration.swift index fdade2a..aa0e65b 100644 --- a/TunnelKit/Sources/Core/SessionProxy+Configuration.swift +++ b/TunnelKit/Sources/Core/SessionProxy+Configuration.swift @@ -197,6 +197,9 @@ extension SessionProxy { /// The optional TLS wrapping. public var tlsWrap: SessionProxy.TLSWrap? + /// If set, overrides TLS security level (0 = lowest). + public var tlsSecurityLevel: Int? + /// Sends periodical keep-alive packets if set. public var keepAliveInterval: TimeInterval? @@ -273,6 +276,7 @@ extension SessionProxy { clientCertificate: clientCertificate, clientKey: clientKey, tlsWrap: tlsWrap, + tlsSecurityLevel: tlsSecurityLevel, keepAliveInterval: keepAliveInterval, renegotiatesAfter: renegotiatesAfter, hostname: hostname, @@ -338,6 +342,9 @@ extension SessionProxy { /// - Seealso: `SessionProxy.ConfigurationBuilder.tlsWrap` public let tlsWrap: TLSWrap? + /// - Seealso: `SessionProxy.ConfigurationBuilder.tlsSecurityLevel` + public let tlsSecurityLevel: Int? + /// - Seealso: `SessionProxy.ConfigurationBuilder.keepAliveInterval` public let keepAliveInterval: TimeInterval? @@ -427,6 +434,7 @@ extension SessionProxy.Configuration { builder.clientCertificate = clientCertificate builder.clientKey = clientKey builder.tlsWrap = tlsWrap + builder.tlsSecurityLevel = tlsSecurityLevel builder.keepAliveInterval = keepAliveInterval builder.renegotiatesAfter = renegotiatesAfter builder.hostname = hostname diff --git a/TunnelKit/Sources/Core/SessionProxy.swift b/TunnelKit/Sources/Core/SessionProxy.swift index a655291..b1be4fa 100644 --- a/TunnelKit/Sources/Core/SessionProxy.swift +++ b/TunnelKit/Sources/Core/SessionProxy.swift @@ -792,12 +792,16 @@ public class SessionProxy { log.debug("Start TLS handshake") - negotiationKey.tlsOptional = TLSBox( + let tls = TLSBox( caPath: caURL.path, clientCertificatePath: (configuration.clientCertificate != nil) ? clientCertificateURL.path : nil, clientKeyPath: (configuration.clientKey != nil) ? clientKeyURL.path : nil, checksEKU: configuration.checksEKU ?? false ) + if let tlsSecurityLevel = configuration.tlsSecurityLevel { + tls.securityLevel = tlsSecurityLevel + } + negotiationKey.tlsOptional = tls do { try negotiationKey.tls.start() } catch let e { From ff0dfc450cb0a1349ad7c39ecf04e2b5c20b7af7 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Wed, 8 May 2019 16:02:48 +0200 Subject: [PATCH 3/3] Get TLS security level via AppExtension Improves #97 --- .../TunnelKitProvider+Configuration.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift index 326cde8..3604a78 100644 --- a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift +++ b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift @@ -147,6 +147,7 @@ extension TunnelKitProvider { throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(S.tlsWrap)]") } } + sessionConfigurationBuilder.tlsSecurityLevel = providerConfiguration[S.tlsSecurityLevel] as? Int ?? ConfigurationBuilder.defaults.sessionConfiguration.tlsSecurityLevel sessionConfigurationBuilder.keepAliveInterval = providerConfiguration[S.keepAlive] as? TimeInterval ?? ConfigurationBuilder.defaults.sessionConfiguration.keepAliveInterval sessionConfigurationBuilder.renegotiatesAfter = providerConfiguration[S.renegotiatesAfter] as? TimeInterval ?? ConfigurationBuilder.defaults.sessionConfiguration.renegotiatesAfter guard let endpointProtocolsStrings = providerConfiguration[S.endpointProtocols] as? [String], !endpointProtocolsStrings.isEmpty else { @@ -245,6 +246,8 @@ extension TunnelKitProvider { static let tlsWrap = "TLSWrap" + static let tlsSecurityLevel = "TLSSecurityLevel" + static let keepAlive = "KeepAlive" static let endpointProtocols = "EndpointProtocols" @@ -451,6 +454,9 @@ extension TunnelKitProvider { if let tlsWrapData = sessionConfiguration.tlsWrap?.serialized() { dict[S.tlsWrap] = tlsWrapData } + if let tlsSecurityLevel = sessionConfiguration.tlsSecurityLevel { + dict[S.tlsSecurityLevel] = tlsSecurityLevel + } if let keepAliveSeconds = sessionConfiguration.keepAliveInterval { dict[S.keepAlive] = keepAliveSeconds } @@ -554,6 +560,11 @@ extension TunnelKitProvider { } else { log.info("\tTLS wrapping: disabled") } + if let tlsSecurityLevel = sessionConfiguration.tlsSecurityLevel { + log.info("\tTLS security level: \(tlsSecurityLevel)") + } else { + log.info("\tTLS security level: default") + } if let keepAliveSeconds = sessionConfiguration.keepAliveInterval, keepAliveSeconds > 0 { log.info("\tKeep-alive: \(keepAliveSeconds) seconds") } else {