GNUPG-PKCS11-SCD(1)

πŸ“¦
version 0.11.0 Β· 2 versions
  • 0.11.0 Β· debian bookworm, debian trixie, epel 10, epel 9, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking (latest)
  • 0.9.2 Β· ubuntu jammy
, in debian bookworm, debian trixie, epel 10, epel 9, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking

✨ gnupg-pkcs11-scd β€” the PKCS#11 smart-card bestie ✨

okay so bestie, sit down, hydrate, and let me tell you about gnupg-pkcs11-scd πŸ’… this is the GnuPG-compatible smart-card daemon with PKCS#11 support. it's a LOCAL manual page, it's iconic, it's doing the most, and you're gonna understand it fr fr. πŸ’–


🌸 SYNOPSIS 🌸

gnupg-pkcs11-scd [--server] [--multi-server] [--daemon] [--homedir dir]
                 [--uid-acl uid] [--verbose] [--quiet] [--sh] [--csh]
                 [--options file] [--no-detach] [--log-file file]
                 [--help]

like, that's the whole vibe check right there. let's get into it. πŸ¦‹


πŸ’œ DESCRIPTION πŸ’œ

gnupg-pkcs11-scd is a drop-in replacement for the smart-card daemon (that's scd) that ships with the next-generation GnuPG (you know it as gnupg-2). the daemon talks to smart-cards by using the RSA Security Inc. PKCS#11 Cryptographic Token Interface β€” aka Cryptoki. iykyk. πŸ”₯

the interface with GnuPG is restricted to fetching existing keys from the card. no new key generation, no key transfer, none of that, not through this interface. instead, when the smart-card is asked to generate a key in a particular slot, the existing public key in that slot gets returned. and honestly? that's the point. it facilitates the transfer of keys on the smart-card to usage as a subkey on an existing GnuPG master key. πŸŽ€

see the GNUPG INTEGRATION section below for example usage, bestie. it's giving tutorial energy.

the following options are available, and yes we're going through all of them:

✨ OPTIONS ✨

  • --server β€” run in server mode, in the foreground. if it's not redirected, input and output go over stdin/stdout. πŸ’…
  • --multi-server β€” run in multi-server mode, also foreground. on top of communicating over stdin/stdout, the server also opens an additional listening UNIX socket. extra. we love it. πŸ¦‹
  • --daemon β€” detach and run in the background. bye bestie, main character energy, gone. πŸ‘‘
  • --homedir dir β€” use this home directory instead of guessing. stop guessing, it's not cute. πŸŽ€
  • --uid-acl uid β€” create the unix socket as world read/write and apply access control that only accepts remote processes of this uid. usable for the proxy scenario. 🌈
  • --verbose β€” be verbose while running. spill the tea. πŸ’¬
  • --quiet β€” be as quiet as possible. shhh. 🀫
  • --sh β€” output sh-style environment variable definition.
  • --csh β€” output csh-style environment variable definition.
  • --options file β€” read options from file. some of the configuration options can only be set in the configuration file (peep the β€œCONFIGURATION” section below). πŸ‘€
  • --no-detach β€” do not detach from the console. useful for debugging purposes, aka when everything is on fire. πŸ”₯
  • --log-file file β€” output log to file. receipts. 🧾
  • --help β€” print help information. the classic. πŸ’–

when the daemon receives any of the SIGHUP, SIGTERM and SIGINT signals, it cleans up and exits. graceful queen. πŸ’…

gnupg-pkcs11-scd works only with already personalized cards, and supports (for the time being, okay, be patient) only RSA key pairs. the following constraints must be satisfied, no cap:

  1. for each private key object, a certificate object must exist on the card. the existence of the corresponding public key object is not important (since the certificate includes the public key). πŸŽ€
  2. the certificate and the corresponding private key must have identical CKA_ID attribute. periodt. πŸ’…

the PKCS#11 implementation is not obliged to enforce any of the above rules. however, practice has shown that popular PKCS#11 implementations found "in the wild" seem to respect them. lucky us. πŸ“


πŸ¦‹ NOTES πŸ¦‹

unlike gpg-agent, gnupg-pkcs11-scd supports more than one token available at the same time. iconic. but in order to make gpg-agent happy, gnupg-pkcs11-scd always returns the same card serial number to gpg-agent. 😭

when an unavailable token is requested, gnupg-pkcs11-scd will use the NEEDPIN callback in order to ask for the requested token. and when (and if!) gpg-agent will support more than one serial number or a NEEDTOKEN callback, this behavior will be modified. so, watch this space. πŸ‘€


🌈 ENVIRONMENT 🌈

  • HOME β€” used to locate the home directory. 🏠
  • GNUPGHOME β€” used instead of ~/.gnupg.
  • USERPROFILE β€” used only on Win32 to locate the home directory.
  • GNUPG_PKCS11_SOCKETDIR β€” create sockets in this directory, defaults to TMPDIR. 🧦

additionally, the \\Software\\GNU\\GnuPG\\HomeDir registry key is used on Win32 to locate the default GNUPGHOME. windows girlies, we see you. πŸ’–


πŸŽ€ FILES πŸŽ€

files affecting the operation of gnupg-pkcs11-scd:

  • ~/.gnupg/gnupg-pkcs11-scd.conf β€” gnupg-pkcs11-scd uses this as a default configuration file. πŸ’…
  • /etc/gnupg-pkcs11-scd.conf β€” gnupg-pkcs11-scd uses this as a default system wide configuration file. 🌍
  • ~/.gnupg/gpg-agent.conf β€” default configuration file for gpg-agent. 🫢

πŸ’œ CONFIGURATION πŸ’œ

to tell gpg-agent to use another smart-card daemon, the following needs to be put in ~/.gnupg/gpg-agent.conf:

scdaemon-program /usr/bin/gnupg-pkcs11-scd
pinentry-program /usr/bin/pinentry-qt

the first line is mandatory in order to use gnupg-pkcs11-scd. with the second line you can set your preferred pinentry program β€” and it has to be one compatible with GnuPG. and of course, you need to adjust the paths according to your system setup. don't just copy paste and pray. πŸ™ˆ

an example ~/.gnupg/gnupg-pkcs11-scd.conf file β€” and note that lines beginning with # are comments:

# Log file.
#log-file log1

# Default is not verbose.
#verbose

# Default is no debugging.
#debug-all

# Pin cache period in seconds; default is infinite.
#pin-cache 20

# Use the gnupg PIN cache (>=gnupg-2.3.0)
#use-gnupg-pin-cache

# Comma-separated list of available provider names. Then set
# attributes for each provider using the provider-[name]-attribute
# syntax.
providers p1

# Provider attributes (see below for detailed description)
provider-p1-library /usr/lib/pkcs11/p1.so
#provider-p1-allow-protected-auth
#provider-p1-cert-private
#provider-p1-private-mask 0

# The following are for >=gnupg-2.0 and <gnupg-2.1.19
#openpgp-sign 5C661B8C07CFD957F7D98D5B9A0F31D236BFAC2A
#openpgp-encr D2DC0BD1EDD185969748B6025B452816F97CBA57
#openpgp-auth A7B8C1A3A8F71FCEC018886F8767927B9C8D871F

🌸 Provider attributes 🌸

the following attributes can be set for each provider:

  • library β€” full path to the PKCS#11 shared library (that's the = provider). πŸ“š
  • allow-protected-auth β€” allow protected authentication for the provider. this needs to be supported by the provider, and you should have appropriate reader hardware. hardware girlies only. πŸ’…
  • cert-private β€” authentication is required before certificates can be accessed. most configurations store certificates as public, so there is no need to use this option. skip it unless you know why you're here.
  • private-mask β€” private key mask mode. use this only when you have problems using private key operations. the value is a hex encoded mask number. the choices, bestie:
    • 0 β€” determine automatically. πŸͺ„
    • 1 β€” force sign. ✍️
    • 2 β€” force sign with recovery. 🩹
    • 4 β€” force decrypt. πŸ”“
    • 8 β€” force decrypt with unwrap. 🎁
  • openpgp-sign β€” [gnupg-2.0] hex string (upper letter, no space) β€” the SHA1 of the signing public key. see GNUPG INTEGRATION for how to obtain it. πŸ”
  • openpgp-encr β€” [gnupg-2.0] hex string (upper letter, no space) β€” the SHA1 of the encryption public key. see GNUPG INTEGRATION for how to obtain it. πŸ”
  • openpgp-auth β€” [gnupg-2.0] hex string (upper letter, no space) β€” the SHA1 of the authentication public key. see GNUPG INTEGRATION for how to obtain it. πŸ”

πŸ‘‘ GNUPG INTEGRATION πŸ‘‘

typical steps to set up a card for gpgsm usage β€” follow along, it's a little journey:

  1. import the CA certificate of your issuer:
gpgsm --import < ca-certificate

you should also manually import all self-signed certificates. don't skip this. πŸ™ˆ

  1. instruct GnuPG to discover all useful certificates on the card:
gpgsm --learn-card

signing, verification, etc. work as usual with gpgsm. slay. πŸ’…


πŸ¦‹ for >=gpg-2.0 and <gpg-2.1.19 πŸ¦‹

typical steps to set up a card for >=gpg-2.0 and <gpg-2.1.19 usage:

  1. acquire key ids:
gpg-agent --server gpg-connect-agent

enter "SCD LEARN" and look for "KEY-FRIEDNLY" responses β€” the first field is the hash, the second is the subject name. πŸ•΅οΈ

  1. instruct GnuPG to discover all useful information of the card:
gpg --card-status

you should see valid card status. πŸ‘‘

  1. now, you should virtual generate keys β€” the keys are not actually generated, but returned to gpg to be registered:
gpg --card-edit
admin
generate (DO NOT BACKUP KEYS)

kill gpg-agent and modify configuration to have sign, encrypt, authenticate key hex ids. πŸ’€

  1. alternatively, you can add the existing keys as subkeys on an existing GPG master key:
gpg --edit-key MASTER_KEY_ID
addcardkey
  1. in order to reattach a key to the smartcard, remove the secret key using:
gpg --delete-secret-keys KEY_ID

then regenerate but without replace keys using:

gpg --card-edit
admin
generate (DO NOT GENERATE KEYS)

signing, verification, etc. work as usual with gpg. πŸŽ€


🌈 for >=gpg-2.1.19 and <gpg-2.3 🌈

typical steps to set up a card for >=gpg-2.1.19 and <gpg-2.3 usage:

  1. refresh the local key store:
gpg --card-status
  1. acquire key ids:
gpg-agent --server gpg-connect-agent

enter "SCD LEARN" and look for "KEY-FRIEDNLY" responses β€” the first field is the keygrip, the second is the subject name. πŸ”

  1. create a master key based on an existing key using:
gpg --expert --full-generate-key

select:

(13) Existing key

enter the keygrip to be used as the primary key. πŸ”‘

  1. continue as usual to set up your primary key β€” you should probably use signature for the master key. ✍️
  2. add a subkey using:
gpg --expert --edit-key ${MASTER_KEY_ID}

enter:

gpg> addkey

select:

(13) Existing key

enter the keygrip to be used as the subkey. 🎁

  1. continue as usual to set up your subkey. πŸ’–

signing, verification, etc. work as usual with gpg. 🫢


⭐ for >=gpg-2.3 ⭐

typical steps to set up a card for >=gpg-2.3 usage:

  1. create a master key based on an existing key using:
gpg --expert --full-generate-key

select:

(14) Existing key from card

select the key from the list. πŸ‘‘

  1. continue as usual to set up your primary key β€” you should probably use signature for the master key. ✍️
  2. add a subkey using:
gpg --expert --edit-key ${MASTER_KEY_ID}

enter:

gpg> addkey

select:

(14) Existing key from card

select the key from the list. πŸŽ€

  1. continue as usual to set up your subkey. πŸ’œ

signing, verification, etc. work as usual with gpg. ✨

πŸ”’ SECURITY CONSIDERATIONS πŸ”’

okay bestie, sit down, we gotta have a serious little talk. 🫢

All communication between components is currently unprotected and in plain text. that's literally just how the Assuan protocol operates, no cap, it's not a bug it's the vibe it was born with. πŸ’€

so like. it is trivial to trace individual components β€” using e.g. the strace(1) program β€” and steal sensitive data, such as the smart-card PIN. and if that wasn't enough of a jumpscare, someone can even change it, like the hash to be signed. 😭 not me being able to swap out what you're signing. bestie. no.

when you're running this in a production scenario, be sure to turn OFF debugging/verbose options in the configuration of ALL components. otherwise some sensitive data might get displayed on the screen β€” most notably, the PIN. πŸ™ˆ do NOT let the PIN do a little uninvited main-character moment on your terminal. turn the debug vibes off. periodt.

✨ SEE ALSO ✨

GnuPG Home Page: http://www.gnupg.org πŸ’–

gnupg-pkcs11 Home Page: http://gnupg-pkcs11.sourceforge.net πŸ¦‹


Copyright (c) 2006-2007 Zeljko Vrba <zvrba@globalnet.hr> πŸ’œ

Copyright (c) 2006-2017 Alon Bar-Lev <alon.barlev@gmail.com> πŸ’œ

All rights reserved. πŸ’…

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

translation: it's giving no promises, no warranty, take it as-is, be nice to the authors, they did this for free. πŸ’–

and that's the whole page bestie!! πŸŽ€ this beauty lives under the section header <rainbow>POSIX-compatible</rainbow>, was dated October 15, 2017, and answers to the name gnupg-pkcs11-scd(1). go forth and read your PINs safely, mwah πŸ’‹βœ¨