Using a Cryptoflex eGate with Debian Sarge

i got a Cryptoflex eGate card from axalto. Note that it's a Cryptoflex, not a Cyberflex device. i've been learning how to make it work with a typical debian sarge workstation (pinhead). I've got the eGate USB Token package -- a small USB key, which accepts the pop-out plug from the card. This page describes what i needed to do to get the tool to work for me.
  1. package requirements
  2. intializing the card
    1. erasing the card
    2. Setting up a PIN
  3. Installing a keypair
    1. Creating the keypair
    2. Storing the keypair on the device
    3. Creating and storing the Certificate
  4. Client Software which uses smartcards
  5. Unknowns and Future Work
  6. Glossary
  7. Useful Links

package requirements

i needed to install two tools: openct and opensc. openct is a library which provides a standardized API to a range of different smartcard readers. opensc is a set of command-line tools which interface to those APIs. i think.

i also had to add my normal user to the scard group so that i'd have access to the devices. After adding myself to that group, i needed to log out and log back in, since group membership takes effect at login.

[dkg@pinhead egate]$ sudo apt-get install opensc openct
[dkg@pinhead egate]$ sudo adduser dkg scard

initializing the card

The device needs to be initialized before it can be used.

erasing the card

i chose to not provide a Security Officer PIN. i'm also providing the -C option to create the initial PKCS #15 filestructures on the device.
[dkg@pinhead egate]$ pkcs15-init -ECT
New Security Officer PIN (Optional - press return for no PIN).
Please enter Security Officer PIN: 
[dkg@pinhead egate]$ pkcs15-tool --list-pins
[dkg@pinhead egate]$ pkcs15-tool --list-keys
[dkg@pinhead egate]$ pkcs15-tool --list-certificates
[dkg@pinhead egate]$ pkcs15-tool --list-public-keys
[dkg@pinhead egate]$

Setting up a PIN

Each key that is stored on the device is associated with a PIN, and is unusable without it. Here's me setting up a new PIN (input i type that doesn't actually show up on the console looks like this):
[dkg@pinhead egate]$ pkcs15-init -PT -a 1 -l dkg -v
Connecting to card in reader Schlumberger E-Gate...
Using card driver Schlumberger Multiflex/Cryptoflex.
Found OpenSC Card
About to store PIN.
New User PIN.
Please enter User PIN: 12345678
Please type again to verify: 12345678
Unblock Code for New User PIN (Optional - press return for no PIN).
Please enter User unblocking PIN (PUK): 09090909
Please type again to verify: 09090909
[dkg@pinhead egate]$ pkcs15-tool --list-pins
PIN [dkg]
	Com. Flags: 0x3
	Auth ID   : 01
	Flags     : [0x32], local, initialized, needs-padding
	Length    : min_len:4, max_len:8, stored_len:8
	Pad char  : 0x00
	Reference : 1
	Type      : -1
	Path      : 3F0050154B01
	Tries left: -1

[dkg@pinhead egate]$

Installing a keypair

You need an RSA keypair to use the device. i belive this device supports both 1024-bit and 2048-bit RSA keys.

Creating the Keypair

You could ask the card to generate the key itself, but then you could never have access to the private key because the private key never leaves the card. So i prefer to generate the keypair myself (so i can manipulate the key with other tools). Here's me generating a 2048-bit RSA keypair with OpenSSL:
[dkg@pinhead egate]$ openssl req -newkey rsa:2048 -keyout dkg-sc0-key.pem -out dkg-sc0-cert-req.pem
Generating a 2048 bit RSA private key
..........................................................+++
..........................................................................................+++
writing new private key to 'dkg-sc0-key.pem'
Enter PEM pass phrase:fubar
Verifying - Enter PEM pass phrase:fubar
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Fifthhorseman Consulting
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:Daniel Kahn Gillmor
Email Address []:dkg@example.org

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[dkg@pinhead egate]$ chmod 400 dkg-sc0-key.pem
[dkg@pinhead egate]$ ls -l
total 20
-rw-r--r--   1 dkg dkg 1078 May 26 01:08 dkg-sc0-cert-req.pem
-r--------   1 dkg dkg 1751 May 26 01:08 dkg-sc0-key.pem
[dkg@pinhead egate]$

Storing the keypair on the device

Now i can put the keypair into the device:
[dkg@pinhead egate]$ pkcs15-init -S dkg-sc0-key.pem -a 1 -u sign,decrypt
Please enter passphrase to unlock secret key: fubar
User PIN required.
Please enter User PIN: 12345678
[dkg@pinhead egate]$ pkcs15-tool --list-keys
Private RSA Key [Private Key]
	Com. Flags  : 3
	Usage       : [0x22E], decrypt, sign, signRecover, unwrap, nonRepudiation
	Access Flags: [0x1D], sensitive, alwaysSensitive, neverExtract, local
	ModLength   : 2048
	Key ref     : 0
	Native      : yes
	Path        : 3F0050154B0130450012
	Auth ID     : 01
	ID          : 45

[dkg@pinhead egate]$ pkcs15-tool --list-public-keys
Public RSA Key [Public Key]
	Com. Flags  : 2
	Usage       : [0x4], sign
	Access Flags: [0x0]
	ModLength   : 2048
	Key ref     : 0
	Native      : no
	Path        : 3F0050154445
	Auth ID     : 
	ID          : 45

[dkg@pinhead egate]$

Creating and Storing the Certificate

So far, i've only generated a certificate request, not a full-fledged x509 certificate. Most software wants to see the certificate itself, not just the public key (Weirdly, openssh seems to want a cert as well, even though it doesn't use the x509 stuff at all!). You can either submit this cert req to your favorite Certificate Authority, or you can just self-sign it if yer testing things out. Here's me self-signing it:
[dkg@pinhead egate]$ openssl x509 -req -signkey ./dkg-sc0-key.pem -in ./dkg-sc0-cert-req.pem  -out ./dkg-sc0-cert.pem
Signature ok
subject=/C=US/ST=New York/L=New York/O=Fifthhorseman Consulting/CN=Daniel Kahn Gillmor/emailAddress=dkg@example.org
Getting Private key
Enter pass phrase for ./dkg-sc0-key.pem:fubar
[dkg@pinhead egate]$ pkcs15-init -X ./dkg-sc0-cert.pem -v -a 1
Connecting to card in reader Schlumberger E-Gate...
Using card driver Schlumberger Multiflex/Cryptoflex.
Found OpenSC Card
About to store certificate.
[dkg@pinhead egate]$ pkcs15-tool --list-certificates
X.509 Certificate [Certificate]
	Flags    : 2
	Authority: no
	Path     : 3F0050154545
	ID       : 45

[dkg@pinhead egate]$

Client Software which uses smartcards

None of this is terribly useful if you don't have client software which can talk to the smartcards.

OpenSSH and smartcards

You need to get a public key in openssh format to use the smartcard at all. Here's me creating the public key and setting up a remote account to use it:
[dkg@pinhead egate]$ ssh-keygen -y -f dkg-sc0-key.pem > dkg-sc0-id_rsa.pub
Enter passphrase: fubar
[dkg@pinhead egate]$ scp dkg-sc0-id_rsa.pub guest@squash:.ssh/authorized_keys
guest@squash's password: yadda yadda
dkg-sc0-id_rsa.pub                            100%  381     0.4KB/s   00:00    
[dkg@pinhead egate]$
Debian's standard packaging of OpenSSH doesn't include opensc support. You can read more about why here.
[dkg@pinhead egate]$ ssh  -I 0 guest@squash
ssh  -I 0 guest@squash
no support for smartcards.
guest@squash's password: ^C

[dkg@pinhead egate]$
Since the only part of ssh that i expect to talk to the smartcard directly in everyday use is ssh-agent, i decided to rebuild that executable. i figured this would require the smartcard development libraries as well. Here's me installing the packages i'd need to build the executable.
[dkg@pinhead egate]$ sudo apt-get build-dep ssh
[dkg@pinhead egate]$ sudo apt-get install libopensc1-dev
So i grabbed the debian source, modified it to include support for opensc, rebuilt it, and grabbed the binary version of ssh-agent created there. Yeah, it's overkill to do this entire build just to grab one executable, but i haven't had the time to narrow it down to just building the one file cleanly.
[dkg@pinhead egate]$ apt-get source ssh
Reading Package Lists... Done
Building Dependency Tree... Done
Need to get 953kB of source archives.
Get:1 http://ftp.debian.org testing/main openssh 1:3.8.1p1-8.sarge.4 (dsc) [906B]
Get:2 http://ftp.debian.org testing/main openssh 1:3.8.1p1-8.sarge.4 (tar) [796kB]
Get:3 http://ftp.debian.org testing/main openssh 1:3.8.1p1-8.sarge.4 (diff) [156kB]
Fetched 953kB in 5s (160kB/s)
dpkg-source: extracting openssh in openssh-3.8.1p1
[dkg@pinhead egate]$ cd openssh-3.8.1p1/
[dkg@pinhead openssh-3.8.1p1]$ patch -p1 <../ssh-with-opensc-patch
patching file debian/rules
[dkg@pinhead openssh-3.8.1p1]$ dpkg-buildpackage -rfakeroot >../ssh-compilation-output.txt 2>&1
[dkg@pinhead openssh-3.8.1p1]$ cd ..
[dkg@pinhead egate]$ cp openssh-3.8.1p1/debian/ssh/usr/bin/ssh-agent ./ssh-agent-with-opensc
[dkg@pinhead egate]$
Now i can launch the new special ssh-agent and it talks to the smartcard successfully. Note that i'm using the system's default ssh-add and ssh binaries. Also, i don't understand why the agent reports that two different private keys are available (RSA and RSA1?). But it works!
[dkg@pinhead egate]$ eval $(./ssh-agent-with-opensc)
Agent pid 22913
[dkg@pinhead egate]$ ssh-add -l
The agent has no identities.
[dkg@pinhead egate]$ ssh-add -s 0 -c
Enter passphrase for smartcard: 12345678
Card added: 0
[dkg@pinhead egate]$ ssh-add -l
2048 43:bc:41:38:7c:6b:e8:f0:b2:19:ee:da:c3:3b:a2:97 Private Key (RSA1)
2048 9e:4e:a4:13:7f:56:67:f5:8f:be:3a:94:66:67:b2:20 Private Key (RSA)
[dkg@pinhead egate]$ ssh guest@squash
guest@squash:~$ exit
logout
Connection to squash closed.
[dkg@pinhead egate]$ 

GnuPG (GPG) and the smartcard

Under Debian Sarge, i found that GPG wouldn't talk to the smartcard initially because it couldn't find the right library. Oddly enough, /usr/lib/libpcsclite.so is only available in debian with the libpcsclite-dev package, not the libpcsclite1 package like i would have thought. Is this a problem with debian's packaging scheme? Why wouldn't gpg be satisfied with /usr/lib/libpcsclite.so.1, which is provided by the non-dev package?

sadly, even with the libpcsclite-dev package installed, gpg doesn't seem to recognize the card.

[dkg@pinhead egate]$ gpg --card-status
gpg: apdu_open_reader: failed to open driver `libpcsclite.so': libpcsclite.so: cannot open shared object file: No such file or directory
gpg: card reader not available
gpg: OpenPGP card not available: general error
[dkg@pinhead egate]$ sudo apt-get install libpcsclite-dev
Reading Package Lists... Done
Building Dependency Tree... Done
The following NEW packages will be installed:
  libpcsclite-dev
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 478kB of archives.
After unpacking 700kB of additional disk space will be used.
Get:1 http://www.example.org testing/main libpcsclite-dev 1.2.9-beta7-5 [478kB]
Fetched 478kB in 3s (158kB/s)           
Selecting previously deselected package libpcsclite-dev.
(Reading database ... 173394 files and directories currently installed.)
Unpacking libpcsclite-dev (from .../libpcsclite-dev_1.2.9-beta7-5_i386.deb) ...
Setting up libpcsclite-dev (1.2.9-beta7-5) ...
[dkg@pinhead egate]$ gpg --card-status
gpg: pcsc_establish_context failed: no service (0x8010001d)
gpg: card reader not available
gpg: OpenPGP card not available: general error
[dkg@pinhead egate]$ 
It looks like gpg may not be willing to work with this device using the OpenPGP standard, according to the gnupg-devel mailing list. How sad. However, it looks like gpg development to include opensc is at least being considered, though it doesn't look terribly promising.

HTTP connections: mozilla and apache

mozilla

Surprisingly, it looks like i didn't need to install any new packages to get mozilla to work with the card. After launching mozilla, i chose Edit|Preferences...|Privacy and Security|Manage Security Devices.... This brings up the security devices dialog box. From there, you can choose Load, and put in Module Name: OpenSC PKCS#11 Module, Module File Name: /usr/lib/pkcs11/opensc-pkcs11.so:

configuration dialog

(i had some weirdnesses with this dialog box appearing under the other dialog boxes, but i was able to maneuver it around so that i could see it...) Then choose OK, OK, and then select the line under the OpenSC element in the security modules and devices pane which has the label for the PIN you created back here, and click Log In:

log in dialog

This will prompt you for your PIN like this:

Dialog asking for
Master Password for the OpenSC Card.

If you want to see clearly what's going on, you might want to fiddle with Edit|Preferences...|Privacy and Security|Client Certificate Selection. By default (for me at least) it was set to Select Automatically. Setting it to Ask Every Time rapidly becomes annoying, but i found it helpful to understand what was happening under the hood.

apache

The next thing i needed to do was to configure apache with mod_ssl to look for appropriately-signed client certificates.

Since appropriately-signed for this particular experiment means i want to recognize the cert stored on my smartcard (which is self-signed in this example), i needed to provide the issuer's cert (which is effectively the Certificate Authority) to apache:

[dkg@pinhead egate]$ sudo cp dkg-sc0-cert.pem /etc/apache/ssl.crt/sc0-ca.pem
[dkg@pinhead egate]$ 

Note that if you had gotten your certificate request signed by some other certificate authority (CA) instead of self-signing it, you should provide the CA's own certificate here instead of your own.

Apache was already set up to use SSL, so i only needed to add this snippet to my apache config:

#   require a client certificate which has to be directly
#   signed by our CA certificate in ca.crt
SSLVerifyClient require
SSLVerifyDepth 1
SSLCACertificateFile /etc/apache/ssl.crt/sc0-ca.pem
SSLOptions +StdEnvVars
That last line (SSLOptions +StdEnvVars) provides a set of environment variables to any scripts which run, so those scripts can present the appropriate data. Alternatively, you could tell apache itself to limit access to certain documents by the Distinguished Name (DN) in the cert.

Here's an example PHP script which prints out the SSL-related variables offered to the script. In particular, the SSL_CLIENT_S_DN* variables would probably be reasonable ones to use for identifying the client (Authentication). Authorization (that is, which clients are allowed which privileges) is outside the scope of this project.

Unknowns and Future Work

Glossary

Security Officer PIN (SOP)
Each card has one PIN for the Security Officer. This PIN grants permission to add and remove identities from the card, but does not allow use of the stored private keys. I think the rationale is that an institution issuing these devices doesn't want people putting their own data on them, but they want to be able to reissue them, say, when an employee leaves. The Security Officer would be responsible for that transaction.
Transport Key
The transport key is a special key which ships with the card to allow someone to:
  1. completely erase the card, and
  2. reset the SOP.
It has the interesting property that if you give the card the wrong transport key three times in a row (or is it three times ever?), you will lock the card, which basically makes it worthless.

i found some folks (link?) suggesting that you never reset this key (because the same key appears to be shipped by default with any Schlumberger eGate, and opensc knows this key internally). However, i haven't found any documentation on how to actually reset the transport key, should i want to do such a thing. i'm leaving it alone for now. Providing the -T flag to pkcs15-tool tells opensc to use the default Transport Key it associates with this particular model of device.

User Unblocking PIN (PUK)
i think if you mis-enter a user's PIN enough times, that PIN can get locked out. You then need to unblock the PIN somehow. i think the PUK is a special code used to unblock a PIN that has been blocked, but i don't know how to invoke it.

Update (2006-08-25): Denis Bodor points out that pkcs15-tool -u can be used to choose a new PIN (thereby unlocking the card) if you know the PUK.

Useful or Interesting Links


If you want to contact me about this page, just mail my user name at fifthhorseman.net

Thanks to Roland Turner for finding and fixing a typo in this page.
Last modified: Tue May 31 02:00:36 EDT 2005