This page aims at clarifying a few points about the Yubikey and creating your own validation system, to complement the existing documentation.

Understanding the Key Usage

Before we go, you must understand this key is not designed to allow subscribing to different providers (like with distributing SSH public keys), but to contain full or partial credentials for one account on a particular provider. If you need to access say your own machines and your staff corporate machines via SSH and PAM+yubikey for example, then you must have two keys. As this is symetrical cryptography, both ends needs to access the secret and i guess you would not share your key between your personnal accounts and staff accounts. In this model, an account provider programs keys and distribute them among its users, which is perfectly appropriate for personnal or corporate purpose but not for a service provider. Nevertheless, your provider can act as an authentication service provider too, using OpenId for example, and then allowing sharing your account with several other service providers.

/!\ Beware you need to change the key data in you Yubykey to be able to manage your own accounts, and doing so will prevent you from using Yubico special services (most being available for demonstration purpose, and most being replacable, like having your own OpenID server; but you can still have a second key if you want to access Yubico's services).

Understanding the Key Internals

The yubikey hold several interresting data inside. A few of them can be modified by the user :

The public name can be whatever you want; you can, for example, set it to an empty string if you don't want to disclose to which it belongs (in case the key is lost), or use the name of your company, or even the name of the user, ... This field is often called the fixed part.

The private name can be whatever you want. It is not an important part of the security system, but can be used to identify the key uniquely. It can hold the real username for exemple (or a number, as the field is quite limited in length). It can also be used to shared the same AES key among user and still be able to distinguish the keys (to be able to revoke key rights if the key was lost, for example). This field is often called the uid part.

The management password is necessary to be able to change the data of the key. Beware not to loose it or you'll never be able to modify it (even if it seems to be possible to use the AES key instead, but i guess you would have lost it either). This field is often called the acc_code part.

The AES key is a secret number used to encrypt data and do the real security stuff. This field is often called the key part.

Also note the counter is never reseted, nor can it be modified, and is not designed to wrap. This is a security design decision, which implies the key would just stop working when it has been used too much. Happily, a better security device would exists long before it dies under most common usage. You can plug the device 65535 times before death, which correspond approximatively to 25 insertions/removals every day for 7 years, or 5 insertions/removals every day for 35 years.

The key does not disclose anything inside. When you push the button (or use the double-capslock sequence in the key with no button, an OTP is generated, but there is no way to get any other output. If you have the AES key, then you're able to decrypt the OTP and validate the identity of the user. In the OTP is also included a few other interresting information:

But, as said, the counter and use cannot be obtained without generating an OTP and decrypting it; nevertheless, it can be used by the validation server.

Creating your own Key

Installing the Personnalization Tool

First, you need to install a library providing all the necessary functions for the personnalization tools (not packaged yet). Get the latest tarball from this page (currently 1.4) and uncompress it.

Install the needed build dependencies:

 apt-get install build-essential

In the source directory:

 ./configure
 make
 make install

(This will install things in /usr/local, but you can pass parameters to the configure script to install it elsewhere)

Then, we can install the tools (not packaged yet). Get the latest tarball from this page (currently 0.92) and uncompress it.

Install the needed build dependencies:

 apt-get install libusb-dev

In the source directory:

 ./configure
 make
 make install

(This will install things in /usr/local, but you can pass parameters to the configure script to install it elsewhere)

Updating the Key Data

You must provide the uid parameter in hexadecimal format. Remember it is a 6 characters long string (not less, not more). You can convert a string to hexadecimal like this:

# echo -n "user01" | hexdump -v -e '1/1 "%02x"'
757365723031

You must provide the public name (fixed) parameter in either the hexadecimal or modhex format. The modhex format is a special encoding used to ensure characters sent by the key are always correctly interpreted whatever keyboard layout you use. You can convert a string to hexadecimal like this:

# echo -n "Foo Corp" | hexdump -v -e '1/1 "%02x"'
466f6f20436f7270

You can convert a string to modhex like this:

# modhex "Foo Corp"
fhhvhvdcfehvidic

You can then generate a new key with the uid and fixed parameters, either with the public name in hexadecimal format:

# ykpersonalize -ouid=757365723031 -ohexfixed=466f6f20436f7270
Passphrase to create AES key: 
Firmware version 1.3.5 Touch level 8864 Program sequence 19
fixed:fhhvhvdcfehvidic
uid:igiehgideceb
key:vujkuvbhchbfihjllrlhjvennfhvfdgt
acc_code:cccccccccccc
ticket_flags:APPEND_CR
config_flags:

or with the modhex format:

ykpersonalize -ouid=757365723031 -ofixed=fhhvhvdcfehvidic
Passphrase to create AES key: 
Firmware version 1.3.5 Touch level 8864 Program sequence 20
fixed:fhhvhvdcfehvidic
uid:igiehgideceb
key:jlevvbgtbueebltnielgfcvfdldthbbd
acc_code:cccccccccccc
ticket_flags:APPEND_CR
config_flags:

Your AES key is given in the key field. I suggest you use an empty password until you're ready for production (it is the acc_code field).

/!\ If you experience the following error:

USB error: could not claim interface 0: Device or resource busy

you can work around this problem with this tip. If it still doesn't work, you can try unbinding the device using the tip at the end of this thread.

You could also provide the AES key with the -a option, and various other options, but it is out of scope of this document. Check the ykpersonalize documentation for more information.

Each time the key data is updated, the Program sequence is increased.

The Validation System

You have a YubiKey and you know how to personalize it : but how YubiKey can authenticate you ?

PAM module

There is two PAM modules which can be used with Yubikey :

yubico-pam

Read documentation, list available issues and patch if you think it's needed. It works.

YubiPam

Control

Data ('yubikey entry') for yubikey authentication are stored by default in /etc/yubikey ('yubikey dayabase'). Tool ykpasswd allow to add or remove yubikey entries. When adding entrie ykpasswd -a -k AESKEY -f PUBLICKEY -p PRIVATEKEY joesmith return no error but tests of authentication failed (need some investigation). The other way to call ykpasswd allow successful authentications : ykpasswd -a -u joesmith -k AESKEY -o OTP

Configure PAM

For example /etc/pam.d/common-auth:

auth    requisite       pam_nologin.so
auth    required        pam_env.so readenv=1 envfile=/etc/default/locale

# if pam_list return success, use yubikey
# else use pam_unix
auth [success=ok default=1] pam_listfile.so item=user sense=allow file=/etc/yubiuser onerr=fail

# here yubikey
auth requisite pam_yubikey.so

# here without yubikey
auth [success=done default=die] pam_unix.so nullok_secure

With this configuration, yubikey usage is not mandatory for all users : only users listed in /etc/yubiuser (man pam_listfile for format) will use the pam_yubikey module. For other users, module pam_yubikey is skipped.

Online Validation System

This system is used by yubico-pam.

The system is split into 3 pieces:

This then defines an AAA system.

In this document we will explain how to setup the two first pieces, as the third one is not necessary to get a working and secure system.

The KSM

In this tutorial, we'll use the PHP KSM server provided by Yubico. The installation phase is properly described in this page, so this document won't duplicate information. The main problem after the system is ready, is to properly feed the database, which is the problem addressed here.

This KSM suggest using a file especially formated for adding many keys at once with the provided ykksm-export.pl script. For security purpose this file should be PGP signed by the user and sent to the administrator, with the content encrypted against the administrator's PGP key. This also avoid storing clear text sensitive files. This method may or may not be used, as you can simply add keys directly to the database using, for example, phpmyadmin.

Here is the meaning of each database field:

In the provided SQL script, the creator field is limited to 8 characters, but recent GNUPG utility return a 40 character key number, so you may want to extend it.

Considering the publicName field is modhex encoded, and the ykpersonalize tool returns modhex data, i choose to modify the program to accept modhex data for internalName and aesKey fields too. If you want to do so, use the following patch:

--- ykksm-decrypt.php.orig      2009-06-06 22:38:51.000000000 +0200
+++ ykksm-decrypt.php   2009-06-06 22:43:59.000000000 +0200
@@ -73,8 +73,8 @@
  }
 
 $row = mysql_fetch_assoc($result);
-$aesKey = $row['aesKey'];
-$internalName = $row['internalName'];
+$aesKey = modhex2hex($row['aesKey']);
+$internalName = modhex2hex($row['internalName']);
 
 $ciphertext = modhex2hex($modhex_ciphertext);
 $plaintext = aes128ecb_decrypt($aesKey, $ciphertext);

With this patch applied, the aesKey would be jlevvbgtbueebltnielgfcvfdldthbbd in the latest example.

Your KSM is now complete. You can use curl to test your installation, as described in the testing procedure at the end of the official installation recipe.

The Validation Server

In this tutorial, we'll use the PHP validation server provided by Yubico. The installation phase is properly described in this page, so this document won't duplicate information. The main problem after the system is ready, is to properly feed the database, which is the problem addressed here.

It is important to note this server is one possible implementation of a validation server. This one follows the Yubico's specification, but it is not the only possible system. In this one a key must be associated with some kind of account defined in the SQL database in the clients table.

Here is the meaning of each database field of this table:

The secret is used to create a HMAC signature for each message when it is not possible to contact the validation server securely, to ensure the request comes from the good user and the answer comes from the good server, to avoid a man-in-the-middle attacks. Then, if you cannot use HTTPS, you should make sure to use this shared secret between the user and validation server to improve things a bit. Beware the current implementation is broken, because if you use an insecure protocol, it doesn't enforce using a message signature. If you use a secure protocol, like HTTPS (and got the CA certificate properly to be able to trust the server replies), then your security level is much higher and you don't need to care about it (you can then leave the secret field empty).

The id field is necessary in this implementation, because it allow matching the OTP received with a user account. Without it it would not be possible to find the correct secret for the HMAC signature (because the secret is different for each user). It is also useful to gather user's statistics. If you use a secure protocol and don't care about these user information, then you might det rid of it if you wrote another validation server implementation.

Each time a valid OTP is found, a record of the latest key information is kept (or made the first time) in the yubikeys table. Here is the meaning of each database field of this table:

The counter, sessionUse, low, and high fields are used to prevent replay and phishing attacks. These are the security policies of the validation server. One could improve the software to add more checks.

YubikeyHelp (last edited 2010-06-16 23:02:44 by TheDuck)