Replace OpenSSL with BoringSSL from SwiftNIO SSL
- Raise iOS target to 13 - Drop support for TLS security level - Address warnings about integer conversion (iOS)
This commit is contained in:
parent
50064fc3d0
commit
bc776eda85
|
@ -5,11 +5,13 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## 4.0.0 (2021-11-05)
|
## Unreleased
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Migrate to SwiftPM. [#210](https://github.com/passepartoutvpn/tunnelkit/issues/210)
|
- Migrate to SwiftPM. [#210](https://github.com/passepartoutvpn/tunnelkit/issues/210)
|
||||||
|
- Replace OpenSSL with BoringSSL from SwiftNIO SSL.
|
||||||
|
- Drop support for TLS security level (not present in BoringSSL).
|
||||||
|
|
||||||
## 3.5.0 (2021-10-18)
|
## 3.5.0 (2021-10-18)
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,21 @@
|
||||||
"object": {
|
"object": {
|
||||||
"pins": [
|
"pins": [
|
||||||
{
|
{
|
||||||
"package": "openssl-apple",
|
"package": "swift-nio",
|
||||||
"repositoryURL": "https://github.com/keeshux/openssl-apple",
|
"repositoryURL": "https://github.com/apple/swift-nio.git",
|
||||||
"state": {
|
"state": {
|
||||||
"branch": null,
|
"branch": null,
|
||||||
"revision": "37043e7c92c9fb348d1d668b0402148c9fa9873c",
|
"revision": "addf69cfe60376c325397c8926589415576b1dd1",
|
||||||
"version": "1.1.112"
|
"version": "2.34.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "swift-nio-ssl",
|
||||||
|
"repositoryURL": "https://github.com/apple/swift-nio-ssl",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "08e701df9a3b9108c56f1aef5d9ef9a78fda2846",
|
||||||
|
"version": "2.16.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@ import PackageDescription
|
||||||
let package = Package(
|
let package = Package(
|
||||||
name: "TunnelKit",
|
name: "TunnelKit",
|
||||||
platforms: [
|
platforms: [
|
||||||
.macOS(.v10_15), .iOS(.v12)
|
.macOS(.v10_15), .iOS(.v13)
|
||||||
],
|
],
|
||||||
products: [
|
products: [
|
||||||
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
||||||
|
@ -35,7 +35,7 @@ let package = Package(
|
||||||
// Dependencies declare other packages that this package depends on.
|
// Dependencies declare other packages that this package depends on.
|
||||||
// .package(url: /* package url */, from: "1.0.0"),
|
// .package(url: /* package url */, from: "1.0.0"),
|
||||||
.package(url: "https://github.com/SwiftyBeaver/SwiftyBeaver", from: "1.9.0"),
|
.package(url: "https://github.com/SwiftyBeaver/SwiftyBeaver", from: "1.9.0"),
|
||||||
.package(url: "https://github.com/keeshux/openssl-apple", from: "1.1.100")
|
.package(url: "https://github.com/apple/swift-nio-ssl", from: "2.0.0")
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||||
|
@ -126,7 +126,7 @@ let package = Package(
|
||||||
dependencies: [
|
dependencies: [
|
||||||
"CTunnelKitCore",
|
"CTunnelKitCore",
|
||||||
"CTunnelKitOpenVPNCore",
|
"CTunnelKitOpenVPNCore",
|
||||||
"openssl-apple"
|
.product(name: "NIOSSL", package: "swift-nio-ssl")
|
||||||
]),
|
]),
|
||||||
.target(
|
.target(
|
||||||
name: "__TunnelKitUtils",
|
name: "__TunnelKitUtils",
|
||||||
|
|
|
@ -34,9 +34,7 @@
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <openssl/evp.h>
|
@import CNIOBoringSSL;
|
||||||
#import <openssl/hmac.h>
|
|
||||||
#import <openssl/rand.h>
|
|
||||||
|
|
||||||
#import "CryptoAEAD.h"
|
#import "CryptoAEAD.h"
|
||||||
#import "CryptoMacros.h"
|
#import "CryptoMacros.h"
|
||||||
|
@ -136,7 +134,7 @@ static const NSInteger CryptoAEADTagLength = 16;
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherInit(self.cipherCtxEnc, NULL, NULL, self.cipherIVEnc, -1);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherInit(self.cipherCtxEnc, NULL, NULL, self.cipherIVEnc, -1);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxEnc, NULL, &x, flags->ad, (int)flags->adLength);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxEnc, NULL, &x, flags->ad, (int)flags->adLength);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxEnc, dest + CryptoAEADTagLength, &l1, bytes, (int)length);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxEnc, dest + CryptoAEADTagLength, &l1, bytes, (int)length);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal(self.cipherCtxEnc, dest + CryptoAEADTagLength + l1, &l2);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal_ex(self.cipherCtxEnc, dest + CryptoAEADTagLength + l1, &l2);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CIPHER_CTX_ctrl(self.cipherCtxEnc, EVP_CTRL_GCM_GET_TAG, CryptoAEADTagLength, dest);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CIPHER_CTX_ctrl(self.cipherCtxEnc, EVP_CTRL_GCM_GET_TAG, CryptoAEADTagLength, dest);
|
||||||
|
|
||||||
*destLength = CryptoAEADTagLength + l1 + l2;
|
*destLength = CryptoAEADTagLength + l1 + l2;
|
||||||
|
@ -183,7 +181,7 @@ static const NSInteger CryptoAEADTagLength = 16;
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CIPHER_CTX_ctrl(self.cipherCtxDec, EVP_CTRL_GCM_SET_TAG, CryptoAEADTagLength, (uint8_t *)bytes);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CIPHER_CTX_ctrl(self.cipherCtxDec, EVP_CTRL_GCM_SET_TAG, CryptoAEADTagLength, (uint8_t *)bytes);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxDec, NULL, &x, flags->ad, (int)flags->adLength);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxDec, NULL, &x, flags->ad, (int)flags->adLength);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxDec, dest, &l1, bytes + CryptoAEADTagLength, (int)length - CryptoAEADTagLength);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxDec, dest, &l1, bytes + CryptoAEADTagLength, (int)length - CryptoAEADTagLength);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal(self.cipherCtxDec, dest + l1, &l2);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal_ex(self.cipherCtxDec, dest + l1, &l2);
|
||||||
|
|
||||||
*destLength = l1 + l2;
|
*destLength = l1 + l2;
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,7 @@
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <openssl/evp.h>
|
@import CNIOBoringSSL;
|
||||||
#import <openssl/hmac.h>
|
|
||||||
#import <openssl/rand.h>
|
|
||||||
|
|
||||||
#import "CryptoBox.h"
|
#import "CryptoBox.h"
|
||||||
#import "CryptoMacros.h"
|
#import "CryptoMacros.h"
|
||||||
|
@ -170,7 +168,7 @@
|
||||||
int code = 1;
|
int code = 1;
|
||||||
|
|
||||||
HMAC_CTX *ctx = HMAC_CTX_new();
|
HMAC_CTX *ctx = HMAC_CTX_new();
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) HMAC_CTX_reset(ctx);
|
HMAC_CTX_reset(ctx);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) HMAC_Init_ex(ctx, secret, (int)secretLength, EVP_get_digestbyname([digestName cStringUsingEncoding:NSASCIIStringEncoding]), NULL);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) HMAC_Init_ex(ctx, secret, (int)secretLength, EVP_get_digestbyname([digestName cStringUsingEncoding:NSASCIIStringEncoding]), NULL);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) HMAC_Update(ctx, data, dataLength);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) HMAC_Update(ctx, data, dataLength);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) HMAC_Final(ctx, hmac, &l);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) HMAC_Final(ctx, hmac, &l);
|
||||||
|
|
|
@ -34,9 +34,7 @@
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <openssl/evp.h>
|
@import CNIOBoringSSL;
|
||||||
#import <openssl/hmac.h>
|
|
||||||
#import <openssl/rand.h>
|
|
||||||
|
|
||||||
#import "CryptoCBC.h"
|
#import "CryptoCBC.h"
|
||||||
#import "CryptoMacros.h"
|
#import "CryptoMacros.h"
|
||||||
|
@ -85,8 +83,8 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
|
||||||
self.cipherIVLength = EVP_CIPHER_iv_length(self.cipher);
|
self.cipherIVLength = EVP_CIPHER_iv_length(self.cipher);
|
||||||
}
|
}
|
||||||
// as seen in OpenVPN's crypto_openssl.c:md_kt_size()
|
// as seen in OpenVPN's crypto_openssl.c:md_kt_size()
|
||||||
self.hmacKeyLength = EVP_MD_size(self.digest);
|
self.hmacKeyLength = (int)EVP_MD_size(self.digest);
|
||||||
self.digestLength = EVP_MD_size(self.digest);
|
self.digestLength = (int)EVP_MD_size(self.digest);
|
||||||
|
|
||||||
if (cipherName) {
|
if (cipherName) {
|
||||||
self.cipherCtxEnc = EVP_CIPHER_CTX_new();
|
self.cipherCtxEnc = EVP_CIPHER_CTX_new();
|
||||||
|
@ -160,7 +158,7 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
|
||||||
|
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherInit(self.cipherCtxEnc, NULL, NULL, outIV, -1);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherInit(self.cipherCtxEnc, NULL, NULL, outIV, -1);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxEnc, outEncrypted, &l1, bytes, (int)length);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxEnc, outEncrypted, &l1, bytes, (int)length);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal(self.cipherCtxEnc, outEncrypted + l1, &l2);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal_ex(self.cipherCtxEnc, outEncrypted + l1, &l2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
NSAssert(outEncrypted == outIV, @"cipherIVLength is non-zero");
|
NSAssert(outEncrypted == outIV, @"cipherIVLength is non-zero");
|
||||||
|
@ -223,7 +221,7 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
|
||||||
|
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherInit(self.cipherCtxDec, NULL, NULL, iv, -1);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherInit(self.cipherCtxDec, NULL, NULL, iv, -1);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxDec, dest, &l1, encrypted, (int)length - self.digestLength - self.cipherIVLength);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxDec, dest, &l1, encrypted, (int)length - self.digestLength - self.cipherIVLength);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal(self.cipherCtxDec, dest + l1, &l2);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal_ex(self.cipherCtxDec, dest + l1, &l2);
|
||||||
|
|
||||||
*destLength = l1 + l2;
|
*destLength = l1 + l2;
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,7 @@
|
||||||
// along with TunnelKit. If not, see <http://www.gnu.org/licenses/>.
|
// along with TunnelKit. If not, see <http://www.gnu.org/licenses/>.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <openssl/evp.h>
|
@import CNIOBoringSSL;
|
||||||
#import <openssl/hmac.h>
|
|
||||||
#import <openssl/rand.h>
|
|
||||||
|
|
||||||
#import "CryptoCTR.h"
|
#import "CryptoCTR.h"
|
||||||
#import "CryptoMacros.h"
|
#import "CryptoMacros.h"
|
||||||
|
@ -69,7 +67,7 @@ static const NSInteger CryptoCTRTagLength = 32;
|
||||||
self.cipherKeyLength = EVP_CIPHER_key_length(self.cipher);
|
self.cipherKeyLength = EVP_CIPHER_key_length(self.cipher);
|
||||||
self.cipherIVLength = EVP_CIPHER_iv_length(self.cipher);
|
self.cipherIVLength = EVP_CIPHER_iv_length(self.cipher);
|
||||||
// as seen in OpenVPN's crypto_openssl.c:md_kt_size()
|
// as seen in OpenVPN's crypto_openssl.c:md_kt_size()
|
||||||
self.hmacKeyLength = EVP_MD_size(self.digest);
|
self.hmacKeyLength = (int)EVP_MD_size(self.digest);
|
||||||
NSAssert(EVP_MD_size(self.digest) == CryptoCTRTagLength, @"Expected digest size to be tag length (%ld)", CryptoCTRTagLength);
|
NSAssert(EVP_MD_size(self.digest) == CryptoCTRTagLength, @"Expected digest size to be tag length (%ld)", CryptoCTRTagLength);
|
||||||
|
|
||||||
self.cipherCtxEnc = EVP_CIPHER_CTX_new();
|
self.cipherCtxEnc = EVP_CIPHER_CTX_new();
|
||||||
|
@ -142,7 +140,7 @@ static const NSInteger CryptoCTRTagLength = 32;
|
||||||
|
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherInit(self.cipherCtxEnc, NULL, NULL, dest, -1);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherInit(self.cipherCtxEnc, NULL, NULL, dest, -1);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxEnc, outEncrypted, &l1, bytes, (int)length);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxEnc, outEncrypted, &l1, bytes, (int)length);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal(self.cipherCtxEnc, outEncrypted + l1, &l2);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal_ex(self.cipherCtxEnc, outEncrypted + l1, &l2);
|
||||||
|
|
||||||
*destLength = CryptoCTRTagLength + l1 + l2;
|
*destLength = CryptoCTRTagLength + l1 + l2;
|
||||||
|
|
||||||
|
@ -183,7 +181,7 @@ static const NSInteger CryptoCTRTagLength = 32;
|
||||||
|
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherInit(self.cipherCtxDec, NULL, NULL, iv, -1);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherInit(self.cipherCtxDec, NULL, NULL, iv, -1);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxDec, dest, &l1, encrypted, (int)length - CryptoCTRTagLength);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxDec, dest, &l1, encrypted, (int)length - CryptoCTRTagLength);
|
||||||
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal(self.cipherCtxDec, dest + l1, &l2);
|
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal_ex(self.cipherCtxDec, dest + l1, &l2);
|
||||||
|
|
||||||
*destLength = l1 + l2;
|
*destLength = l1 + l2;
|
||||||
|
|
||||||
|
|
|
@ -34,12 +34,7 @@
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <openssl/ssl.h>
|
@import CNIOBoringSSL;
|
||||||
#import <openssl/err.h>
|
|
||||||
#import <openssl/evp.h>
|
|
||||||
#import <openssl/x509v3.h>
|
|
||||||
#import <openssl/rsa.h>
|
|
||||||
#import <openssl/pem.h>
|
|
||||||
|
|
||||||
#import "TLSBox.h"
|
#import "TLSBox.h"
|
||||||
#import "Allocation.h"
|
#import "Allocation.h"
|
||||||
|
@ -61,8 +56,6 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) {
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NSInteger TLSBoxDefaultSecurityLevel = -1;
|
|
||||||
|
|
||||||
@interface TLSBox ()
|
@interface TLSBox ()
|
||||||
|
|
||||||
@property (nonatomic, strong) NSString *caPEM;
|
@property (nonatomic, strong) NSString *caPEM;
|
||||||
|
@ -215,7 +208,6 @@ static BIO *create_BIO_from_PEM(NSString *pem) {
|
||||||
self.checksEKU = checksEKU;
|
self.checksEKU = checksEKU;
|
||||||
self.checksSANHost = checksSANHost;
|
self.checksSANHost = checksSANHost;
|
||||||
self.bufferCipherText = allocate_safely(TLSBoxMaxBufferLength);
|
self.bufferCipherText = allocate_safely(TLSBoxMaxBufferLength);
|
||||||
self.securityLevel = TLSBoxDefaultSecurityLevel;
|
|
||||||
self.hostname = hostname;
|
self.hostname = hostname;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
@ -242,9 +234,6 @@ static BIO *create_BIO_from_PEM(NSString *pem) {
|
||||||
self.ctx = SSL_CTX_new(TLS_client_method());
|
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_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_verify(self.ctx, SSL_VERIFY_PEER, TLSBoxVerifyPeer);
|
||||||
if (self.securityLevel != TLSBoxDefaultSecurityLevel) {
|
|
||||||
SSL_CTX_set_security_level(self.ctx, (int)self.securityLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.caPEM) {
|
if (self.caPEM) {
|
||||||
BIO *bio = create_BIO_from_PEM(self.caPEM);
|
BIO *bio = create_BIO_from_PEM(self.caPEM);
|
||||||
|
@ -436,7 +425,7 @@ static BIO *create_BIO_from_PEM(NSString *pem) {
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
const int num = sk_ASN1_OBJECT_num(eku);
|
const int num = (int)sk_ASN1_OBJECT_num(eku);
|
||||||
char buffer[100];
|
char buffer[100];
|
||||||
BOOL isValid = NO;
|
BOOL isValid = NO;
|
||||||
|
|
||||||
|
@ -457,7 +446,8 @@ static BIO *create_BIO_from_PEM(NSString *pem) {
|
||||||
|
|
||||||
#pragma mark SAN
|
#pragma mark SAN
|
||||||
|
|
||||||
- (BOOL)verifySANHostWithSSL:(SSL *)ssl {
|
- (BOOL)verifySANHostWithSSL:(SSL *)ssl
|
||||||
|
{
|
||||||
X509 *cert = SSL_get_peer_certificate(self.ssl);
|
X509 *cert = SSL_get_peer_certificate(self.ssl);
|
||||||
if (!cert) {
|
if (!cert) {
|
||||||
return NO;
|
return NO;
|
||||||
|
@ -465,43 +455,43 @@ static BIO *create_BIO_from_PEM(NSString *pem) {
|
||||||
|
|
||||||
GENERAL_NAMES* names = NULL;
|
GENERAL_NAMES* names = NULL;
|
||||||
unsigned char* utf8 = NULL;
|
unsigned char* utf8 = NULL;
|
||||||
names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0 );
|
names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
|
||||||
if(!names) {
|
if (!names) {
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0, count = sk_GENERAL_NAME_num(names);
|
int i = 0, count = (int)sk_GENERAL_NAME_num(names);
|
||||||
if(!count) {
|
if (!count) {
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
GENERAL_NAMES_free(names);
|
GENERAL_NAMES_free(names);
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
BOOL isValid = NO;
|
BOOL isValid = NO;
|
||||||
|
|
||||||
for( i = 0; i < count; ++i ) {
|
for (i = 0; i < count; ++i) {
|
||||||
GENERAL_NAME* entry = sk_GENERAL_NAME_value(names, i);
|
GENERAL_NAME* entry = sk_GENERAL_NAME_value(names, i);
|
||||||
if(!entry) {
|
if (!entry) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(GEN_DNS != entry->type) {
|
if (GEN_DNS != entry->type) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int len1 = 0, len2 = -1;
|
int len1 = 0, len2 = -1;
|
||||||
len1 = ASN1_STRING_to_UTF8(&utf8, entry->d.dNSName);
|
len1 = ASN1_STRING_to_UTF8(&utf8, entry->d.dNSName);
|
||||||
if(!utf8) {
|
if (!utf8) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
len2 = (int)strlen((const char*)utf8);
|
len2 = (int)strlen((const char *)utf8);
|
||||||
|
|
||||||
if(len1 != len2) {
|
if (len1 != len2) {
|
||||||
OPENSSL_free(utf8);
|
OPENSSL_free(utf8);
|
||||||
utf8 = NULL;
|
utf8 = NULL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(utf8 && len1 && len2 && (len1 == len2) && strcmp((const char *)utf8, self.hostname.UTF8String) == 0) {
|
if (utf8 && len1 && len2 && (len1 == len2) && strcmp((const char *)utf8, self.hostname.UTF8String) == 0) {
|
||||||
isValid = YES;
|
isValid = YES;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -512,10 +502,10 @@ static BIO *create_BIO_from_PEM(NSString *pem) {
|
||||||
|
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
|
|
||||||
if(names) {
|
if (names) {
|
||||||
GENERAL_NAMES_free(names);
|
GENERAL_NAMES_free(names);
|
||||||
}
|
}
|
||||||
if(utf8) {
|
if (utf8) {
|
||||||
OPENSSL_free(utf8);
|
OPENSSL_free(utf8);
|
||||||
}
|
}
|
||||||
return isValid;
|
return isValid;
|
||||||
|
|
|
@ -42,8 +42,6 @@ extern const NSInteger TLSBoxMaxBufferLength;
|
||||||
|
|
||||||
extern NSString *const TLSBoxPeerVerificationErrorNotification;
|
extern NSString *const TLSBoxPeerVerificationErrorNotification;
|
||||||
|
|
||||||
extern const NSInteger TLSBoxDefaultSecurityLevel;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// cipher text is safe within NSData
|
// cipher text is safe within NSData
|
||||||
// plain text might be sensitive and must avoid NSData
|
// plain text might be sensitive and must avoid NSData
|
||||||
|
@ -52,8 +50,6 @@ extern const NSInteger TLSBoxDefaultSecurityLevel;
|
||||||
//
|
//
|
||||||
@interface TLSBox : NSObject
|
@interface TLSBox : NSObject
|
||||||
|
|
||||||
@property (nonatomic, assign) NSInteger securityLevel; // TLSBoxDefaultSecurityLevel for default
|
|
||||||
|
|
||||||
+ (nullable NSString *)md5ForCertificatePath:(NSString *)path error:(NSError **)error;
|
+ (nullable NSString *)md5ForCertificatePath:(NSString *)path error:(NSError **)error;
|
||||||
+ (nullable NSString *)md5ForCertificatePEM:(NSString *)pem error:(NSError **)error;
|
+ (nullable NSString *)md5ForCertificatePEM:(NSString *)pem error:(NSError **)error;
|
||||||
+ (nullable NSString *)decryptedPrivateKeyFromPath:(NSString *)path passphrase:(NSString *)passphrase error:(NSError **)error;
|
+ (nullable NSString *)decryptedPrivateKeyFromPath:(NSString *)path passphrase:(NSString *)passphrase error:(NSError **)error;
|
||||||
|
|
|
@ -205,9 +205,6 @@ extension OpenVPN {
|
||||||
/// The optional TLS wrapping.
|
/// The optional TLS wrapping.
|
||||||
public var tlsWrap: TLSWrap?
|
public var tlsWrap: TLSWrap?
|
||||||
|
|
||||||
/// If set, overrides TLS security level (0 = lowest).
|
|
||||||
public var tlsSecurityLevel: Int?
|
|
||||||
|
|
||||||
/// Sends periodical keep-alive packets if set.
|
/// Sends periodical keep-alive packets if set.
|
||||||
public var keepAliveInterval: TimeInterval?
|
public var keepAliveInterval: TimeInterval?
|
||||||
|
|
||||||
|
@ -324,7 +321,6 @@ extension OpenVPN {
|
||||||
clientCertificate: clientCertificate,
|
clientCertificate: clientCertificate,
|
||||||
clientKey: clientKey,
|
clientKey: clientKey,
|
||||||
tlsWrap: tlsWrap,
|
tlsWrap: tlsWrap,
|
||||||
tlsSecurityLevel: tlsSecurityLevel,
|
|
||||||
keepAliveInterval: keepAliveInterval,
|
keepAliveInterval: keepAliveInterval,
|
||||||
keepAliveTimeout: keepAliveTimeout,
|
keepAliveTimeout: keepAliveTimeout,
|
||||||
renegotiatesAfter: renegotiatesAfter,
|
renegotiatesAfter: renegotiatesAfter,
|
||||||
|
@ -407,9 +403,6 @@ extension OpenVPN {
|
||||||
/// - Seealso: `ConfigurationBuilder.tlsWrap`
|
/// - Seealso: `ConfigurationBuilder.tlsWrap`
|
||||||
public let tlsWrap: TLSWrap?
|
public let tlsWrap: TLSWrap?
|
||||||
|
|
||||||
/// - Seealso: `ConfigurationBuilder.tlsSecurityLevel`
|
|
||||||
public let tlsSecurityLevel: Int?
|
|
||||||
|
|
||||||
/// - Seealso: `ConfigurationBuilder.keepAliveInterval`
|
/// - Seealso: `ConfigurationBuilder.keepAliveInterval`
|
||||||
public let keepAliveInterval: TimeInterval?
|
public let keepAliveInterval: TimeInterval?
|
||||||
|
|
||||||
|
@ -527,7 +520,6 @@ extension OpenVPN.Configuration {
|
||||||
builder.clientCertificate = clientCertificate
|
builder.clientCertificate = clientCertificate
|
||||||
builder.clientKey = clientKey
|
builder.clientKey = clientKey
|
||||||
builder.tlsWrap = tlsWrap
|
builder.tlsWrap = tlsWrap
|
||||||
builder.tlsSecurityLevel = tlsSecurityLevel
|
|
||||||
builder.keepAliveInterval = keepAliveInterval
|
builder.keepAliveInterval = keepAliveInterval
|
||||||
builder.keepAliveTimeout = keepAliveTimeout
|
builder.keepAliveTimeout = keepAliveTimeout
|
||||||
builder.renegotiatesAfter = renegotiatesAfter
|
builder.renegotiatesAfter = renegotiatesAfter
|
||||||
|
@ -586,11 +578,6 @@ extension OpenVPN.Configuration {
|
||||||
} else {
|
} else {
|
||||||
log.info("\tTLS wrapping: disabled")
|
log.info("\tTLS wrapping: disabled")
|
||||||
}
|
}
|
||||||
if let tlsSecurityLevel = tlsSecurityLevel {
|
|
||||||
log.info("\tTLS security level: \(tlsSecurityLevel)")
|
|
||||||
} else {
|
|
||||||
log.info("\tTLS security level: default")
|
|
||||||
}
|
|
||||||
if let keepAliveSeconds = keepAliveInterval, keepAliveSeconds > 0 {
|
if let keepAliveSeconds = keepAliveInterval, keepAliveSeconds > 0 {
|
||||||
log.info("\tKeep-alive interval: \(keepAliveSeconds.asTimeString)")
|
log.info("\tKeep-alive interval: \(keepAliveSeconds.asTimeString)")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -759,9 +759,6 @@ public class OpenVPNSession: Session {
|
||||||
checksSANHost: configuration.checksSANHost ?? false,
|
checksSANHost: configuration.checksSANHost ?? false,
|
||||||
hostname: configuration.sanHost
|
hostname: configuration.sanHost
|
||||||
)
|
)
|
||||||
if let tlsSecurityLevel = configuration.tlsSecurityLevel {
|
|
||||||
tls.securityLevel = tlsSecurityLevel
|
|
||||||
}
|
|
||||||
negotiationKey.tlsOptional = tls
|
negotiationKey.tlsOptional = tls
|
||||||
do {
|
do {
|
||||||
try negotiationKey.tls.start()
|
try negotiationKey.tls.start()
|
||||||
|
|
Loading…
Reference in New Issue