What is the equivalent code for mutual auth in iOS? - ios

I am trying to make an API call to a server that requires mutual auth.
Using NodeJS and the request library I am able to hit the API with the following code
var keyFile = '/Users/username/Documents/Certificates/example-key.pem';
var certificateFile = '/Users/username/Documents/Certificates/cert.pem';
var options = {
uri: 'https://myserver.com/apiOne',
key: fs.readFileSync(keyFile),
cert: fs.readFileSync(certificateFile),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic ' + new Buffer(userId + ':' + password).toString('base64')
},
body: data //JSON body
};
request.postAsync(options)
.spread(function (response, body) {
res.status(200).json(JSON.parse(body));
})
.catch(function (err) {
res.status(400).send(err);
})
How do I make hit the same API from an iOS app?
I am using the following code, but there is no response from the server
func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential!) -> Void) {
if challenge.protectionSpace.authenticationMethod == "NSURLAuthenticationMethodServerTrust" {
let credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)
What do the key and cert mean in the NodeJS code? How do I pass them in iOS?

First, you will need to convert you key and cert into a p12 file.
To do that run the following command
openssl pkcs12 -export -out new.p12 -inkey example-key.pem -in cert.pem
It will also prompt you to enter a password. Use the path of this created p12 and password in the following code
#pragma mark - Get Identity
- (SecIdentityRef)getIdentity {
SecIdentityRef identity = nil;
CFStringRef password = (__bridge CFStringRef)certPassword; //the password that you entered while creating the p12 file
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
NSData *certData = [NSData dataWithContentsOfFile:certFilePath]; //the path to the p12 file. You can get this from bundle
CFArrayRef items = CFArrayCreate(nil, 0, 0, nil);
OSStatus status = SecPKCS12Import((__bridge CFDataRef)(certData), options, &items);
CFRelease(options);
CFRelease(password);
if (status == errSecSuccess) {
NSLog(#"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items));
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
identity = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
} else {
NSLog(#"Error opening Certificate.");
}
return identity;
}
#pragma mark - Get Certificates
- (CFArrayRef)getCertificates:(SecIdentityRef) identity {
SecCertificateRef certificate = nil;
SecIdentityCopyCertificate(identity, &certificate);
SecCertificateRef certs[1] = { certificate };
CFArrayRef array = CFArrayCreate(NULL, (const void **) certs, 1, NULL);
return array;
}
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {
NSString *authMethod = challenge.protectionSpace.authenticationMethod;
NSLog(#"auth method %#", authMethod);
if ([authMethod isEqualToString:#"NSURLAuthenticationMethodServerTrust"] || [authMethod isEqualToString:#"NSURLAuthenticationMethodClientCertificate"]) {
SecIdentityRef identity = [self getIdentity]; // Go get a SecIdentityRef
CFArrayRef certs = [self getCertificates:identity]; // Get an array of certificates
NSArray *myArray = (__bridge NSArray *)certs;
NSURLCredential *newCredential = [NSURLCredential credentialWithIdentity:identity certificates:myArray persistence:NSURLCredentialPersistencePermanent];
[challenge.sender useCredential:newCredential forAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeUseCredential, newCredential);
}
}

Related

Get public/private key from certificate

I try to get public or private key from certificate saved on device.
I'm using this method:
- (SecKeyRef)publicKeyFromFile:(NSString *)path
{
NSData * certificateData = [[NSData alloc] initWithData:[[NSFileManager defaultManager] contentsAtPath:path]];
if (certificateData != nil && certificateData.bytes != 0) {
CFDataRef cfDataPath = CFDataCreate(NULL, [certificateData bytes], [certificateData length]);
SecCertificateRef certificateFromFile = SecCertificateCreateWithData(NULL, cfDataPath);
if (certificateFromFile) {
SecPolicyRef secPolicy = SecPolicyCreateBasicX509();
SecTrustRef trust;
SecTrustCreateWithCertificates( certificateFromFile, secPolicy, &trust);
SecTrustResultType resultType;
SecTrustEvaluate(trust, &resultType);
SecKeyRef publicKeyObj = SecTrustCopyPublicKey(trust);
return publicKeyObj;
}
}
return nil;
}
There is data in cfDataPath, but certificateFromFile is always nil...
Does anyone know where's the problem?
Apple doc refers:
Obtaining a SecKeyRef Object for Public Key Cryptography
Extracting Keys from the Keychain If you are using existing public and private keys from your keychain, read Certificate, Key, and Trust Services Programming Guide to learn how to retrieve a SecKeychainItemRef object for that key.
Once you have obtained a SecKeychainItemRef, you can cast it to a SecKeyRef for use with this API.
Importing Existing Public and Private Keys Importing and exporting public and private key pairs is somewhat more complicated than generating new keys because of the number of different key formats in common use.
This example describes how to import and export a key pair in PEM (Privacy Enhanced Mail) format.
Read more : https://developer.apple.com/library/mac/documentation/Security/Conceptual/SecTransformPG/SigningandVerifying/SigningandVerifying.html and https://developer.apple.com/library/mac/documentation/Security/Conceptual/CertKeyTrustProgGuide/01introduction/introduction.html#//apple_ref/doc/uid/TP40001358
Try with this:
-(BOOL)trustCertFromChallenge:(NSURLAuthenticationChallenge *)challenge
{
SecTrustResultType trustResult;
SecTrustRef trust = challenge.protectionSpace.serverTrust;
OSStatus status = SecTrustEvaluate(trust, &trustResult);
//DLog(#"Failed: %#",error.localizedDescription);
//DLog(#"Status: %li | Trust: %# - %li",(long)status,trust,(long)trustResult);
if (status == 0 && (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed)) {
SecKeyRef serverKey = SecTrustCopyPublicKey(trust);
NSString *certPath = [[NSBundle mainBundle] pathForResource:#"MYCert" ofType:#"der"];
NSData *certData = [NSData dataWithContentsOfFile:certPath];
SecCertificateRef localCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData);
SecKeyRef localKey = NULL;
SecTrustRef localTrust = NULL;
SecCertificateRef certRefs[1] = {localCertificate};
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, (void *)certRefs, 1, NULL);
SecPolicyRef policy = SecPolicyCreateBasicX509();
OSStatus status = SecTrustCreateWithCertificates(certArray, policy, &localTrust);
if (status == errSecSuccess)
localKey = SecTrustCopyPublicKey(localTrust);
CFRelease(localTrust);
CFRelease(policy);
CFRelease(certArray);
if (serverKey != NULL && localKey != NULL && [(__bridge id)serverKey isEqual:(__bridge id)localKey])
return YES;
else
return NO;
}
//DLog(#"Failed: %#",error.localizedDescription);
return NO;
}
Follow the accepted answer for more details: Objective-C / C pulling private key (modulus) from SecKeyRef

How to load certificates in tls connection using gcdasyncsocket

I am working on an iPhone app that works on GcdAsyncSocket and creates TLS connection, I generate RSA keys and CSR using those and sent CSR to server, server responded with a certificate and some other certificate that is like public key to it. Now I need to make another TLS connection with server and send private key nd 2 certificates back to it. I have gone through many posts but didn't find any way how to achieve this.
If anyone could help and with some code that would be great help.
Thanks.
After spending good amount of time, I was able to resolve the issues using open SSL library. I used following code
+(PKCS12*)convertToP12Certificate:(NSString*)certificate
certificateChain:(NSArray*)certificateChain
publicCertificate:(NSString*) publicCertificate
andPrivateKey:(NSString*)privateKey
{
//we create a x509 from primary certificate which goes as a single entity when creating p12
const char *cert_chars = [certificate cStringUsingEncoding:NSUTF8StringEncoding];
BIO *buffer = BIO_new(BIO_s_mem());
BIO_puts(buffer, cert_chars);
X509 *cert;
cert = PEM_read_bio_X509(buffer, NULL, 0, NULL);
if (cert == NULL) {
NSLog(#"error");
}
X509_print_fp(stdout, cert);
//create a evp from private key which goes as a separate entity while creating p12
const char *privateKey_chars = [privateKey cStringUsingEncoding:NSUTF8StringEncoding];
BIO *privateKeyBuffer = BIO_new(BIO_s_mem());
BIO_puts(privateKeyBuffer, privateKey_chars);
EVP_PKEY *evp;
evp =PEM_read_bio_PrivateKey(privateKeyBuffer, NULL, NULL, "Enc Key");
if (evp == NULL) {
NSLog(#"error");
}
if (!X509_check_private_key(cert, evp))
{
NSLog(#"PK error");
}
PKCS12 *p12;
SSLeay_add_all_algorithms();
ERR_load_crypto_strings();
const char *cert_chars2 = [publicCertificate cStringUsingEncoding:NSUTF8StringEncoding];
BIO *buffer2= BIO_new(BIO_s_mem());
BIO_puts(buffer2, cert_chars2);
X509 *cert2;
cert2 = PEM_read_bio_X509(buffer2, NULL, 0, NULL);
if (cert2 == NULL) {
NSLog(#"error");
}
X509_print_fp(stdout, cert2);
STACK_OF(X509) *sk = sk_X509_new_null();
sk_X509_push(sk, cert2);
for(NSString * tempCertificate in certificateChain)
{
const char *cert_chars3 = [tempCertificate cStringUsingEncoding:NSUTF8StringEncoding];
BIO *buffer3= BIO_new(BIO_s_mem());
BIO_puts(buffer3, cert_chars3);
X509 *cert3;
cert3 = PEM_read_bio_X509(buffer3, NULL, 0, NULL);
if (cert3 == NULL) {
NSLog(#"error");
}
X509_print_fp(stdout, cert3);
sk_X509_push(sk, cert3);
}
p12 = PKCS12_create(P12_Password, P12_Name, evp, cert, sk, 0,0,0,0,0);
return p12;
}
+(NSArray*)getCertificateChainForCertificate:(NSString*)certificate
certificateChain:(NSArray*)certificateChain
publicCertificate:(NSString*) publicCertificate
andPrivateKey:(NSString*)privateKey
{
PKCS12 *p12 = [CryptoHelper convertToP12Certificate:certificate
certificateChain:certificateChain
publicCertificate: publicCertificate
andPrivateKey:privateKey];
NSData *PKCS12Data = [CryptoHelper convertP12ToData:p12];
NSArray *certs = nil;
SecIdentityRef identityRef = nil;
CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
CFStringRef password = CFSTR(P12_Password);
const void *keys[] = { 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);
CFRelease(options);
CFRelease(password);
if (securityError == errSecSuccess)
{
NSLog(#"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items));
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
identityRef = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
if(certificateChain)
{
CFArrayRef certificates = (CFArrayRef)CFDictionaryGetValue(identityDict,kSecImportItemCertChain);
// There are 3 items in array when we retrieve certChain and for TLS connection cert
SecIdentityRef chainIdentity = (SecIdentityRef)CFArrayGetValueAtIndex(certificates,1);
certs = [[NSArray alloc] initWithObjects:(__bridge id)identityRef,(__bridge id)chainIdentity, nil];
}
else
{
certs = [[NSArray alloc] initWithObjects:(__bridge id)identityRef, nil];
}
} else
{
NSLog(#"Error opening Certificate.");
}
return certs;
}
We can pass this array to TLS connection for key GCDAsyncSocketSSLCertificates.

X.509 RSA Encryption/Decryption iOS

I need to implement encryption / decryption using a X.509 RSA public/private key pair.
So far, I have something which I think will work for encryption, but I have no way of decrypting to check. Everything I try has issues reading the private key.
Generating the key pairs (returns a .der and a .pem)
openssl req -x509 -out public_key.der -outform der -new -newkey rsa:1024 -keyout private_key.pem -days 3650
Encryption (Not sure if this works, but looks like it does)
+ (NSData *) RSAEncryptData:(NSData *)content {
SecKeyRef publicKey;
SecCertificateRef certificate;
SecPolicyRef policy;
SecTrustRef trust;
size_t maxPlainLen;
NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:#"public_key" ofType:#"der"];
NSData *base64KeyData = [NSData dataWithContentsOfFile:publicKeyPath];
certificate = SecCertificateCreateWithData(kCFAllocatorDefault, ( __bridge CFDataRef) base64KeyData);
if (certificate == nil) {
NSLog(#"Can not read certificate from data");
return nil;
}
policy = SecPolicyCreateBasicX509();
OSStatus returnCode = SecTrustCreateWithCertificates(certificate, policy, &trust);
if (returnCode != 0) {
NSLog(#"SecTrustCreateWithCertificates fail. Error Code: %d", (int)returnCode);
return nil;
}
SecTrustResultType trustResultType;
returnCode = SecTrustEvaluate(trust, &trustResultType);
if (returnCode != 0) {
return nil;
}
publicKey = SecTrustCopyPublicKey(trust);
if (publicKey == nil) {
NSLog(#"SecTrustCopyPublicKey fail");
return nil;
}
maxPlainLen = SecKeyGetBlockSize(publicKey) - 12;
size_t plainLen = [content length];
if (plainLen > maxPlainLen) {
NSLog(#"content(%ld) is too long, must < %ld", plainLen, maxPlainLen);
return nil;
}
void *plain = malloc(plainLen);
[content getBytes:plain
length:plainLen];
size_t cipherLen = 128; // currently RSA key length is set to 128 bytes
void *cipher = malloc(cipherLen);
OSStatus encryptReturnCode = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, plain,
plainLen, cipher, &cipherLen);
NSData *result = nil;
if (encryptReturnCode != 0) {
NSLog(#"SecKeyEncrypt fail. Error Code: %d", (int)returnCode);
}
else {
result = [NSData dataWithBytes:cipher
length:cipherLen];
}
free(plain);
free(cipher);
return result;
}
Decryption
I have tried using OpenSSL's PEM_read_X509 also PEM_read_RSAPrivateKey, but both fail to read the cert. I have not even gotten past that. If I could do this without having a dependency on the OpenSSL library, that would be even better.
+(void)readTest{
FILE *fp;
X509 *x;
NSString *path =[[NSBundle mainBundle] pathForResource:#"private_key" ofType:#"pem"];
fp=fopen([path UTF8String],"r");
x=NULL;
PEM_read_X509(fp,&x,NULL,NULL); // I have also tried PEM_read_RSAPrivateKey
if (x == NULL) {
NSLog(#"Cant Read File"); // This ALWAYS fires
}
fclose(fp);
X509_free(x);
}
If someone could help me out with encryption/decryption using X.509 RSA pairs, I'd appreciate it. Thanks.
Where you are stuck
It seems your private key is encrypted (openssl asked you for a password on the command line), yet you do not decrypt it when you try to open it. Besides, private_key.pem is an RSA key, not a certificate, so you should use PEM_read_RSAPrivateKey.
The following decoding code should work:
int pass_cb(char *buf, int size, int rwflag, void* password) {
snprintf(buf, size, "%s", (char*) password);
return strlen(buf);
}
+(void)readTest{
FILE *fp;
RSA *x;
NSString *path =[[NSBundle mainBundle] pathForResource:#"private_key" ofType:#"pem"];
fp=fopen([path UTF8String],"r");
x = PEM_read_RSAPrivateKey(fp,&x,pass_cb,"key password");
if (x == NULL) {
NSLog(#"Cant Read File"); // This ALWAYS fires
}
fclose(fp);
X509_free(x);
}
Alternatively, you could generate a non-encrypted key. Pass -nodes to openssl when creating the keys and the certificate.
Please note that you might need to make sure OpenSSL is properly initialized with:
SSL_library_init();
OpenSSL_add_all_algorithms();
Besides, OpenSSL generates error messages that could help you through development. You load the error strings with:
SSL_load_error_strings();
And you could call:
ERR_print_errors_fp(stderr);
RSA encryption and decryption on iOS
OpenSSL is not the only solution as Security framework on iOS contains everything you need. I guess you turned to OpenSSL because you did not know how to convert your private key file to valid parameters for SecKeyDecrypt.
The trick is to produce a PKCS#12 file and to call SecPKCS12Import.
You can produce this file with OpenSSL:
openssl x509 -inform der -outform pem -in public_key.der -out public_key.pem
openssl pkcs12 -export -in public_key.pem -inkey private_key.pem -out private_key.p12
This will ask you for an export password. This password should be passed to SecPKCS12Import ("key password" below).
NSString *privateKeyPath = [[NSBundle mainBundle] pathForResource:#"private_key" ofType:#"p12"];
NSData *pkcs12key = [NSData dataWithContentsOfFile:privateKeyPath];
NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys: #"key password", kSecImportExportPassphrase, nil];
CFArrayRef importedItems = NULL;
OSStatus returnCode = SecPKCS12Import(
(__bridge CFDataRef) pkcs12key,
(__bridge CFDictionaryRef) options,
&importedItems
);
importedItems is an array containing all imported PKCS12 items, and basically, the "identity" (private key + certificate).
NSDictionary* item = (NSDictionary*) CFArrayGetValueAtIndex(importedItems, 0);
SecIdentityRef identity = (__bridge SecIdentityRef) [item objectForKey:(__bridge NSString *) kSecImportItemIdentity];
SecKeyRef privateKeyRef;
SecIdentityCopyPrivateKey(identity, &privateKeyRef);
Then you can use privateKeyRef to perform the decryption with SecKeyDecrypt. To match your encryption routine:
size_t cipherLen = [content length];
void *cipher = malloc(cipherLen);
[content getBytes:cipher length:cipherLen];
size_t plainLen = SecKeyGetBlockSize(privateKeyRef) - 12;
void *plain = malloc(plainLen);
OSStatus decryptReturnCode = SecKeyDecrypt(privateKeyRef, kSecPaddingPKCS1, cipher, cipherLen, plain, &plainLen);

Accessing certificates pushed by MDM

I wanted to know is there a way to access certificate pushed by MDM server through your app?
A few years later - is there still no way to access the MDM issued X.509 certificates?
I'm using this code, but getting zero results. And as far as google helps, there is also no way to see if there is any cert at all?
CFTypeRef certificateRef = NULL; // 1
const char *certLabelString = "XenMobile MDM";
CFStringRef certLabel = CFStringCreateWithCString(
NULL, certLabelString,
kCFStringEncodingUTF8);
const void *keys[] = { kSecClass, kSecAttrLabel, kSecReturnRef };
const void *values[] = { kSecClassCertificate, certLabel, kCFBooleanTrue };
CFDictionaryRef dict = CFDictionaryCreate(NULL, keys,
values, 3,
NULL, NULL);
status = SecItemCopyMatching(dict, &certificateRef);
if (status == errSecItemNotFound) {
_UILabelINFO.text = #"error The item cannot be found (errSecItemNotFound) :";
_UILabelINFO.text = [_UILabelINFO.text stringByAppendingString:(__bridge NSString *)(certLabel)];
} else {
_UILabelINFO.text = #"retrieved keychain reference";
}

How to verify (and require) self-signed certificate in iOS

I'd like to create an SSL connection to my server using self-signed certificates that are shipped with the code in iOS. That way I don't have to worry about more sophisticated man-in-the-middle attacks where someone has access to a high level "trusted" cert authority. I'm having issues doing so using what I believe to be Apple's standard way.
Generating the certificate, via the procedure found here
# Create root CA & private key
openssl req -newkey rsa:4096 -sha512 -days 9999 -x509 -nodes -out root.pem.cer
# Create a certificate signing request
openssl req -newkey rsa:4096 -sha512 -nodes -out ssl.csr -keyout ssl.key
# Create an OpenSSL Configuration file from http://svasey.org/projects/software-usage-notes/ssl_en.html
vim openssl.conf
# Create the indexes
touch certindex
echo 000a > certserial
echo 000a > crlnumber
# Generate SSL certificate
openssl ca -batch -config openssl.conf -notext -in ssl.csr -out ssl.pem.cer
# Create Certificate Revocation List
openssl ca -config openssl.conf -gencrl -keyfile privkey.pem -cert root.pem.cer -out root.crl.pem
openssl crl -inform PEM -in root.crl.pem -outform DER -out root.crl && rm root.crl.pem
And the iOS code:
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
if ([protectionSpace authenticationMethod] == NSURLAuthenticationMethodServerTrust) {
// Load anchor cert.. also tried this with both certs and it doesn't seem to matter
NSString *path = [[NSBundle mainBundle] pathForResource:#"root.der" ofType:#"crt"];
NSData *data = [[NSData alloc] initWithContentsOfFile:path];
SecCertificateRef anchorCert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)data);
CFMutableArrayRef anchorCerts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
CFArrayAppendValue(anchorCerts, anchorCert);
// Set anchor cert
SecTrustRef trust = [protectionSpace serverTrust];
SecTrustSetAnchorCertificates(trust, anchorCerts);
SecTrustSetAnchorCertificatesOnly(trust, YES); // only use that certificate
CFRelease(anchorCert);
CFRelease(anchorCerts);
// Validate cert
SecTrustResultType secresult = kSecTrustResultInvalid;
if (SecTrustEvaluate(trust, &secresult) != errSecSuccess) {
[challenge.sender cancelAuthenticationChallenge:challenge];
return;
}
switch (secresult) {
case kSecTrustResultInvalid:
case kSecTrustResultDeny:
case kSecTrustResultFatalTrustFailure:
case kSecTrustResultOtherError:
case kSecTrustResultRecoverableTrustFailure: {
// !!! It's always kSecTrustResultRecoverableTrustFailure, aka 5
NSLog(#"Failing due to result: %lu", secresult);
[challenge.sender cancelAuthenticationChallenge:challenge];
return;
}
case kSecTrustResultUnspecified: // The OS trusts this certificate implicitly.
case kSecTrustResultProceed: { // The user explicitly told the OS to trust it.
NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
return;
}
default: ;
/* It's somebody else's key. Fall through. */
}
/* The server sent a key other than the trusted key. */
[connection cancel];
// Perform other cleanup here, as needed.
} else {
NSLog(#"In weird space... not handling authentication method: %#", [protectionSpace authenticationMethod]);
[connection cancel];
}
}
I'm always getting kSecTrustResultRecoverableTrustFailure as the result. I don't think this is localhost issue as I've tried using Apple's code to change that too. What to do?
Thanks!
If the trust result is kSecTrustResultRecoverableTrustFailure, you might be able to recover from the failure.
Here is the workaround.
https://developer.apple.com/library/mac/#documentation/security/conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html#//apple_ref/doc/uid/TP40001358-CH208-SW8
Please be sure that your certificate is valid. I think it's name shouldn't be root.der.crt. You can take a look for certificate types from here. The below code is for p12 certificate, I hope it will help.
NSData *PKCS12DataQA = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"CERTIFICATE NAME" ofType:#"CERTIFICATE TYPE"]];
BOOL result = [self extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12DataQA];
- (BOOL)extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef*)outTrust fromPKCS12Data:(NSData *)inPKCS12Data
{
OSStatus securityError = errSecSuccess;
//testtest is the passsword for the certificate.
NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:#"testtest" forKey:(id)CFBridgingRelease(kSecImportExportPassphrase)];
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
securityError = SecPKCS12Import((__bridge CFDataRef)(inPKCS12Data),(CFDictionaryRef)CFBridgingRetain(optionsDictionary),&items);
if (securityError == 0) {
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
*outIdentity = (SecIdentityRef)tempIdentity;
const void *tempTrust = NULL;
tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
*outTrust = (SecTrustRef)tempTrust;
} else {
NSLog(#"Failed with error code %d",(int)securityError);
return NO;
}
return YES;
}

Resources