I decided to set up smart-card authentication on my laptop, using my Estonian national ID card. This was remarkably easy, primarily as the tricky stuff (getting the card working in Arch Linux) had already been done during a previous project.
Getting the smart card working on Arch Linux
This was the tricky bit, since most of the on-line documentation was (a) for Ubuntu and (b) out-dated. As Arch Linux is much much more “bare metal” and is often closer to the upstream software than Debian/Ubuntu/CentOS/RHEL/etc, the Arch instructions should be applicable to other distributions too.
Install the relevant smart-card access packages
- ccid – CCID driver
- pcsclite – smart card middleware
- pcsc-tools – smart card utilities (might not actually be required)
- p11-kit – a utility that probably isn’t actually required
- opensc – more smart card tools
I then wrapped the PCSC daemon in a systemd service
[code]
/etc/systemd/system/pcscd.service
———————————
[Unit]
Description=pcsc daemon
Wants=multi-user.target
[Service]
Type=simple
ExecStart=/usr/bin/pcscd -f
[Install]
WantedBy=multi-user.target
[/code]
Start the pcscd service
[code]
systemctl daemon-reload
systemctl enable pcscd.service
systemctl start pcscd.service
[/code]
Test with DigiDoc
Install the Linux EsteID package
- qesteidutil – Official package for using Estonian ID cards to digitally sign documents.
- qdigidoc – On Arch, you will need to first instal xsd3-bin then modify the libqdigidoc PKGBUILD to use this instead of xsd.
Run DigiDoc and ensure that it detects your card and identifies you. Maybe also try signing a file with it.
Integrating with Firefox
There was pretty much no documentation online at all for this, unless you count ancient guide that refer to non-existent browser plugins – and that’s just the Windows guides…
Integrating with Chrome/Chromium
Inspect the script at the Estonian ID Subversion repository and if you trust it, pipe it into bash:
[code]
$ curl ‘https://svn.eesti.ee/projektid/idkaart_public/branches/3.9/packaging/ubuntu/estonianidcard/esteid-update-nssdb’ | bash
[/code]
Note that the configuration provided by that script is per-user, so will need to be repeated for each account that you want to enable use of Estonian ID in Chrome within.
Integrating with Internet Explorer
lol.
Install EsteID PKCS11 Loader
Configure firefox
In Firefox, go through the following:
- Menu (button with three horizontal lines), or Alt+E,N
- Preferences (menu item)
- Advanced (tab, rightmost)
- Certificates (tab, rightmost)
- Security Devices (button)
- Load (button)
- Path: /usr/lib/opensc-pkcs11.so
- Give it a nice name such as “Estonian ID card”
Once Firefox loads the module, insert your ID card and it should soon appear in the list of security devices. Restart Firefox, then you’re good to go using the ID card to sign into website that support it.
Linux login with Estonian ID card
On most Linux systems, authentication is handled by PAM. There are some guides online for how to set up smart-card authentication, but ignore any by IBM as they are horribly out of date and/or incorrect (as per usual IBM quality).
Install the PAM module
- pam_pkcs11 – Authentication with PKCS11 (Public Key Cryptography Standards)
Install root certificates
Download the the root certificates from SK (the issuer) in PEM format and store them to /etc/pam_pkcs11/cacerts.
Install the revolcation lists
Optionally, also install the revocation lists to /etc/pam_pkcs11/crls. This will allow the system to reject certificates that are blacklisted (e.g. reported stolen/lost).
Generate hash mapping
Run pkcs11_make_hash_link in the certificate folder, and also in the revolcation list folder if you decided to use revocation lists.
Create the certificate -> user mapping
[code]
$ pkcs11_inspect
$ PIN for token:
Printing data for mapper subject:
{certificate data}
$
[/code]
Some versions of pkcs11_inspect may not display the certificate data in its entirety, use pkcs11_listcerts in this case. Copy the {certificate data} line and paste it into a newly created subject_mapping file:
[code]
/etc/pam_pkcs11/subject_mapping
——————————-
{certificate data} -> {user name}
[/code]
For example:
[code]
/etc/pam_pkcs11/subject_mapping (example)
——————————-
/C=EE/O=ESTEID/OU=authentication/CN=MALEV,,42/SN=MALEV/GN=/serialNumber=42 -> malev
[/code]
Configure pam_pkcs11
[code]
/etc/pam_pkcs11/pam_pkcs11.conf
——————————-
pam_pkcs11 {
# Forbid empty passcodes
nullok = false;
# No debug output
debug = false;
# Don’t use stored passwords
use_first_pass = false;
try_first_pass = false;
use_authtok = false;
# Name of PKCS11 module
use_pkcs11_module = opensc;
pkcs11_module opensc {
module = /usr/lib/opensc-pkcs11.so;
description = "OpenSC PKCS#11 module";
# use first slot available
slot_description = "none";
# Where are CA certificates stored
ca_dir = /etc/pam_pkcs11/cacerts;
# Where are revocation lists stored
crl_dir = /etc/pam_pkcs11/crls;
# Certificate verification policy (remove crl_auto if you aren’t using revocation lists)
cert_policy = ca,signature,crl_auto;
# Name of smart card
token_type = "Estonian ID card";
}
# How to map certificates to users?
use_mappers = subject,null;
mapper subject {
debug = false;
module = internal;
ignorecase = false;
# File to use for mappings
mapfile = file:///etc/pam_pkcs11/subject_mapping;
}
# Null mapper: reject always
mapper null {
debug = false;
module = internal;
default_match = false;
default_user = nobody;
}
}
[/code]
That’s the PAM module all configured, now we just have to configure PAM to use it.
Configure PAM
IMPORTANT: Keep a root shell open on another TTY so that if you screw this part up, you don’t get locked out of your system. PAM can be configured either through /etc/pam.conf, with syntax:
[code]
/etc/pam.conf syntax
——————–
service type control module arguments
[/code]
or via /etc/pam.d/[service], with syntax:
[code]
/etc/pam.d/[service] syntax
—————————
type control module arguments
[/code]
The syntax is very similar, with the exception that the latter has no “service” fields, since the service name is implied by the file name. My system uses the pam.d/[service] style, and it is the system-auth service that we are interested in configuring: To begin with, I inserted the following line:
[code]
/etc/pam.d/system-auth
———————-
#%PAM-1.0
auth sufficient pam_pkcs11.so
[original contents]
[/code]
Note that we use “sufficient” rather then “require”. This means that if the smart card authentication succeeds, then PAM will grant us access, but if it fails then PAM will just try the next module rather than giving us an “access denied”. After saving that, I logged out (keeping a backup root shell open on another TTY), plugged the card reader/card in, then logged back in. The PAM module detected the card and asked me for the PIN code. Upon entry, I was granted a shell.
Don’t bork remote logins or sudo
Unfortunately, this creates a problem for remote access: if I SSH into the machine, it will try to authenticate using a smart card first, which is pointless since I am not around to insert it. This is where a handy conditional module pam_succeed_if comes in. Insert the following line before the pam_pkcs11.so module that you previously added
[code]
/etc/pam.d/system-auth
———————-
#%PAM-1.0
auth [success=1 default=ignore] pam_succeed_if.so service notin login use_uid
auth sufficient pam_pkcs11.so
[original contents]
[/code]
pam_succeed_if checks the name of the service requesting the authentication against the list given in its parameters (“login”). If the service is not in the list, then pam_succeed_if succeeds, else it fails. The “success=1” line specifies that if this module succeeds (i.e. returns success), take action “1” which is PAM-language for “skip over the next 1 module(s)”. The “default=ignore” means ignore return values that we haven’t explicitly given an action for (e.g. if the test condition fails). This means that when we log in via a TTY’s “login” process, the test fails and is ignored – resulting in the next module (PKCS11) being tried. If we log in via SSH then the test condition succeeds, and the PKCS11 module is skipped over without being tried. Add your desktop managers to the list of services if you want to use smart card authentication for them, for example:
[code]
auth [success=1 default=ignore] pam_succeed_if.so service notin login:gdm:gnome:gnome-screensaver:xdm:xscreensaver:kdm:kde:kscreensaver use_uid
[/code]
To log in using the smart card with KDM/GDM/etc, enter your smart card password in the password field, NOT your user account password.
Require smart-card authentication if a card is present
Rather than specifying “sufficient” as the control for the PKCS11 module, we can customize it a bit:
[code]
auth [success=done authinfo_unavail=ignore ignore=ignore default=die] pam_pkcs11.so
[/code]
When PKCS11 authentication succeeds then we take action “done”, i.e. stop processing the PAM module stack and return success. If authentication info is not available (authinfo_unavail) or the module returns “ignore”, we ignore the result and continue to the next module. For all other results, we take action “die” and thus authtication fails. Hence when a smart card is present then smart card authentication is used instead of passwords for local logins, but password authentication is still used for remote logins.
SSH access with smart card on client
To use smart cards for SSH login, you need to configure the client. This includes ensuring that the client system can access the smart card. Then use SSH with the -I option to use the PKCS11 module.