IPhone app with SSL client certs
Asked Answered
J

7

20

I'm building an iphone app that needs to access a web service over https using client certificates. If I put the client cert (in pkcs12 format) in the app bundle, I'm able to load it into the app and make the https call (largely thanks to stackoverflow.com).

However, I need a way to distribute the app without any certs and leave it to the user to provide his own certificate. I thought I would just do that by instructing the user to import the certificate in iphone's profiles (settings->general->profiles), which is what you get by opening a .p12 file in Mail.app and then I would access that item in my app. I would expect that the certificates in profiles are available through the keychain API, but I guess I'm wrong on that.

1) Is there a way to access a certificate that I've already loaded in iphone's profile in my app?

2) What other options I have for loading a user specified certificate in my app? The only thing I can come up with is providing some interface where the user can give an URL to his .p12 cerificate, which I can then load into the app's keychain for later use, but thats not exactly user-friednly. I'm looking for something that would allow the user to put the cert on phone (email it to himself) and then load it in my app.

Jermainejerman answered 10/1, 2010 at 13:48 Comment(7)
Can you tell me how load the .p12 into the app, please? I need to extract the publick key of the client certificate. ThanksLyndel
I got in touch with an Apple Security framework evangelist, who confirmed what has already been said here - certificates loaded in seting->general->profiles can only be used by the built-in apps (mail, safari). Your app can use only what you store in its keychain (or keychains of other 3rd party apps that share the same provisioning certificate). As for the actual loading, I've built an app bundled with the certificate (just for the test). I read the .p12 from my app bundle and I get the identity with SecPKCS12Import. You can then use it to get the private key with SecIdentityCopyPrivateKey.Jermainejerman
I've tried with this: NSString *thePath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"p12"]; NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath]; CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data; CFStringRef password = CFSTR("pass"); const void *keys[] = { kSecImportExportPassphrase }; const void *values[] = { password }; CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); SecPKCS12Import(inPKCS12Data, optionsDictionary, &items); items is empty.What is happening?Lyndel
I have tried with SecPKCS12Import but doesn't work... I have added an answer with the codeLyndel
Does this still hold true??? That only built-in apps can read the certificates from the iPhone keychain??? The Junos Pulse VPN Client provides a list of certs installed in the system keychain as part of it's in app configuration... I don't think it can be classified as a built-in app... How does it read the system keychain???Yevette
@PabloAlejandro did you get solution for your problem, i am having same problem :(Modernistic
Is it possible to access system keychain in a read-only mode? If I try to open a https connection from within an application and the server uses some of the "trusted" certificates, such as VeriSign, connection succeeds without errors. How is that possible? That would mean my application somehow has access to the trusted certificates. So is it possible to access system keychain in a read-only mode?Olives
L
3

I've tried with this:

NSString *thePath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"p12"]; 
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath]; 
CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data; 
CFStringRef password = CFSTR("pass"); 
const void *keys[] = { kSecImportExportPassphrase }; 
const void *values[] = { password }; 
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); 
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); 
SecPKCS12Import(inPKCS12Data, optionsDictionary, &items); 

inPKCS12Data is correct but items is empty. What is happening?

Lyndel answered 27/1, 2010 at 9:27 Comment(3)
That same code works for me. SecPKCS12Import returns OSStatus status code - get that and see what the error is.Jermainejerman
I'm having the same issue with the 4.3.2 simulator. But it works with the simulator in iOS SDK 5.0 beta6. Don't know with other versions.Wendel
Another reason it might be empty: If self-signed, your certificates have expiry dates too far in the future.Yolondayon
H
2

I've done this for a recent app by making the documents folder for the app accessible via itunes. Our users are then instructed to drag their generated key (in a p12 format file) into the documents panel for our app in iTunes. When the app is started, it checks for the existence of the p12 file and, if it exists, imports the file into the keychain.

It's not the simplest procedure, but it is the most secure because you don't have a private key file being sent around via email.

Hilda answered 25/4, 2011 at 19:13 Comment(0)
I
1

If a .p12 file isn't too big you could encode it using Base64 and then embed a link in an email with a custom url scheme, e.g.:

myapp://certificate/<base 64 data>

User clicks the link, your app saves the certificate somewhere for future use. Just make sure that Mail.app on the iPhone won't mangle the email.

Imparity answered 10/1, 2010 at 14:24 Comment(3)
There is a reason behind this and I might end up trying it, but even if it works, the user has to encode the cert in Base64 and craft this email which is not user-friendly.Jermainejerman
Thinking about it, the easiest way to get Mail.app to play ball, is to send an HTML email and use A tags for the link.Imparity
Could you not provide an application or a website to do it for them?Imparity
A
1

Apple does restrict the use of device-wide keys/certificates to it's own applications/services, such as WiFi, VPN, Mail, etc. Third-party applications are not able to use any of these keys/certs (without jailbreaking). However, applications are able to import, store, and use keys and certificates in a in-app keychain. In addition, you can share keys/certs across multiple applications with the keychain-access-group feature in iOS.

I recently published a blog post titled In-App Mobile Certificates Made Easy with mCMS, which may have helped you out. Our company is developing an API that makes it easy to support in-app certificates, obtained directly from your Microsoft-based PKI. Our solution also offers on-device key generation, instead of generating a P12 on another machine and trying to import it into your app.

Ardent answered 27/7, 2012 at 14:32 Comment(0)
G
1

If you're using AirWatch for app distribution, their SDK provides the ability to provision certificates from your Certificate Authority to your registered devices. This allows you to provision your certs, and then access them from your app's code.

Grackle answered 4/12, 2015 at 16:23 Comment(2)
Do you have a code snippet that accesses the certificates?Nickola
Yes, a code snippet that works for you with Airwatch will really help. Thanks!Guardian
G
0

Does the code suggested in Finding a Certificate In the Keychain work for you?

Goodloe answered 10/1, 2010 at 13:58 Comment(2)
No, I tried searching for kSecClass key with values kSecClassIdentity, kSecClassCertificate and kSecClassKey but I always get an empty result. Then I read on some more to find out that the iphone keychain is per-app, that is you can access only what you put in it and only your app (and other apps signed with a provisioning certificate with the same AppID) have access to that keychain.Jermainejerman
Well, then to answer your second question - there is no API or AppStore-approvable way to load a file into iPhone other than specify an URL and download it...Attire
V
0

Oh man, this brings up painful memories from October/November 2009. I was able to successfully get client-side certs to work but I had to port libcurl to the iPhone (which wasn't easy since the NDA was still in effect at the time).

I haven't done iPhone app development in over a year so I don't know how much is changed, but if I were you I'd first try to get by without client-side certs and if you absolutely must have them you can use libcurl with PEM formatted certs.

Villeneuve answered 2/4, 2010 at 2:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.