From 450960eaaf48291182ace6a46e049dbfbbaf4063 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 27 Aug 2018 00:34:34 -0700 Subject: [PATCH] Fix credential storage on tvOS --- Limelight/Crypto/CryptoManager.h | 2 +- Limelight/Crypto/CryptoManager.m | 112 ++++++++++++------ Limelight/Crypto/mkcert.c | 15 --- Limelight/Crypto/mkcert.h | 1 - Limelight/Network/DiscoveryManager.m | 2 +- Limelight/Stream/StreamManager.m | 2 +- .../ViewControllers/MainFrameViewController.m | 2 +- 7 files changed, 77 insertions(+), 59 deletions(-) diff --git a/Limelight/Crypto/CryptoManager.h b/Limelight/Crypto/CryptoManager.h index 30ca57e..6e84804 100644 --- a/Limelight/Crypto/CryptoManager.h +++ b/Limelight/Crypto/CryptoManager.h @@ -8,7 +8,7 @@ @interface CryptoManager : NSObject -+ (void) generateKeyPairUsingSSl; ++ (void) generateKeyPairUsingSSL; + (NSData*) readCertFromFile; + (NSData*) readKeyFromFile; + (NSData*) readP12FromFile; diff --git a/Limelight/Crypto/CryptoManager.m b/Limelight/Crypto/CryptoManager.m index a47ec3d..5e5367e 100644 --- a/Limelight/Crypto/CryptoManager.m +++ b/Limelight/Crypto/CryptoManager.m @@ -159,47 +159,53 @@ static NSData* p12 = nil; return signedData; } -// TODO: these three methods are almost identical, fix the copy-pasta ++ (NSData*) readCryptoObject:(NSString*)item { +#if TARGET_OS_TV + return [[NSUserDefaults standardUserDefaults] dataForKey:item]; +#else + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + NSString *file = [documentsDirectory stringByAppendingPathComponent:item]; + return [NSData dataWithContentsOfFile:file]; +#endif +} + ++ (void) writeCryptoObject:(NSString*)item data:(NSData*)data { +#if TARGET_OS_TV + [[NSUserDefaults standardUserDefaults] setObject:data forKey:item]; +#else + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + NSString *file = [documentsDirectory stringByAppendingPathComponent:item]; + [data writeToFile:file atomically:NO]; +#endif +} + + (NSData*) readCertFromFile { if (cert == nil) { - NSArray *paths = [CryptoManager getPaths]; - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"]; - cert = [NSData dataWithContentsOfFile:certFile]; + cert = [CryptoManager readCryptoObject:@"client.crt"]; } return cert; } + (NSData*) readP12FromFile { if (p12 == nil) { - NSArray *paths = [CryptoManager getPaths]; - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"]; - p12 = [NSData dataWithContentsOfFile:p12File]; + p12 = [CryptoManager readCryptoObject:@"client.p12"]; } return p12; } + (NSData*) readKeyFromFile { if (key == nil) { - NSArray *paths = [CryptoManager getPaths]; - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *keyFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"]; - key = [NSData dataWithContentsOfFile:keyFile]; + key = [CryptoManager readCryptoObject:@"client.key"]; } return key; } + (bool) keyPairExists { - NSArray *paths = [CryptoManager getPaths]; - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *keyFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"]; - NSString *p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"]; - NSString *certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"]; - - bool keyFileExists = [[NSFileManager defaultManager] fileExistsAtPath:keyFile]; - bool p12FileExists = [[NSFileManager defaultManager] fileExistsAtPath:p12File]; - bool certFileExists = [[NSFileManager defaultManager] fileExistsAtPath:certFile]; + bool keyFileExists = [CryptoManager readCryptoObject:@"client.key"] != nil; + bool p12FileExists = [CryptoManager readCryptoObject:@"client.p12"] != nil; + bool certFileExists = [CryptoManager readCryptoObject:@"client.crt"] != nil; return keyFileExists && p12FileExists && certFileExists; } @@ -218,34 +224,62 @@ static NSData* p12 = nil; return [NSData dataWithBytes:x509->signature->data length:x509->signature->length]; } -+ (void) generateKeyPairUsingSSl { ++ (NSData*)getKeyFromCertKeyPair:(CertKeyPair*)certKeyPair { + BIO* bio = BIO_new(BIO_s_mem()); + + PEM_write_bio_PrivateKey(bio, certKeyPair->pkey, NULL, NULL, 0, NULL, NULL); + + BUF_MEM* mem; + BIO_get_mem_ptr(bio, &mem); + NSData* data = [NSData dataWithBytes:mem->data length:mem->length]; + BIO_free(bio); + return data; +} + ++ (NSData*)getP12FromCertKeyPair:(CertKeyPair*)certKeyPair { + BIO* bio = BIO_new(BIO_s_mem()); + + i2d_PKCS12_bio(bio, certKeyPair->p12); + + BUF_MEM* mem; + BIO_get_mem_ptr(bio, &mem); + NSData* data = [NSData dataWithBytes:mem->data length:mem->length]; + BIO_free(bio); + return data; +} + ++ (NSData*)getCertFromCertKeyPair:(CertKeyPair*)certKeyPair { + BIO* bio = BIO_new(BIO_s_mem()); + + PEM_write_bio_X509(bio, certKeyPair->x509); + + BUF_MEM* mem; + BIO_get_mem_ptr(bio, &mem); + NSData* data = [NSData dataWithBytes:mem->data length:mem->length]; + BIO_free(bio); + return data; +} + ++ (void) generateKeyPairUsingSSL { static dispatch_once_t pred; dispatch_once(&pred, ^{ if (![CryptoManager keyPairExists]) { - Log(LOG_I, @"Generating Certificate... "); CertKeyPair certKeyPair = generateCertKeyPair(); - NSArray* paths = [CryptoManager getPaths]; - NSString* documentsDirectory = [paths objectAtIndex:0]; - NSString* certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"]; - NSString* keyPairFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"]; - NSString* p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"]; + NSData* certData = [CryptoManager getCertFromCertKeyPair:&certKeyPair]; + NSData* p12Data = [CryptoManager getP12FromCertKeyPair:&certKeyPair]; + NSData* keyData = [CryptoManager getKeyFromCertKeyPair:&certKeyPair]; - //Log(LOG_D, @"Writing cert and key to: \n%@\n%@", certFile, keyPairFile); - saveCertKeyPair([certFile UTF8String], [p12File UTF8String], [keyPairFile UTF8String], certKeyPair); freeCertKeyPair(certKeyPair); + + [CryptoManager writeCryptoObject:@"client.crt" data:certData]; + [CryptoManager writeCryptoObject:@"client.p12" data:p12Data]; + [CryptoManager writeCryptoObject:@"client.key" data:keyData]; + Log(LOG_I, @"Certificate created"); } }); } -+ (NSArray*) getPaths { -#if TARGET_OS_TV - return NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); -#else - return NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); -#endif -} - @end diff --git a/Limelight/Crypto/mkcert.c b/Limelight/Crypto/mkcert.c index d6beb64..c283fc1 100644 --- a/Limelight/Crypto/mkcert.c +++ b/Limelight/Crypto/mkcert.c @@ -62,21 +62,6 @@ void freeCertKeyPair(struct CertKeyPair certKeyPair) { PKCS12_free(certKeyPair.p12); } -void saveCertKeyPair(const char* certFile, const char* p12File, const char* keyPairFile, CertKeyPair certKeyPair) { - FILE* certFilePtr = fopen(certFile, "w"); - FILE* keyPairFilePtr = fopen(keyPairFile, "w"); - FILE* p12FilePtr = fopen(p12File, "wb"); - - //TODO: error check - PEM_write_PrivateKey(keyPairFilePtr, certKeyPair.pkey, NULL, NULL, 0, NULL, NULL); - PEM_write_X509(certFilePtr, certKeyPair.x509); - i2d_PKCS12_fp(p12FilePtr, certKeyPair.p12); - - fclose(p12FilePtr); - fclose(certFilePtr); - fclose(keyPairFilePtr); -} - int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) { X509 *x; EVP_PKEY *pk; diff --git a/Limelight/Crypto/mkcert.h b/Limelight/Crypto/mkcert.h index 1e3aba3..f3c62f8 100644 --- a/Limelight/Crypto/mkcert.h +++ b/Limelight/Crypto/mkcert.h @@ -20,6 +20,5 @@ typedef struct CertKeyPair { struct CertKeyPair generateCertKeyPair(void); void freeCertKeyPair(CertKeyPair); -void saveCertKeyPair(const char* certFile, const char* p12File, const char* keyPairFile, CertKeyPair certKeyPair); #endif diff --git a/Limelight/Network/DiscoveryManager.m b/Limelight/Network/DiscoveryManager.m index 08dd1fc..0652034 100644 --- a/Limelight/Network/DiscoveryManager.m +++ b/Limelight/Network/DiscoveryManager.m @@ -41,7 +41,7 @@ _opQueue = [[NSOperationQueue alloc] init]; _mdnsMan = [[MDNSManager alloc] initWithCallback:self]; - [CryptoManager generateKeyPairUsingSSl]; + [CryptoManager generateKeyPairUsingSSL]; _uniqueId = [IdManager getUniqueId]; _cert = [CryptoManager readCertFromFile]; return self; diff --git a/Limelight/Stream/StreamManager.m b/Limelight/Stream/StreamManager.m index 59d71f9..b28a45d 100644 --- a/Limelight/Stream/StreamManager.m +++ b/Limelight/Stream/StreamManager.m @@ -36,7 +36,7 @@ } - (void)main { - [CryptoManager generateKeyPairUsingSSl]; + [CryptoManager generateKeyPairUsingSSL]; NSString* uniqueId = [IdManager getUniqueId]; NSData* cert = [CryptoManager readCertFromFile]; diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m index 2f443ff..572736b 100644 --- a/Limelight/ViewControllers/MainFrameViewController.m +++ b/Limelight/ViewControllers/MainFrameViewController.m @@ -704,7 +704,7 @@ static NSMutableSet* hostList; currentPosition = FrontViewPositionLeft; // Set up crypto - [CryptoManager generateKeyPairUsingSSl]; + [CryptoManager generateKeyPairUsingSSL]; _uniqueId = [IdManager getUniqueId]; _cert = [CryptoManager readCertFromFile];