Gnupg with Smartcard on Ubuntu 13.10

A few days ago I switched my PGP key to 4096bit in order to increase the security level a bit ;-). That also reminded me of my Notebook (Dell Latitude E4300) having a built-in smart card reader. So why not combine these two and further increase security?!

The smart card reader of the Dell Latitude E4300 is a BCM5880 by Broadcom with vendor id 0x0a5c and product id 0x5801 (a product id of 0x5800 seems also be available and is presumably the version without the fingerprint reader). A first test with pcsc_scan yielded positive results. The smart card could obiously be detected:

$ pcsc_scan 
PC/SC device scanner
V 1.4.21 (c) 2001-2011, Ludovic Rousseau <ludovic.rousseau@free.fr>
Compiled with PC/SC lite version: 1.8.6
Using reader plug'n play mechanism
Scanning present readers...
0: Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00

Sun Mar 23 23:01:53 2014
Reader 0: Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00
  Card state: Card inserted, 
  ATR: 3B DA 18 FF 81 B1 FE 75 1F 03 00 31 C5 73 C0 01 40 00 90 00 0C

ATR: 3B DA 18 FF 81 B1 FE 75 1F 03 00 31 C5 73 C0 01 40 00 90 00 0C
+ TS = 3B --> Direct Convention
+ T0 = DA, Y(1): 1101, K: 10 (historical bytes)
  TA(1) = 18 --> Fi=372, Di=12, 31 cycles/ETU
    129032 bits/s at 4 MHz, fMax for Fi = 5 MHz => 161290 bits/s
  TC(1) = FF --> Extra guard time: 255 (special value)
  TD(1) = 81 --> Y(i+1) = 1000, Protocol T = 1 
-----
  TD(2) = B1 --> Y(i+1) = 1011, Protocol T = 1 
-----
  TA(3) = FE --> IFSC: 254
  TB(3) = 75 --> Block Waiting Integer: 7 - Character Waiting Integer: 5
  TD(3) = 1F --> Y(i+1) = 0001, Protocol T = 15 - Global interface bytes following 
-----
  TA(4) = 03 --> Clock stop: not supported - Class accepted by the card: (3G) A 5V B 3V 
+ Historical bytes: 00 31 C5 73 C0 01 40 00 90 00
  Category indicator byte: 00 (compact TLV data object)
    Tag: 3, len: 1 (card service data byte)
      Card service data byte: C5
        - Application selection: by full DF name
        - Application selection: by partial DF name
        - EF.DIR and EF.ATR access services: by GET DATA command
        - Card without MF
    Tag: 7, len: 3 (card capabilities)
      Selection methods: C0
        - DF selection by full DF name
        - DF selection by partial DF name
      Data coding byte: 01
        - Behaviour of write functions: one-time write
        - Value 'FF' for the first byte of BER-TLV tag fields: invalid
        - Data unit in quartets: 2
      Command chaining, length fields and logical channels: 40
        - Extended Lc and Le fields
        - Logical channel number assignment: No logical channel
        - Maximum number of logical channels: 1
    Mandatory status indicator (3 last bytes)
      LCS (life card cycle): 00 (No information given)
      SW: 9000 (Normal processing.)
+ TCK = 0C (correct checksum)

Possibly identified card (using /usr/share/pcsc/smartcard_list.txt):
3B DA 18 FF 81 B1 FE 75 1F 03 00 31 C5 73 C0 01 40 00 90 00 0C
   GnuPG card V2

Sun Mar 23 23:01:54 2014
Reader 0: Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00
  Card state: Card removed,

For this to work you have to install at least pcscd and pcs-tools to carry out this test. For using gpg with 4096bit RSA keys we need a few packages. The usually installed gnupg V1.x cannot work with 4096bit RSA keys so it has to be replaced with the V2.x version. On Ubuntu 13.10 you will need:

gnupg2
pcscd
gpgsm
scdaemon

Confusion about Agents

Having all these installed I could not get any result from gpg2 --card-status. Executing this command as root with sudo worked and showed some details about the smardcard:

$ gpg2 --card-status 
Application ID ...: D2760001240102012345012323C40000
Version ..........: 2.0
Manufacturer .....: ZeitControl
Serial number ....: 00000042
Name of cardholder: [not set]
Language prefs ...: de
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: 2048R 2048R 2048R
Max. PIN lengths .: 32 32 32
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]

After fiddling around with this I found out that the gnome-keyring-daemon conflicts with the gpg2 card stuff. To get around this I killed the daemon and gpg2 --card-status worked even as a user. In order to prevent the gnome daemon from beeing launched automatically I removed the two files:

/etc/xdg/autostart/gnome-keyring-gpg.desktop
/etc/xdg/autostart/gnome-keyring-ssh.desktop

After a reboot I could also use the smart card with user privileges. The next problem lies with gpg-agent providing the agent functionalities for SSH authentication. This task was formerly done by the gnome-keyring daemon and should now be done by the gpg-agent because the gnome daemons cannot provide the smart card functionalities. gpg-agent is normally running but without the --enable-ssh-supportoptions. These are needed to authenticate with the authentication key stored on the smart card. From [1] I learnd that gpg-agent is now started as an upstart script. So setting the options in /etc/X11/Xsession.d/90gpg-agent simply does not work because the script checks if gpg-agent is running. As the agent started by upstart before this script runs options cannot be set here.

Instead I used the method metioned in the bug report I created a file ~/.init/gpg-agent.conf with this content:

description "GPG Agent"
author "Stéphane Graber <stgraber@ubuntu.com>"

start on starting xsession-init

pre-start script
    GNUPGHOME=$HOME/.gnupg
    [ -d $GNUPGHOME ] || { stop; exit 0; }

    grep -qs '^[[:space:]]*use-agent' "$GNUPGHOME/gpg.conf" "$GNUPGHOME/options" || { stop; exit 0; }


    eval "$(gpg-agent --daemon --sh --enable-ssh-support)" >/dev/null
    initctl set-env --global GPG_AGENT_INFO=$GPG_AGENT_INFO
    initctl set-env --global SSH_AUTH_SOCK=$SSH_AUTH_SOCK
    initctl set-env --global SSH_AGENT_PID=$SSH_AGENT_PID
end script

post-stop script
    GPG_AGENT_PID=$(echo $GPG_AGENT_INFO | cut -d : -f2)
    kill $GPG_AGENT_PID 2>/dev/null || true
    initctl unset-env --global GPG_AGENT_INFO
    initctl unset-env --global SSH_AUTH_SOCK
    initctl unset-env --global SSH_AGENT_PID
end script

which is basically take from [2] with a line about SSH_AGENT_PID added. This starts gpg-agent with the --enable-ssh-support option on a X session login. So after creating an authentication key on the smart card this key can be used for SSH authentication.

References

[1] https://bugs.launchpad.net/ubuntu/+source/gnupg2/+bug/1257706
[2] https://launchpadlibrarian.net/158755271/gpg-agent.conf