Welcome to Session 709: Protecting Secrets with the Keychain. If you have ever used a keychain or if you think you should, this is your session; iOS, OS X, we're quite agnostic here Let's get started. What will you learn here?
Well, I'll tell you what keychains are I'll tell you how to use them. There is iOS specific information and there is OS X specific information I'll mark them very specifically so you know when to go off and check your tweets And pointers to more stuff because there's always more stuff. All right So why do we have a keychain?
We've actually had one for a very long time. There was a keychain API and keychains in Mac OS 9; so long time There's a lot of small secrets that your programs need to handle passwords, account numbers maybe, PINs you want to store them securely, but you don't want to do that cryptographic thing because it sounds dangerous and it's hard. And you really want to be as particular as you can about who gets those little secrets, not just in terms of which user, but also which programs because we all know that not all programs are is meticulous with the user's secrets as yours And you want some assurance that if the user loses their laptop or their iPhone and somebody walks away with it, those secrets actually stay secrets. That's called "off-line attack" in security lingo. The control over these secrets in the keychain universe is always the users. This is kind of important point to get out of the way up front. These are the user's secrets. These are not your secrets A keychain doesn't give you a way of hiding something from the user of the system It's just a way for you to protect the user's secrets better and more easily. And, of course, we all know, less code is better So keychain APIs try to be a high level API. Fewer calls, fewer parameters for the most part. It may not always seem that way, but believe me, the low-level solutions look a lot worse than this. Okay So what is a keychain?
It's a database I mean, in its heart, it's a database. It's got rows which in keychain lingo are called "items"; and the items have values, that's where you put the secrets; and they have attributes which is things that you find them by or that you stick on the side We call those "metadata."
And keychains are optimized for storing small secrets and finding them quickly That's what they do for a living. You know, the prototypical example is a user's password to a website or some web service or something else; little secrets, little individual secrets that you use one at a time. Now, there is nothing in the APIs that keeps you from storing 150,000 secrets in a keychain, and there's nothing in the APIs that keeps you from storing a 50 megabytes large secret in the keychain But don't do that because that's not what the APIs are written for. You can do it, but it will hurt. It will definitely hurt your program, and it may hurt the system depending on the circumstances So remember, this is for small secrets Don't sweat it, you know; couple hundred bytes is fine, kilobytes probably fine Thousands of secrets is fine as long as you're not trying to iterate through all of them and pick them up one at a time in your program while the user waits. So that's kind of the environment they we're here for. You can stretch this, just don't overstretch it Yeah, and this is the point where somebody always raises their finger and says, "I just write it to a file," you know "I'll encrypt it myself," or "Why do I bother anyway?
I'll use ROT-13," you know "Nobody's going to find the data. Why should I call these weird APIs with their weird security things?"
Well, the keychain APIs give you canned access control Essentially, a predefined way of determining what programs, and to a certain extent, what users get at the secret, and they give you a way of controlling how your program and other programs can share access to these secrets If you write your secrets to a file, then anybody who gets a hold of the file has the secret I mean, they may not know where to look but eventually they'll figure it out, and that's not good. Plain files, there is many, many ways of scanning for files in the system And I don't just mean on OS X There's ways of finding files in iOS by. Jailbreak or other ways. And besides, when you start manipulating this data yourself you copy it around, you write it to a file, you fetch it back - every time you make a copy, there's another place where the secret sits, and once you lose control of a secret, once it goes to places where you didn't realize it was going, there's no way of getting it back because you just wrote it there. Keychain is about doing the cryptography right without you having to think about it. And believe me This is hard. It really is very hard. And it's not typically what you want to spend your time on. So that's why you want to bother using the keychain. The less code, the better. So let's start with the minimum kind of code you can get away with if your needs are simple you want to store a password, you want to store a PIN. You can create a keychain item, which is an entry in this database that is the keychain, with a single API call it's called SecItemAdd. It's a core foundation level API, so you pass it a CFDictionary but we're all rather happier with writing Objective-C code so I wrote you the sample code in Objective-C. Basically, what you do is, you make up a dictionary, you stick in all of the attributes that you want the item to have, you stick in the value, you say go, and it goes. It returns an OS status, and you always, always check the OS status of course. You would never even think of ignoring an error code And that's it. If the call returns no error, zero, then it worked. You now have a keychain item, and you don't have to worry about protecting it because that's what the API's for. Okay So how do you get it back?
Oh, one note. Just like any good database, it has a notion of uniquely identifying items In the case of these kinds of items, that's the service attribute and the account attribute And if you're trying to create another item with the same service and account values, it will not work because these are unique. So one of the errors you can get back from SecItemAdd is, this item already exists so I'm not going to make you another one. So keep that in mind Uniquing. Okay So this is how you get it back SecItemCopyMatching, which is literally what this does. Let me give you a bag of attributes and I'll match that against items in the keychain and I'll give you back the matching value So this is the same dictionary that you passed in, with the same attributes, service attribute an account attribute. You typically pass in "return data", that is, give me the value. You can also get back references to items that let you manipulate the items themselves. And, again, you check the error code, it gives you back the value These values, by the way, are datas. They're not strings. Of course, you know, secrets come in many different shapes and forms so keep that one in mind And that's basically the tools you have to work with. You can create an item You can get the value back, you know. Sometimes it's convenient to do the other two things that you typically do with databases. You can change an existing item. That's done with SecItemUpdate This one actually takes two dictionaries because it's sort of a combination of a lookup and a creation; so it takes one dictionary that you use to find the item you want to update, and another dictionary with all of the stuff you want to change. It's really quite straightforward And we have a call for deleting, which, again, you pass a dictionary saying which item you want to delete and off it goes and deletes it Always check your error codes And there you have it: Keychain APIs. That's all you need to know When you want to change an item, a lot of people fall into that one, really change the item, use SecItemUpdate. It's sometimes tempting to go, "Yeah, well, I'll just delete the old item I'll make a new one. Who's going to notice?"
Programs will notice because there are attributes to items that you may not actually know about. There are there may be attributes to items that don't exist yet because we'll invent them in the next version of the operating system If you delete an item, you're throwing everything about it away. You forget about it, and then you make a new one and it gets default values for stuff you don't specify, and this may not actually be the same values that the old item had; so don't do that. If you need to change an existing keychain item, use SecItemUpdate because that way, you keep the stuff. And well, if you're in a situation where you have a particular place in your UI where the user gives you the secret for safekeeping, then you call SecItemAdd right there. And then if you have another place in your code where you know now you need it, you call SecItemCopyMatching, and these calls are all you need. But a lot of times that's not really what you want to do A lot of times you start to write your program and it goes something like, oh, I need to connect to that website. Oh, wait He says I need a password, so let's go ask the user about the password, pop up a dialog or, you know, something like that, and the user types in the password, you send it to the website, and that's great until it happens again and you ask the user again. So, no, wait I heard this is keychain, so let's use that keychain to remember the thing that the user gave me I call this the "memory work flow" because it's really not a store and retrieve from the user's perspective The user just want to remember something he's already told you once And this happens often enough that I wrote up a little bit of pseudo code just to get you started with it. What you do in a situation where, oh, suddenly I need a password, is the first thing you do is you look it up in the keychain in case it's already there. And if that worked, if the keychain retrieval succeeds, you just take this and you use it and you don't bother the user. That's, after all, the whole point of this. If you don't find it in the keychain, then go off and ask the user this may be the first time or, you know, something may have happened to the keychain and the user gives you the password and you try it out, and if it works, then you stick it in the keychain with SecItemAdd so that the next time when you're running through the same code flow, you're hitting the copy matching at the top and you don't ask the user again. This is about as straightforward as it can go. The password you retrieved or the password that the user gave you may not actually work. The user may have mistyped it or it may have been changed; so you do need code for, well, that didn't work And give a little bit of thought to what you do when it didn't work. Try it first before you store in the keychain If it didn't work the keychain item you've retrieved didn't work and you ask the user for a new one, try that one before you go off and replace it in the keychain But it's basically your workflow I didn't put a loop in here If you want to keep asking the user three times, as many of you want, you know, just add the code, the obvious code, but that's basically the idea. This is how to just remember stuff for the user. The only thing the user notices is that you don't keep asking the same question, which is kind of the Apple thing. Couple things to think about when you build this workflow: As I said, don't store a password until you have some assurance that it works; It's kind of silly to store something that turns out not to be the right secret. If you can at all, when you try out this password, this secret, this PIN, whatever, try to distinguish between this is the wrong password and this didn't work. There are programs out there and I am trying really hard not to mention them whose response to network problems is, oh, that password didn't work I'll delete it from the keychain There. Aren't you happy?
No. Try to distinguish between a environmental problems, which basically means you don't know if the password worked because you never got there, and a perfectly good connection to a service that tells you no, no, no, that's not good I don't like your password. If the answer is "I don't like your password," then go ask the user for a new one, replace it in the keychain. That's good If the problem you're having is, I'm having connectivity problems or the service down, or if you're not so totally sure, when in doubt, leave the old item in the keychain because if you're not sure that it's wrong, it's probably better to keep it. Always keep in mind that in most environments, particularly with websites, there's always another way of changing the password that doesn't involve your application So just because everything worked fine the last time doesn't mean it's going to work today And ask yourself a little bit how hard it is for the user to get the stuff back. We security people like to say that when doubt, erase the secret and start over and that's a very good security rule. And if this is a password that the user probably remembers and you're just doing some convenience for him, then that's good. When it doubt, throw it out ask the user. But if that happens to be a password that they have to get out of their safe and read it off of a piece of paper because it's some highly valuable recovery password, then maybe you want to err on the side of keep it in the keychain unless you're totally sure that it's wrong And in all of these keychain workflows, have a way to continue working if everything falls apart If the keychain APIs just give you these mysterious error codes that you've never seen before, don't just splat on the user and say, you can't have your website, you can't have your service. Always fall back when everything else fails on ask the user for the secret and then feed it out to the service. That's your last defense; if you build your workflow, that's always where you want to end up if everything else fails.
I told you that a keychain item has a value and attributes, or metadata. Now, this is important because it's really the value we are protecting with our high-grade cryptographic munitions. The attributes are what we use to find stuff with, and that means that they can't be that secret, because, after all, you can look them up in the keychain to find items So anything that you want to store for the user that the user thinks is a secret, that the user wants to keep a secret, needs to go into the item value not into attributes. Now, obviously, if it's a password, it goes in the value. If it's a PIN, it goes in the value If it's their name, it's probably not a secret It's a good thing to use as an attribute. But sometimes this is a little bit not so clear. Security people tend to think of account numbers as not as secret Social Security numbers; let's take a Social Security number. We all know it's not a secret, and it's pretty easy to find somebody's Social Security number But there are banks and there are lots of companies who think that knowing somebody's Social Security number actually makes a difference and proves something; so there is a lot of users out there who think that their Social Security number, if you happen to store it, should be a secret So you probably want to make it a secret and not use it as an attribute. Same thing with credit card numbers: Credit card numbers are not really very good secrets, but strangely enough, a lot of banks seem to think that they should be So think a little bit about how you are identifying your keychain items, because in the end, in order to find them, you need to give them attributes that make them easy to find; otherwise, you know, you'll end up with your keychain being a write once store and you can't ever get it back out. So if you can come up with something that you and the user agree is pretty obvious and a public identification of the user and what the user's trying to do, then use that. If you have a hard time coming up with something that you don't think some user will think is a disclosure of dangerous proportions, your fall back is to make up something. If you can't think up anything else, generate a UUID, use that as a key. Of course, then you need to store that, but since it's an identifier that you're only using to identify the keychain item, you can just store that in a key value attribute in your cloud storage, or in your file if you're so inclined So that's your way out of the "I don't have anything to tag my keychain items with."
In the end, you can make something up. This is not really keychain specific but it's something that we always tell you. The whole point of having secrets is that you don't leak them; so retrieve them from the keychain right when you need them, use them, and then throw them away. Do not keep your secrets in a variable in memory; do not write your secrets to a file because it was so annoying to get them out of the keychain in the first place; and do not send them to your buddy, the helpful XPC service for the helpful daemon to hold them for you. The whole keychain workflow is based on, just get it, use it, throw it out. Let the keychain hold it for any time when you don't actively use the secret And that's basically all you need to know in order to use keychains as a high-level service on Apple products. Everything I've told you so far is true on iOS and OS X. Everything I've told you so far works on both That is good. That's a really good argument for using just what I told you so far because it works. You don't have to worry about it. But, well, okay. Maybe you want to know a little bit more. So let's talk about iOS first. The SecItem APIs that I told you about are going to serve you well on iOS because they're the only API that is there, so cool. If you store a keychain item on iOS, it is secured, cryptographically secured, by the user. And by that we mean, by the PIN or password that the user enters to unlock the device. That's how the off-line protection thing works: If somebody steals your phone and walks away with it and, you know, does a big storage dump of the phone, if they don't know your passcode and your phone wasn't jailbroken to begin with when you lost it, there is no shortcut other than brute force attack to actually get your secrets out of the keychain. You can also connect keychain items on iOS to the particular hardware platform to the instance of device, which means that it's also cryptographically linked to a secret that is embedded baked into your particular phone That's a cool feature, because, well, it means you can make secrets that belong to this particular phone and non other, and the user. On iOS, by default, if you just use the calls that I showed you, a keychain item is totally bound to the application that made it; so if you write a app and you call SecItemAdd, no other app in the universe can see that item. On iOS, this is done totally by visibility. You basically just don't see keychain items made by other applications. On the other hand, if you can see it and the user has, you know, unlocked their phone, then you can actually get them So this is the fundamental access control that we're having on iOS. And that's cool unless, of course, you want to make a family of three apps the share a secret it's been known to happen so we have a way of doing that And the way you do it is you add an entitlement. It's called the Keychain-Access-Groups Entitlement, and it's basically just a name that the different apps agree on and that is used as a rendezvous point If you are storing a keychain item under a particular keychain access group name, then all the applications that have this entitlement with that value have access to the item. This is how you share. Obviously, this is an entitlement so you can set it up in Xcode when you build your app. And it wouldn't be much of security if you could share it with everybody, so there are some restrictions that guarantee that somebody else will not come along and say, "I'll share that with you."
The basic restriction is that the keychain access group names, in order to be acceptable to the store, needs to start with your team ID. So all of these names are teamID, dot, and then make up something What this practically means, of course, is you get to share whatever you want with yourself, with your own apps, between your apps. You just don't get to share them with somebody else's app. Not by accident and also not on purpose. You just can't. Whereby can't, I mean that you can build the app like that but the store take it. And if you are sending out ad hoc copies of your app to your friends, you would need a provisioning profile, and the provisioning profiles will not allow you to have this entitlement. So basically, you can't. You get to share with yourself between your own apps and that's all the sharing you get In Xcode there's this little section in the general configuration of your app called keychain. Basically, that's what you add it. The bundle ID of your app acts as essentially a keychain access group; so by default you're only sharing yourself. What you do is you add another value there and you start sharing with other apps that have the same value there If you're ever wondering about whether your app actually has an entitlement like that, there is the good old codesign command. Of course, you have to run it on OS X. Just ask it to display entitlements and you'll get back the plist that contains your keychain access groups entitlement. You've probably heard of data protection I certainly hope you've heard of data protection. That's iOS's way of classifying data as to when it becomes available. And one of the attributes you can specify when you create item is its data protection class. So, yes, each item can have a different data protection class. The default, if you don't say anything, is this line, so you don't have to specify but you can. What that means is that keychain items can be retrieved when the phone is unlocked, which is kind of what you want If the phone is locked, well, your code's not running and then the user loses the phone and user's very happy that the keychain item is not accessible. Of course, if there happens to be a way of running your app in the background, as I've heard maybe there might be, and you want your app to have access to a keychain item, even though the phone's locked because the user locked it and walked away, then you need to weaken the protection of the item and specify after first unlock. What this basically means is that the item is still not accessible if the phone got rebooted or powered off, but after the user unlocked it at least once, even if he locks it after that, the item is still available So if you do need to access an item from a background activity while the user is not using the phone, this is what you need to specify when you make the item But don't do that unless that's a situation you're in because it means that your item is protected less well. It means that if the user loses his phone and the thief walks away and manages to bypass the lock screen, they might get at the item. If you are in a situation where you have background activity that you need to do because it's part of your feature set because it's really cool that your code is doing stuff while the user isn't around, and you're uncomfortable with taking the primary password of the user, the primary secret, the one that you're safekeeping for him, and sticking it into and after first unlock protected item. There's a trick you can use sometimes, and that is to do what we call "derive secrets."
If you have control over the service because, let's say, you're making it, you're actually running that service on the Web, you can authenticate to it with a secret that is cryptographically derived from the real password of the user. The advantage is that then you can store that derived password in the less protected keychain item and if it gets out for some reason, your service can be attacked with the user's derived password, but the user's password is still secure. That matters because users are so terribly bad at reusing passwords That's extra work, and it's a little bit beyond the scope of just talking about keychains, but I thought I'd mention it because, well, it matters. What happens when you backup your phone?
Pretty much what you'd expect Your keychains get backed up along with the phone as long as your backups are encrypted and all of your backups are encrypted, right?
You can restore them back onto the phone and you will get all of the items back that were in the keychain when the backup was made; so this is totally seamless it just works. Items that were marked as belonging to a particular piece of hardware, to a particular device, can be restored to that device, and that will work fine. If you are migrating to another device, then, by the nature of their security, they won't come along So if you are if the user is migrating to another device and they're restoring a backup, they will essentially get a keychain that has all of the device specific keychain items missing. Be prepared for these items to disappear in what seems to be a random moment in time because the user just bought a new iPhone something All right. This all looks perfectly, so there will be no need to debug anything That's a good thing because here's the bad news: There is on iOS no tool for introspecting the keychain data. There is no command line tool, because where would you run it; and there is no utility that has access to all of the keychain items of all of the applications on your phone. That's actually a security feature. Remember that the access control on iOS is based on you can only see keychain items made by your app So if Apple wrote a utility for inspecting your keychain, it would only see the keychain items that it wrote, which is kind of pointless So this being the bad news, the tip is, you need to put your debugging code inside of your app because only code that's running inside of your app actually can see the keychain items that you're having trouble with. You all know how to put debug code in your program, and you know, you know what kind of debug code you're comfortable with One thing: If you actually ship your debug code in some neat, tricky little if you triple tap over there while holding the phone sideways, and then a new debug menu pops up and you can actually figure out why the keychains aren't working, tell App Review because otherwise they might get the idea that you have a secret feature in your phone that you don't want people to know about and that would be sad Debugging tip: When you are passing these dictionaries to the keychain APIs, particularly for Add, understand that these entries in those dictionaries fall into two classes. There are the values that become attributes and item values. They're data They are stuff that goes into the item. And then there are other keys that are control keys that say what you want to happen. Like the storage class as an example. If you reuse those dictionaries between the ItemAdd call and the CopyMatching call and the Update call be really careful because all of the keys in your dictionary may not all be useful and valuable on all the API calls. It may actually be safer to make up these dictionaries from scratch for each call And if you run into any problems where the APIs are yelling at you and telling you that you are just having a "parameter error"@, something that just doesn't make any sense other than I don't know what you're talking about, that often means one of the keys that you passed in doesn't make a sense here so. And that's it for iOS. Hey, that's great. Welcome back OS X crowd. The keychain on OS X has been around for much longer, and we have a lot more API and a lot more complexity simply because it's been around that much longer. So let me tell you about it. The SecItem APIs that I've told you about work on OS X, and they are what you what we want to use. Honestly, seriously, if you can at all, please use the SecItem APIs to work with your keychains because that's what all the new work goes. If there's a bug in them, we'll fix it much with much more alacrity than in the older APIs. So try that first. There are some things and I'll tell you about them that you cannot do with the SecItem APIs on OS X and then you'll have to fall back on the older APIs we call SecKeychain APIs because they are all folded around the SecKeychain calls in the API suite. These are not deprecated. They are supported API. They are just not where we're putting the new cool stuff On OS X a keychain is a file in the file system. Seriously, if you look in your home directory in Library Keychains, there's a file in there, it's called login.keychain. That's where your secrets sit. It's just a file. So just deal with that That means that standard file access controls apply to keychains. Your login.keychain is owned by you, it's not generally readable or writable by other users And if you mess with permissions, you can actually mess up access to your keychain OS X keychains are cryptographically protected by the user's login password. Just like on iOS, they are protected by the users PIN or, you know, the password they entered to unlock the phone; on OS X, they're protected by the password the user uses to log in. Makes perfect sense. Now, while on iOS the default is that there's no sharing and you have to do a special thing to start sharing between applications, on OS X keychains keychain items of one user are all visible to all applications run by that user. Remember, OS X multiuser files, Posix permissions, all of that stuff. So OS X sort of has the reverse logic: Instead of starting with you can't even see any items that aren't yours and then you'll have to do special things to make them visible, OS X's approach is you can see all the items made by all the applications for that user, and then we put on controls that determine which applications actually are allowed to retrieve the item The way this is done is with access control lists. Every Keychain item on OS X has an ACL And the ACL says what applications are allowed to retrieve the value. You set the ACL when you create the item If you don't specify anything in particular, you'll get pretty much exactly the behavior you'd expect, which is that the creating application is the only one that is allowed to retrieve the item. So the default behavior on iOS and OS X is very similar but the machinery is very different. There are calls for changing the ACL of an existing item I do not recommend you use them because they are pretty complicated and the system will throw up a dialog to confirm that you actually wanted to change the ACL, which is usually not a very good user experience So the 98 percent takeaway rule is: Create the ACLs right when you create the item and then forget about them So what is in these ACLs An access control list on a keychain item is essentially a list of applications that are allowed to access the item. As I said, by default, it's the creating application, but you can, when you make the item, make a list and say, me and that app over there and that third app over there; and on OS X, that doesn't have to be your own. You can, if you want, create an item and say, "and Safari has access to this item."
I'm not sure why you would want to but you can System does. The APs are SecAccess, SecACL, and SecTrustedApplication, if you are unfortunate enough to have to do this, go read the documentation, which is public documentation on the keychain, and it's, you know, pretty good actually Here is one other distinction that is important between iOS and OS X: On iOS if you don't have access to an item, you don't see it, you can't do anything with it, end of story. There's just no discussion. On OS X if you're in an application that doesn't have access to an item because it's not on the access control list and you try anyway, the system will try to put up a dialog. Now, you've probably seen that one. We lovingly call it the "rogue application alert" because it's the system saying, hey, this program wants access to the item and I don't think it should, but do you want to allow it anyway. So on OS X, the user actually has the ability to override your access control list by saying, yes, I want it and it's my secret and he can have it. So keep that in mind. There is a separate keychain file on OS X that's called the system keychain. It's in /Library because it belongs to the system And the system keychain belongs to the system as a whole. It's a multiuser operating system, remember. If you write a system daemon and you use the keychain APIs, that's where your secrets go But the system keychain is actually accessible to every program in the system So if you're in a situation where you need to create a keychain item that is shared between users, you want that secret to go into the system keychain, because the system keychain can be read by every user on the system. That's a capability that, well, OS X has. Of course, the system keychain does belong to the system as a whole, so asking a user, hey, do you want this program to have access to that system secret wouldn't be very fair if the user isn't perhaps even an administrator; so if that happens to a secret in the system keychain, we're not just asking, is this okay to do this. We're actually asking, hey, prove that you're an administrator So the keychain dialog for overriding ACL control for the system keychain is an admin check. Let's talk a little bit more about these prompts There's a particular error code, one of the OSStatus values that can come out of a keychain call, it's called "user interaction not allowed."
And a lot of people get very confused by it; like, what user interaction?
I did want any user interaction I just want the item. What this means is, I needed to put up a dialog to get you what you want and I couldn't. Well, why would the system put up a dialog?
We've already had one situation If the application isn't on the ACL approved list, if it's an intruder and an interloper that is trying to get an item that the ACL says it shouldn't have, system tries to put up a dialog. The other situation is for keychains that are not actually at the moment unlocked. Remember, I told you that the cryptographic protection of a keychain is based on the user's login password?
When you log in through the standard OS X login screen, the password you type in that allows you to log into the system is also used to unlock the user's keychain The passwords are in sync As a matter of fact, when you change your pass your login password, it actually changes the cryptographically secured password on the login keychain at the same time So it's always unlocked, right?
So why would the system ever need to ask for it?
Because there are preferences for paranoid people where you can actually say that you want your keychain to lock automatically after inactivity. And some people turn that on. Yeah, I do At which point if you then asking the keychain API for an item and the keychain is locked at this point, the system will put up a dialog and say, Could you please enter that password again because you're paranoid?
Which is fine as long as this dialog can come up. If your program is not running in a graphic context, meaning, if it doesn't have the ability to put up standard CocoaDialogs, the system knows that the keychain system knows that, and in any situation where it's trying to put up a dialog on your behalf from the user's behalf and it can't, instead the call fails and that's the error code you're getting user interaction not allowed I was trying to talk to the user and ask him if it's okay but I couldn't So what this really means, what this error code really means to you, is you are in a nongraphical environment for some reason. You are in the cron job, you are in the system daemon, you SSHed into the system SSHing does not get you graphical access even if you are logged in as the same user at the same time on the same Mac. They are totally separate security sessions. So keep this in mind because that's like probably 50 to 80 percent of all of the problems people have So what do you do if you're in a nongraphical context?
You want to use the keychain anyway. There are API calls and the SecKeychain APIs that allow you to unlock the keychain Of course, you'll have to say, "and the password is this" because you can't put up a dialog. There are APIs for retrieving items and all of this good stuff; so if you happen to have the user's login password or whatever secret protects the keychain, you can just pass that to API. But if you have a command that normally works fine from terminal but now you want to use it from an SSH session, the easiest way is to use the security command. That's a command line command, it's the Swiss Army keychain command And it has an option for "I want to unlock this keychain now. Here's the password."
So most of the time if the problem is unlocking keychains, just running security unlock before you run your program will get you out of your hole. If the problem is that your application isn't on the access control list of the item, well, that's your mistake. You should have created the item with the right ACL to begin with. And I should mention that when we're talking about application identity here, these are codesigning identities And I am glad everybody here is signing their code because the keychain stuff system doesn't work very well if your programs unsigned anymore. Well, let's talk a little bit about backup and migration. There isn't have much to stay I told you keychains are files. If you backup your files and restore them, everything will be fine And if you're migrating accounts using Migration Assistant, it will migrate your keychains Everything's fine. Hardly a problem actually. If you happen to be writing system daemons, I've already alluded to that, system daemons are not in graphic sessions. They can't put up security dialogs So you are in that particular hole. The system keychain is your default keychain. If you are in a system daemon, you can store secrets in the keychain, but it will go into the system keychain. The system keychain is writable by root only; so in order to write to the system keychain, in order to create or modify keychain items, you need to run as root. Retrieving is fine no matter what UID you are So as a daemon, your keychain is the system keychain And you have no access without a lot of back flipping to the user's keychain because if you're a system daemon, you don't have a user For all you know, there might be four users logged into the system right now, or none at all; so if you're searching for keychain items in a system daemon, anything that the user created the normal way inside of that normal login keychain, you just can't see. So the not so bad news on OS X is that there is a tool that allows to you to work with keychain files. It's called the "security command."
It's in usr/bin, and because the default sharing rule on OS X is, if you can see it, you can fondle it, you just can't get the value out without passing the ACL test The security command can show you all of the items in the user's keychain, or for that matter, all of the items in the system keychain, and it will, if you pass it, the right convoluted options will actually tell you what access control lists it has and what its attributes are. In fact, you can use the keychain the security command to essentially preflight APIs from the command line if you're so inclined. If you're wondering if a particular combination of attributes will work to find an item, there is a security subcommand that just searches the keychain for items with particular attributes So it's pretty handy. There's security dump keychain with dumps out the entire keychain for your introspection Of course, it was still not give you the actual values of the secrets unless you have access to them. So they're just to clarify: The security command has no special magic features. It's just a normal API client for the keychain APIs It will not do anything that the normal keychain APIs cannot do. But on OS X, that's actually a heck of a lot All right. Welcome back IOS crowd We're now talking about both systems again And this is the section where I talk about stuff that just didn't make it anywhere earlier in the presentation I've talked about secrets so far accounts, passwords, and PINS, you know, all that stuff that you generally retrieve from a keychain in order to use it as the text or data value that it is for something, authenticating, passing it off to a service, whatever. The keychain actually can store a lot of other things, too I told you it's a database, and it really is, and in particular, it has database schemas. And one of the things that you can store in the keychain is certificates and cryptographic keys. This presentation focuses on how to simply work with passwords, but I should at least mention, if you're doing things like client-side SSL authentication, what will happen is that your cryptographic identity, the key and the certificate that you're presenting to the web server will end up stored in a keychain, and the CF network APIs will essentially, if everything works well, automatically fetch them out of there and use them. Keys and keychains are actually handled by reference, which is a really cool feature. It means that unlike certain other legacy APIs, you don't ever have to have the keys in your address space. And so if you get compromised all, is not lost. That's good. So keep in mind there is an API suite called SecKey for dealing with cryptographic keys, and those are typically stored in keychains, works on iOS and OS X. There is a SecCertificate API for dealing with certificates; mostly for finding them, but there's also and API for creating them And there is SecIdentity which is a little bit odd because it's literally a pair of private key and a certificate SecIdentity objects aren't actually anything physical. They are a pair of a certificate and a private key that were found in your keychain so that belong together. The system knows how they fit together. This is what you use for cryptographic authentication. What yeah. Okay. All right Well, one last thing: iCloud keychain. It's been announced so I can tell you about it. Once upon a time there was a way to synchronize secrets in keychains and that feature disappeared awhile ago because times change. So now we have something better. The SecItem APIs are our simple APIs, the "straightforward, just do this if you can get away with it, don't get any more complicated if you can avoid it" APIs. You can add one more key to them this one. And it starts sharing your items between OS X devices and iOS devices for that user That's all you have to do.
We try to make things simple. So this works on iOS, it works on OS X; of course, iOS 7, OS X 10.9. You need to add that attribute to all of your API calls, not just the creation call. And as it says on the label usually, "some restrictions apply"; in particular the lower-level APIs I told you about on OS X, the SecKeychain APIs, they don't play nice with iCloud keychain So if you are planning on using iCloud keychain, you really, really need to stick to the high-level APIs. Just call SecItem, add that attribute, and keep it simple. It does work with the application sharing feature. So to sum it all up: Use the keychain APIs to store your secrets. It's better for you. It's better for the user. It's better for the environment. Don't do your own secret storage. It's going to end up badly, if not now, then later, because this is hard and you're doing enough hard coding already Keep your APIs as simple as possible, and that's not just because complicated breeds more bugs, but also because complicated is a really bad thing when you're doing security. The more complicated you make your secret storage setup, the more likely it is that some combination of circumstances that you didn't even think about it, is going to lead to a hole in your security strategy If you can at all, stick with this SecItem APIs Stick with the memory workflows if that's what you're doing Try not to manipulate ACLs unless you absolutely have to, and if you do, stick with the sample code for that on OS X, and you'll be living happily ever after. All right Paul Danbold, the gentleman here, is usually lonely and bored, and he loves to get e-mails; the more the better He's the evangelist, and he has gotten very good at telling you who should be talking to you. The keychain APIs are public APIs They're documented on the developer website. There is plenty of documentation to go around. Start with this URL if you haven't ever looked at it, and there will be cross-references leading you elsewhere. If you are wondering about storing keys and certificates in keychains, there is a technical Q&A, 1745, that focuses on that and should serve to get you started with how to set this all up. If you're just wondering how all of that cryptographic protection thing works and why you should trust us, there's a white paper that describes how it works under the hood. You don't need to read that in order to use the keychain, but if you're curious And if you have any questions start asking each other in the developer forums, and then we'll take it from there. And that's it.