From f37bfb357967a19c16ecc47a0a757db4140e2431 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Mon, 25 Mar 2019 16:53:38 +0100 Subject: [PATCH] Implement RSA privkey decryption via OpenSSL --- TunnelKit/Sources/Core/TLSBox.h | 2 ++ TunnelKit/Sources/Core/TLSBox.m | 57 +++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/TunnelKit/Sources/Core/TLSBox.h b/TunnelKit/Sources/Core/TLSBox.h index d47e50d..d162e11 100644 --- a/TunnelKit/Sources/Core/TLSBox.h +++ b/TunnelKit/Sources/Core/TLSBox.h @@ -52,6 +52,8 @@ extern NSString *const TLSBoxPeerVerificationErrorNotification; @interface TLSBox : NSObject + (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; - (instancetype)initWithCAPath:(NSString *)caPath clientCertificatePath:(nullable NSString *)clientCertificatePath diff --git a/TunnelKit/Sources/Core/TLSBox.m b/TunnelKit/Sources/Core/TLSBox.m index 274b9d9..9b62356 100644 --- a/TunnelKit/Sources/Core/TLSBox.m +++ b/TunnelKit/Sources/Core/TLSBox.m @@ -39,6 +39,8 @@ #import #import #import +#import +#import #import "TLSBox.h" #import "Allocation.h" @@ -107,6 +109,61 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) { return hex; } ++ (NSString *)decryptedPrivateKeyFromPath:(NSString *)path passphrase:(NSString *)passphrase error:(NSError * _Nullable __autoreleasing *)error +{ + BIO *bio; + if (!(bio = BIO_new_file([path cStringUsingEncoding:NSASCIIStringEncoding], "r"))) { + return NULL; + } + NSString *ret = [[self class] decryptedPrivateKeyFromBIO:bio passphrase:passphrase error:error]; + BIO_free(bio); + return ret; +} + ++ (NSString *)decryptedPrivateKeyFromPEM:(NSString *)pem passphrase:(NSString *)passphrase error:(NSError * _Nullable __autoreleasing *)error +{ + BIO *bio; + if (!(bio = BIO_new_mem_buf([pem cStringUsingEncoding:NSASCIIStringEncoding], (int)[pem length]))) { + return NULL; + } + NSString *ret = [[self class] decryptedPrivateKeyFromBIO:bio passphrase:passphrase error:error]; + BIO_free(bio); + return ret; +} + ++ (NSString *)decryptedPrivateKeyFromBIO:(BIO *)bio passphrase:(NSString *)passphrase error:(NSError * _Nullable __autoreleasing *)error +{ + RSA *rsaKey; + if (!(rsaKey = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, (void *)passphrase.UTF8String))) { + return NULL; + } + + EVP_PKEY *evpKey = EVP_PKEY_new(); + if (!EVP_PKEY_set1_RSA(evpKey, rsaKey)) { + EVP_PKEY_free(evpKey); + return NULL; + } + BIO *output = BIO_new(BIO_s_mem()); + if (!PEM_write_bio_PKCS8PrivateKey(output, evpKey, NULL, NULL, 0, NULL, NULL)) { + BIO_free(output); + EVP_PKEY_free(evpKey); + return NULL; + } + + const int decLength = (int)BIO_ctrl_pending(output); + char *decKeyBytes = malloc(decLength + 1); + if (BIO_read(output, decKeyBytes, decLength) < 0) { + BIO_free(output); + EVP_PKEY_free(evpKey); + return NULL; + } + BIO_free(output); + EVP_PKEY_free(evpKey); + + decKeyBytes[decLength] = '\0'; + return [NSString stringWithCString:decKeyBytes encoding:NSASCIIStringEncoding]; +} + - (instancetype)init { [NSException raise:NSInvalidArgumentException format:@"Use initWithCAPath:clientCertificatePath:clientKeyPath:"];