Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ jobs:
with:
config: --enable-debug

# Build the library, examples and tests as C++ to catch regressions in
# C++ compatibility (e.g. missing void* casts, enum-from-int conversions,
# use of the "template" keyword, C99 compound literals). -Werror=narrowing
# promotes the int->CK_ULONG narrowing warning to an error so it is caught
# under GCC as well (clang already treats it as an error).
cpp_build:
uses: ./.github/workflows/build-workflow.yml
with:
config: CC=g++ C_EXTRA_FLAGS="-Werror=narrowing"

wolfssl_v5_6_6:
uses: ./.github/workflows/wolfssl-v5.6.6-build-workflow.yml

Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
You must delete them, or cmake will refuse to work.")
endif()

project(wolfpkcs11 VERSION 2.0.0 LANGUAGES C)
project(wolfpkcs11 VERSION 2.1.0 LANGUAGES C)

# shared library versioning
# increment if interfaces have been removed or changed
Expand Down
7 changes: 7 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ EXTRA_DIST+= cmake/wolfpkcs11ConfigVersion.cmake.in
TEST_EXTENSIONS=.test
TESTS += $(check_PROGRAMS)

# Tests set WOLFPKCS11_TOKEN_PATH to a two-level relative path (./store/<name>)
# and the storage layer only creates a single directory level. Ensure the
# parent "store" directory exists in the build tree before any test runs, so
# tests pass from a fresh build dir (e.g. under "make distcheck"). Also export
# srcdir so scripts can find distributed data files in VPATH builds.
AM_TESTS_ENVIRONMENT = mkdir -p store; srcdir='$(srcdir)'; export srcdir;

check_SCRIPTS+= $(dist_noinst_SCRIPTS)
TESTS += $(check_SCRIPTS)

Expand Down
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,77 @@ Set to any value to stop storage of token data.

## Release Notes

### wolfPKCS11 Release 2.1 (TBD, 2026)

**Summary**

This release adds post-quantum cryptography support (ML-DSA and ML-KEM), CMake
build support, and Doxygen API documentation. It also closes a large number of
PKCS#11 specification compliance gaps and bugs found through static and
negative analysis, and improves CI and interoperability testing.

**Compatibility with 2.0 behavior**

Several PKCS#11 attribute defaults were corrected to match the specification.
These changes can affect applications and stored tokens created with 2.0. The
following build defines restore the pre-2.1 (2.0) behavior if needed:

* `WOLFPKCS11_LEGACY_COPYABLE_FALSE_DEFAULT` - restore the old behavior where an
unset `CKA_COPYABLE` reads back as `CK_FALSE` (the PKCS#11 default is
`CK_TRUE`).
* `WOLFPKCS11_LEGACY_PRIVATE_FALSE_DEFAULT` - restore the old behavior where an
unset `CKA_PRIVATE` reads back as `CK_FALSE` for `CKO_PRIVATE_KEY` /
`CKO_SECRET_KEY` (the PKCS#11 default is `CK_TRUE`). Also disables the
matching login-state check on object creation.
* `WOLFPKCS11_LEGACY_WRAP_TRUE_DEFAULT` - restore the old behavior where an
unset `CKA_WRAP` / `CKA_UNWRAP` defaults to `CK_TRUE` (the PKCS#11 default is
`CK_FALSE`).

See the "Behavior changes for PKCS#11 spec compliance" section above for the
related `C_DeriveKey`, `C_CopyObject`, `C_DestroyObject`, encapsulation and
`C_Login` enforcement changes.

**Detail**

* Added ML-DSA (Dilithium) support, including `CKA_SEED` private key import.
(PR #161)
* Added ML-KEM support. (PR #175)
* Added preparation work for post-quantum cryptography support. (PR #157)
* Renamed ML-DSA mechanisms/identifiers to the final naming. (PR #188)
* Added CMake build support. (PR #156)
* Added PKCS#11 Doxygen API documentation. (PR #144)
* Added support for `CKR_OPERATION_ACTIVE`. (PR #176)
* Use the DHUK to wrap/unwrap the seed value used for the token. (PR #159)
* Added file storage safety to wolfPKCS11. (PR #150)
* Fixed empty PIN handling for FIPS. (PR #143)
* Fixed loading a token with an empty PIN. (PR #158)
* Fixed SHA-512 truncated forms (SHA-512/224 and SHA-512/256). (PR #147)
* Fixed `C_WrapKey` not checking `CKA_EXTRACTABLE` on the key being wrapped.
(PR #165)
* Fixed `falseVal` initialized to `CK_TRUE` instead of `CK_FALSE`. (PR #162)
* Fixed a read-only lock not being released on an early return. (PR #163)
* Added a missing NULL check. (PR #166)
* Fixed a typo in an `#ifndef` macro. (PR #167)
* Fixed a typo in `configure.ac`. (PR #164)
* Fixed resource leaks and ensured secure buffer erasing. (PR #172)
* Fixed numerous PKCS#11 compliance and static analysis findings from Fenrir.
(PR #168, PR #169, PR #171, PR #173, PR #178, PR #185, PR #186, PR #187,
PR #189)
* Added negative testing and validation for wolfPKCS11. (PR #179)
* Added Fenrir findings fixes and test additions. (PR #177)
* Added a multi-call HMAC regression test. (PR #181)
* Added a `C_VerifyRecover` test and fixed test attributes. (PR #184)
* Fixed ML-KEM templates in tests. (PR #183)
* Fixed a couple of failing tests. (PR #145)
* Added an interoperability test against wolfSSL master. (PR #148)
* Added a wolfBoot integration test to intercept regressions. (PR #170)
* Reduced the wolfBoot integration test flow (unstable emulator). (PR #174)
* Removed `--enable-cryptocb` usage. (PR #149)
* Fixed CI failures from upstream dependency drift. (PR #180)
* Fixed CI issues. (PR #182)
* Fixed the Firefox Dockerfile. (PR #160)
* Fixed Debian rules for the documentation. (PR #153)

### wolfPKCS11 Release 2.0 (August 26, 2025)

**Summary**
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#
AC_COPYRIGHT([Copyright (C) 2014-2023 wolfSSL Inc.])
AC_PREREQ([2.63])
AC_INIT([wolfpkcs11],[2.0.0],[https://github.com/wolfssl/wolfpkcs11/issues],[wolfpkcs11],[http://www.wolfssl.com])
AC_INIT([wolfpkcs11],[2.1.0],[https://github.com/wolfssl/wolfpkcs11/issues],[wolfpkcs11],[http://www.wolfssl.com])
AC_CONFIG_AUX_DIR([build-aux])

# The following sets CFLAGS to empty if unset on command line.
Expand Down
2 changes: 1 addition & 1 deletion doc/formats/html/Doxyfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Doxyfile for wolfPKCS11 HTML docs

PROJECT_NAME = "wolfPKCS11"
PROJECT_NUMBER = "2.0.0"
PROJECT_NUMBER = "2.1.0"

OUTPUT_DIRECTORY = .
GENERATE_HTML = YES
Expand Down
2 changes: 1 addition & 1 deletion doc/formats/pdf/Doxyfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Doxyfile for wolfPKCS11 PDF/LaTeX docs

PROJECT_NAME = "wolfPKCS11"
PROJECT_NUMBER = "2.0.0"
PROJECT_NUMBER = "2.1.0"

OUTPUT_DIRECTORY = .
GENERATE_HTML = NO
Expand Down
9 changes: 9 additions & 0 deletions doc/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,12 @@ clean-local:
-rm -rf doc/html/
-rm -f doc/refman.pdf
-rm -f doc/doxygen_warnings
# Test runs create token storage under the build-dir "store/" directory (see
# AM_TESTS_ENVIRONMENT and the WOLFPKCS11_TOKEN_PATH values in the tests).
# Remove these artifacts on clean so the tree is left pristine, in particular
# for "make distcheck"'s distcleancheck step. The tracked store/.dummy
# placeholder in the source tree is preserved. These live in the single
# clean-local rule (automake permits only one) alongside the doc cleanup above.
-rm -rf store/*/
-rm -f store/wp11_*
-rmdir store 2>/dev/null || true
8 changes: 6 additions & 2 deletions examples/examples.test
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,17 @@ RESULT=$?
RESULT=$?
[ $RESULT -ne 0 ] && echo "\n\nAdding an RSA key to the token failed" && exit 1

# Locate the RSA DER file. It is a distributed source file, so for VPATH
# builds (e.g. "make distcheck") it lives in $srcdir, not the build tree.
RSA_DER="${srcdir:-.}/examples/rsa-2048.der"

# Add an RSA key from file to the session
./examples/add_rsa_key_file -rsa ./examples/rsa-2048.der
./examples/add_rsa_key_file -rsa "$RSA_DER"
RESULT=$?
[ $RESULT -ne 0 ] && echo "\n\nAdding an RSA key from file failed" && exit 1

# Add an RSA key to the token
./examples/add_rsa_key_file -privId "rsa-2048.der" -rsa ./examples/rsa-2048.der
./examples/add_rsa_key_file -privId "rsa-2048.der" -rsa "$RSA_DER"
RESULT=$?
[ $RESULT -ne 0 ] && echo "\n\nAdding an RSA key from file to the token failed" && exit 1

Expand Down
2 changes: 1 addition & 1 deletion examples/mech_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ static CK_RV pkcs11_mechs_info(CK_SLOT_ID slotId)
CHECK_CKR(ret, "Get Mechanism List count");

if (ret == CKR_OK) {
mechTypes = malloc(cnt * sizeof(CK_MECHANISM_TYPE));
mechTypes = (CK_MECHANISM_TYPE*)malloc(cnt * sizeof(CK_MECHANISM_TYPE));
if (mechTypes == NULL) {
ret = 1;
}
Expand Down
25 changes: 17 additions & 8 deletions examples/obj_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,9 @@ static void pkcs11_final(CK_SESSION_HANDLE session)
}


static void pkcs11_print_class(CK_ULONG* objClass)
static void pkcs11_print_class(CK_VOID_PTR pValue)
{
CK_ULONG* objClass = (CK_ULONG*)pValue;
const char* name = "Unknown";

switch (*objClass) {
Expand All @@ -175,8 +176,9 @@ static void pkcs11_print_class(CK_ULONG* objClass)
printf(" Class: %s\n", name);
}

static void pkcs11_print_key_type(CK_ULONG* keyType)
static void pkcs11_print_key_type(CK_VOID_PTR pValue)
{
CK_ULONG* keyType = (CK_ULONG*)pValue;
const char* name = "Unknown";

switch (*keyType) {
Expand All @@ -200,26 +202,31 @@ static void pkcs11_print_key_type(CK_ULONG* keyType)
printf(" Key Type: %s\n", name);
}

static void pkcs11_print_num(const char* label, CK_ULONG* val)
static void pkcs11_print_num(const char* label, CK_VOID_PTR pValue)
{
printf("%10s: %ld\n", label, *val);
CK_ULONG* val = (CK_ULONG*)pValue;
printf("%10s: %lu\n", label, *val);
}

static void pkcs11_print_boolean(const char* label, CK_BBOOL* val)
static void pkcs11_print_boolean(const char* label, CK_VOID_PTR pValue)
{
CK_BBOOL* val = (CK_BBOOL*)pValue;
printf("%10s: %s\n", label, (*val == CK_TRUE) ? "TRUE" : "FALSE");
}

static void pkcs11_print_boolean_on_true(const char* label, const char* name,
CK_BBOOL* val)
CK_VOID_PTR pValue)
{
CK_BBOOL* val = (CK_BBOOL*)pValue;
if (*val == CK_TRUE) {
printf("%10s: %s\n", label, name);
}
}

static void pkcs11_print_data(const char* label, byte* val, CK_ULONG len)
static void pkcs11_print_data(const char* label, CK_VOID_PTR pValue,
CK_ULONG len)
{
byte* val = (byte*)pValue;
CK_ULONG i;

printf("%10s: ", label);
Expand All @@ -229,8 +236,10 @@ static void pkcs11_print_data(const char* label, byte* val, CK_ULONG len)
printf("\n");
}

static void pkcs11_print_string(const char* label, byte* val, CK_ULONG len)
static void pkcs11_print_string(const char* label, CK_VOID_PTR pValue,
CK_ULONG len)
{
char* val = (char*)pValue;
printf("%10s: %.*s\n", label, (int)len, val);
}

Expand Down
2 changes: 1 addition & 1 deletion examples/slot_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ static CK_RV pkcs11_slots_info(void)
CHECK_CKR(ret, "Get Slot List count");

if (ret == CKR_OK) {
slots = malloc(cnt * sizeof(CK_SLOT_ID));
slots = (CK_SLOT_ID*)malloc(cnt * sizeof(CK_SLOT_ID));
if (slots == NULL) {
ret = 1;
}
Expand Down
6 changes: 5 additions & 1 deletion m4/hexversion.m4
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
AC_DEFUN([CREATE_HEX_VERSION],[

# Emit a byte-packed hex version (0xMMmmpp00) so the major/minor extraction
# in internal.h (>> 24, (>> 16) & 0xff) yields the correct components. The
# previous decimal field widths (%0.2d%0.3d%0.3d) misaligned the bytes, e.g.
# 2.1.0 produced 0x02001000 which reads back as v2.0.
HEX_VERSION=`echo $VERSION | sed 's|[\-a-z0-9]*$||' | \
awk -F. '{printf "0x%0.2d%0.3d%0.3d", $[]1, $[]2, $[]3}'`
awk -F. '{printf "0x%02x%02x%02x00", $[]1, $[]2, $[]3}'`
AC_SUBST([HEX_VERSION])
])
15 changes: 8 additions & 7 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -9873,7 +9873,7 @@ int WP11_Object_DataObject(WP11_Object* object, unsigned char** data,
if (data[0] != NULL && len[0] > 0) {
XFREE(object->data.genericData.data, NULL, DYNAMIC_TYPE_CERT);
object->data.genericData.data =
XMALLOC(len[0], NULL, DYNAMIC_TYPE_CERT);
(byte*)XMALLOC(len[0], NULL, DYNAMIC_TYPE_CERT);
if (object->data.genericData.data == NULL) {
ret = MEMORY_E;
}
Expand All @@ -9892,7 +9892,7 @@ int WP11_Object_DataObject(WP11_Object* object, unsigned char** data,
if (ret == 0 && data[1] != NULL && len[1] > 0) {
XFREE(object->data.genericData.application, NULL, DYNAMIC_TYPE_CERT);
object->data.genericData.application =
XMALLOC(len[1], NULL, DYNAMIC_TYPE_CERT);
(byte*)XMALLOC(len[1], NULL, DYNAMIC_TYPE_CERT);
if (object->data.genericData.application == NULL) {
ret = MEMORY_E;
}
Expand All @@ -9911,7 +9911,7 @@ int WP11_Object_DataObject(WP11_Object* object, unsigned char** data,
if (ret == 0 && data[2] != NULL && len[2] > 0) {
XFREE(object->data.genericData.objectId, NULL, DYNAMIC_TYPE_CERT);
object->data.genericData.objectId =
XMALLOC(len[2], NULL, DYNAMIC_TYPE_CERT);
(byte*)XMALLOC(len[2], NULL, DYNAMIC_TYPE_CERT);
if (object->data.genericData.objectId == NULL) {
ret = MEMORY_E;
}
Expand Down Expand Up @@ -15543,8 +15543,8 @@ int WP11_Digest_Init(CK_MECHANISM_TYPE mechanism, WP11_Session* session)
ret = wp11_digest_hash_type(mechanism, &hashType);

if (ret == 0) {
digest->hashType = hashType;
ret = wc_HashInit(&digest->hash, hashType);
digest->hashType = (enum wc_HashType)hashType;
ret = wc_HashInit(&digest->hash, (enum wc_HashType)hashType);
}

return ret;
Expand Down Expand Up @@ -16230,8 +16230,9 @@ int WP11_SetOperationState(WP11_Session* session, unsigned char* stateData,
if (ret != CKR_OK)
return ret;

session->params.digest.hashType = hashType;
ret = wc_HashInit(&session->params.digest.hash, hashType);
session->params.digest.hashType = (enum wc_HashType)hashType;
ret = wc_HashInit(&session->params.digest.hash,
(enum wc_HashType)hashType);

if (ret != CKR_OK)
return ret;
Expand Down
6 changes: 3 additions & 3 deletions tests/object_id_uniqueness_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ static CK_RV create_token_cert_object(CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE* objHandle)
{
CK_RV ret;
CK_ATTRIBUTE template[] = {
CK_ATTRIBUTE tmpl[] = {
{ CKA_CLASS, &certClass, sizeof(certClass) },
{ CKA_CERTIFICATE_TYPE, &certType, sizeof(certType) },
{ CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
Expand All @@ -321,9 +321,9 @@ static CK_RV create_token_cert_object(CK_SESSION_HANDLE session,
{ CKA_LABEL, (char*)label, strlen(label) },
{ CKA_VALUE, (char*)certData, certLen }
};
CK_ULONG templateCount = sizeof(template) / sizeof(template[0]);
CK_ULONG templateCount = sizeof(tmpl) / sizeof(tmpl[0]);

ret = funcList->C_CreateObject(session, template, templateCount, objHandle);
ret = funcList->C_CreateObject(session, tmpl, templateCount, objHandle);
CHECK_CKR(ret, "Create Token Certificate Object");

return ret;
Expand Down
Loading
Loading