Fedora 28: Better smart card support in OpenSSH

Smart card support was introduced around 2010 with OpenSSH 5.4. The inital scope was restricted to the RSA keys — the only supported key type at that time in OpenSSH — other than legacy DSA keys. Previously, users needed to specify the PKCS#11 driver for the smart card. Additionally, the OpenSSH client had to query the server with all the stored keys in the card, until an acceptable key was found.  This slowed down authentication, and reveals public keys to the server that might not be necessary (e.g., if we have a single card with keys for distinct servers).

Over the years, OpenSSH gained support for additional authentication keys, such as ECDSA and later EdDSA. However, the smart card subsystem has not changed much since the early days. Cards with ECDSA keys are not yet supported, and there is no option for the user to specify the key to use when connecting to a server. Fedora 28 addresses these limitations. This article describes these improvements, the background behind them, and how they can be used.

Support for ECDSA keys

OpenSSH has supported ECDSA keys OpenSSH 5.7 (released in 2011). This  includes widespread support for smart cards such as Yubikey and Nitrokey. Nevertheless, ECDSA support was not reflected in the OpenSSH PKCS#11 subsystem, which is still RSA-only. A patch to support the ECDSA keys in PKCS#11 was submitted to the OpenSSH project in 2015, but despite a long history of revisions it is still not incorporated. The motivation to use ECDSA keys can be either to avoid hardware RSA key vulnerabilities (ROCA: CVE-2017-15361) or to use shorter keys for faster connection times.

In Fedora 28 we include that patch set to allow you to use ECDSA keys from your security tokens. You can list them with ssh-keygen as any other keys:

$ ssh-keygen -D /usr/lib64/pkcs11/opensc-pkcs11.so
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHA[...]k3J0hkYnnsM=

Or use them for authentication, if the server is configured to accept this key:

$ ssh -vvv -I /usr/lib64/pkcs11/opensc-pkcs11.so example.com
debug1: Offering public key: ECDSA SHA256:5BrE5wevULd5wipj2bXYAr4gXQIICiywfV+kF5hA9X8 ECDSA jjelen@example.com
debug1: Offering public key: ECDSA SHA256:q4zxb5Woucr1HlUSh9Fq66sKdv3r5hlxIIqQQtaQKy4 pkcs11:id=%01?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so
debug1: Server accepts key: pkalg ecdsa-sha2-nistp256 blen 104
debug2: input_userauth_pk_ok: fp SHA256:q4zxb5Woucr1HlUSh9Fq66sKdv3r5hlxIIqQQtaQKy4
debug3: sign_and_send_pubkey: ECDSA SHA256:q4zxb5Woucr1HlUSh9Fq66sKdv3r5hlxIIqQQtaQKy4
Enter PIN for 'PIV Card Holder pin (PIV_II)': 
debug1: Authentication succeeded (publickey).

Specify the key to use

Historically, applications were using various ways how to reference keys in PKCS#11 modules, because there was no standard way to do so. Alternatively some applications were using just everything that was made available by a PKCS#11 module.

This works fine if the smart card is a company-issued with few keys. But this does not work well if one has several private keys to access different services or there are more security tokens aggregated in a single system-wide PKCS#11 module. In such cases, you need to map private keys to services, rather than to leave it on the tool to try all of them sequentially. Selecting an explicit key will always be faster, and prevents exceeding maximum of authentication tries. Furthermore, it allows to the use of different identities, for example on Github.

PKCS#11 URIs defined in RFC7512 provide a standard way to identify a specific object/key on PKCS#11 module according to their attributes. That, when supported universally, enables you to configure all the system and applications with the same configuration string in form of URI.

Additionally, as Fedora 28 provides p11-kit proxy which acts as a wrapper over the registered smart card drivers in the system,  we took advantage of it and it allows you to avoid the path to shared object altogether. The unique URI scheme allows you to specify the PKCS#11 URI in every place, where the path to a local private key file would be, including the configuration file, ssh-add or command-line ssh.


You can list all the keys provided by OpenSC PKCS#11 module (including their PKCS#11 URIs):

$ ssh-keygen -D /usr/lib64/pkcs11/opensc-pkcs11.so
ssh-rsa AAAAB3NzaC1yc2E...KKZMzcQZzx pkcs11:id=%02;object=SIGN%20pubkey;token=SSH%20key;manufacturer=piv_II?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so
ecdsa-sha2-nistp256 AAA...J0hkYnnsM= pkcs11:id=%01;object=PIV%20AUTH%20pubkey;token=SSH%20key;manufacturer=piv_II?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so

To connect to the server example.com using the ECDSA key from above (referenced by ID), you can use just a subset of the URI, which uniquely references our key:

$ ssh -i pkcs11:id=%01?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so example.com
Enter PIN for 'SSH key':
[example.com] $

You can use the same URI string in ~/.ssh/config to make the configuration permanent:

$ cat ~/.ssh/config
IdentityFile pkcs11:id=%01?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so
$ ssh example.com
Enter PIN for 'SSH key':
[example.com] $

Since the OpenSC PKCS#11 module is registered by default to p11-kit in Fedora, which is via p11-kit-proxy, used by OpenSSH, you can simplify the above commands:

$ ssh -i pkcs11:id=%01 example.com
Enter PIN for 'SSH key':
[example.com] $

The ssh-agent interface accepts the same URIs. For example, you can add only the ECDSA key to the agent and connect to example.com (this was not previously possible):

$ ssh-add pkcs11:id=%01
Enter passphrase for PKCS#11: 
Card added: pkcs11:id=%01
$ ssh example.com
[example.com] $

If you skip the ID, OpenSSH will load all the keys that are available in the proxy module, which usually matches the previous behavior, but is much less typing:

$ ssh -i pkcs11: example.com
Enter PIN for 'SSH key':
[example.com] $

Known issues

While the smart cards work generally fine, there are some corner cases, that are not handled ideally yet. Most of them are tracked upstream bugzilla.

From the most painful ones, we can note that the keys stored in ssh-agent do not support reauthentication. Therefore once you physically remove the token, you also need to remove and re-add it in the ssh-agent. Its interface does not provide a functionality to this automatically, so there is still some work to be done.

The ssh-agent also does not allow you to use keys that require PIN verification before signature (ALWAYS_AUTHENTICATE flag). This is very common in PIV cards to ensure non-repudiation of digital signatures. In this case, the easy workaround is to use different key, that does not enforce this policy.


The new OpenSSH comes with few improvements for private keys stored in smart cards and security tokens. These changes make the usage of security tokens easier for new users, allow them to take advantage of secure storage, in comparison to keys on disk. They also integrate OpenSSH into Fedora which already supports the RFC7512 identifiers for objects stored in tokens and uses p11-kit for smart card driver registration.

If you found an issue with the above functionality, or you have and idea what could be improved, feel free to comment, open a bug or start a discussion on Fedora or OpenSSH mailing lists.

The aforementioned features are available in Fedora, but not yet in the upstream OpenSSH releases. We include these changes in the hope they will be useful for users and it can make the upstream adoption of them faster.

For Developers For System Administrators New in Fedora Using Hardware Using Software


  1. mrroman

    It is maybe a little of topic, but how to setup smartcard/permissions to work with user account? I have yubikey and I can’t set it so I don’t have to run “gpg –card-status” with root permissions.

    • You should not need to do that. This worked fine for me on whole systems until I gave up using GPG. What particular errors are you getting if you try to access the smart card? Do you have pcscd daemon (or at least socket) running?

      • mrroman

        Thanks Jakub! Everything works after installing pcsc-lite and starting pcscd service. I didn’t stumble upon an article about yubikey that suggested installing pcscd daemon.

    • Shujie

      You should use gpg2 instead of gpg.

      gpg is gpg (version 1.4) and gpg2 is gpg ( version 2.2) that’s default in Fedora

      • mrroman

        Yes, I have both installed but neither was working. But installing pcsc-lite package helped.

  2. Leslie Satenstein

    Very useful and very informative.

    Thank you Jakub.

  3. David F. Lanphere Sr.

    will this software allow the use of the US Government CAAC ID Cards? I am striving to use only Linux in my every day computer activities, and feel compromised every time I am forced to revert to Windoz.

    • The CAC Smart Cards are supported in OpenSC (and in Fedora and RHEL) since last year so you should be able to do everything from above (except they do not have ECDSA keys) and much more as you do on Windows.

  4. Joao Rodrigues

    Let’s say I wanted to login in my computer using a smartcard (with PIN) instead of login/password. And lock the session when the card was removed. Is it doable?

    • Yes, but it is out of the scope of this article.

      Local login can be configured either with pam_pkcs11 (the old way), or with SSSD (new and preferred way), but I do not have the exact steps at hand. Though, it is a nice idea for next article, since it can be interesting for more people.

  5. Etienne Champetier

    If I remember correctly Fedora 27 was using gnome-keyring-daemon instead of ssh-agent (at least Fedora 26 was). I now see that Fedora 28 uses ssh-agent, which is a wonderful news as this allow to use ssh-add with ED25519 keys or with ssh certs (ssh agent forwarding with ssh certificates)

    • Yes, you are right. Until Fedora 27, the gnome-keyring was unable to handle new key types (including ECDSA and ed25519), certificates and smart cards.

      We fixed this in Fedora 28’s gnome-keyring, because it was common pain among users. The new gnome-keyring now wraps normal ssh-agent to provide better user experience (preloading public keys) but not limiting the supported functionality.

      Thank you for mentioning this. It is indeed an improvement worth saying, but it was somehow hidden behind other changes that we brought in with this release.

      • Etienne Champetier

        Is it a Fedora only fix, or was it done in Gnome upstream and will come to other distro ~soon ? (asking for some coworkers, they should be using Fedora already 🙂 )
        Thanks for this nice improvements!!

        • The gnome-keyring was fixed in latest GNOME 3.28 so it should show up in other distros eventually. The smart cards support described in this article are only in Fedora so far.

Comments are Closed

The opinions expressed on this website are those of each author, not of the author's employer or of Red Hat. Fedora Magazine aspires to publish all content under a Creative Commons license but may not be able to do so in all cases. You are responsible for ensuring that you have the necessary permission to reuse any work on this site. The Fedora logo is a trademark of Red Hat, Inc. Terms and Conditions