Because your machine hosts extremely sensitive data (or, more probably, just for the geek factor) passwords sometimes just don't cut it. Thanks to the OpenSC project, Linux users can also use Smart cards in lieu of passwords to authenticate against various services, which, in addition to being immune to dictionary or brute force attacks, just looks way cooler. This guide will describe the steps needed to use Smart cards for various authentication and encryption purposes; most importantly logins (both console and graphical), e-mail signing and encryption, SSH remote logins, TrueCrypt file encryption, and more if I feel like it. ;) I'd like to thank UF user Berduchwal for starting work (and getting me interested to it) in this thread.
This guide is licensed under the WTFPL: you can do whatever you want with it. (The normal wording would be inappropriate for this forum, use your favourite search engine if you want to know more about it.)
Getting Started
The first section of this guide will describe the basic steps you will need to get your smart card ready to be used in various authentication procedures. Each single application will be described in a separate post and linked at the end of this section.
The Hardware
First and foremost, you will obviously need the correct hardware. It can be either a smart card and a smart card reader, or an USB token that provides the same functionality as a smart card, but plugs directly into an USB port, thus eliminating the need for an additional reader. The OpenSC project's Wiki has a list of supported smart cards and USB tokens, as well as a small list of compatible readers.
The hardware I will use for this guide is an Feitian EnterSafe smart card and SCR301 USB smart card reader. Gooze sells them as a bundle for 31,90 EUR plus shipping (ships only to the EU for legal reasons).
The Software
All the necessary software is in the Ubuntu repositories. The packages you need are opensc, pcsc-tools, and libccid. More packages might be needed for specific applications (e.g. PAM authentication), those will be covered in the relevant sections of this guide.
The OpenSC project strongly recommends using the PCSC driver. It is a good idea to set reader_drivers to pcsc in /etc/opensc/opensc.conf so that OpenSC won't bother trying other drivers unsuccessfully.
First Steps
Now that you have your smart card, reader and all the packages, let's get to business. First, make sure your reader is detected and supported. First, the usual suspect when it comes to detecting USB devices:
Code:
firas@tsukino ~ % lsusb
Bus 004 Device 007: ID 096e:0503 Feitian Technologies, Inc.
Bus 004 Device 004: ID 05ac:8213 Apple, Inc.
Bus 004 Device 002: ID 0a5c:4500 Broadcom Corp. BCM2046B1 USB 2.0 Hub (part of BCM2046 Bluetooth)
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 003: ID 05ac:0237 Apple, Inc.
Bus 003 Device 002: ID 05ac:8242 Apple, Inc.
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 004: ID 05ac:8403 Apple, Inc.
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 05ac:8507 Apple, Inc.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
My Feitian card reader appears. The opensc-tool command can give us more information:
Code:
firas@tsukino ~ % opensc-tool --list-readers
Readers known about:
Nr. Driver Name
0 pcsc Feitian SCR301 00 00
You will probably see some error messages in bold red, don't worry, they're "normal" (i.e. I get them too, and it still works). You can eliminate them by editing /etc/opensc/opensc.conf, uncommenting the error_file line, and setting it to /dev/null. Now to see whether your card is supported:
Code:
firas@tsukino ~ % opensc-tool --reader 0 --name
Card not present.
But insert the card first. ;)
Code:
firas@tsukino ~ % opensc-tool --reader 0 --name
entersafe
This is the name of your card. If you run the command with the -v (verbose) flag, it will also tell you the name of the driver your card uses:
Code:
firas@tsukino ~ % opensc-tool --reader 0 --name -v
Connecting to card in reader Feitian SCR301 00 00...
Using card driver entersafe.
Card name: entersafe
Now that we've made sure the card is supported, we can initialise it (roughly the same thing as formatting a filesystem) so we can store stuff on it:
Code:
firas@tsukino ~ % pkcs15-init -C --label "Firas Kraiem"
Using reader with a card: Feitian SCR301 00 00
New User PIN.
Please enter User PIN:
Please type again to verify:
Unblock Code for New User PIN (Optional - press return for no PIN).
Please enter User unblocking PIN (PUK):
Please type again to verify:
The label is optional, it will appear in some authentication prompts, so you probably want to put your name there. Note that some smart cards, such as the Schlumberger CryptoFlex used on the Quick Start page on the OpenSC wiki, will ask you for a "Security Officer" PIN. This is because they support creating several users, each with his own User PIN, keys and data, that will be able to use the same smart card. My EnterSafe, on the other hand, is single-user, so I am directly asked for the User PIN. If your card is multi-users, you will have to create a user, as described on the wiki.
A small note on the codes: the PIN (Personal Identification Number) is the code you will need to enter when you use the smart card (for example when you store a key on it, or when you want to use a key). The PUK (PIN Unlock Key) is used to reinitialise the PIN if you forget it or it gets compromised.
We can now see the structure of the card with:
Code:
firas@tsukino ~ % pkcs15-tool -D
Using reader with a card: Feitian SCR301 00 00
PKCS#15 Card [Firas Kraiem]:
Version : 1
Serial number : 2812504610040810
Manufacturer ID: EnterSafe
Last update : 20100821125517Z
Flags : EID compliant
PIN [User PIN]
Com. Flags: 0x3
ID : ff
Flags : [0x30], initialized, needs-padding
Length : min_len:4, max_len:16, stored_len:16
Pad char : 0x00
Reference : 1
Type : ascii-numeric
Path : 3f005015
First Key
You generate a RSA key pair on your card with the -G flag of pkcs15-init (you will be asked for your PIN several times):
Code:
firas@tsukino ~ % pkcs15-init -G rsa/1024 --auth-id ff --label "My Private Key" --public-key-label "My Public Key"
Using reader with a card: Feitian SCR301 00 00
User PIN required.
Please enter User PIN:
User PIN required.
Please enter User PIN:
User PIN required.
Please enter User PIN:
User PIN required.
Please enter User PIN:
Replace 1024 with 2048 or 4096 for a longer key (if supported by your card). Replace ff with the auth-id of the user who will use the key (you can find a user's auth-id under his PIN section in the output of pkcs15-tool -D). Labels are, once again, optional.
We can use the same command as above to see our new keys in the card's structure:
Code:
firas@tsukino ~ % pkcs15-tool -D
Using reader with a card: Feitian SCR301 00 00
PKCS#15 Card [Firas Kraiem]:
Version : 1
Serial number : 2812504610040810
Manufacturer ID: EnterSafe
Last update : 20100821130157Z
Flags : EID compliant
PIN [User PIN]
Com. Flags: 0x3
ID : ff
Flags : [0x30], initialized, needs-padding
Length : min_len:4, max_len:16, stored_len:16
Pad char : 0x00
Reference : 1
Type : ascii-numeric
Path : 3f005015
Private RSA Key [My Private Key]
Com. Flags : 3
Usage : [0x4], sign
Access Flags: [0x1D], sensitive, alwaysSensitive, neverExtract, local
ModLength : 1024
Key ref : 1
Native : yes
Path : 3f005015
Auth ID : ff
ID : 45
Public RSA Key [My Public Key]
Com. Flags : 2
Usage : [0x4], sign
Access Flags: [0x0]
ModLength : 1024
Key ref : 0
Native : no
Path : 3f0050153045
Auth ID :
ID : 45
Or we can use --list-keys to see only the keys:
Code:
firas@tsukino ~ % pkcs15-tool --list-keys
Using reader with a card: Feitian SCR301 00 00
Private RSA Key [My Private Key]
Com. Flags : 3
Usage : [0x4], sign
Access Flags: [0x1D], sensitive, alwaysSensitive, neverExtract, local
ModLength : 1024
Key ref : 1
Native : yes
Path : 3f005015
Auth ID : ff
ID : 45
firas@tsukino ~ % pkcs15-tool --list-public-keys
Using reader with a card: Feitian SCR301 00 00
Public RSA Key [My Public Key]
Com. Flags : 2
Usage : [0x4], sign
Access Flags: [0x0]
ModLength : 1024
Key ref : 0
Native : no
Path : 3f0050153045
Auth ID :
ID : 45
If you need to send the public key to other people, you can retrieve it with:
Code:
firas@tsukino ~ % pkcs15-tool --read-public-key 45
Using reader with a card: Feitian SCR301 00 00
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClRLcuudoW62NzWO7s/HSMqhjR
edFkxqxKdTuNksi+oCG5QDmZtzOuAX5eCtXLKiAyt8cSNQWUhOlS9jK/5vpwMyee
+qWQuh2jA0wfi6eoNIWGz5ZdjDn/b2BwvsOZUtpNKOtMwnceLWtbJCcg5nTd3DyV
X+qfJsGatuLB0CgHQwIDAQAB
-----END PUBLIC KEY-----
Of course, replace 45 with the ID of the key you want to read (you can get it, once again, in the output of pkcs15-tool -D).
Note that there is normally no way to extract the private key from the card. If you need a backup, you must generate the key on your computer, store it on your card (see below) and back it up in a safe location (which could be on another card).
Our RSA key is now ready to be used. I will cover each application in a separate message, so stay tuned. ;)
Applications
PAM Authentication: for logins (both console and graphical), sudo and more.
OpenSSH Authentication
TrueCrypt
Other Stuff
This section will document other procedures that are not specific to a single application.
Using a pre-existing key
In some circumstances, you might want to use a pre-existing key instead of generating one directly on your card. This can be useful, for example, if you need a backup of your key, or if you need to distribute the key to several users.
Starting with a freshly initialised card:
Code:
firas@tsukino ~ % pkcs15-tool -D
Using reader with a card: Feitian SCR301 00 00
PKCS#15 Card [My Smart Card]:
Version : 1
Serial number : 2812504610040810
Manufacturer ID: EnterSafe
Last update : 20100822165926Z
Flags : EID compliant
PIN [User PIN]
Com. Flags: 0x3
ID : ff
Flags : [0x30], initialized, needs-padding
Length : min_len:4, max_len:16, stored_len:16
Pad char : 0x00
Reference : 1
Type : ascii-numeric
Path : 3f005015
Generate the new key on your computer (of course skip this step if you want to use a key you already have):
Code:
firas@tsukino ~ % openssl genrsa -des3 -out mykey.key 1024
Generating RSA private key, 1024 bit long modulus
...........++++++
...++++++
e is 65537 (0x10001)
Enter pass phrase for mykey.key:
Verifying - Enter pass phrase for mykey.key:
And store the key on your card with the -S flag of pkcs15-init:
Code:
firas@tsukino ~ % pkcs15-init -S mykey.key --auth-id ff --label "My Private Key" --public-key-label "My Public Key"
Using reader with a card: Feitian SCR301 00 00
Please enter passphrase to unlock secret key:
User PIN required.
Please enter User PIN:
User PIN required.
Please enter User PIN:
User PIN required.
Please enter User PIN:
User PIN required.
Please enter User PIN:
We can see the key in the output of pkcs15-tool -D:
Code:
firas@tsukino ~ % pkcs15-tool -D
Using reader with a card: Feitian SCR301 00 00
PKCS#15 Card [My Smart Card]:
Version : 1
Serial number : 2812504610040810
Manufacturer ID: EnterSafe
Last update : 20100822170433Z
Flags : EID compliant
PIN [User PIN]
Com. Flags: 0x3
ID : ff
Flags : [0x30], initialized, needs-padding
Length : min_len:4, max_len:16, stored_len:16
Pad char : 0x00
Reference : 1
Type : ascii-numeric
Path : 3f005015
Private RSA Key [My Private Key]
Com. Flags : 3
Usage : [0x4], sign
Access Flags: [0x1D], sensitive, alwaysSensitive, neverExtract, local
ModLength : 1024
Key ref : 1
Native : yes
Path : 3f005015
Auth ID : ff
ID : 45
Public RSA Key [My Public Key]
Com. Flags : 2
Usage : [0x4], sign
Access Flags: [0x0]
ModLength : 1024
Key ref : 0
Native : no
Path : 3f0050153045
Auth ID :
ID : 45
Reinitialise your card
If you want to reinitialise your card and start again, just use the same initialisation command as above, but add the -E flag:
Code:
firas@tsukino ~ % pkcs15-init -E -C --label "Firas Kraiem"
Using reader with a card: Feitian SCR301 00 00
New User PIN.
Please enter User PIN:
Please type again to verify:
Unblock Code for New User PIN (Optional - press return for no PIN).
Please enter User unblocking PIN (PUK):
Please type again to verify:
Needless to say, the keys stored on the card will be lost (if you didn't back them up).
OpenSSL
You can use the private key stored on your card with OpenSSL wherever you can use an on-disk key. Among other things, you can sign files, decrypt files encrypted with your public key, or generate X.509 certificates for your key. Since this is not an OpenSSL guide, I will not describe those operations in detail, you can refer to the OpenSSL page in the Ubuntu Server Guide if you are not familiar with them, the syntax is the same (except for the necessary command flags to tell OpenSSL to use your smart card, see below).
First, install the package libengine-pkcs11-openssl. Then fire up the OpenSSL prompt and initialise the smart card engine with this long command (copy-and-paste is your friend):
Code:
firas@tsukino ~ % openssl
OpenSSL> engine dynamic -pre SO_PATH:/usr/lib/engines/engine_pkcs11.so -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre MODULE_PATH:opensc-pkcs11.so
(dynamic) Dynamic engine loading support
[Success]: SO_PATH:/usr/lib/engines/engine_pkcs11.so
[Success]: ID:pkcs11
[Success]: LIST_ADD:1
[Success]: LOAD
[Success]: MODULE_PATH:opensc-pkcs11.so
Loaded: (pkcs11) pkcs11 engine
OpenSSL>
TODO: Is there a way to automate that?
You can now run the desired OpenSSL commands. To use the key stored on your smart card, you must add -keyform engine -engine pkcs11 to your command, and use id_XX as the value for the -key flag (where XX is the ID of your key). For example, here's how to generate a self-signed X.509 certificate (which will be useful also for PAM authentication, among other things):
Code:
OpenSSL> req -new -x509 -days 365 -keyform engine -engine pkcs11 -key id_45 -out mysmartcard.cert.pem
[...]
OpenSSL> quit
You probably want to store the certificate on the card, this is done with the -X flag of pkcs15-init:
Code:
firas@tsukino ~ % pkcs15-init -X mysmartcard.cert.pem --auth-id ff --id 45 --format pem
Using reader with a card: Feitian SCR301 00 00
User PIN required.
Please enter User PIN:
User PIN required.
Please enter User PIN:
As usual, replace ff with the auth-id of the user, and 45 with the ID of the key.