Skip to content

Let custom stores report records that did not commit - #265

Open
LinuxJedi wants to merge 1 commit into
wolfSSL:masterfrom
LinuxJedi:store-close-status
Open

LinuxJedi wants to merge 1 commit into
wolfSSL:masterfrom
LinuxJedi:store-close-status

Conversation

@LinuxJedi

@LinuxJedi LinuxJedi commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

#257 writes only the token objects that changed, and relies on storeDirty: a store pass that fails or is skipped makes the next pass write every object again. A custom store (WOLFPKCS11_CUSTOM_STORE) cannot set it when a record fails to commit, because wolfPKCS11_Store_Close() returns void. wolfBoot's TrustZone keyvault commits flash on close, so a failed flash commit leaves the record missing or stale while wolfPKCS11 carries on as if it were stored.

This declares wolfPKCS11_Store_CloseCommit(void* store, int commit) in store.h. The file and TPM stores already implement it (it was a static function). A custom store opts in by defining WOLFPKCS11_CUSTOM_STORE_CLOSE_COMMIT and implementing it. Written records are then closed through it, and a non-zero return fails the operation and marks the token for a full store. commit is 0 when writing the record failed, so a store that can discard the record may do so. Without the define, custom stores build and behave exactly as before, and wolfPKCS11_Store_Close() still closes records that were read.

Why a define: changing wolfPKCS11_Store_Close() to return int would break every existing custom store at compile time, and weak symbols are not portable to every compiler a custom store is built with. A store can define the macro and the function unconditionally: older wolfPKCS11 versions ignore the define and keep calling wolfPKCS11_Store_Close(). wolfSSL/wolfBoot#957 does this for the keyvault.

A custom store's failure code is now mapped to BUFFER_E, on close and on write. Passed through, wolfBoot's -1 from a failed write reads as PIN_INVALID_E, so C_CreateObject returned CKR_USER_NOT_LOGGED_IN, and a -4 on close would read as storage being turned off.

New test tests/custom_store_test.c. It builds the library sources with a store kept in memory, twice: with the define (custom_store_test) and without it (custom_store_legacy_test, which checks that a store with only wolfPKCS11_Store_Close() still builds and keeps objects). With the define, it checks that a failed commit and a failed write both fail the create with CKR_FUNCTION_FAILED, that the failed write closes the record with commit set to 0, that the next create writes every object again and the one after only its own, and that the objects load back after C_Finalize. It fails on master at the failed commit check. The tests are not built with --enable-nss, which needs the file store, or with -DWOLFPKCS11_TPM_STORE, which cannot be built with a custom store (BUILD_CUSTOM_STORE_TEST in configure.ac). They are also the first CI coverage of a custom store build.

Testing:

  • make check passes with no failures in the default, --enable-debug, --enable-nss, --enable-static --disable-shared, C++ (CC=clang++) and C++ debug configs. The pre-commit hook make test passes.
  • With Report failed flash commits from the PKCS#11 keyvault, check STM32U5 flash errors wolfBoot#957, the stm32h5-tz PKCS#11 test app passes in m33mu (as in the wolfBoot integration job) and wolfPKCS11 closes written records with wolfPKCS11_Store_CloseCommit(). The stm32u5-wolfcrypt-tz config builds. wolfBoot master with this change also passes, using the old close.
  • Not tested on hardware.

ZD 21908

A custom store (WOLFPKCS11_CUSTOM_STORE) closes a written record with
wolfPKCS11_Store_Close(), which returns void. A store that commits on
close, such as wolfBoot's flash keyvault, cannot report a failed commit,
so storeDirty stays clear and the next store does not write the records
again.

Declare wolfPKCS11_Store_CloseCommit() in store.h. The file and TPM
stores already implement it. A custom store opts in by defining
WOLFPKCS11_CUSTOM_STORE_CLOSE_COMMIT and implementing it; written
records are then closed through it, and a non-zero return fails the
operation and marks the token for a full store. Without the define,
custom stores build and behave as before. wolfPKCS11_Store_Close() still
closes records that were read.

A custom store's failure code is now mapped to BUFFER_E, on close and on
write. Passed through, wolfBoot's -1 from a failed write read as
PIN_INVALID_E, so C_CreateObject returned CKR_USER_NOT_LOGGED_IN, and a
-4 on close would read as storage being turned off.

tests/custom_store_test.c builds the library sources with a store kept
in memory, once with the define and once without. It checks that a
failed commit or write fails the create, that a failed write closes the
record with commit set to 0, and that the next create writes every
object again, then that the objects load back after C_Finalize. It is
not built for NSS, which needs the file store, or with
WOLFPKCS11_TPM_STORE, which cannot be built with a custom store.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant