https://bugs.kde.org/show_bug.cgi?id=459173
--- Comment #10 from John Scott <[email protected]> --- Signing documents with a smartcard is possible already and I don't think the title of this bug accurately describes a problem, but I'd like to describe some background information about how smartcard support actually works, because the fine details are unfortunately not described well in any single place. Right now there are two signature backends in Okular and both support smartcards for X.509 signatures even if in two slightly different ways: • the gpgsm backend, which uses a "GnuPG agent" (conceptually similar to an SSH agent) via interprocess communication, usually a Unix domain socket, to issue requests for things to be signed. • the Mozilla NSS backend, which is a cryptography library from Mozilla which supports its own internal key and certificate stores but also commonly uses PKCS#11 modules to interface with other key stores, software and hardware, and which may include both public certificates as well as secret keys Now, a word about smartcards. Smartcards come in a lot of different physical-layer form factors such as on-board TPMs, USB, Bluetooth, or NFC devices, over TCP/IP, software emulation, and more. They may also use different conventions for communicating with the host or offer different capabilities, with notable "profiles" including PIV cards (now an international standard) and OpenPGP cards. Some cards may require their own "drivers" of sorts if they operate in some custom way, and in that case you usually get that from the card manufacturer. Other times, as with PIV cards that (for the most part) "work alike", you may use a manufacturer-agnostic shim to communicate with the hardware. OpenSC is a project that aims to do this for many families of cards. Most applications, like Okular, or web browsers and such, would rather not care about this. Fortunately there is a standard that helps called PKCS#11, the Cryptographic Token Interface ("cryptoki") maintained by OASIS: https://www.oasis-open.org/committees/pkcs11/ It defines a standard API for shared objects (".so" in Unix land), referred to as "modules", that can be loaded (such as with dlopen()/dlsym()) to interface with some driver for some hardware, learn its capabilities, and get info about the keypairs it may store. Cards may store mere cryptographic (mathematical) objects ("raw" key pairs, identified by their subjectPublicKeyInfo in X.509 jargon) and leave higher-level interpretation to the PKCS#11 module software, or to applications. Other cards may have enough flash storage to hold a convenience copy of the *public* certificate, so that a card can be plugged into a host computer and used easily right away. OpenPGP cards, for example, usually store a URL that an OpenPGP public key can be obtained from, intended to be on the public internet. So in this conceptual model, we have this arrangement going on: user agent/application [Okular, LibreOffice, web browser...] ↔ PKCS#11 shared object (basically a software library for talking to some vendor's hardware with a pluggable standard API) ↔ actual smartcard hardware (which may have on-board storage for arbitrary data as a convenience, or which may retain almost no metadata itself and expects the vendor's PKCS#11 "driver" to take up that responsibility) This is a theoretical model though and more layers of abstraction are actually spliced in. Okular does not speak PKCS#11 or even care to have knowledge of cryptographic algorithms. It uses its backend (we'll focus on NSS for right now) to probe for what X.509 certificate authorities the user trusts, what private keys (if any) the user possesses, what public keys they may correspond to, and so on. The NSS library, separately from using PKCS#11, knows how to handle secret keys and store them on disk in its database, but it also has good support for using PKCS#11 modules when configured to use them (see the 'modutil' utility). Unlike other TLS/CMS libraries, NSS is designed mainly to meet Mozilla Firefox's needs, so it's usually configured at the user level instead of with system-wide configuration files as with OpenSSL. (OpenSSL seldom needs explicit configuration anyway.) When used with Firefox, NSS stores all of its per-user preferences—including which certificate authorities to trust, your public and private keys, and desired means to perform revocation checking—in tandem with Firefox profiles in a user's home directory. In Firefox's settings it's possible to tweak NSS's advanced settings right from the GUI. This includes such things as "I would like to introduce you to my PKCS#11 module. You should try talking to /usr/lib/pkcs11/foo.so whenever you're doing 'roll call' to see what public/private keys I possess, in addition to your internal on-disk store." If you don't use Firefox, you may not even have an NSS database set up anywhere... and that's where things get puzzling, because other NSS-using applications like Okular and LibreOffice don't expose detailed settings like Firefox does. That's not their fault—it's just that Firefox does double-duty as being an ordinary application, but also being the de facto configuration UI for NSS. That's important not just for telling NSS about your favorite PKCS#11 modules, but even just importing a certificate with a private key file to store on disk. Okular and LibreOffice are designed with the assumption that things are already set up to your liking, and if they find a Firefox installation with an NSS database for your user, they'll sometimes try to use it automagically—that's better than a clean slate anyway, right? Otherwise different NSS-using applications may choose to duplicate settings or store them in totally different places which can get kind of crazy, but Okular and LibreOffice allow you to set the path manually so you can get them all to agree. A de facto standard, including with GNOME's Evolution, has emerged to use the directory ~/.pki/nssdb/ as one possible location for an NSS DB. If you don't use Firefox, such a database can be manipulated with command-line tools 'certutil' (for handling public and private certificates stored internally or otherwise known to NSS, their nicknames, trust levels for particular applications, generating new key pairs, and so on), and also 'modutil' (for setting up what PKCS#11 modules—if any—you'd like to use). Such configuration only benefits NSS applications, not programs using OpenSSL, GnuTLS, or other crypto libraries. What crypto library an application uses behind the scenes often doesn't really make a difference to a user, and figuring out what installed PKCS#11 modules should actually be used is also a common toss-up. That's where p11-glue/p11-kit comes in, which (optionally) provides a PKCS#11 "reverse proxy" module that rounds up all of the other PKCS#11 modules on your system and presents them as a virtualized one, so you can centralize your choice of smartcard configuration and which modules to use in a way amenable to all of the crypto libraries. That's what p11-kit-client is. This isn't necessary but often simplifies setup on workstations. It also makes it easy to use different cards, even from different vendors, and which may need different "drivers" via different PKCS#11 modules, all at the same time. And in this case, you only need to use 'modutil' to tell NSS about p11-kit-client. GnuTLS usually tries p11-kit-client by default in the absence of other configuration, and I don't have personal experience with the OpenSSL bits but it's probably a small configuration option with the provider/engine. If you don't want to use the p11-kit shim, using modutil to tell NSS about your PKCS#11 module(s) directly is also okay. OpenSC provides drivers for many common card types, including PIV and OpenPGP cards, and so you may inform NSS of opensc-pkcs11.so. There's also a PKCS#11 module from the folks behind GnuPG called Scute that (going through gpg-agent and scdaemon) lets you use your OpenPGP card, even for X.509 crypto. This can be convenient because usually only one PKCS#11 module can talk to a piece of hardware at a time, so if you're a GnuPG user even occasionally, OpenSC and GnuPG will fight for custody of the smartcard. Also, SoftHSM is a PKCS#11 module that, effectively, just stores your private keys on disk using software. It would be useful if you wanted a software keystore but Mozilla NSS didn't make one of their own, or if you wanted to have a centralized location to keep your private key so many applications on your system could use it (think a TLS certificate's key for example, which might be used by both an HTTP daemon and an SMTP daemon). Now the network diagram looks more like this for possibilities: Okular ↔ Mozilla NSS ↔ { NSS Internal Crypto Store, PKCS#11 module (opensc-pkcs11.so) ↔ { Foobar Inc. USB Token ↔ { flash storage, RPC-like transport of signed or to-be-signed data, vendor extensions, ... } , ... }, another PKCS#11 module (...), p11-kit's PKCS#11 module wrapper (p11-kit-client.so) ↔ { PKCS#11 module (opensc-pkcs11.so), ... } ... } Yes, recursion is absolutely possible here. I don't make the rules 🤷. And aside from all of this, there's one problem worth mentioning and which may cause the reporter's problems: NSS does not cope with multiple certificates (from any combination of sources) having the same nickname nicely at all. It's possible to get into a state where you have multiple certificates that end up with the same nickname in NSS, and when doing 'pdfsig -nick foo', or signing in Okular or another application, you'll practically reach uncharted territory with no practical way out. certutil doesn't help since the use of a nickname is (apparently) the only way to specify a certificate you'd like to *rename*, so if you're trying to rename certificates to ensure they have unique names, you're in a chicken-and-egg problem. After renewing a certificate and importing the new one in NSS's software store, or if any two key stores (the internal one or any number of PKCS#11 modules) offer up keypairs under the same nickname, you're kind of toast. One possible future avenue for exploration would be that, sometimes, NSS allows using a PKCS#11 URI (RFC 7512) in place of a nickname. With pdfsig on the command-line this is an effective way to unambiguously say what certificate you'd like to sign with. In my scripts I usually have something like > pdfsig -backend NSS -nick > pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;serial=XXXXXXXXXXXXXXXX;token=X.509%20certificate;id=%47%E3%4A{...}%A8;object=Certum where, in some higher-level interfaces like '-list-nicks', 'Certum' would usually appear to be the nickname, sometimes prefixed with the "token name" which I've aptly named "X.509 certificate". The reporter's issues may come from having the certificate imported in both the software certificate store as well as via a PKCS#11 card, which makes NSS get into that "undefined" state I alluded to before. I would suggest to the reporter to share the output of 'certutil -K -h all -d ~/.pki/nssdb/', where that path at the end may need to be replaced with whatever NSS DB location Okular is actually trying to use (visible in Okular's PDF backend settings). This will list all private keys that NSS is discovering from any token anywhere, including the internal software store. If any two keys have the same nickname (displayed in the rightmost column), that's going to be a problem. -- You are receiving this mail because: You are watching all bug changes.
