Locking down the computer: USB-tokens plug into Linux-PAM

On Windows there is an increased use of configurations requiring an electronic key in the USB bus during logon. On Linux, this is currently still rare. We recently received a Linux developer's kit plus USB token, making it time for some development!

This article is modified from a previous publication in the Dutch Linux Magazine, issue 5 of 2003

The distributor Novaris sent us an ePass1000 key that plugs directly in the USB bus. The picture shows that it looks somewhat like a memory stick, but a key is much smarter than that. It employs a cryptographic processor, making it possible to perform calculations for authentication. Using this, a password can be kept hidden, but nevertheless be used for system logon.

The nice thing of these devices is mainly that it is an independent piece of hardware. Independent of the scaringly-complex computer with all its background programs, users and other impurities. No system can be as secure as one without users working on it. According to the commercial announcements, these pieces of hardware lend themselves well for hanging on ones key ring, but it is doubtful whether an agerage USB bus enjoys the weight of an average key ring. Well, extension cables for USB should solve that easily.

These keys allow something called two-factor authentication, in which two aspects are needed for proper authentication, namely something you know (a password) and something you possess (the hardware). Everything in the hardware is aimed at avoiding forgery of the hardware's functions. This does mean that some cryptography is involved, and as we will see, this allows for some decent tricks.

The internals of a key

Keys, formally known as cryptographic tokens, all have a similar internal structure. They offer a file system with read and write operations, plus special operations to be performed on the files. But in case you thought of file systems in the DOS world as a bumpy road, you are about to face a ride on a roller coaster.

Files in a token have a number instead of a name. Often written in hexadecimal notation, because that is so handy for 16 bit numerals (...) Basically this is no problem, because applications for a token only require a few fixed files. To support multiple applications on a single token, files can be placed in a directory, which can be named, so that applications need not interfere. In the sequel we will construct a directory named OpenFortress_pam_epass, containing a key that is distributed over files 0x0001 and 0x0002.

The files in a token can have a few predefined types -- in any case raw data is supported (to store certificates, public keys and if you care for it, your phone number) en secrets. The latter are important -- the contain the values that are strictly kept inside the token, and can only be used as input to cryptographic calculations. The secrets are safe, is the underlying idea. The casing of a token is intended to support that as well -- the best ones are `tamper proof' meaning that secrets will break before the encasing does so you will never be able to get them out. The ePass1000 classifies as `tamper evident' to indicate that you will clearly notice when the token has been physically assaulted.

As under Linux, files offer a form of access control. Raw data can be set with permissions for reading and writing, secrets can only be assigned permissions for use in crypto-routines. On the ePass, these permissions can be set to public, or only usable to the user, or only to the security officer (the token's root user, so to say) or never. The user is the person who signs on to the token with a password (tokens often call that a PIN-code) and the security officer has another password (called the SO-PIN) and token management rights. Every granted logon to the token is relinquished when removing the token from the USB bus, which is taken care of by the hardware.

Classes of cryptografic tokens

A few different classes of these tokens exist. We have all heard the term `smart card', which is a general reference to a card with a built-in processor. This is fairly simple technology, and not very good at keeping the contained information secure; in addition, the processor on those devices is not very powerful.

Security applications become possible on smart cards capable of particular complicated mathematical operations from the field of cryptography; if in addition they can encapsulate stored secrets and only use those for these cryptographic calculations, then they become usable for authentication.

It is becoming increasingly common for USB tokens to appear to the computer as a smart card reader with a nailed-on smart card, which creates tokens like the ePass. Useful, because standard software for smart cards works on these devices.

The cryptographic operations supported on these tokens can be distinguished in two categories, namely symmetrical or a-symmetrical. The latter is the most powerful, because it supports public key operations. We will first take a look a look at these two classes of crypto-algorithms; but before doing so, let's take a quick look at passwords in plain vanilla Linux systems.

Passwords, the standard Unix way

Normally, users logon to Unix systems such as Linux using a password. This is not verified in the login-program by comparing the typed password to one stored on the system, but by comparing the outcome of a one-way function applied to the typed password to dito stored information. Classically, the one-way function was crypt, but modern developments increasingly embrace the so-called `secure hashes' because these are very thorough in this one-way property.

Secure hashes are easy to calculate, for example using the secure hash algorithm MD5. For example, try these two commands:

echo -n Yippi | openssl md5
echo -n Yippy | openssl md5

Even though these rules hardly differ, they give totally different results:

f588b7f2bbca96d18fb54e2f9ebf0c7a
3803470d6e0289558662961eda63eb30

These two values are 128 bit long, as always returned from the MD5 algorithm ,and this small differentation in input causes an output difference of 67 bits, or 52.3% of the bits. No matter how much or how little you change, the number of changing bits will always approach 50% -- bit it cannot be predicted which ones. In other words, the chance the the output reveals any pattern in the input is minimal. In fact, it is so minute that it is not considered harmful to ignore it.

Current recommendations advise to use SHA1 instead of MD5 as much as possible, because the latter is not believed totally safe from so-called `birthday attacks', but hardware cannot advance as fast as software, so tokens for symmetric operations will often still be MD5-based.

In the /etc/shadow file (or in /etc/passwd in older distributions) you see a weird character sequence for each account, and as you may have guessed these are the ones compared to the hash of the password you typed when logging on. This means that your password is not stored on the system, only a value that is derived from it and that cannot be used to recover the password itself. Mathematics can be useful at times, eh?

Symmetric authentication

Some applications require a bit more protection, particularly when an intermediate network is involved. Imagine a malicuous lad tapping network traffic and oping to replay parts of it. For example until you have logged on to a service. A password is particularly interesting for this lad, but also a hash of a password, because if it crosses the network it appears to suffice for authentication.

What you would prefer in such an application is an authentication sequence that is different every time, in such a way that the server that you logon to influences the variation. This is possible with so-called challenge/response systems. These do not calculate the hash over just the password (which is constant over long periods) but over the password plus a server-determined sequence of random bits, the so-called challenge. Imagine the password being `sekreet' and the challenge from the server being `abcde', then the response to such a challenge could be calculated with something like this:

echo sekreet:abcde | openssl md5

The outcome of this calculation is the so-called response, and it is sent to the server who repeats the calculation and compares his outcome to the client's. Next time the challenge will be a different one, and thus the response will be different. Which is a pitty for the wire-tapping lad, because he will not get anywhere trying to replay the authentication sequence.

The ePass1000 is capable of this kind of challenge/response algorithm, and nothing more than that. It uses the popular HMAC-MD5 algorithm to do this, which is a well-standardised authentication approach. The password `sekreet' is sent to the token only once, and from this it infers internal secrets that can only be used through the HMAC-MD5 algorithm. This algorithm is invoked with the `abcde' challenge, in reply to which it produces the response, using a calculation which is a bit like the one shown before.

Before feeling all warm and fuzzy about this approach, it should be noted that this is still a bit of poor man's crypto. The tokens fall in the same price range as the popular storage sticks, but the applications are somewhat limited. This is because the password itself is required on the authenticating side. If this side is well-protected from break-ins that is not much of a problem, but if it is intended for logon to your own system it would require storage of the literal password, which is far from desirable! But keep reading, this can certainly be stretched somewhat.

Public key authentication

The ideal cryptographic mechanism is that of public key authentication. The algorithms implemented for this purpose are usually RSA and DSA. These algorithms are complex, increasing the cost of the hardware. A few names of tokens capable of running them are the iKey USB-token, the STARCOS smart cards and the ePass2000.

Public key authentication involves two keys that reverse each others effect. One key is kept secret (preferrably encapsulated on a cryptographic token) and the other may be announced publicly (perhaps as a certificate, which attaches your identity to it).

Hardware tokens that provide these operations will be capable of generating keys internally, and the private keys will never leave the token if it is instructed thusly. For those who need it there is a bypass allowing the import of a private key from one's pre-token period. As may be clear, the operations invoked on this class of tokens are not HMAC-MD5, but private key operations for the intended public key algorithm, such as RSA.

If you send a challenge to this class of token, its response is calculate with a private key operation. The validation of this response is done by reversing this calculation with the public key. Since the latter is widely published, this form of authentication does not involve secret data on the validating side, only public data. This shows the power of public key crypto. And it is the reason why it is usable for digital signatures as well -- they can only be placed by the individual owning the private key, but everybody can validate them.

Hardware also tends to lag behind a bit in this area -- constant advances in computer power and in cracker knowledge the keys must be made a few bits longer every year. RSA keys of 1024 bit are the longest possible for most hardware tokens, while the most sceptical sources stopped trusting this key size in 2002, based on sound reasoning and accurate calculations. To comfort token users somewhat, it is worth noting that an enormous temptation to crackers exists, namely VeriSign who seems unhindred by this knowledge; they still use root keys of this size and claim that they are reliable for the coming 25 years. VeriSign is as popular in the crypto-arena as Microsoft under Linux users, so it remains to be seen if this is a smart course of action...

A crypto-trick

To achieve the maximum effect with a simple symmetric token, some creativity was needed. It would be unacceptable to store a password in literal form on a hard disk of a system to logon to. In addition, the secret password stored on the token should never be retrievable from it. This turnt out to be possible!

At some point you can deduce from a successful challenge/response interaction that the right key is in the USB bus, and as long as it has not been pulled out you can send it another challenge, to see what response the token calculates from it. If you would store this challenge/response pair for use at a future moment, you could then use it to establish that the same token is plugged into the USB bus. At that time you can calculate yet another challenge/response pair, and so on. This way, the token actually behaves like a key, because the same piece of hardware is required every time. At least, if a sufficiently long random bit string is stored in the key as the secret for the HMAC-MD5 operation, and if this bit string is not stored anywhere else.

The tripwire in this approach is the storage of the repsonse on the hard disk. If someone broke into the system he could tap it, and offer it to the system with a self-programmed USB device. At that time, the key could be made unneeded for future authentication, which is highly undesirable. The solution to this problem happens to be quite simple: instead of storing the response on hard disk, the secure hash of the response can be stored. Doing so makes it possible to validate the token's response values, while the response cannot be derived from stored data, if it were read in some devious way.

Even so, there are still issues requiring attention -- overwriting the challenge/response-hash pairs on the hard disk with a once-tapped value still makes replay attacks (on the USB bus), and you must rely on the non-tappability of the USB bus. But this is as far as we can see symmetric tokens can be stretched. Even if it is not perfect, it still is a very good method of authentication.

Linux-PAM completes the application

The ePass1000 devekit for Linux comes with a halfway attempt to support PAM, but it appears that the programmer struggled with it and came to the conclusion that on-disk password storage was needed, and that he did not make the creative step that we did in the above. Please ignore the devkit PAM-code for that reason, but install my code which is available for download.

We can specify the ePass module as an alternative approach for logon by adding to files like /etc/pam.d/sudo a line like

auth sufficient /lib/security/pam_epass_onetimehmac.so realm=admin

This uses admin as the name of the realm (or authentication-environment) to logon to. This module searches in /etc/pam_epass/onetimehmac for a directory with the name of this realm, and underneath for the user logging on -- for su the latter is always `user=root' by the way. The thusly found directory must store a challenge/response-hash pair for that realm/user combination, which can be setup with

welcome_pam_epass_user user=root realm=admin

The same command is used to recover damaged access rights; the key must be plugged in to support this, and it goes without saying that these directories must be protected from abuse; the welcome_pam_epass_user arranges all this.

Errors that occur while attempting authentication are reported in the secure log, usually /var/log/secure, that should be readable to root only. PAM does not provide detailed feedback on the desktop, for reasons of security. If this authentication alternative functions properly, it is possible to replace sufficient in the PAM configuration line with required -- in other words, using the key as a requirement on top of existing ones. Take care with this, because doing it wrong may lock you out from the system and you may need an alternative boot medium to gain access -- if your BIOS permits...

The most interesting PAM configurations to experiment with are probably su and sudo to become root, as well as gdm, kdm, xdm and login for system logon. The only thing that implements too little of PAM to work properly is xscreensaver, which is a pitty because that would have made it possible to demand token-supported system access after the screensaver starts due to a timeout or desktop lock.

The result... is wonderful!

As demonstrated above, it is possible to use even the simples crypto-token to construct a powerful authentication mechanism for your Linux system. It is thanks to the flexibility of Linux-PAM that it becomes straightforward to use the key as an add-on restriction to all sorts of services; depending on needs as an added constraint or as an alternative authentication mechanism instead of plain passwords.

It is wonderful to see your good-old system suddenly refuse your access if the token is not in the USB bus. And that you are welcome as before after plugging in the key. This gives the tingling sensation of control over one's system that we like so much about Linux.

Linux-PAM, an obvious success

PAM is short for Pluggable Authentication Modules, en this essay explains the workings of a pluggable module made for ePass hardware tokens. The /etc/pam.d directory is the home of an authentication configuration file per application, for example su and login. In these files, there are `auth' lines with constraints on authentication. For example to indicate that the root user may skip authentication you would write

auth sufficient /lib/security/pam_rootok.so 

and to indicate that traditional Unix-authentication with a username and password is required, you would write

auth requried /lib/security/pam_unix.so

These constraints can be stacked ias desired. Either all required rule must succeed at the same time, or a single sufficient rule must succeed.

PAM is sufficiently flexible to reques additional information, such as the PIN of the token. On RedHat 8 this worked fine with gdm, su, sudo and login. Only xscreensaver turnt out a disappointment because it neglected to fulfil these standard PAM requests.

PAM has orignally been developed on Sun systems, followed by Linux, and because it is so powerful it has caught on quite well ever since. Aside from Linux and SunOS, it is also available for FreeBSD, Mac OS X, HP-UX and IBM systems. In most cases the Linux implementation, known as Linux-PAM, is used so we can safely say that this Linux project is an abvious success!

Cheaper than Windows... what's new?

As explained before, the most ideal authentication systems are based on public key cryptography, but this is also the most expensive form. The calculations are complicated, and demand much more from the hardware, which is correspondingly more expensive.

The ePass1000 is a bit overzealous with this form of authentication -- it comes with a Windows-library that provides public key functionality, but that is a bit too suggestive. Since the public key calculations must be run in software, the secret key has to be retained from the ePass and this voids all advantages from using a hardware token. So do not use this functionality.

To logon to Windows with a token, you are therefore forced to use public key tokens, and to pay more money. Which can become quite costly for a company that wants to provide each employee with a token. This techology is cheaper for Linux because it employs a simpler token at the right level. Note that this was only possible because Linux provides the openness to deal with this approach!

Killer app? Circumvent root passwords

Distributions such as RedHat usually ask for the root passowrd before allowing you to edit the system configuration. This usually goes through access configuration files in the /etc/pam.d directory, so it can be adapted. It is useful to introduce a new realm for it, for example `syscfg', in which you use welcome_pam_epass_user to welcome only those users who may configure the system.

Then, edit all PAM files for these configuration tools, inserting a first line like this:

auth sufficient /lib/security/pam_epass_onetimehmac.so realm=syscfg

The now-welcome users need not use the root password to administer the system -- the presence of the ePass suffices. And thanks to PAM it is possible to be very subtle in the things that may, and may not be done. It would even be possible to use a separate (red?) ePass dedicated for system configuration tasks if you would want to!

Links


 
   ------ 8< ---------- 8< ----------- 8< ------ | OpenFortress*