Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2006-416
$eventId
ID of event: wwdc2006
$eventContentId
ID of session without event part: 416
$eventShortId
Shortened ID of event: wwdc06
$year
Year of session: 2006
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC06 • Session 416

Token-Based Authentication Using Smart Cards

OS Foundations • 43:27

Today's high-security systems combine traditional password-based authentication with novel token-based mechanisms such as smart cards. Tiger extended the powerful keychain services at the heart of Mac OS X to work with smart cards and other types of tokens. Learn about the different daemons, APIs, and plug-ins that make up the smart card ecosystem on Mac OS X. Find out more about creating smart-card aware applications, making resources on smart cards available through keychain services, and deploying smart-card based solutions.

Speaker: John Hurley

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

We're the group that does keychain and cryptography and PKI and things like that, and also smart cards. So in this session, we're going to go over how we use smart cards and other tokens in Mac OS X. It's particularly about actually the last bullet point, which is how to add support for new types of tokens. So we'll be just going over very, very quickly how to configure a system for token-based authentication, how to write applications that support tokens, and then we'll spend most of the time on how to add support for new types of tokens. support for new types of tokens.

Okay, so quickly going over configuration. We have had built-in support for smart cards for several releases now. We've been adding more capabilities as time goes on. One of the things that we added for Tiger was support for something we called a TokenD, which gives us the ability to support additional types of smart cards and tokens.

So we've had support for PCSC Drivers and PCSC Lite, actually I think since release 10.2. But with TokenDs, we get the ability to support different types of cards. If you look inside System Library Security TokenD, you'll see the few different ones that we ship built in with Tiger and, of course, with Leopard 2.

And if you look in User LibExec Smart Card Services Drivers, you'll see some of the different PCSC drivers for the different devices. The different types of TokenDs that we support so far on Tiger are for the Common Access Card, which is the U.S. Department of Defense-issued smart card for identification.

The Belgian Identity Card, which is issued to every Belgian citizen. They'll have completed their rollout by 2008. And also the Japanese PKI card. So those are the token deeds that are built in now, but you'll learn through this session how if you have a token, you can add support for it as well.

Now, this slide is kind of surprising and I think very important. But with Leopard, you do not have to do any client-side modification at all to enable token-based authentication. And if you've ever tried to do this, this is actually, as I say, it's surprising. Currently on Tiger, you do have to change something on the system to enable the smart card sniffer. But still, actually, there's no client-side modification needed.

So part of the authentication process, if you went to the session yesterday about login and authorization, you learned how this worked in detail. But part of it is, as a user starts to log in to the system or starts to authenticate to the system, they make a claim about who they are.

And As part of this process, you want to validate whether that claim is true or not. So if you're looking at smart card login, The authorization plug-in will actually make calls off to directory services to look up the user in the directory services or in the back-end directory.

So you can see all the directories shown in purple down below. Those are all the different kinds of directories that we support. And you'll be going through the different layers, the authentication API or security framework. We'll be looking up and doing all the different things. We'll be looking at the standard directory services to find that user.

So again, I want to emphasize that for the really, really gory details about how to do this, there's a session on Friday morning. The number will be shown at the end here. So if you're in IT, then that will be the session you'll really want to see. But for the recommended way of setting up token-based authentication, what we recommend is storing the public key hash associated with the key that you want to use to log in or authenticate with, storing that in the directory. So you can figure out what the different public key hashes are by typing in scauth hash. And if you have a smart card or token, one that's supported, it will list all the different public key hashes.

Okay, you can then add this to the authentication authority attribute for the user. And again, using the SCAuth script. You can say seauth accept my user and then follow that by the hash of the public key. And to borrow from a commercial from a while back that Apple did, there is no step three. That's it. That's all you have to do. So it's very, very easy in the sort of the recommended setup to add a user and allow them to authenticate using their token.

So again, go to the session on Friday to see some of the caveats and other things that you might run into. But a very, very common one that sort of prevents you from doing that recommended scheme is that you don't have the ability to add items to your directory schema.

So you might be in an organization that doesn't allow changes like that or would be prohibitive to do. That can be a difficulty. There is a way to create a configuration file that will allow you to use other items on the token to look up credentials that you can use to authenticate with, and there are more details on that.

One specific example that unfortunately doesn't work with this setup is that the Active Directory plug-in generates authentication authority on the fly, and so you can't really add that in using this script. But we are thinking about ways of improving that experience, and so it could be that when the final version of Leopard ships that we'll have sorted that out.

Okay, so now again a brief thing for people that are writing application-level code that needs to talk to smart cards or other tokens. So how do you get token support? Now traditionally, this has really been very, very difficult because as an application writer, often you're not really that concerned with security or that's not your primary focus. And so it's a lot of extra work to add security layers in.

But it's even worse when you look at all the different types of tokens that you might have to talk to. So it rapidly gets out of hand if you want to start supporting these. So typically what happens is you'll write an application and then you'll write maybe through a PKCS11 layer. And then you'll write directly to a particular token that's maybe unique to your organization. But that really doesn't scale very well.

So we had thought about this for a while, and the recommendation that we have to work on Mac OS X is to use the CDSA or SEC APIs inside your application. So if you do that, you will get automatic support for tokens underneath. So some of the SEC APIs, Secure Transport, CF Network, WebKit, SEC Keychain Calls, those are all examples of these. And if you write to these APIs, then you'll automatically have support for tokens at the same level that you would have for a file-based keychain, for example.

And that last bullet point is important, that you should be able to do most, if not all, of your testing just using soft keys. So in other words, a key that you've picked up that's, say, from VeriSign or Thought, that's in a P12 file imported into your keychain, if it works with that, then you should be able to just go ahead and expect that it will work with tokens. So we have a concrete example of this working, Microsoft Entourage.

This is an existing Mac OS X app, and actually this story is really from last year. When they were working on Office 2004, they wanted to add the ability to have smart card support. And we didn't even have the APIs finalized or anything. We had nothing for them to work with at that point. But we knew that we would be basing it on this idea of talking to the sec APIs. So we said, okay, just write everything down. And we said, okay, just write everything down.

Okay, so now I'm going to talk a little bit about the architecture of tokens in Mac OS X Leopard.

[Transcript missing]

We wanted it to work with existing applications using current Mac OS X APIs. We wanted it to be able to support single sign-on, and as a follow-on to that, it needed to be able to allow the token to be shared among different applications.

So we wanted the ability to enter a PIN here, and then, unless you disallow it, allow some other application to also use that card. So we had looked at different things like writing a CSP, which is a cryptographic service provider, data library module. We could have written one of those per card, but then only that particular app would know about that PIN. Writing the PKCS11 driver has some of the drawbacks that I mentioned, which is it tends to be very, very vertical, very specific to the token.

So what advantages did we get out of the TokenD solution? Excuse me. We ended up with horizontal support for the tokens. So across all these different applications, they could all share the token and use the token without all of them having to do all of the work. So out of the box on actually for some features going back as far as Panther, but certainly Tiger and Leopard, there's support for login, authorization, mail using S-MIME, Safari for client-side authentication. Screen locking. And also any apps that are using CDSA or CDSA-type APIs. So again, including WebKit or CF Network.

If the token allows it, you can have single sign-on with the token. So in other words, you authenticate once to the token using your PIN, and that will remain unlocked until the developer wants that to be locked. We have support for ACLs. And as I mentioned, previously all you had was support for vertical applications based on PCSC.

So here, conceptually, what we're trying to do with this is just think of tokens, either smart cards or other hardware tokens, as keychains. That's the best way to think of them. They're not file-based like the regular keychain that you're used to, but they are still keychains, so they support all the same APIs.

You can see from the diagram up above, you have the applications written on top of the smart card. of the Sec APIs and those Sec APIs are calling into the CDSA pieces of CSSM and this new cryptographic service provider called the SDCSPDL. So that's a smart card device cryptographic service provider.

The SDCSP DL communicates back and forth with Security D, which is the process that's responsible for managing sort of traffic directing for cryptographic operations. And Security D will communicate not only with individual token Ds, but also back and forth to PCSC D. Now, the communication to PCSC D is mostly deciding whether or not to launch a new token or not to launch a new token.

So if it sees the insertion of a device, it will say, okay, I better launch PCSC D, start that rolling. But it can also detect removal events and things like that. You can see from the diagram, too, PCSC D will communicate with the readers or has the APIs to talk to the readers, and it knows when readers are inserted or removed. And then the individual token Ds will talk to the readers through the PCSC D. APIs.

Now to make these token Ds possible, we have something called the Security Token D Framework, which helps you-- it sort of wraps around each token D. A token D, by the way, is--

[Transcript missing]

So a token D, again, is a process that's loaded for each token or card that's inserted. And you'll have one token D per active token.

As you go up through the different layers of the API, the higher levels of the system just see those as additional keychains. And as you insert and remove tokens, they'll be added to the dynamic search list for keychains. The API for this has a number of callback functions which are called by the system as they're needed. So there's a set of functions that are initially invoked to kind of get the token D up and running, and then there are another set of callbacks which are invoked as the higher-level applications call down through the CDSA stack.

So here you can see, this is just a larger version of that previous diagram, where you can see that the SDCS PDL is just another cryptographic service provider alongside the other modules that are inside the CDSA architecture. If you're not familiar with CDSA, it's an acronym for Common Data Security Architecture, and this is our framework for doing cryptography and public key infrastructure and things like that. It's roughly equivalent in size and thickness of manual to something like Crypto API on the Windows side.

So what happens, how does a token D sort of come into life? As a device is inserted, PCSC, well actually IOCIT, will send a notification that PCSC picks up and Security D will notice that this new device is there. An additional step ahead of this is if PCSC is not running, then Security D is actually looking for notifications of insertions as well. Assuming PCSC is running, it will get that notification. And then Security D will look at each token D that is inside system library security token D.

It's going to launch each one of those token Ds in turn, and it makes an API call called probe to each token. The token D that returns the highest score through probe will end up living and will be assigned by security D to work with the token. The other token Ds will be killed off. John Hurley And then after that process is done, established is called, and that's a chance for your code to do whatever it might need to do to initially set up the token.

Okay, so now that's a very, very brief overview of the architecture and configuration, whatever. Now we're going to dive right into the implementation. Okay, so the one-day token D, that's the goal. That's what hopefully we can do as we step through these different slides. You might think that the one-day token D is sort of hyperbole or whatever, but we've actually had more than one developer write a pretty functioning token D in a single day. John Hurley The standard token D for the common access card, DOD common access card, is only 1,900 lines of code total. And a lot of lines in that set of code don't have to be modified to make it work with your token.

John Hurley So, our goal...

[Transcript missing]

You can use either the Common Access Card or the BellPix sources from Darwin as starting points. And at some point pretty soon, we should have a sample token D where we took the CAC token D and stripped out everything that's CAC-specific so it's even easier to start from. The interesting thing is that most of the code, so I mentioned there were 1,900 lines in the CAC code.

Excuse me, in the CAC token D, I would say probably

[Transcript missing]

Okay, so our plan of attack for this one-day token D, we're going to go through a few steps here. Implement at least a stub for probe and identify, so that tells security D whether or not it should leave, you know, whether or not your token D wins and knows how to talk to the card.

There are two classes called XYZ record in this sample code and XYZ key record that we will modify to know more about our token. We'll add at least one key and one certificate in the populate call, and then we'll fill in the actual data in get data attribute. Then we'll try it out.

Okay, so there are a few functions that you will need to change. So starting from that base of either the XYZ sample or the CAC token D sample, you will have to change these functions. So they are probe, identify, which is really just a sub-function of probe. Populate, which will put items into the local database, and get data attribute. So these, you're going to have to write at least four functions.

Okay, so now let's go on to our stub for probe and identify. So you can see from the

[Transcript missing]

The point of Probe is that you, as the token D writer, know your token, and if somebody inserts a token, you need to know whether that's a token that you can handle or not.

If it's something that you can handle, return a score, say, of 100. Or if it's something you might be able to handle, maybe you'll return something like a 50. Whichever token D comes up with the highest score will stay running. John Hurley If you're familiar with PCSE and using that, there's a structure in there called SCARD reader state, and that is passed to this call, or it's available from this call, and you can get things like the ATR out of that.

If you decide that, yes, you really know how to handle this token and you want to be in charge of it, then you should do your best to fill in token UID with a really unique identifier for that card. So, the best thing is if your card has a, you know, you've issued it to employee, you know, 12345 and your company name is, you know, XYZ Corp, maybe return an identifier of, you know, XYZ Corp 12345.

And the reason that you want to do that is as part of establish, you get past a directory which is your cache directory and security D keeps track, helps you keep track of different cards that are inserted by this unique ID. So you want to try and... Okay. Do a good job filling that out.

Okay, so here's a very, very simple implementation of probe. You call the probe for the base class, which will do some basic stuff. You can go off and look at the class there to see the different things that it's doing, but you'll almost certainly want to do that.

[Transcript missing]

So looking at identify, again, you as the owner and manufacturer of the token or populator of the token are going to know what will uniquely identify that as one of the tokens that you know how to handle. It may be that you identify that by something in the ATR. In the case of, say, a Java card like the Common Access card, if you look at the sources for that, you'll see that it selects a particular Java applet. If it manages to select that, then it's pretty confident that it's found an actual CAC card.

Here it shows a couple things. You pull out the, by calling startup reader info, you will get back a copy of the ATR. And here at the bottom, you can see, well, okay, we're going to say if byte 12 and byte 14 are these values, then this must be one of our tokens.

Okay, so next, I'm not going to go over how you change XYZ record and XYZ key record in detail, but we do need to add at least one key and one certificate in Populi. So what Populate does is it's a chance for you to push records into the local database. So as I mentioned earlier on the architecture diagram, Say the file-based keychain is a combination CSP and DL, data library module.

That means it's a database of sorts. It contains your keys and passwords and secure notes and things like that. In this populate call, you're saying, okay, I have a few different record types on my token, and when the upper levels call down and make CDSA calls, it will be able to iterate through those records and find them.

So on this slide, you'll see that we're basically doing some database housekeeping here. We're describing to the schema class some of the different relations or tables that we have on this token database. So we have one relation for an X.509 certificate, we have a different relation for a private key, and we have another one for generic. Generic might be if you have data records. For example, the common access card has pay grade and it has social security number and date of birth and things like that. So those would be generic data type records.

One thing I didn't mention at the end there, you do not have to actually go and fetch any of the data at populate time. If you want, you can defer actual data retrieval to when somebody calls a get data attribute call. Okay, so to continue on with Populate, see the first set of lines there? It's creating a new certificate record called ID cert.

And the next two parameters there to the new call, there's one that's in blue that's K select XYZ applet PK ID. This is an example of something that you might be doing if you had a Java card. So on Java, Java cards you have applets which are little Java applets, you know, a subset of Java. And they have ATR kind of identifiers, you know, hex identifiers, and you pick a particular one and it will do a particular function for you.

So here I'm passing that as an identifier. If you have different type of token, that might not be relevant to you. So you can change, this is what I meant when I said you might have to change the XYZ certificate record call. In particular, the constructor to take something that's useful for you to be able to identify different applets or files on your token. And we passed along this name identity certificate. That's also just really for your purposes.

The second line of that cert relation dot insert record, you actually take that new cert record that you created and you add it into the local database. So this doesn't actually have any data in it yet. It's really just a pointer saying, yep, there's one certificate on this card. And if I had a bunch of certificates, I could either have a bunch of new calls or I could have a loop that goes and checks with my card or maybe most cards are very small.

They don't have a lot of items on them, so you can just enumerate them. We're going to do a very, very similar thing for the private key record. So you can see we're creating a new XYZ key record called IDKey. And again, we're passing in this XYZ applet PKID just to pick out that particular Java applet.

And then we're going to also insert that record into the local database. Now the last set of lines there, probably the least familiar to anyone. with the particular private key that you're working with, you want to be able to associate a certificate record. So we provided a way to do that by saying set adornment.

So you take the private key record and you say, oh, yeah, this private key, I use that certificate over there. So you don't have to do lots of searches to find the certificate that goes with the private key. That's all that line is really doing. Okay, so next we're going to fill in the data in getDataAttribute.

So, get data attribute is the actual call where you're going to be going off to your token and retrieving data. You will make the calls that you need to read the certificate data or do key operations. Sorry, not key operations. So, if you look at the CAC token, you'll see a really detailed example that has a lot of

[Transcript missing]

But what I did put in here, just to illustrate sort of the general layout of this call, You're passed in a reference to a token record.

And when this call is called. And I've highlighted the PCSC transaction. So you can use that class to start a transaction. And then the lines below that, you're going to do whatever you need to do with your card to retrieve that data. So in the case of a CAC card, you're going to be talking with that Java applet.

John Hurley There are classes that are built in to help you cache that data, which you may want to do. Like smart cards have very low data rate. So you're going to want to read the certificate once. It's public. You might as well cache it. So read it in. You can use these classes to help you cache that data. John Hurley At the end, you're going to end up with a blob of data that you want to return in this call. And you can see the last line there. The two parameters there are data.

John Hurley Data.data and data.length. That data is a CSSM data structure, which is just a pointer and a length. And you're going to return that up. And that will get passed up through the different levels and get mushed around as necessary to turn it into something that looks like a certificate.

Okay, so now that's it. Those are the four things that you had to change. So build it. You install it into system library security token D, which of course you have to be able to do that. And then try it out in keychain access. So there you go, success. This is what it should look like.

This is an example of actually the shipping CAC token D, but you'll see something very similar to this. You can see on the top left, this shows up as smart card number three. So it's a dynamic keychain, and it's just added to your keychain list. If you click on that, you will then see the contents of that keychain. So here you can see it has a couple different keys and a couple different certs, three keys and three certs on that token.

Okay, now, you probably did all that in about an hour, right? It's all ready to go, and you're practically ready to ship. But probably you should add some calls to the crypto code. So these are the calls that you're going to be calling or modifying to add the actual cryptographic operations for your token. So compute crypt.

Compute Crypt, I should point out, is where the bulk of your cryptographic work is going to happen. So you'll either be making requests to the card to do encryption or... you know, perhaps use a key in other ways. There's a lot of code, if you look at the CAC example, you'll see there's a lot of code that's there that deals with things like different types of padding, you know, notepad, pad, different RSA things. A lot of that code you should be able to reuse because it's just standard things that you have to do before you can set up for a cryptographic operation.

So in many cases you won't change any of those lines of code. But of course, ultimately you'll end up calling out either to your card directly or you may have a PKCS 11 library that you can make the crypto calls to PKCS 11 to actually have that library do the work for you.

You'll certainly need to implement verify pin if you want to be able to do anything that requires the card to be unlocked. That takes a pin number and the pin and the pin length. And you will be passed these from the upper layers. So for example, when you're logging in, if you set your machine up for smart card login and insert a supported token, you'll see that the login window dialog changes from password to pin. If you enter the pin, that'll go through security agent, which will talk with security D, which will then pass it down to your token D. So that's the path for that. Change pin, very, very similar type thing.

And pin status essentially tells you whether or not the card is unlocked or not. So if you think back to keychain access where you see the card is locked or unlocked, pin status will help the upper levels do the right thing in terms of showing you whether the token's locked or not.

Okay, so it's kind of a quick summary of token-Ds in general. TokenDs allow you to have shared access to different smart cards or other tokens. They're pretty simple to implement, especially using the C++ layer. It does require that you understand your particular token, but given that, the additional work involved to get these working with Mac OS X is relatively small on a development scale.

TokenD is not PKCS 11, although you can, if you want, you could wrap a TokenD around a PKCS 11 driver. Maybe you've written it for another platform, and that would be a good way to do it. We've had developers that have done, that have, you know, We already have an existing PKCS 11 driver, and one developer started wrapping their PKCS 11 library with a token D and realized, no, it's just easier to just call their functions directly. We had another developer that decided, no, we'll keep that separation so that it's easier for us to maintain. Either way should work for you.

It's certainly the additional work for writing a token D is much, much less work than writing a PKCS 11 library. Not only because, well, if you already have that, you already know how to do crypto operations with your token, but the C++ layers handle so much of the database management and the key management for you that you don't have to write a lot of things that you would have to do in a PKCS 11 library.

I didn't go into modifying the token at all. The callbacks are there, but we don't currently have any token-Ds that write to the card. If you are writing, say, a provisioning system for smart cards or tokens, It's possible that you'll want to do that just using, say, PCSC calls directly.

I think the main point behind a token D is that you get a user-level experience that's really, really nice because all these apps that the users are used to using, they don't have to do anything special for smart cards. They just kind of work once you have this token D.

For more information, you can contact Craig Keithley, who's the biotechnology and security evangelist. We have... Some sample code coming up, particularly the XYZ token, which hopefully we'll be able to release very soon. It's already completed. And in addition, you can look at the Darwin sources for the sources to the CAC and BellPIC tokens.