Importing an SSL cert under the iPhone SDK
Asked Answered
H

4

9

My app connects to the Schwab OFX server using NSURLConnection. Unfortunately the server uses a very recent intermediate certificate that is trusted on the Mac desktop but not yet the iPhone. (Try the URL—you'll get a cert error on iPhone.)

There's no easy way to tell NSURLConnection to ignore an invalid cert that I know of. Thus I'm trying to import the cert into the Keychain manually and set its trust level but I've hit a block.

I call SecCertificateCreateWithData successfully to import the certificate from a .cer file. On the desktop I would then call SecTrustSettingsSetTrustSettings, but it doesn't exist in the iPhone SDK.

Any workaround?

Horvitz answered 17/11, 2009 at 1:16 Comment(0)
H
12

Apple technical support responded to me promptly with a perfect answer.

First, I am incorrect in saying that Schwab uses "a very recent intermediate certificate that is trusted on the Mac desktop but not yet the iPhone". Intermediate certificates are never in the built-in root certificate store. The issue is that most SSL servers bundle all intermediate certificates needed for verification, but Schwab uses an alternate SSL process that expects you to fetch the intermediate certificate from a URL. The Mac desktop supports intermediate-certificate fetching, but not the current iPhone OS.

Here's the gist of the actual code:

OSStatus            err;
NSString *          path;
NSData *            data;
SecCertificateRef   cert;

path = [[NSBundle mainBundle] pathForResource:@"OFX-G3" ofType:@"cer"];
assert(path != nil);

data = [NSData dataWithContentsOfFile:path];
assert(data != nil);

cert = SecCertificateCreateWithData(NULL, (CFDataRef) data);
assert(cert != NULL);

err = SecItemAdd(
    (CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:
        (id) kSecClassCertificate,  kSecClass, 
        cert,                       kSecValueRef, 
        nil
    ], 
    NULL
);
assert(err == noErr);

CFRelease(cert);

This assumes that OFX-G3.cer is the intermediate SSL certificate and is located in the Resources folder.

Horvitz answered 18/11, 2009 at 23:25 Comment(2)
Weird - I can e-mail myself the certificate and it parses it correctly, yet if I try to load it this way I get a null for cert.Phylogeny
I changed the last assert to: assert(err == noErr || err == errSecDuplicateItem); to account for the "error" if it is already installed For me, I had to convert the certificates to DER format else this code would not work. I did that in this way: openssl x509 -in UTN-USERFirst-Hardware.cer -out UTN-USERFirst-Hardware.der -outform DERClausen
G
2

You can bypass ssl settings using CoreFoundation's CFStream object. You'll need to do something like create a stream that connects to the appropriate port on the OFX server, then use CF(Read|Write)StreamSetProperty to provide a CFDictionary (which you can cast an NSDictionary to) with keys like kCFStreamSSLLevel, kCFStreamSSLAllowsAnyRoot, kCFStreamSSLValidatesCertificateChain, etc.

Garfish answered 17/11, 2009 at 4:22 Comment(1)
Great answer. However Apple's technical support responded with a better answer--see my own response to this question.Horvitz
N
1

You can install to the cert directly into the simulator's TrustStore.sqlite3 file. Charles Proxy uses this to install their root cert into the simulator. http://www.charlesproxy.com/documentation/faqs/ssl-connections-from-within-iphone-applications/

Nereid answered 24/2, 2012 at 20:17 Comment(0)
U
0

Are you trying to do this programmatically or is it okay to do it via normal UI?

The iPhone Configuration Utility from Apple allows you to add certificates to the phone. You can also just email the certificate to a user that can read email on the phone, then open the certificate on the phone and it will ask you if you want to install the cert.

I'm sorry I can't give you more details instructions right now, but I'm away from my iphone. I'll check back later after I can get to the iphone to see if you've met with success.

Unavailing answered 17/11, 2009 at 4:14 Comment(1)
Installing certs "manually" in this way will let the user browse to that website in Mobile Safari without error – but does NOT help for requests opened in the App (at least, in my testing with iPod Touch Gen 2, iOS 3.0).Clausen

© 2022 - 2024 — McMap. All rights reserved.