About SSH and Smart Card support (RHEL 7)
How to set up smart cards for authentication in Red Hat Enterprise Linux 6 is described in the article : How to configure smart card authentication with openssh on Red Hat Enterprise Linux .
Prerequisites
Server side
There is no special requirement for the server side in this setup. openssh-server
accepts public key authentication in default configuration (PubkeyAuthentication yes
option in sshd_config
).
Client side
On the client side, it is required to have installed a PKCS#11 library. There is opensc
and coolkey
in RHEL7 to interact with smart cards. For special cards supported by IBM, there is opencryptoki
package (also providing soft token) and softhsm
providing software token.
The list of the libraries with is below:
/usr/lib64/pkcs11/opensc-pkcs11.so
- provided by
opensc
package - works with SmartCard-HSM and YubiKey NEO
- provided by
/usr/lib64/pkcs11/libcoolkeypk11.so
- for Gemalto hardware tokens, CAC and PIV cards
- provided by
coolkey
package
/usr/lib64/pkcs11/libopencryptoki.so
- software token provided by
opencryptoki-swtok
package - other tokens by IBM in related
opencryptoki-*
packages
- software token provided by
/usr/lib64/pkcs11/libsofthsm2.so
- software token provided by
softhsm
package
- software token provided by
To use Secure Shell, you need to install openssh-clients
. To work with the smart cards, there are several tools available, that will be also useful, but they are not required for the smart card usage itself:
p11tool
andcerttool
- provided by
gnutls-utils
package - for key generation and certificates signatures.
- provided by
yubico-piv-tool
- provided by Fedora/EPEL package
- for Yubikey NEO
- possibly
pkcs11-tools
- provided by package
opensc
- provided by package
Hardware
There are many smart cards and cryptographic devices supporting PKCS#11 interface (Cryptoki) and most of them are supported by the opensc
project.
This guide was tested with:
- SmartCard-HSM
- YubiKey NEO
- Gemalto Smart Card (Government PIV cards)
Soft tokens
All the tasks can be performed also with software tokens, which provide simpler and faster way of testing. This article was tested with these software tokens:
- Opencryptoki-swtok
- SoftHSM
Generating keys and certificates
Most of the cards are read-only and do not need this step. If your card is issued by the third party (a government), you already have pre-generated keys and certificates and you can skip this section.
Yubikey NEO (yubico-piv-tool
)
Yubikey is not exactly smart card, but it has a Privilege and Identification Card (PIV ) module providing PKCS#11 interface. There is a tool provided by the Yubico: yubico-piv-tool
to prepare the key. It can be done using these commands:
[localhost ~] $ yubico-piv-tool -s 9a -a generate -o public.pem
[localhost ~] $ yubico-piv-tool -a verify-pin -P 123456 -a selfsign-certificate -s 9a \
-S "/CN=SSH key/" -i public.pem -o cert.pem
[localhost ~] $ yubico-piv-tool -a import-certificate -s 9a -i cert.pem
(based on developers.yubico.com)
Directly using p11tool
The straight way of accessing smart cards is using tool p11tool
. This method can be used for all types of tokens. Some are detected automatically, for some you need to specify shared object handling this token using --provider
switch (see examples later). We will go through the same steps as with yubico-piv-tool
above
List tokens
First, you need to get URI of your token. This can be found using command:
[localhost ~] $ p11tool --list-tokens
[...]
Token 6:
URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=[...]
Label: GnuTLS-Test (UserPIN)
Type: Hardware token
Manufacturer:
Model: PKCS#15 emulated
Serial: DECC0100271
Generate key pair
Then you will generate a new RSA key pair:
[localhost ~] $ p11tool --generate-rsa --login \
"pkcs11:model=PKCS%2315%20emulated;manufacturer=[...]"
Directly using pkcs11-tool
Creation of new RSA key pair is quite easy using pkcs11-tool
. You need only one command to do so.
List tokens
But again, first, you need to find out in which slot is your card and specify library for a provider in module option (example with opencryptoki software token).
[localhost ~] $ pkcs11-tool --list-slots --module=/usr/lib64/pkcs11/libopencryptoki.so
Available slots:
Slot 0 (0x3): Linux
token label : OCToken
token manufacturer : IBM Corp.
token model : IBM SoftTok
token flags : rng, login required, PIN initialized, token initialized, SO PIN to be changed, other flags=0x40
hardware version : 1.0
firmware version : 1.0
serial num : 123
[localhost ~] $ pkcs11-tool --keypairgen --key-type=rsa:1024 --slot 03
--module=/usr/lib64/pkcs11/libopencryptoki.so --login --id=03
Software token using softhsm
First of all you need to create configuration and initialize your token. By default they are stored in system directory, but to have them writeable by user, you should move them to safe location in user's home directory in a safe place and initialize the token:
[localhost ~] $ echo "directories.tokendir = ~/tokens/" > ~/.softhsm2.conf
[localhost ~] $ mkdir ~/tokens
[localhost ~] $ export SOFTHSM2_CONF=~/.softhsm2.conf
[localhost ~] $ softhsm2-util --init-token --slot 0 --label "My token 1"
We can list the tokens and generate the key pair In a similar way as with the hardware tokens before:
[localhost ~] $ p11tool --provider=/usr/lib64/pkcs11/libsofthsm2.so --list-tokens
Token 0:
URL: pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;serial=c23bb5e747eea608;token=My%20token%201
Label: My token 1
Type: Generic token
Manufacturer: SoftHSM project
Model: SoftHSM v2
Serial: c23bb5e747eea608
[localhost ~] $ p11tool --provider=/usr/lib64/pkcs11/libsofthsm2.so --generate-rsa --login \
"pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;serial=c23bb5e747eea608;token=My%20token%201"
Opencryptoki soft token
This soft token has more complicated setup than the previous one and shows some differences from the others. First you need to add your user to group pkcs11
to be able to access tokens: usermod -aG pkcs11 $USER
. Also you need to make sure pkcsslotd
daemon is running, which you can verify by running systemctl status pkcsslotd
.
You will be able to see the token information and slot information using pkcsconf
:
[localhost ~] $ /usr/sbin/pkcsconf -t
Token #3 Info:
Label: test
Manufacturer: IBM Corp.
Model: IBM SoftTok
[...]
Before creating keys, you need to initialize token in the slot and set up Security Officer (SO) pin and User PIN again using pkcsconf
, where the $SLOT_ID
is the slot number you will gain as the result of the using the previous command (3 for software token). The default SO password is 87654321
.
[localhost ~] $ /usr/sbin/pkcsconf -I -c $SLOT_ID
Enter the SO PIN: 87654321
Enter a unique token label: Test
[localhost ~]$ /usr/sbin/pkcsconf -u -c $SLOT_ID
Enter the SO PIN:
Enter the new user PIN:
Re-enter the new user PIN:
Generate RSA key pair
New key can be generated again using p11tool
, but you need to explicitly specify provider and specify an output file for your public key:
[localhost ~] $ p11tool --generate-rsa --login \
--provider=/usr/lib64/pkcs11/libopencryptoki.so --outfile id_rsa.pub \
"pkcs11:model=IBM%20SoftTok;manufacturer=IBM%20Corp.;serial=123;token=test"
[localhost ~] $ cat id_rsa.pub
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0p8PKdxsAehCkvylYKVt
[...]iQIDAQAB
-----END PUBLIC KEY-----
This command doesn't store public key on the card so without further workaround, you will not be able to get public key using ssh-keygen
nor connect to remote server using ssh
.
Create and write certificate
OpenSSH is searching for the public keys and certificates, that have the same ID. If both keys are not written to the card at the same time, you can do that later or store the self-signed certificate as Yubikey does it under the hood of their tool. First of all you need to find out the object that contains your private key. It is done using p11tool
, then self sign certificate and then finally store it to the smart card:
[localhost ~] $ p11tool --list-all --login \
--provider=/usr/lib64/pkcs11/libopencryptoki.so
Enter PIN:
Object 0:
URL: pkcs11:model=IBM%20SoftTok;manufacturer=IBM%20Corp.;serial=123;token=test;id=%10%1a%35%55%33%de%86%f5%fc%04%b2%74%a2%7a%23%1d%95%c2%5b%54;object=test;type=private
Type: Private key
Label: test
Flags: CKA_WRAP/UNWRAP; CKA_PRIVATE;
ID: 10:1a:35:55:33:de:86:f5:fc:04:b2:74:a2:7a:23:1d:95:c2:5b:54
[...]
[localhost ~] $ certtool --generate-self-signed --outfile=id_rsa.cert \
--provider=/usr/lib64/pkcs11/libopencryptoki.so --load-privkey \
"pkcs11:model=IBM%20SoftTok;manufacturer=IBM%20Corp.;serial=123;token=test;id=%10%1a%35%55%33%de%86%f5%fc%04%b2%74%a2%7a%23%1d%95%c2%5b%54;object=test;type=private"
[localhost ~] $ p11tool --login --write --load-certificate=id_rsa.cert \
--provider=/usr/lib64/pkcs11/libopencryptoki.so \
"pkcs11:model=IBM%20SoftTok;manufacturer=IBM%20Corp.;serial=123;token=test"
Unfortunately, this tool does not accept setting the ID during this time so we need to do that now.
Update certificate ID
The certificate ID has to match with a private key. This can't be done with the current version of p11tool
so we need to use more complicated pkcs11-tool
. First, we need to find out ids of the objects on our smart card and then modify the ID:
[localhost ~] $ pkcs11-tool --list-objects --slot 3 --login \
--module=/usr/lib64/pkcs11/libopencryptoki.so
Logging in to "test".
Please enter User PIN:
Private Key Object; RSA
label: test
ID: 101a355533de86f5fc04b274a27a231d95c25b54
Usage: decrypt, sign, unwrap
[...]
Certificate Object, type = X.509 cert
label: SSH cert
ID: ab2d0e6743341243dd0f0d66e4e4c1d9c9cb5166
[localhost ~] $ pkcs11-tool --slot 3 --id ab2d0e6743341243dd0f0d66e4e4c1d9c9cb5166 --type=cert \
--set-id 101a355533de86f5fc04b274a27a231d95c25b54 --login \
--module=/usr/lib64/pkcs11/libopencryptoki.so
From now on, you will be able to list your public key using ssh-keygen
and ssh
will correctly pair it with your private key.
Configure authentication in SSH
Connecting using public key in SSH requires the presence of the public key on the server to verify clients signatures. If we don't have the public key stored separately in PEM format, we can get it from the card in expected format using ssh-keygen
.
Retrieve public key from card
Public key or certificate is available on smart card
You can list public keys on the card directly using ssh-keygen
. There is -D
switch for a shared library, which handles smart card communication. In the next example I will use opensc
library as an example, but it works the same way with opencryptoki
, coolkey
or softhsm
.
[localhost ~] $ ssh-keygen -D /usr/lib64/pkcs11/opensc-pkcs11.so
ssh-rsa AAAAB3NzaC1yc[...]+g4Mb9
Public key is stored separately in file
The public key generated using p11tool
is in PEM format (file id_rsa.pub
) and needs to be converted the OpenSSH format. This can be easily done again using ssh-keygen
, where -i
converts keys between various formats:
[localhost ~] $ ssh-keygen -f id_rsa.pub -i -m PKCS8
ssh-rsa AAAAB3NzaC1...hZaJ
Store public key on server
To enable authentication using a smart card on a remote server, you need to transfer the public key (smartcard.pub
) retrieved in the previous step (in the OpenSSH format) to the remote server. You can do it by simply copy paste to remote shell, or by using ssh-copy-id
:
[localhost ~] $ SSH_COPY_ID_LEGACY=1 ssh-copy-id -i smartcard.pub user@hostname
user@hostname's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh user@hostname"
and check to make sure that only the key(s) you wanted were added.
You will get prompted for your current remote password. Storing a public key without a private key file requires to use the SSH_COPY_ID_LEGACY=1
environment variable (or -f
switch in Fedora).
Authenticate to server with smartcard
OpenSSH has a possibility to read public key from a smart card and let it do operations with a private key without exposing the key itself. This means that the private key doesn't leave the card. A smart card is handled by a shared library, which you need to provide to the `ssh command, so the client will know how to communicate with the card. The connection to remote server can be issued using this command (a smart card is usually protected by PIN so you are prompted before accessing the operation on the card):
[localhost ~] $ ssh -I /usr/lib64/pkcs11/opensc-pkcs11.so hostname
Enter PIN for 'Test (UserPIN)':
[hostname ~] $
Client configuration
Additionally, you can store the path to this library in your ssh_config
and save typing the path over and over again for every connection. Create ~/.ssh/config
or append this snippet to your existing file
Host hostname
PKCS11Provider /usr/lib64/pkcs11/opensc-pkcs11.so
Then you can connect simply without any additional options:
[localhost ~] $ ssh hostname
Enter PIN for 'Test (UserPIN)':
[hostname ~] $
Using ssh-agent
To save the typing of your PIN every time you connect using a smart card, you can add the card into your ssh-agent
. If it is not running in your session yet, you need to run it by your own:
eval `ssh-agent`
Adding card is done using ssh-add
:
[localhost ~] $ ssh-add -s /usr/lib64/pkcs11/opensc-pkcs11.so
Enter PIN for 'Test (UserPIN)':
Card added: /usr/lib64/pkcs11/opensc-pkcs11.so
The next connections will not require to enter a PIN and you will not have to specify PKCS11Provider
option in configuration nor library path on command line:
[localhost ~] $ ssh hostname
[hostname ~] $
Card can be later removed using this command:
[localhost ~] $ ssh-add -e /usr/lib64/pkcs11/opensc-pkcs11.so
Card removed: /usr/lib64/pkcs11/opensc-pkcs11.so
Comments