wolfPKCS11 2.2.0 Released

We are pleased to announce the release of wolfPKCS11 2.2.0. This release adds verify-only support for the LMS/HSS and XMSS/XMSS^MT stateful hash-based signature schemes, an option to ship wolfPKCS11 as a single self-contained library with wolfSSL linked in, and much faster token writes on custom storage backends.

It also delivers a large round of PKCS#11 compliance, memory-safety and concurrency hardening, along with fixes for TPM, Windows and NSS users.

New features

LMS/HSS and XMSS/XMSS^MT signature verification
wolfPKCS11 can now verify signatures from the two stateful hash-based signature families approved in NIST SP 800-208: LMS/HSS (RFC 8554) and XMSS/XMSS^MT (RFC 8391). Public keys are imported from their raw encoding, can be stored on the token, and are used through C_Verify with the standard PKCS#11 v3.3 CKM_HSS, CKM_XMSS and CKM_XMSSMT mechanisms.

Support is enabled with –enable-lms and –enable-xmss, and is off by default. This first step is verify only: key generation, private key import and signing are rejected.

A self-contained library with static wolfSSL
wolfPKCS11 can now link a static wolfSSL into libwolfpkcs11, using –with-static-wolfssl=/path/to/libwolfssl.a with Autotools or -DWOLFPKCS11_STATIC_WOLFSSL=yes with CMake. The module then ships as one library with no run-time dependency on libwolfssl.

The embedded wolfSSL symbols stay hidden, so an application that uses its own wolfSSL, even one built with a different configuration, can still load the module through dlopen() or wc_Pkcs11_Initialize(). This option needs an ELF linker and cannot be combined with wolfTPM support. As part of this work, the Autotools build now exports the PKCS#11 v3.0 and v3.2 functions, and the CMake build exports only the C_* functions.

Faster token writes
Creating or destroying a token object used to rewrite every object on the token. wolfPKCS11 now writes only the objects that change, and C_SetAttributeValue on a token object is stored straight away. On an STM32U585 running a wolfBoot TrustZone keystore, creating eight token objects dropped from 24.9 seconds to 6.3 seconds.

Security and compliance hardening

Much of this release closes findings from Fenrir, our internal code-scanning tooling, across PKCS#11 compliance, memory safety and concurrency. The main areas are:

  • Access control and login state: private objects are limited to user sessions, setting CKA_TRUSTED needs an SO session, login lockout counts also cover C_SetPIN, and closing all sessions now logs the application out.
  • Stored objects: each object’s policy (class, key type, key generation mechanism and operation flags) is now bound to its encrypted key data as authenticated data. Stored records are validated before use, and store failures are reported and rolled back.
  • Operations and parameters: operation state is released when an operation is replaced, cancelled or fails. AES-GCM, AES-CCM, OAEP, PSS, CMAC, ECDH, DH, HKDF and TLS derive parameters are checked, and lengths that do not fit in 32 bits are rejected.
  • Templates and attributes: attribute templates are validated before an object is changed, and key material and certificate values are fixed once an object is created.
  • Zeroisation: key material and transient MAC, AES and RNG buffers are cleared after use and on error paths.

On the concurrency side, the internal read/write lock has been rewritten so it is never released by a thread that did not take it. We also fixed a double free when two sessions destroy the same token object, and a race where C_DestroyObject could remove a different object. ThreadSanitizer now runs in CI to keep it that way.

Object handles also stay unique when object IDs run out. Previously, after about 268 million objects, a session object could take the handle of an existing token object.

Notable fixes

  • TPM ECDH: EC keys generated on a TPM slot are now created with TPM capabilities that match CKA_SIGN and CKA_DERIVE, and ECDH runs on the TPM itself.
  • Windows: the PKCS#11 structures now use the 1-byte packing other PKCS#11 modules use on Windows, fixing crashes in applications that call through C_GetFunctionList. The default token path is now %APPDATA%\wolfPKCS11, and MinGW-w64, Cygwin and MSYS2 builds work again.
  • Default token path: WOLFPKCS11_DEFAULT_TOKEN_PATH is now used ahead of the home directory, and a path set with –with-default-token-path or CMake now works.
  • NSS: database paths with a sql:, dbm: or extern: prefix now work, and C_WrapKey no longer leaves an operation active after a length query, which broke pk12util -o.
  • PIN changes: C_SetPIN now re-encrypts protected token objects under the new token key, so they can still be read after the next C_Initialize.
  • Attributes: CKA_CHECK_VALUE is now computed by key type, and C_GetAttributeValue returns CKR_ATTRIBUTE_TYPE_INVALID for attributes an object does not have while still filling in the rest of the template.
  • Memory leak: decoding already-loaded keys at C_Login no longer leaks memory when wolfSSL is built with HAVE_WOLF_BIGINT, for example with –enable-pkcs11.
  • FIPS: the AES key wrap with padding code now builds against FIPS v5.2 modules.

Upgrading from 2.1

Some of these fixes change behaviour that applications or stored tokens may depend on. Please check the following before upgrading:

  • Stored tokens: tokens written by 2.1 and earlier load as before, and each object moves to the new policy-bound format the next time it is stored. Earlier releases cannot read the new format, so a token used with 2.2 cannot be moved back to 2.1.
  • Token path: the lookup order is now WOLFPKCS11_TOKEN_PATH, the NSS store directory, WOLFPKCS11_DEFAULT_TOKEN_PATH, then the home directory. Builds that set a default path and keep tokens in $HOME/.wolfPKCS11 should set WOLFPKCS11_TOKEN_PATH or move the token files.
  • Windows: applications must be rebuilt against the new headers because of the structure packing change. Define WOLFPKCS11_NO_PACKED_STRUCTS to keep the old layout.
  • AES-CMAC: CKM_AES_CMAC now produces and checks a full 16-byte MAC, where earlier releases used 8 bytes.
  • Check values: the CKA_CHECK_VALUE of a generic secret key is now the first three bytes of the SHA-1 hash of its value, as PKCS#11 3.2 defines.
  • Stricter checks: C_SetAttributeValue rejects changes to CKA_TOKEN, CKA_PRIVATE, CKA_MODIFIABLE, key components and certificate values. C_CreateObject requires the key or certificate value, and deriving, encapsulating or decapsulating into a private key needs a user login.
  • TPM EC keys: keys stored by earlier releases were created for signing only and cannot be used for ECDH.

The full list, including the smaller changes, is in the 2.2 release notes.

With thanks

Our thanks go to Peter Dennis Bartok for reporting the C_GetAttributeValue and CKA_CHECK_VALUE issues (#221, #245), and to Nazar Serhiichuk for reporting the Windows ABI issue (#208).

Get the release

wolfPKCS11 2.2.0 is available now. You can find the full changelog and download the release from the wolfPKCS11 GitHub releases page, or clone the repository directly for source access and integration.

If you have questions about any of the above, please contact us at facts@wolfssl.com or call us at +1 425 245 8247.

Download wolfSSL Now