Saturday, 15 March 2014

Importing your existing GPG key into a Yubikey Neo using Linux

NOTE: Since July 2014 Yubico have been shipping the Neo with the required applets already installed. You should be able to skip the first half of this guide. I've left it up for anyone who wants to start using an older Yubikey.

The Yubikey Neo is a very interesting piece of kit. It can generate secure passwords on the press of a button via a USB connection or by swiping over a NFC sensor. This allows it to be used as a second factor authentication for a variety of websites and services like Lastpass. I've previously blogged about getting a Yubikey working to authenticate a VPN tunnel with Netscreen SSG Firewalls linked to Active Directory and use it to secure my Lastpass account. However it can also be used as a CCID virtual smartcard for encrypting files with GPG and authenticating SSH connections in a very secure manner. Because your private key is stored on the Yubikey Neo and can not be removed this means that you can use it in less secure environments without the risk of your private key itself being compromised.

There are already lots of good guides on the net regarding how to do this if you are happy to generate your private keys on the Neo itself however this has one big drawback (which is also one of the big security features). A private key cannot be removed from the Neo. This means that if you generate the key on the Neo itself and then lose the Neo you have lost your only copy of that private key. In many cases this is good - you do not want anyone to "borrow" your Neo and copy your private keys. Generating new Keys can be done relatively easily. However if you already have a private key that you use in secure environments but also want the ability to access it elsewhere (maybe you have a private key you use personally which you want to also use at work but all the system administrators at your work can access your work file system for example) then I have not seen many guides for importing existing keys to the Neo. Partly this is because the firmware that comes with the Neo only supports generating keys on the device not importing. Once you hit software that needs compiling a lot of assumed knowledge can get in the way. So for a full walk-through of adding an existing key to a Neo read on:

Initial Linux Setup

The first thing you will need to do is get a Yubikey Neo (Sorry, it has to be the Neo for now - other Yubikeys do not include the ccid/GPG abilities).

For this guide I started with a fresh install of Debian 7.3.0 64 bit from the netinstall image and then upgraded to testing (from Wheezy to Jessie). I did not install the Desktop or Print Server components during install but if you do this with a desktop installation then it should not make much difference. Any recent Linux distro should work but writing this guide from a fresh install means you can reproduce my steps exactly if required. I had multiple issues with Gnupg 2.0.19 which is the version in Debian Stable which is why I upgraded to Testing which has version 2.0.22 (improved support for card readers).

The first step is therefore to install Debian Stable and check internet access is working. To upgrade to Debian Testing edit /etc/apt/sources.list and change every instance of the word wheezy to jessie. Then start the upgrade - this step will take a while.
# apt-get update
# apt-get dist-upgrade
 - Accept warning about needing to uninstall a few packages that are blocking the upgrade, then later press q to close the screen of upgrade notices about various packages.
After upgrading I always prefer to reboot to ensure there are no unexpected issues that will appear next time I turn the machine on. There are then a few packages that you need to install from the repositories so you might as well get them all now:

To compile the new applet for installing on your Yubikey you will need:
# aptitude install openjdk-6-jdk ant
# aptitude install junit4
To compile the Yubikey Personalisation Tool you also need:
# aptitude install libyubikey-dev pkg-config libusb-1.0-0-dev libjson0-dev make
And to compile gpshell (for installing the new applet on the Neo) you need:
# apt-get install libpcsclite-dev zlib1g-dev libssl-dev
GPG version 2 is required for this:
# apt-get install gnupg2 scdaemon
Finally to actually access the card you need pcsc:
# apt-get install pcscd
Download the Java Card Classic Development Kit from http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javame-419430.html#java_card_kit-2.2.2-oth-JPR, then extract some of the files:
# mkdir jckit
# cd jckit
# unzip /path/to/java_card_kit-2_2_2-linux.zip
# cd java_card_kit-2_2_2/
# unzip java_card_kit-2_2_2-rr-bin-linux-do.zip

Compile the new Applet

Then you will need to download and compile an upgraded applet from https://github.com/Yubico/ykneo-openpgp/tree/features/jckit3. Download the applet source directly from https://github.com/Yubico/ykneo-openpgp/archive/master.zip, unzip and compile it.
# wget https://github.com/Yubico/ykneo-openpgp/archive/master.zip
# unzip master.zip
# cd ykneo-openpgp-master
# ant -DJAVACARD_HOME=/path/to/jckit/java_card_kit-2_2_2/
You should now have a cap file in the sub folder applet/bin/openpgpcard/javacard/openpgpcard.cap

Enable CCID mode on Neo

By default the Yubikey Neo does not have CCID smartcard functionality enabled, so that needs to be turned on. http://opensource.yubico.com/yubikey-personalization/

Note: If you want a slightly quicker way to do this then download the Windows version - it comes with a pre-compiled executable so you can jump straight to running the command.

# wget http://opensource.yubico.com/yubikey-personalization/releases/ykpers-1.15.0.tar.gz
# tar xvf ykpers-1.15.0.tar.gz
# cd ykpers-1.15.0
# ./configure
# make check install
# ldconfig
Plug in your Neo now - you are ready to enable the CCID functionality.
# ykpersonalize -m82
Confirm that you want to set mode 0x82 Take the NEO out and plug it back in to restart it in the new mode.

Install updated openPGP Applet on Neo

Download the gpshell, global platform and the gppcscconnectionplugin  from  http://sourceforge.net/projects/globalplatform/
# tar zxvf globalplatform-6.0.0.tar.gz
# cd globalplatform-6.0.0
# ./configure
# make
# make install
# cd .. 
# tar zxvf gpshell-1.4.4.tar.gz
# cd gpshell-1.4.4
# ./configure
# make
# make install
# cd .. 
# tar zxvf gppcscconnectionplugin-1.1.0.tar.gz
# cd gppcscconnectionplugin-1.1.0.tar.gz
# ./configure
# make
# make install

Unplug the Neo and plug it in again so it is detected correctly. Now you need to go back to the ykneo-openpgp-master folder (from when you compiled the applet) and install the applet on the Yubikey:
# LD_LIBRARY_PATH=/usr/local/lib gpshell gpinstall.txt
You should be rewarded with several screens of text rushing by.

Prepare GPG key and back it up

The Yubikey NEO can support GPG keys up to 2048 bit RSA - bigger keys will not fit. A lot of people store their main key offline and generate encryption and signing subkeys which they import onto a card for day to day use. This has the advantage that if the card is lost they can just generate new encryption and signing subkeys and their main GPG identity will not lose all the signatures which validate their real identity. Another advantage is that the main key can then be 4096 bits in strength (if you are that paranoid) and the subkeys only 2048 bit so they fit on the The certification part of the key is not present however so they will not be able to certify any other persons key is genuine without getting access to their main/full key.

By default GPG will create 2 keys - the first is used for signing (files) and certifying (other GPG keys). The second is used for Encryption. I'm going to create a new subkey for signing so only this goes onto the Yubikey. Gpg outputs a lot of text and this post feels big enough already so I'm going to skip most of the output - you will get far more on your screen than is shown here.

First to add a new signing key of 2048 bit size. My main key ID in this example is 3edda8ae - change this for your ID:
# gpg2 --edit-key 3edda8ae
pub  2048R/3EDDA8AE  created: 2014-03-14  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
sub  2048R/581671D8  created: 2014-03-14  expires: never       usage: E
[ultimate] (1). test key (test 2048R key) <[email protected]>
gpg> addkey
Please enter the passphrase to unlock the secret key: *****

Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
Your selection? 4
What keysize do you want? (2048) 2048
Key is valid for? (0) 1y
Is this correct? (y/N) y
Really create? (y/N) y
pub  2048R/3EDDA8AE  created: 2014-03-14  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
sub  2048R/581671D8  created: 2014-03-14  expires: never       usage: E
sub  2048R/5B48E4AF  created: 2014-03-14  expires: 2015-03-14  usage: S
[ultimate] (1). test key (test 2048R key) <[email protected]>
You should now be able to see the extra line ending in "usage: S" to denote the signing only key. If you are using an existing key and the Encryption key is not shown as "sub 2048R" then you will need to create a new encryption subkey as above but choosing "RSA (encrypt only) as the type.

Final step before you move the keys to the Neo is to back them all up. If you do not want to trap your only copy of the private key on a Neo then back it up first! Once more because this step is important: BACK UP YOUR KEYS!
gpg> save
# gpg2 --export -a 3edda8ae >public_key_backup.key
# gpg2 --export-secret-key -a 3edda8ae > private_key_backup.key
# ls
private_key_backup.key      public_key_backup.key

Move these backup files somewhere safe - you do not want to accidentally overwrite or delete them. Next lets put the encryption subkey onto the Yubikey (you need to pulg the Yubikey in now if it is not already):

Move the keys to the Neo

# gpg2 --edit-key 3edda8ae
gpg> toggle
sec 2048R/3EDDA8AE created: 2014-03-14 expires: never
ssb 2048R/581671D8 created: 2014-03-14 expires: never
ssb 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14
(1) test key (test 2048R key) <[email protected]>
gpg> key 1
sec 2048R/3EDDA8AE created: 2014-03-14 expires: never
ssb* 2048R/581671D8 created: 2014-03-14 expires: never
ssb 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14
(1) test key (test 2048R key) <[email protected]>
gpg> keytocard
Please select where to store the key:
(2) Encryption key
Your selection?
2
Please enter the passphrase to unlock the secret key: *****
scdaemon[22389]: 3 Admin PIN attempts remaining before card is permanently locked
Please enter the Admin PIN: *****
writing new key
sec 2048R/3EDDA8AE created: 2014-03-14 expires: never
ssb* 2048R/581671D8 created: 2014-03-14 expires: never
                                     card-no: 0000 00000001
ssb 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14
(1) test key (test 2048R key) <[email protected]>
"key 1" selects the first subkey (it is shown with an asterisk). "keytocard" MOVES the selected subkey to the card after you have confirmed both the gpg pass-phrase as well as the card administrator pin. There is only one slot to store this kind of key so you need to choose option 2. Finally the keys are shown but with the encryption key having a card number underneath it to show it is no longer present on the computer.

Next we need to move the signing key to the NEO:
gpg> key 1
gpg> key 2
sec  2048R/3EDDA8AE  created: 2014-03-14  expires: never  
ssb  2048R/581671D8  created: 2014-03-14  expires: never  
                     card-no: 0000 00000001
ssb* 2048R/5B48E4AF  created: 2014-03-14  expires: 2015-03-14
(1)  test key (test 2048R key) <[email protected]>
gpg> keytocard
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1
Please enter the passphrase to unlock the secret key: *****
writing new key
sec  2048R/3EDDA8AE  created: 2014-03-14  expires: never  
ssb  2048R/581671D8  created: 2014-03-14  expires: never  
                     card-no: 0000 00000001
ssb* 2048R/5B48E4AF  created: 2014-03-14  expires: 2015-03-14
                     card-no: 0000 00000001
(1)  test key (test 2048R key) <[email protected]>
gpg> quit
Save changes? (y/N) y
"key 1" deselects the first (encryption) subkey, then "key 2" selects the second (signing) subkey. "keytocard" is used to MOVE the signing subkey to the NEO. Finally quit saving changes.

As a quick test remove the Neo. Encrypt a random file to this new key and then try to decrypt it - you will get an error:
# echo "my secret message" > test.txt
# gpg2 -r test -e test.txt 
# ls
test.txt      test.txt.gpg
# gpg -d test.txt.gpg 
gpg: pcsc_list_readers failed: unknown PC/SC error code (0x8010002e)
gpg: card reader not available
gpg: encrypted with 2048-bit RSA key, ID 581671D8, created 2014-03-14
      "test key (test 2048R key) <[email protected]>"
gpg: public key decryption failed: general error
gpg: decryption failed: secret key not available
 Now plug the NEO in again and run exactly the same command:
# gpg -d test.txt.gpg 
gpg: detected reader `Yubico Yubikey NEO OTP+CCID 00 00'
Please enter the PIN
Enter PIN:
*****
gpg: encrypted with 2048-bit RSA key, ID 581671D8, created 2014-03-14
      "test key (test 2048R key) <[email protected]>"
my secret message
The output at the end will be the secret message you added to test.txt. This would only be possible to decrypt with the NEO plugged in, as only a stub of the private encryption key is stored on the local hard drive.

You can now backup the private key from your computer (which only contains a stub of the full private key). This stub and the public key you saved earlier can be manually imported on any other computer without risking loss of control of your keys as you also need the Yubikey connected to use it.

From your working computer:
# gpg2 --export-secret-key -a 3edda8ae > private_key_backup_STUB.key
Copy those 2 files to another computer and import them with:
# gpg2 --import public_key_backup.key
# gpg2 --allow-secret-key-import --import private_key_backup_STUB.key
You can make life a bit easier in 2 ways. Firstly if you upload your key to a keyserver then you can automatically pull down the required files with this command (after plugging in the NEO):

# gpg2 --card-edit
gpg/card> fetch

If however you do not want to upload this key to the public keyservers you can upload it to a specific url and program the NEO to look there. The --armor switch below instructs gpg to only use a character set that is safe to use in emails (mail programs have a habit of treating some obscure characters inconsistently which is not good if those characters are in the middle of your key!

# gpg2 --armor --export 3edda8ae > public_key_armor.key

Upload this file to anywhere you control and make a note of the direct link to the file. I uploaded to my Dropbox account so for me the file was accessible at https://dl.dropboxusercontent.com/u/120364/public_key_armor.key. We need to add this link to the URL field of the NEO:
# gpg2 --card-edit
Application ID ...: D2760001240102000000000000010000
Version ..........: 2.0
Manufacturer .....: test card
Serial number ....: 00000001
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: 2048R 2048R 2048R
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
Signature key ....: 26EF 14F4 A5B6 B24A 0EFE  E39C F5E2 68CB 5B48 E4AF
      created ....: 2014-03-14 16:56:48
Encryption key....: CFA0 0AE0 1C27 0463 36DE  2960 0FBF CAD4 5816 71D8
      created ....: 2014-03-14 16:22:28
Authentication key: [none]
General key info..:
pub  2048R/5B48E4AF 2014-03-14 test key (test 2048R key) <[email protected]>
sec   2048R/3EDDA8AE  created: 2014-03-14  expires: never  
ssb>  2048R/581671D8  created: 2014-03-14  expires: never  
                      card-no: 0000 00000001
ssb>  2048R/5B48E4AF  created: 2014-03-14  expires: 2015-03-14
                      card-no: 0000 00000001
gpg/card> admin
Admin commands are allowed
gpg/card> url
URL to retrieve public key: https://dl.dropboxusercontent.com/u/120364/public_key_armor.key
scdaemon[2887]: 3 Admin PIN attempts remaining before card is permanently locked
Please enter the Admin PIN :
gpg/card> quit
You can check this worked as expected by running gpg2 --card-status and checking the output now contains your URL. To make this a decent test I am going to delete the entire local public and private keyring files, then import the keys using the NEO and online public file before repeating the encryption test I performed earlier to prove decryption only works with the NEO installed. First to delete the local files:
# cd .gnupg/
:~/.gnupg# ls
gpg.conf  private-keys-v1.d  pubring.gpg  pubring.gpg~ random_seed  reader_0.status  secring.gpg  trustdb.gpg
:~/.gnupg# rm pub ring.gpg
:~/.gnupg# rm pubring.gpg~ :~/.gnupg# rm secring.gpg :~/.gnupg# rm trustdb.gpg 

Trying to list keys will now just show GPG creating new keyring files:
:~/.gnupg# gpg2 --list-keys
gpg: keyring `/root/.gnupg/pubring.gpg' created
gpg: /root/.gnupg/trustdb.gpg: trustdb created

Time to fetch the public key. Plug in the NEO and run the following commands:
:~/.gnupg# gpg2 --card-edit
gpg: keyring `/root/.gnupg/secring.gpg' created
scdaemon[3125]: reading public key failed: Card error
Application ID ...: D2760001240102000000000000010000
Version ..........: 2.0
<SNIP extra info>
Sex ..............: unspecified
URL of public key : https://dl.dropboxusercontent.com/u/120364/public_key_armor.key
Login data .......: [not set]
<SNIP extra info>
gpg/card> fetch
gpg: requesting key 5B48E4AF from https server dl.dropboxusercontent.com
gpg: key 3EDDA8AE: public key "test key (test 2048R key) <[email protected]>" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
gpg/card> quit

You can now try encrypting a message to your private key and it will only decrypt if the NEO is plugged in:
# echo "my secret message encrypted to NEO key" > test_file_Neo.txt
# gpg2 -r test -e test_file_Neo.txt
# gpg2 -d test_file_Neo.txt.gpg 
scdaemon[3285]: DBG: asking for PIN '||Please enter the PIN'
      "test key (test 2048R key) <[email protected]>"
my secret message encrypted to NEO key
Congratulations! Firstly for reading through everything above (assuming you didn't cheat and skip all the way down here!) You should now have a GPG key which you can use relatively easily on any computer with GPG but you do not need to place the private key on that computer. For me this means I can freely use my personal GPG key on work computers without any chance of losing control of a copy, but it could just as easily be that you want to protect your work GPG key when visiting client sites.

I have not tested this thoroughly on different distributions but as far as I know any distro with gnupg 2.0.22 available should also meet the other requirements. If you know of any distros that this will or will not work on then please let me know and I'll update this guide. Any questions please ask - I'll help if I can.

Changing the user and admin pin on the NEO

Use of the gpg key stored on the NEO requires you to enter a pin code (default is normally 123456). Getting the pin code wrong 3 times locks the user pin. The default admin pin is normally 12345678. Getting the admin pin code wrong 3 times will lock the card and cannot be reset. Make sure you remember these pin codes!

use the "gpg --change-pin" command and change both the user and admin pin to something you will remember:
# gpg2 --change-pin
gpg: detected reader `Yubico Yubikey NEO OTP+CCID 00 00'
gpg: OpenPGP card no. D2760001240102000000000000010000 detected
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Other things to do

There are several other things you should do to if you have not already:

Problems...

There are a few problems that are worth bearing in mind when following this guide depending on how secure you want your end result to be.

Randomness matters. A computer builds up a pool of entropy from various sources during use. This entropy is then used by /dev/random when anything needs random numbers - however on a clean install with no extra software running that has probably only just booted up there is not much entropy to go around. This could lead to weak keys being generated. A program like haveged may well eliminate this problem if you can not use a genuine hardware random number generator like the Entropykey (I know nothing about this project beyond the fact is looks cool and is reasonably cheap).

By using Debian Testing I am also using a system with less immediate security patching. Stable Debian receives security patches very quickly and Unstable Debian also receives them quickly (but then it receives everything quickly, including patches, new software and new bugs/security problems - that is why it is called "Unstable" Testing Debian tends to receive updates after they have been tested a for a while and have no known serious bugs so sometimes a security problem might be unpatched on Testing after both Stable has been patched and Unstable has received a newer version that also fixes the problem. Alternatives if you are concerned - gnupg 2.0.22 is not in Debian Backports so you could either manually install packages from the Debian Jessie repository or use a different distro with a later version of gnupg. Or compile gnupg from source if you were feeling adventurous.

I did all this as the root user. Normally bad but in my defense: A lot of this had to be done as root anyway, you need to trust the system you are generating the keys on completely (eg don't use if for browsing facebook!) and you have to trust the software you are installing completely. Since I'm using a fresh minimal install and not connecting to random internet sites the risks are minimized.

Troubleshooting

Yubikey Neo not recognised as a CCID device.

If you are using an older distro that does not fully recognise the Yubikey Neo as a ccid device then you need to take a few more steps:

A Debian Wheezy install I have been using does not know that the Yubikey can be a smart card. Not too hard to fix though: edit /etc/libccid_Info.plist. You need to add two lines at the top of 3 sections.
Find array ifdVendorID and add the following two lines at the top:
<string>0x1050</string>
<string>0x1050</string>
Find array ifdProductID and add the following two lines at the top:
<string>0x0111</string>
<string>0x0112</string>
Find array ifdFriendlyName and add the following two lines at the top:
<string>YubiKey Neo Composite</string>
<string>YubiKey Neo CCID</string>
Restart the service:
/etc/init.d/pcscd restart
Unplug and replug the neo and the output of dmesg should now include "Yubikey NEO OTP+CCID"


Guides used to create this guide:

Far too many web pages to list fully, but the main sources of information I used were:
https://github.com/Yubico/ykneo-openpgp
Yubico Forums eg: Adding the Yubikey Neo to known hardware (not required in the end as I switched to Debian Testing) http://forum.yubico.com/viewtopic.php?f=26&t=982&start=10#p3767
Creating subkeys and seperating out from the main key for security reasons: http://www.void.gr/kargig/blog/2013/12/02/creating-a-new-gpg-key-with-subkeys/
How to add GPG keys to cards: http://www.gnupg.org/howtos/card-howto/en/ch05.html

If you have any comments or suggestions then please let me know.

6 comments:

  1. augh. EXISTING KEY. There should only be a few steps. Why did you copy and paste instructions that are like five years old? Simplify. Linux is already installed, applets are already installed. Why post information that isn't necessary. Hurts my head. I quit.

    ReplyDelete
  2. Sorry to have given you a headache! ;)
    Unfortunately at the time of writing many distro's did not have a compatible version of GPG, the Yubikey did not come with the applet installed and I was looking for a challenge to learn from. As I mentioned in the article if you want an easy option the windows tools let you do most of this much more easily. That said I am sure many more Linux distro's now work out of the box and all recent Neo's have the applets pre installed anyway making most of this article redundant.

    ReplyDelete
  3. Hello, all. I am trying to install my existing PGP key into my brand new yubikey neo n, using my Linux Mint 17.1 machine. Can you tell me how to do this (in a simple or otherwise way?) I tried following the steps, but I do not get the cap file, apparently because I do not have a java compiler.

    ReplyDelete
    Replies
    1. Hi Roberto,

      Good news: since July last year all new Yubikeys have had the applets etc already loaded so you can skip 75% of my guide! :)

      If you start at "Move the keys to the Neo" it should work out for you. Just make sure you have pcscd, scdaemon and gnupg2 installed.

      Mint 17 also has gpg 2.0.22 so you should miss half the problems I had last year anyway. If you find the Yubikey only working when you running as root then try installing yubikey-personalization and yubikey-personalization-gui to add the correct UDEV rules.

      Good luck!

      Delete
    2. Sorry for replying to myself - I just had to set this up again and round that there was another step to get this working as a non root user. Add the following to ~/.bashrc (create if file not already there)

      unset GPG_AGENT_INFO

      The GPG agent that starts with Mint 17.1 does not support smartcards, and since it is already active the GPG2 agent does not get run. By adding this line and rebooting GPG2 is free to connect properly.

      Delete
  4. I performed similar steps as you describe when I received my YubiKeys, and it worked. But now after the recent security advisory, I wanted to upgrade the applet. But now I get errors about missing packages: e.g. "package javacard.framework does not exist"
    Did something change in the java environment in the meantime?
    java_card_kit-2_2_2 is still on my harddrive from last time, and I'm referencing it with an absolute path.

    ReplyDelete