Is There Any Point To Using The Keychain API On iPhone?
I’ve always liked the Keychain technology in Mac OS X. Sure, the API is notoriously confusing and awkward, but the end-user benefits are compelling:
- Secure, encrypted storage for all passwords and keys.
- Items can be shared between applications—so in principle you don’t have to enter a given password more than once, since other apps will find the existing item in the keychain.
- Items have access control lists, so they can be restricted to certain apps.
- The user can “lock” the keychain, requiring a passphrase to be entered before there’s any further access to it. This happens by default when the system goes to sleep, which is a good security feature especially for laptops.
- If an app’s code changes, it has to ask permission to use the keychain again (protects against malicious code patches)
For the past few weeks’ worth of Copious Spare Time, I’ve been trying to get my MYCrypto framework, which is in part a friendly API to the Keychain, to run on iPhone. The iPhone has a Keychain API, but it’s a different API than the Mac OS one. At first glance it looks simpler and easier to use, and maybe it would be if it were properly documented, but in practice the item-storage part of it (the SecItem* functions) is incredibly frustrating because the documentation is both incomplete and just plain wrong.
Currently I’ve gotten a lot of it working, but I’m stuck on some issues that seem like either major Keychain bugs or philosophical differences (parts of the API don’t seem to work at all with items that exist in memory but haven’t been persistently added to the Keychain store.) I’ve filed at least six bug reports to Apple in the last week, including the kind of basic unit tets that I would have hoped Apple QA engineers would have written before iPhone 2.0 ever went to developers. I’m very frustrated.
All this for what?
After finishing the bug reports, I had the crazy idea: why should I be using the Keychain store at all on iPhone? Going through my above list of benefits, I realized that hardly any of them apply:
- The iPhone security model relies on app sandboxing to protect data. Even malicious app code can’t reach the keychain file because it’s outside the app sandbox.
(I have some data that implies that the file is in fact just a plaintext SQLite database, not the fancy encrypted store it is on OS X.)[ Update: I now have confirmation that the Keychain file is encrypted on the device and in backups, making it secure against most attacks.] - iPhone apps can’t share keychain items. Every app effectively has its own sandboxed keychain. So there’s no usability benefit of putting passwords in it.
- No sharing means no point in access control lists, of course.
- There’s no keychain passphrase or lock/unlock behavior on iPhone. Once you unlock the iPhone itself, all apps can access their keychains freely.
- Since all apps are signed, there’s no question of malicious patches.
So much for that. What you’re left with is a rudimentary flat-file database, specialized for just a few data types, with a really clunky and badly documented API. Other than the fact that it happens to already exist, there’s nothing about it that’s as good as something you could write in a few hours using CoreData, or your favorite high-level SQLite API like FMDB or QuickLite. Heck, for simple needs you could just use a property list, for example an NSDictionary mapping URLs to [username, password] pairs. It ought to be just as secure, because the sandbox prevents any other apps from being able to access the file.
Updated: What you’re left with is an encrypted flat-file database, specialized for just a few data types, with a really clunky and badly documented API. As I wrote above, its functionality could be duplicated, with a better API, without much effort. The encryption part is significant, though, since its primary purpose is to keep keys and passwords safe. A DIY key database could be protected by encrypting it with a symmetric key, and then putting that key in the Keychain.
I’m not sure where that leaves MYCrypto. I’m not sure I’m motivated to write a general-purpose version of this data store myself. If I can get some good answers and workaround to my Keychain API bug reports, I may just continue to tough it out.
June 14th, 2009 at 5:41 PM
My original understanding was that any apps that share the same identifier will share the same keychain. So if you use a wildcard identifier like com.mooseyard.* then you would indeed be able to reap benefits of keychains sharing on the phone. At least, in theory.
The other thing to keep in mind is keychain security is more about run-time safety. It (hopefully) ensures that the sensitive data is stored encrypted on “disk” on the phone. So if somebody steals your phone and peeks around in the disk, they’ll have a lot harder time gleaning useful private data if it’s been stored via the keychain, versus say a plain dictionary.
June 14th, 2009 at 5:45 PM
I had similar thoughts when coding one of my iPhone apps.
The only reason I came up with to use the keychain is in case of theft (of the device itself).
If you store passwords or other sensitive information in just a regular old file (or the StandardUserDefaults) then whoever gets the phone can copy that file off and look through the info.
Storing it in the keychain encrypts it which adds a layer of security to the sensitive information.
That was the only benefit I found to using it.
June 14th, 2009 at 6:05 PM
Mind posting the bug numbers? I’d like to track them. Thanks!
June 14th, 2009 at 6:34 PM
I presume one point of the Keychain framework on the phone is that, when iTunes makes backups, any private data stored on the host in the backup files will be encrypted. Or is that already true?
June 14th, 2009 at 6:48 PM
@Chris Ryland
I believe that iTunes encrypts the backup itself. Thats the impression I got from the WWDC keynote anyways.
June 14th, 2009 at 6:49 PM
@Daniel — The shared-identifier thing is a benefit, but a small one since it applies only to apps by the same developer. (And I wasn’t sure if it was added in 3.0 and still covered by NDA, so I thought it safer not to mention it.)
June 14th, 2009 at 6:53 PM
@Eric — Here they are:
6971230 Searching for certs by data returns non-matching certs
6971226 Adding a second cert to keychain fails with bogus dup-item error
6971224 SecItemAdd fails if asked to return an item ref
6971217 Can’t get attributes of certs loaded from data
6964197 SecItemAdd returns incorrect error code if application-tag is used with cert
6960130 SecCertificateCreateWithData fails on valid self-signed X.509v1 certs
6960126 SecTrustCreateWithCertificates fails to accept single cert on iPhone
and as a bonus:
6971173 ER: Release iPhone version of Security framework source code
…because if I had the source I could at least try to figure out how the SecItem API is supposed to work.
June 14th, 2009 at 6:55 PM
To those who mentioned the iPhone keychain file being encrypted: Do you have any evidence that it is? The only evidence that I have (which I won’t mention until the 3.0 NDA is lifted) is that it’s a vanilla SQLite database, but it’s not ironclad proof.
June 14th, 2009 at 7:24 PM
As an aside, to solve the problem of an odd API, I find the oft-overlooked NSURLCredentialStorage often does the job nicely.
June 14th, 2009 at 7:57 PM
I had someone who was using a jailbroken phone to get the keychain DB off the phone submit a bug for my iPhone keychain wrapper because he had noticed that the passwords were being stored in clear text. I made a fix assuming that the problem was that I was storing the passwords as “general” keychain objects, not as the special password type, but admittedly I’ve never been able to confirm that the fix was doing the right thing since I don’t want to jailbreak my phone.
I definitely agree with your criticisms of the keychain framework—it’s a complicated, poorly documented, confusing black box whose benefits are not at all well understood. I guess I started using it as a matter of course because I assumed it was the right, secure thing to do, but I would be curious to know the answers to your questions as well.
June 14th, 2009 at 9:27 PM
If the keychain is unencrypted on the device, I’d assume it’s probably also unencrypted in the back-up on the user’s PC. That’s worse than unencrypted on the device, because the PC doesn’t have the iPhone’s security restrictions (Mac OS X’s sandboxing is voluntary, and I don’t know about Windows). Even in the possession of a thief, the back-up file is more exposed than the iPhone’s file-system.
Therefore, if Keychain does store data unencrypted on the device (assuming it doesn’t get encrypted on the way to the back-up), I say that that’s a bug worth filing.
Also, you should continue using and filing bugs against Keychain regardless of whether it’s encrypted. If it’s not, it’s no worse than anything else, but even then, Apple could start encrypting it in a future release—whereupon you should pick up that change for free.
June 15th, 2009 at 6:11 AM
Peter: The backup should actually be more secure than the data on the phone (which only has the 4-digit unlock) because it’s also encrypted with a (presumably longer) key that stays on the phone, according to Greg Parker.
June 15th, 2009 at 7:36 AM
Just occurred to me — A DIY key/password store could be made secure by using that recently-released sqlite encryption extension (I can’t remember what it’s called). The key for that file could be stored in the keychain; that way you only need two or three Keychain API calls to store and look up that key.
June 17th, 2009 at 8:38 PM
Such as this?
http://www.mobileorchard.com/tutorial-iphone-sqlite-encryption-with-sqlcipher/
June 17th, 2009 at 8:57 PM
Yup — except that for some reason SQLCipher uses OpenSSL instead of the built-in crypto APIs, which makes your build process more complicated and your app bigger. Not sure why they did that (except maybe because it’s cross-platform.)
June 29th, 2009 at 11:23 AM
Would you care to comment about why you think the keychain isn’t safe? According to this doc:
http://developer.apple.com/DOCUMENTATION/Security/Conceptual/keychainServConcepts/02concepts/concepts.html#//apple_ref/doc/uid/TP30000897-CH204-DontLinkElementID_3
it would appear that it is safe, even during app backup.
June 30th, 2009 at 9:07 AM
Craig — Thanks for the link. I had not seen any explicit confirmation that the keychain file is in fact encrypted on the iPhone. That’s good to know — thanks!
July 9th, 2009 at 12:42 PM
I agree that documentation is a major hurdle for the keychain API on the phone. It’s nice that you can query the keychain by putting together a fairly arbitrary set of properties, but it appears that only some of the properties are actually used when running the query. Figuring out which might be used and which are not is… a challenge.
Now that 3.0 has been released, it is the case that two applications can be set up to share their keychains, however, there is a bug that if you do that the two applications will not be able to participate in the notifications API.
July 9th, 2009 at 1:27 PM
Scott — I filed a Radar last month requesting that Apple post the source code to the iPhone security stack, just as they’ve long posted the Mac security code. That would help a lot in figuring out how the keychain actually works!