diff --git a/Limelight/CryptoManager.h b/Limelight/CryptoManager.h index 85b1757..73f5195 100644 --- a/Limelight/CryptoManager.h +++ b/Limelight/CryptoManager.h @@ -8,10 +8,11 @@ #import -@interface CryptoManager : NSObject - -- (void) generateKeyPairUsingSSl; -- (NSString*) getUniqueID; -- (NSData*) readCertFromFile; +@interface CryptoManager : NSObject ++ (void) generateKeyPairUsingSSl; ++ (NSString*) getUniqueID; ++ (NSData*) readCertFromFile; ++ (NSData*) readKeyFromFile; ++ (NSData*) readP12FromFile; @end diff --git a/Limelight/CryptoManager.m b/Limelight/CryptoManager.m index 663d9c6..5adc135 100644 --- a/Limelight/CryptoManager.m +++ b/Limelight/CryptoManager.m @@ -12,33 +12,44 @@ @implementation CryptoManager -- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { - - -} - -- (NSData*) readCertFromFile { +// TODO: these three methods are almost identical, fix the copy-pasta ++ (NSData*) readCertFromFile { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"]; return [NSData dataWithContentsOfFile:certFile]; } -- (void) generateKeyPairUsingSSl { - NSLog(@"Generating Certificate: "); - CertKeyPair certKeyPair = generateCertKeyPair(); - ++ (NSData*) readP12FromFile { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"]; - NSString *keyPairFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"]; + NSString *p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"]; + return [NSData dataWithContentsOfFile:p12File]; +} + ++ (NSData*) readKeyFromFile { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + NSString *keyFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"]; + return [NSData dataWithContentsOfFile:keyFile]; +} + ++ (void) generateKeyPairUsingSSl { + NSLog(@"Generating Certificate... "); + CertKeyPair certKeyPair = generateCertKeyPair(); - NSLog(@"Writing cert and key to: \n%@\n%@", certFile, keyPairFile); - saveCertKeyPair([certFile UTF8String], [keyPairFile UTF8String], certKeyPair); + NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString* documentsDirectory = [paths objectAtIndex:0]; + NSString* certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"]; + NSString* keyPairFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"]; + NSString* p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"]; + + //NSLog(@"Writing cert and key to: \n%@\n%@", certFile, keyPairFile); + saveCertKeyPair([certFile UTF8String], [p12File UTF8String], [keyPairFile UTF8String], certKeyPair); freeCertKeyPair(certKeyPair); } -- (NSString*) getUniqueID { ++ (NSString*) getUniqueID { // generate a UUID NSUUID* uuid = [ASIdentifierManager sharedManager].advertisingIdentifier; NSString* idString = [NSString stringWithString:[uuid UUIDString]]; diff --git a/Limelight/HttpManager.h b/Limelight/HttpManager.h index 2d6aa20..dec7757 100644 --- a/Limelight/HttpManager.h +++ b/Limelight/HttpManager.h @@ -8,9 +8,9 @@ #import -@interface HttpManager : NSObject -- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId deviceName:(NSString*) deviceName; +@interface HttpManager : NSObject +- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId deviceName:(NSString*) deviceName cert:(NSData*) cert; - (NSString*) generatePIN; - (NSData*) saltPIN:(NSString*)PIN; -- (NSURL*) newPairRequestWithSalt:(NSData*)salt andCert:(NSData*)cert; +- (NSURL*) newPairRequest; @end diff --git a/Limelight/HttpManager.m b/Limelight/HttpManager.m index 934c105..0551d96 100644 --- a/Limelight/HttpManager.m +++ b/Limelight/HttpManager.m @@ -7,32 +7,36 @@ // #import "HttpManager.h" +#import "CryptoManager.h" @implementation HttpManager { NSString* _baseURL; NSString* _host; NSString* _uniqueId; NSString* _deviceName; + NSData* _salt; + NSData* _cert; } static const NSString* PORT = @"47984"; -- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId deviceName:(NSString*) deviceName { +- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId deviceName:(NSString*) deviceName cert:(NSData*) cert { self = [super init]; _host = host; _uniqueId = uniqueId; _deviceName = deviceName; + _cert = cert; _baseURL = [[NSString stringWithFormat:@"https://%@:%@", host, PORT] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; return self; } -- (NSURL*) newPairRequestWithSalt:(NSData*)salt andCert:(NSData*)cert { - NSLog(@"host: %@ \nport: %@ \nuniqueID: %@ \ndeviceName: %@ \nsalt: %@ \ncert: %@", _host, PORT, _uniqueId, _deviceName, salt, cert); - NSString* urlString = [[NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=getservercert&salt=%@&clientcert=%@", _baseURL, _uniqueId, _deviceName, [self bytesToHex:salt], [self bytesToHex:cert]] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; +- (NSURL*) newPairRequest { + //NSLog(@"host: %@ \nport: %@ \nuniqueID: %@ \ndeviceName: %@ \nsalt: %@ \ncert: %@", _host, PORT, _uniqueId, _deviceName, salt, cert); + NSString* urlString = [[NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=getservercert&salt=%@&clientcert=%@", _baseURL, _uniqueId, _deviceName, [self bytesToHex:_salt], [self bytesToHex:_cert]] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL* url = [[NSURL alloc] initWithString:urlString]; - NSLog(@"pair url: %@", url); + //NSLog(@"pair url: %@", url); return url; } @@ -58,8 +62,8 @@ static const NSString* PORT = @"47984"; [saltedPIN appendData:[self randomBytes:16]]; [saltedPIN appendBytes:[PIN UTF8String] length:4]; - NSLog(@"Salted PIN: %@", [saltedPIN description]); - + //NSLog(@"Salted PIN: %@", [saltedPIN description]); + _salt = saltedPIN; return saltedPIN; } @@ -71,4 +75,77 @@ static const NSString* PORT = @"47984"; return randomData; } +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { + NSLog(@"Received response: %@", response); +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + NSLog(@"Received data: %@", data); +} + +- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { + SecIdentityRef identity = [self getClientCertificate]; // Go get a SecIdentityRef + CFArrayRef certs = [self getCertificate:identity]; // Get an array of certificates + // Convert the CFArrayRef to a NSArray + NSArray *myArray = (__bridge NSArray *)certs; + + // Create the NSURLCredential + NSURLCredential *newCredential = [NSURLCredential credentialWithIdentity:identity certificates:myArray persistence:NSURLCredentialPersistencePermanent]; + + // Send + [challenge.sender useCredential:newCredential forAuthenticationChallenge:challenge]; +} + +// Returns an array containing the certificate +- (CFArrayRef)getCertificate:(SecIdentityRef) identity { + SecCertificateRef certificate = nil; + + SecIdentityCopyCertificate(identity, &certificate); + SecCertificateRef certs[1] = { certificate }; + + CFArrayRef array = CFArrayCreate(NULL, (const void **) certs, 1, NULL); + + SecPolicyRef myPolicy = SecPolicyCreateBasicX509(); + SecTrustRef myTrust; + + OSStatus status = SecTrustCreateWithCertificates(array, myPolicy, &myTrust); + if (status == noErr) { + NSLog(@"No Err creating certificate"); + } else { + NSLog(@"Possible Err Creating certificate"); + } + return array; +} + +// Returns the identity +- (SecIdentityRef)getClientCertificate { + SecIdentityRef identityApp = nil; + NSData *PKCS12Data = [CryptoManager readP12FromFile]; + CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data; + + CFStringRef password = CFSTR("limelight"); // no password + const void *keys[] = { kSecImportExportPassphrase };//kSecImportExportPassphrase }; + const void *values[] = { password }; + CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); + CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); + OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items); + + if (securityError == errSecSuccess) { + NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items)); + CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0); + identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity); + } else { + NSLog(@"Error opening Certificate."); + } + + CFRelease(options); + CFRelease(password); + + return identityApp; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + NSLog(@"connection error: %@", error); +} + @end diff --git a/Limelight/MainFrameViewController.m b/Limelight/MainFrameViewController.m index 0e29635..4a8b3db 100644 --- a/Limelight/MainFrameViewController.m +++ b/Limelight/MainFrameViewController.m @@ -14,7 +14,7 @@ #import "HttpManager.h" @implementation MainFrameViewController -NSString* hostAddr; +NSString* hostAddr = @"cement-truck.case.edu"; MDNSManager* mDNSManager; + (const char*)getHostAddr @@ -87,20 +87,20 @@ MDNSManager* mDNSManager; self.hostPickerVals = [[NSArray alloc] init]; mDNSManager = [[MDNSManager alloc] initWithCallback:self]; - [mDNSManager searchForHosts]; - CryptoManager* cryptMan = [[CryptoManager alloc] init]; - NSString* uniqueId = [cryptMan getUniqueID]; - [cryptMan generateKeyPairUsingSSl]; - NSData* cert = [cryptMan readCertFromFile]; - HttpManager* hMan = [[HttpManager alloc] initWithHost:hostAddr uniqueId:uniqueId deviceName:@"roth"]; + //[mDNSManager searchForHosts]; + + [CryptoManager generateKeyPairUsingSSl]; + NSString* uniqueId = [CryptoManager getUniqueID]; + NSData* cert = [CryptoManager readCertFromFile]; + + HttpManager* hMan = [[HttpManager alloc] initWithHost:hostAddr uniqueId:uniqueId deviceName:@"roth" cert:cert]; NSString* PIN = [hMan generatePIN]; NSData* saltedPIN = [hMan saltPIN:PIN]; NSLog(@"PIN: %@, saltedPIN: %@", PIN, saltedPIN); - NSURL* pairUrl = [hMan newPairRequestWithSalt:saltedPIN andCert:cert]; + NSURL* pairUrl = [hMan newPairRequest]; NSURLRequest* pairRequest = [[NSURLRequest alloc] initWithURL:pairUrl]; - NSLog(@"making pair request: %@", [pairRequest description]); - NSData* pairData = [NSURLConnection sendSynchronousRequest:pairRequest returningResponse:nil error:nil]; - NSLog(@"Pair response: %@", [pairData description]); + // NSLog(@"making pair request: %@", [pairRequest description]); + [NSURLConnection connectionWithRequest:pairRequest delegate:hMan]; } - (void)updateHosts:(NSArray *)hosts { diff --git a/Limelight/mkcert.c b/Limelight/mkcert.c index c9241b4..6a2828c 100644 --- a/Limelight/mkcert.c +++ b/Limelight/mkcert.c @@ -6,6 +6,7 @@ #include #include +#include #ifndef OPENSSL_NO_ENGINE #include @@ -13,7 +14,7 @@ static const int NUM_BITS = 2048; static const int SERIAL = 0; -static const int NUM_YEARS = 20; +static const int NUM_YEARS = 10; int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years); int add_ext(X509 *cert, int nid, char *value); @@ -22,12 +23,21 @@ struct CertKeyPair generateCertKeyPair() { BIO *bio_err; X509 *x509 = NULL; EVP_PKEY *pkey = NULL; + PKCS12 *p12 = NULL; + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - mkcert(&x509, &pkey, NUM_BITS, SERIAL, NUM_YEARS); + SSLeay_add_all_algorithms(); + ERR_load_crypto_strings(); + mkcert(&x509, &pkey, NUM_BITS, SERIAL, NUM_YEARS); + + p12 = PKCS12_create("limelight", "GameStream", pkey, x509, NULL, 0, 0, 0, 0, 0); + if (p12 == NULL) { + printf("Error generating a valid PKCS12 certificate.\n"); + } + // Debug Print statements //RSA_print_fp(stdout, pkey->pkey.rsa, 0); //X509_print_fp(stdout, x509); @@ -43,21 +53,26 @@ struct CertKeyPair generateCertKeyPair() { CRYPTO_mem_leaks(bio_err); BIO_free(bio_err); - return (CertKeyPair){x509, pkey}; + return (CertKeyPair){x509, pkey, p12}; } void freeCertKeyPair(struct CertKeyPair certKeyPair) { X509_free(certKeyPair.x509); EVP_PKEY_free(certKeyPair.pkey); + PKCS12_free(certKeyPair.p12); } -void saveCertKeyPair(const char* certFile, const char* keyPairFile, CertKeyPair certKeyPair) { +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); } @@ -91,7 +106,7 @@ int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) { goto err; } - X509_set_version(x, 3); + X509_set_version(x, 2); ASN1_INTEGER_set(X509_get_serialNumber(x), serial); X509_gmtime_adj(X509_get_notBefore(x), 0); X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*365*years); @@ -121,6 +136,7 @@ int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) { *x509p = x; *pkeyp = pk; + return(1); err: return(0); diff --git a/Limelight/mkcert.h b/Limelight/mkcert.h index f6d3627..052d823 100644 --- a/Limelight/mkcert.h +++ b/Limelight/mkcert.h @@ -10,13 +10,16 @@ #define Limelight_mkcert_h #include +#include typedef struct CertKeyPair { X509 *x509; EVP_PKEY *pkey; + PKCS12 *p12; } CertKeyPair; struct CertKeyPair generateCertKeyPair(); void freeCertKeyPair(CertKeyPair); -void saveCertKeyPair(const char* certFile, const char* keyPairFile, CertKeyPair certKeyPair); +void saveCertKeyPair(const char* certFile, const char* p12File, const char* keyPairFile, CertKeyPair certKeyPair); #endif +