provider-pkcs11(7)

πŸ’… pkcs11-provider(7) β€” the OpenSSL provider that talks straight to your PKCS#11 drivers

okay so bestie, this is the manual page for provider-pkcs11(7) and it's literally the glow-up your OpenSSL setup has been waiting for. buckle up πŸŽ€


✨ NAME ✨

pkcs11-provider β€” an OpenSSL provider that lets you interface directly with pkcs11 drivers. no middleman, no cap. πŸ¦‹


🌸 DESCRIPTION 🌸

So here's the lore: starting with version 3.0, the OpenSSL project introduced a whole new modular system to extend OpenSSL, and it replaces the deprecated Engines modules. iconic behavior honestly πŸ‘‘

Providers(1) get loaded via configuration directives in the openssl configuration file β€” or they can be loaded directly by applications, if the app is feeling independent like that.

The pkcs11 provider lets applications linked to openssl use keys and cryptographic operations from a hardware or software token, via their PKCS#11(2) driver and the use of pkcs11 URIs(3). yes, that's a lot of acronyms, but trust, it slaps πŸ’œ

And the pkcs11 provider can be configured to be automatically loaded via openssl.cnf. set it and forget it, main character energy fr fr ✨


πŸŽ€ CONFIGURATION πŸŽ€

These are the configuration options the provider recognizes. every single one, no skipping πŸ’–

🌈 pkcs11-module-path

A file path to the pkcs11 driver you want to use. simple as that.

Default: if compiled with p11-kit, it defaults to its proxy driver. otherwise, none.

NOTE: see also PKCS11_PROVIDER_MODULE in the environment variables section πŸ‘€

Example:

pkcs11-module-path = /usr/lib64/opensc-pkcs11.so

🌈 pkcs11-module-init-args

Non-standard initialization arguments that some pkcs11 drivers may need. generally this goes unused, but some software tokens β€” like NSS's softokn β€” do require it. picky little things πŸ’…

Default: None

Example:

pkcs11-module-init-args = configDir=/etc/pki/token

🌈 pkcs11-module-token-pin

The user PIN to be used with the token. if a PIN isn't set in configuration, it can be asked interactively (when the application uses prompters), or it can be specified right there in the pkcs11 URI together with the key identifiers. when you specify a file, that file has to be a text file containing just the PIN on the first line plus a terminator. keep it tidy 🧚

Default: None

Example:

pkcs11-module-token-pin = file:/etc/pki/pin.txt
cat /etc/pki/pin.txt
123456

🌈 pkcs11-module-allow-export

Whether the pkcs11 provider will let you export public keys through OpenSSL. here's the tea: OpenSSL often tries to export public keys from non-default providers over to the default provider, and then uses OpenSSL's own functions to handle whatever operation is associated with that public key. this option is genuinely useful for forcing public key operations to be executed on the token β€” for example when your pkcs11 thing is an accelerator with better performance on signature checking or asymmetric encryption than OpenSSL's own code. let the specialist cook πŸ”₯

Default: 0 (Allow Export)

Example:

pkcs11-module-allow-export = 1 (This disallows export of public keys)

🌈 pkcs11-module-cache-keys

Whether the pkcs11-provider should ask the token to cache token keys in the session. this is used in some tokens as a performance optimization. like, software tokens that store keys encrypted can keep a copy of the key in the session to speed up access. or networked HSMs that allow exporting key material can cache the key in the session instead of re-requesting it over the network. speed ✨

Two options are available:

  • true
  • false

Default: true (note: if the token doesn't support session caching, then caching will be auto-disabled after the first attempt)

Example:

pkcs11-module-cache-keys = false (Disable any attempt of caching keys in the session)

🌈 pkcs11-module-cache-pins

Whether the pkcs11-provider should cache a PIN entered interactively. this is useful for starting a service and providing the PIN only manually, yet still letting the service perform multiple logins as needed β€” for example, after forking. lowkey essential 🫢

Only one option is currently available:

  • cache: caches the PIN

Default: unset (No caching)

Example:

pkcs11-module-cache-pins = cache (Will cache a pin that has been entered manually)

🌈 pkcs11-module-cache-sessions

Lets you tune how many pkcs11 sessions may be kept open and cached for rapid use. this parameter is adjusted based on the maximum number of sessions the token declares as supported. heads up: the login session is always cached to keep the token operable. no takebacks πŸ’€

Default: 5

Example:

pkcs11-module-cache-sessions = 0 (Disables caching)

🌈 pkcs11-module-encode-provider-uri-to-pem

Whether the pkcs11 provider registers a PEM encoder for private keys. it encodes private keys in PEM files that contain a PKCS#11 URI referencing the key. these PEM files use the non-standard PKCS#11 PROVIDER URI header/trailer.

This encoder is necessary for non-extractable keys, because otherwise OpenSSL will fail to export such keys (for example, during openssl genpkey). it's also necessary for legacy applications that require keys to be passed as PEM files instead of as PKCS#11 URIs (peep USE IN OLDER APPLICATIONS).

The corresponding PEM decoder is always registered. always, bestie πŸ’–

Default: false

Example:

pkcs11-module-encode-provider-uri-to-pem = true

🌈 pkcs11-module-login-behavior

Whether the pkcs11 provider will attempt to login to the token when a public key is being requested.

Three options are available:

  • auto: try without, but fall back to login behavior if no keys are found
  • always: always login before trying to load public keys (some HSMs require this)
  • never: never login for public keys

Default: "auto"

Example:

pkcs11-module-login-behavior = always (Always tries to login before loading public keys)

🌈 pkcs11-module-load-behavior

Whether the pkcs11-provider immediately loads and initializes the pkcs11 module the second OpenSSL loads the provider (generally at application startup), or defers initialization until the first time a pkcs11 key is loaded (or some other operation explicitly requiring the pkcs11 provider gets requested). your choice, your timeline ⭐

Only one option is available:

  • early: loads the pkcs11 module immediately

Default: unset (Loads only at first use)

Example:

pkcs11-module-load-behavior = early (Loads pkcs11 module immediately at application startup)

🌈 pkcs11-module-quirks

Workarounds that may be needed to deal with some tokens, which can't be autodetected yet and aren't appropriate defaults. messy, but necessary πŸ™ˆ

πŸ’« luna-non-standard-cku-user

Use the non-standard Crypto User (user type 0x80000001) available in Thales Luna HSMs instead of the normal Crypto Officer (CKU_USER).

πŸ’« no-deinit

It prevents de-initing when OpenSSL winds down the provider. NOTE: this option may leak memory, and may cause some modules to misbehave if the application intentionally unloads and reloads them. be careful, babe ⚠️

πŸ’« no-operation-state

OpenSSL by default assumes contexts with operations in flight can be easily duplicated. that's only possible if the tokens support getting and setting the operation state. if this quirk is enabled, the context duplication is not performed.

πŸ’« no-session-callbacks

Some implementations of PKCS11 don't allow setting pApplication and Notify callback functions in C_OpenSession. this option sets NULL values for both callbacks.

πŸ’« no-allowed-mechanisms

Some implementations of PKCS11 don't support the CKA_ALLOWED_MECHANISMS attribute on keys. setting this quirk prevents the provider from attempting to set and read this attribute. respect the boundaries πŸ’…

Default: none

Example:

pkcs11-module-quirks = no-deinit no-operation-state (Disables deinitialization, blocks context duplication)

🌈 pkcs11-module-block-operations

Lets you block specific "provider operations" even if the token actually supports the necessary mechanisms. this is useful for working around cases where you want to enforce use of the token for all operations by setting ?provider=pkcs11 in the default properties, but you want an exception for one specific type of operation β€” like digests. NOTE: some operations may depend on others, or may be fundamental to the correct working of the provider, so not all configurations of this parameter will work. use carefully, seriously 🚨

Default: none

Example: pkcs11-module-block-operations = digest (Disables digest mechanisms, which will be instead routed to the OpenSSL default provider in most configurtions)

🌈 pkcs11-module-assume-fips

Assume the token used by the PKCS#11 module is FIPS certified.

Due to the incomplete specification for signalization of the certification from the pkcs11 modules, this can not be determined automatically. so if you know your token is FIPS certified, you need to set this configuration option to true. otherwise the pkcs11-provider will not work in FIPS Mode. no FIPS for you 😭

Default: False

Example:

pkcs11-module-assume-fips = true

🌈 pkcs11-module-default-slot-id

The default slot ID for new objects.

The default slot is used for any objects that don't have an explicitly selected slot. such objects include, for example, public keys.

This option is useful when multiple slots with different PINs are used. in those cases, it lets you make sure that pkcs11-module-token-pin points to the expected slot. no mixups 🎯

If no value is specified, the first listed slot is used.

Default: none

pkcs11-module-default-slot-id = 12345

🌈 pkcs11-max-pin-length

Set the maximum length (in bytes) allowed for token PINs when reading PINs from files or pin sources.

If not explicitly set, it defaults to 256. during provider slot initialization, if any token reports a larger maximum PIN length (ulMaxPinLen), the limit is automatically adjusted to match the maximum value reported across available tokens. self-adjusting icon πŸ’«

Default: 256

Example:

pkcs11-max-pin-length = 512

πŸ¦‹ ENVIRONMENT VARIABLES πŸ¦‹

Environment variables the provider recognizes πŸ’–

⭐ PKCS11_PROVIDER_MODULE

This variable can be used to set a different pkcs11 driver to be used. it's useful when an application needs to use a different driver than the rest of the system. this environment variable overrides the pkcs11-module-path option set in openssl.cnf. yes, overrides. env wins, periodt πŸ‘‘

Example:

PKCS11_PROVIDER_MODULE = /usr/lib64/opensc-pkcs11.so

⭐ PKCS11_PROVIDER_DEBUG

This variable can be set to obtain debug information. two sub-options can be specified: file, level.

The normal debug_level is 1. if you set a higher level, then additional information (like all supported mechanism info for each slot) is printed in the specified debug file. the comma character separates options, and the colon character is used to separate an option and its value. there is no escape character, therefore the characters , and : cannot be used in values. plan accordingly 🧚

Examples:

PKCS11_PROVIDER_DEBUG=file:/tmp/debug.log
PKCS11_PROVIDER_DEBUG=file:/dev/stderr,level:2

PINs can also be provided in PKCS#11 URIs via environment variables using the env: schema (e.g., pin-source=env:VARIABLE_NAME). sneaky and convenient πŸ“

πŸ’… USE IN OLDER APPLICATIONS (URIs in PEM files)

Okay bestie, real talk: if your app is still doing the old-school thing, the strongly suggested glow-up is to update it to use the new OSSL_STORE API provided by OpenSSL 3.0. Why? Because it accepts URIs and transparently loads keys from either files or any other supported mechanism, PKCS#11 URIs included. It's giving effortless. ✨

But like… we know not every app can be changed yet. No shade. So for those applications that cannot yet be changed, there's a tool that generates a "wrapper" PEM file containing the PKCS#11 URI you need to identify a key on a token. πŸŽ€

This PEM file can be loaded via the classic methods used to parse PEM/DER representations of keys, and it will trigger the use of the pkcs11-provider decoders when the provider is loaded. An error will be returned if the provider isn't pre-loaded, or if an older version of OpenSSL is used. So like, pre-load it. πŸ‘‘

In tools/uri2pem.py there's a sample python script that can take a key URI and produce a PEM file that references it. Cute, right?

⚠️ Okay but serious moment: storing PINs within these PEM files is not secure. These files are not encrypted. Not even a little. Do not put your PIN in there and act surprised, bestie. 😭

To register an encoder for such PEM files with OpenSSL, see pkcs11-module-encode-provider-uri-to-pem.

And this little command right here can list all keys on a token and print their identifying URI β€” honestly iconic:

openssl storeutl -keys -text pkcs11:

🌸 EXAMPLES

Your openssl.cnf, serving looks:

HOME = .

# Use this in order to automatically load providers.
openssl_conf = openssl_init

[openssl_init]
providers = provider_sect

[provider_sect]
default = default_sect
pkcs11 = pkcs11_sect

[default_sect]
activate = 1

[pkcs11_sect]
module = /usr/lib64/ossl-modules/pkcs11.so
pkcs11-module-path = /usr/lib64/pkcs11/vendor_pkcs11.so
pkcs11-module-token-pin = file:/etc/ssl/pinfile.txt
activate = 1

Copy it, paste it, live your truth. πŸ’–


πŸ¦‹ SEE ALSO

  1. PROVIDER(7) man page β€” https://www.openssl.org/docs/manmaster/man7/provider.html
  2. PKCS#11 Technical committe and standards β€” https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=pkcs11
  3. PKCS#11 URI Scheme - RFC 7512 β€” https://www.rfc-editor.org/rfc/rfc7512

That's the whole vibe, bestie β€” go forth and pkcs11 responsibly. 🫢 This was provider-pkcs11(7), and yes, that's the source/version and date situation you're looking at, signed off with love. πŸ’œπŸŒˆ

πŸ“¦ where this page comes from