]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
pkcs11: properly fall back to thread-unsafe module init
authorDaiki Ueno <ueno@gnu.org>
Mon, 22 Dec 2025 06:29:06 +0000 (15:29 +0900)
committerDaiki Ueno <ueno@gnu.org>
Tue, 23 Dec 2025 01:27:31 +0000 (10:27 +0900)
The PKCS#11 module initialization logic introduced in
aa5f15a872e62e54abe58624ee393e68d1faf689 first attempts to initialize
the module with CKR_NEED_TO_CREATE_THREADS|CKF_OS_LOCKING_OK, which
may return either CKR_CANT_LOCK or CKR_NEED_TO_CREATE_THREADS, where
the latter was previously treated as a hard error. This fixes it and
also makes the second attempt to not supply any flags.

Signed-off-by: Daiki Ueno <ueno@gnu.org>
.gitignore
lib/pkcs11.c
tests/pkcs11/pkcs11-mock4.c

index 0c24e010c93c31c88573db95eb2574616ffd8731..8f00901e649cb161db3538680fcf51414ba03e66 100644 (file)
@@ -755,6 +755,7 @@ tests/softhsm-*.db/
 tests/softhsm-distrust-after.config
 tests/softhsm-long-label.config
 tests/softhsm-neg-no-key.config
+tests/softhsm-os-locking-ok.config
 tests/softhsm-post-handshake-with-cert-pkcs11.config
 tests/spki
 tests/spki-abstract
index 021974f5fa87732d5d391581094b7a4e617ee53d..668d91bb137fe53c3b1a43e2d8a226a468077d73 100644 (file)
@@ -255,10 +255,6 @@ static const struct ck_c_initialize_args default_init_args = {
        NULL,
 };
 
-static const struct ck_c_initialize_args no_thread_init_args = {
-       NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS, NULL,
-};
-
 static void pkcs11_provider_deinit(struct gnutls_pkcs11_provider_st *provider)
 {
        p11_kit_module_finalize(provider->module);
@@ -284,15 +280,22 @@ static int pkcs11_provider_init(struct gnutls_pkcs11_provider_st *provider,
                reserved = (char *)(p + sizeof("p11-kit:") - 1);
        }
 
-       /* First try with CKF_OS_LOCKING_OK, then fall back without it */
+       /* First try with CKF_LIBRARY_CANT_CREATE_OS_THREADS |
+        * CKF_OS_LOCKING_OK, then fall back without it */
        args = default_init_args;
        args.reserved = (void *)reserved;
        rv = module->C_Initialize(&args);
 
-       if (rv == CKR_CANT_LOCK) {
-               args = no_thread_init_args;
-               args.reserved = (void *)reserved;
-               rv = module->C_Initialize(&args);
+       if (rv == CKR_NEED_TO_CREATE_THREADS || rv == CKR_CANT_LOCK) {
+               struct ck_c_initialize_args *pargs;
+               if (reserved) {
+                       memset(&args, 0, sizeof(args));
+                       args.reserved = (void *)reserved;
+                       pargs = &args;
+               } else {
+                       pargs = NULL;
+               }
+               rv = module->C_Initialize(pargs);
        }
 
        if (rv != CKR_OK) {
index ffa684b52f8c737f121e7725097e9d4657fdbf6d..3fd24eae29c446e505bacdf1de277e0eb77df81a 100644 (file)
@@ -54,19 +54,21 @@ static CK_FUNCTION_LIST override_funcs;
 #define _DESTRUCTOR __attribute__((destructor))
 #endif
 
+#define LOCK_FLAGS (CKF_LIBRARY_CANT_CREATE_OS_THREADS | CKF_OS_LOCKING_OK)
+
 static CK_RV override_C_Initialize(void *args)
 {
        CK_C_INITIALIZE_ARGS *init_args = args;
        static bool first = true;
 
-       assert(init_args);
-
        if (first) {
-               assert(init_args->flags & CKF_OS_LOCKING_OK);
+               assert(init_args &&
+                      (init_args->flags & LOCK_FLAGS) == LOCK_FLAGS);
                first = false;
                return CKR_CANT_LOCK;
        } else {
-               assert(!(init_args->flags & CKF_OS_LOCKING_OK));
+               assert(!init_args ||
+                      (init_args->flags & LOCK_FLAGS) != LOCK_FLAGS);
        }
 
        return base_C_Initialize(args);