]> granicus.if.org Git - p11-kit/commitdiff
Fix endless loop if module forks during initialization.
authorStef Walter <stefw@collabora.co.uk>
Sun, 14 Aug 2011 16:46:50 +0000 (18:46 +0200)
committerStef Walter <stefw@collabora.co.uk>
Sun, 14 Aug 2011 16:49:55 +0000 (18:49 +0200)
 * If a module forks during its C_Initialize, previously our
   fork handler would try to initialize it again, ad nauseum.

Reported by Nikos on the mailing list.

.gitignore
p11-kit/modules.c
tests/Makefile.am
tests/mock-module.c [new file with mode: 0644]
tests/mock-module.h [new file with mode: 0644]
tests/p11-test.c [new file with mode: 0644]

index f4e65d0a36066c38e385f64bd4b3705936aa5ac4..9359157372255e5b41e6d9e844b016617ad8ab0b 100644 (file)
@@ -70,6 +70,7 @@ temp.txt
 /tests/coverage
 /tests/coverage.info
 /tests/hash-test
+/tests/p11-test
 /tests/pin-test
 /tests/ptr-array-test
 /tests/conf-test
index 693d342523f1405ad70038a8438d47e49f42dfbb..d5dae32ce6ce498d4c2a6d9419ec3ddce5f63e95 100644 (file)
@@ -446,7 +446,7 @@ initialize_module_unlocked_reentrant (Module *mod)
        assert (mod);
 
        /*
-        * Initialize first, so module doesn't get freed out from
+        * Increase ref first, so module doesn't get freed out from
         * underneath us when the mutex is unlocked below.
         */
        ++mod->ref_count;
@@ -499,10 +499,12 @@ reinitialize_after_fork (void)
                if (gl.modules) {
                        hash_iterate (gl.modules, &iter);
                        while (hash_next (&iter, NULL, (void **)&mod)) {
-                               mod->initialize_count = 0;
+                               if (mod->initialize_count > 0) {
+                                       mod->initialize_count = 0;
 
-                               /* WARNING: Reentrancy can occur here */
-                               initialize_module_unlocked_reentrant (mod);
+                                       /* WARNING: Reentrancy can occur here */
+                                       initialize_module_unlocked_reentrant (mod);
+                               }
                        }
                }
 
@@ -953,8 +955,8 @@ p11_kit_registered_option (CK_FUNCTION_LIST_PTR module, const char *field)
 CK_RV
 p11_kit_initialize_module (CK_FUNCTION_LIST_PTR module)
 {
-       Module *mod;
        Module *allocated = NULL;
+       Module *mod;
        CK_RV rv = CKR_OK;
 
        /* WARNING: This function must be reentrant for the same arguments */
index 430b89ef909490342483430a1b8e7d19bf3971ee..a7796e807f0c9bc65a03b55ac92284515300cf96 100644 (file)
@@ -6,32 +6,21 @@ INCLUDES = \
        -DSRCDIR=\"$(srcdir)\" \
        -DP11_KIT_FUTURE_UNSTABLE_API
 
+LDADD = \
+       $(top_builddir)/p11-kit/libp11-kit-testable.la \
+       $(LTLIBINTL)
+
 noinst_PROGRAMS = \
        hash-test \
        ptr-array-test \
        conf-test \
        uri-test \
-       pin-test
-
-hash_test_LDADD = \
-       $(top_builddir)/p11-kit/libp11-kit-testable.la \
-        $(LTLIBINTL)
-
-ptr_array_test_LDADD = \
-       $(top_builddir)/p11-kit/libp11-kit-testable.la \
-        $(LTLIBINTL)
+       pin-test \
+       p11-test
 
-conf_test_LDADD = \
-       $(top_builddir)/p11-kit/libp11-kit-testable.la \
-        $(LTLIBINTL)
-
-uri_test_LDADD = \
-       $(top_builddir)/p11-kit/libp11-kit-testable.la \
-        $(LTLIBINTL)
-
-pin_test_LDADD = \
-       $(top_builddir)/p11-kit/libp11-kit-testable.la \
-        $(LTLIBINTL)
+p11_test_SOURCES = \
+       p11-test.c \
+       mock-module.c mock-module.h
 
 check-am:
        ./hash-test
@@ -39,6 +28,7 @@ check-am:
        ./conf-test
        ./uri-test
        ./pin-test
+       ./p11-test
 
 EXTRA_DIST = \
        cutest \
diff --git a/tests/mock-module.c b/tests/mock-module.c
new file mode 100644 (file)
index 0000000..a1a6a7e
--- /dev/null
@@ -0,0 +1,886 @@
+/*
+ * Copyright (c) 2011, Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *     * Redistributions of source code must retain the above
+ *       copyright notice, this list of conditions and the
+ *       following disclaimer.
+ *     * Redistributions in binary form must reproduce the
+ *       above copyright notice, this list of conditions and
+ *       the following disclaimer in the documentation and/or
+ *       other materials provided with the distribution.
+ *     * The names of contributors to this software may not be
+ *       used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#include "config.h"
+
+#include "pkcs11.h"
+#include "mock-module.h"
+
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* -------------------------------------------------------------------
+ * GLOBALS / DEFINES
+ */
+
+/* Various mutexes */
+static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* Whether we've been initialized, and on what process id it happened */
+static int pkcs11_initialized = 0;
+static pid_t pkcs11_initialized_pid = 0;
+
+/* -----------------------------------------------------------------------------
+ * LOGGING and DEBUGGING
+ */
+
+#define DEBUG_OUTPUT 0
+
+#if DEBUG_OUTPUT
+#define debug(x) mock_log x
+#else
+#define debug(x)
+#endif
+
+#define warning(x) mock_log x
+
+#define return_val_if_fail(x, v) \
+       if (!(x)) { mock_log ("'%s' not true at %s", #x, __func__); return v; }
+
+static void
+mock_log (const char *format, ...)
+{
+       va_list va;
+       va_start (va, format);
+       fprintf (stderr, "mock-module: ");
+       vfprintf (stderr, format, va);
+       fprintf (stderr, "\n");
+       va_end (va);
+}
+
+/* -------------------------------------------------------------------
+ * INITIALIZATION and 'GLOBAL' CALLS
+ */
+
+CK_RV
+mock_C_Initialize (CK_VOID_PTR init_args)
+{
+       CK_C_INITIALIZE_ARGS_PTR args = NULL;
+       CK_RV ret = CKR_OK;
+       pid_t pid;
+
+       debug (("C_Initialize: enter"));
+
+       pthread_mutex_lock (&init_mutex);
+
+               if (init_args != NULL) {
+                       int supplied_ok;
+
+                       /* pReserved must be NULL */
+                       args = init_args;
+
+                       /* ALL supplied function pointers need to have the value either NULL or non-NULL. */
+                       supplied_ok = (args->CreateMutex == NULL && args->DestroyMutex == NULL &&
+                                      args->LockMutex == NULL && args->UnlockMutex == NULL) ||
+                                     (args->CreateMutex != NULL && args->DestroyMutex != NULL &&
+                                      args->LockMutex != NULL && args->UnlockMutex != NULL);
+                       if (!supplied_ok) {
+                               warning (("invalid set of mutex calls supplied"));
+                               ret = CKR_ARGUMENTS_BAD;
+                               goto done;
+                       }
+
+                       /*
+                        * When the CKF_OS_LOCKING_OK flag isn't set return an error.
+                        * We must be able to use our pthread functionality.
+                        */
+                       if (!(args->flags & CKF_OS_LOCKING_OK)) {
+                               warning (("can't do without os locking"));
+                               ret = CKR_CANT_LOCK;
+                               goto done;
+                       }
+               }
+
+               pid = getpid ();
+               if (pkcs11_initialized) {
+
+                       /* This process has called C_Initialize already */
+                       if (pid == pkcs11_initialized_pid) {
+                               warning (("C_Initialize called twice for same process"));
+                               ret = CKR_CRYPTOKI_ALREADY_INITIALIZED;
+                               goto done;
+                       }
+               }
+
+done:
+               /* Mark us as officially initialized */
+               if (ret == CKR_OK) {
+                       pkcs11_initialized = 1;
+                       pkcs11_initialized_pid = pid;
+               } else if (ret != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
+                       pkcs11_initialized = 0;
+                       pkcs11_initialized_pid = 0;
+               }
+
+       pthread_mutex_unlock (&init_mutex);
+
+       debug (("C_Initialize: %d", ret));
+       return ret;
+}
+
+CK_RV
+mock_C_Finalize (CK_VOID_PTR reserved)
+{
+       debug (("C_Finalize: enter"));
+       return_val_if_fail (pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+       return_val_if_fail (!reserved, CKR_ARGUMENTS_BAD);
+
+       pthread_mutex_lock (&init_mutex);
+
+               /* This should stop all other calls in */
+               pkcs11_initialized = 0;
+               pkcs11_initialized_pid = 0;
+
+       pthread_mutex_unlock (&init_mutex);
+
+       debug (("C_Finalize: %d", CKR_OK));
+       return CKR_OK;
+}
+
+static const CK_INFO MOCK_INFO = {
+       { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
+       "MOCK MANUFACTURER              ",
+       0,
+       "MOCK LIBRARY                   ",
+       { 45, 145 }
+};
+
+
+CK_RV
+mock_C_GetInfo (CK_INFO_PTR info)
+{
+       return_val_if_fail (info, CKR_ARGUMENTS_BAD);
+
+       memcpy (info, &MOCK_INFO, sizeof (*info));
+       return CKR_OK;
+}
+
+CK_RV
+mock_C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+       /* This would be a strange call to receive */
+       return C_GetFunctionList (list);
+}
+
+CK_RV
+mock_C_GetSlotList__no_tokens (CK_BBOOL token_present,
+                               CK_SLOT_ID_PTR slot_list,
+                               CK_ULONG_PTR count)
+{
+       return_val_if_fail (count, CKR_ARGUMENTS_BAD);
+
+       /* No tokens */
+       *count = 0;
+       return CKR_OK;
+}
+
+CK_RV
+mock_C_GetSlotInfo__invalid_slotid (CK_SLOT_ID id,
+                                    CK_SLOT_INFO_PTR info)
+{
+       return_val_if_fail (info, CKR_ARGUMENTS_BAD);
+
+       return CKR_SLOT_ID_INVALID;
+}
+
+CK_RV
+mock_C_GetTokenInfo__invalid_slotid (CK_SLOT_ID id,
+                                     CK_TOKEN_INFO_PTR info)
+{
+       return_val_if_fail (info, CKR_ARGUMENTS_BAD);
+
+       return CKR_SLOT_ID_INVALID;
+}
+
+CK_RV
+mock_C_GetMechanismList__invalid_slotid (CK_SLOT_ID id,
+                                         CK_MECHANISM_TYPE_PTR mechanism_list,
+                                         CK_ULONG_PTR count)
+{
+       return_val_if_fail (count, CKR_ARGUMENTS_BAD);
+
+       return CKR_SLOT_ID_INVALID;
+}
+
+CK_RV
+mock_C_GetMechanismInfo__invalid_slotid (CK_SLOT_ID id,
+                                         CK_MECHANISM_TYPE type,
+                                         CK_MECHANISM_INFO_PTR info)
+{
+       return_val_if_fail (info, CKR_ARGUMENTS_BAD);
+
+       return CKR_SLOT_ID_INVALID;
+}
+
+CK_RV
+mock_C_InitToken__invalid_slotid (CK_SLOT_ID id,
+                                  CK_UTF8CHAR_PTR pin,
+                                  CK_ULONG pin_len,
+                                  CK_UTF8CHAR_PTR label)
+{
+       return CKR_SLOT_ID_INVALID;
+}
+
+CK_RV
+mock_C_WaitForSlotEvent__no_event (CK_FLAGS flags,
+                                   CK_SLOT_ID_PTR slot,
+                                   CK_VOID_PTR reserved)
+{
+       return_val_if_fail (slot, CKR_ARGUMENTS_BAD);
+
+       return CKR_NO_EVENT;
+}
+
+CK_RV
+mock_C_OpenSession__invalid_slotid (CK_SLOT_ID id,
+                                    CK_FLAGS flags,
+                                    CK_VOID_PTR user_data,
+                                    CK_NOTIFY callback,
+                                    CK_SESSION_HANDLE_PTR session)
+{
+       return_val_if_fail (session, CKR_ARGUMENTS_BAD);
+
+       return CKR_SLOT_ID_INVALID;
+}
+
+CK_RV
+mock_C_CloseSession__invalid_handle (CK_SESSION_HANDLE session)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_CloseAllSessions__invalid_slotid (CK_SLOT_ID id)
+{
+       return CKR_SLOT_ID_INVALID;
+}
+
+CK_RV
+mock_C_GetFunctionStatus__not_parallel (CK_SESSION_HANDLE session)
+{
+       return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+CK_RV
+mock_C_CancelFunction__not_parallel (CK_SESSION_HANDLE session)
+{
+       return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+CK_RV
+mock_C_GetSessionInfo__invalid_handle (CK_SESSION_HANDLE session,
+                                       CK_SESSION_INFO_PTR info)
+{
+       return_val_if_fail (info, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_InitPIN__invalid_handle (CK_SESSION_HANDLE session,
+                                CK_UTF8CHAR_PTR pin,
+                                CK_ULONG pin_len)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_SetPIN__invalid_handle (CK_SESSION_HANDLE session,
+                               CK_UTF8CHAR_PTR old_pin,
+                               CK_ULONG old_pin_len,
+                               CK_UTF8CHAR_PTR new_pin,
+                               CK_ULONG new_pin_len)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_GetOperationState__invalid_handle (CK_SESSION_HANDLE session,
+                                         CK_BYTE_PTR operation_state,
+                                         CK_ULONG_PTR operation_state_len)
+{
+       return_val_if_fail (operation_state_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_SetOperationState__invalid_handle (CK_SESSION_HANDLE session,
+                                          CK_BYTE_PTR operation_state,
+                                          CK_ULONG operation_state_len,
+                                          CK_OBJECT_HANDLE encryption_key,
+                                          CK_OBJECT_HANDLE authentication_key)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_Login__invalid_handle (CK_SESSION_HANDLE session,
+                              CK_USER_TYPE user_type,
+                              CK_UTF8CHAR_PTR pin,
+                              CK_ULONG pin_len)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+
+}
+
+CK_RV
+mock_C_Logout__invalid_handle (CK_SESSION_HANDLE session)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+
+}
+
+CK_RV
+mock_C_CreateObject__invalid_handle (CK_SESSION_HANDLE session,
+                                     CK_ATTRIBUTE_PTR template,
+                                     CK_ULONG count,
+                                     CK_OBJECT_HANDLE_PTR new_object)
+{
+       return_val_if_fail (new_object, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_CopyObject__invalid_handle (CK_SESSION_HANDLE session,
+                                   CK_OBJECT_HANDLE object,
+                                   CK_ATTRIBUTE_PTR template,
+                                   CK_ULONG count,
+                                   CK_OBJECT_HANDLE_PTR new_object)
+{
+       return_val_if_fail (new_object, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+
+CK_RV
+mock_C_DestroyObject__invalid_handle (CK_SESSION_HANDLE session,
+                                      CK_OBJECT_HANDLE object)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_GetObjectSize__invalid_handle (CK_SESSION_HANDLE session,
+                                      CK_OBJECT_HANDLE object,
+                                      CK_ULONG_PTR size)
+{
+       return_val_if_fail (size, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_GetAttributeValue__invalid_handle (CK_SESSION_HANDLE session,
+                                          CK_OBJECT_HANDLE object,
+                                          CK_ATTRIBUTE_PTR template,
+                                          CK_ULONG count)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_SetAttributeValue__invalid_handle (CK_SESSION_HANDLE session,
+                                          CK_OBJECT_HANDLE object,
+                                          CK_ATTRIBUTE_PTR template,
+                                          CK_ULONG count)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_FindObjectsInit__invalid_handle (CK_SESSION_HANDLE session,
+                                        CK_ATTRIBUTE_PTR template,
+                                        CK_ULONG count)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_FindObjects__invalid_handle (CK_SESSION_HANDLE session,
+                                    CK_OBJECT_HANDLE_PTR objects,
+                                    CK_ULONG max_count,
+                                    CK_ULONG_PTR count)
+{
+       return_val_if_fail (count, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_FindObjectsFinal__invalid_handle (CK_SESSION_HANDLE session)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_EncryptInit__invalid_handle (CK_SESSION_HANDLE session,
+                                    CK_MECHANISM_PTR mechanism,
+                                    CK_OBJECT_HANDLE key)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_Encrypt__invalid_handle (CK_SESSION_HANDLE session,
+                                CK_BYTE_PTR data, CK_ULONG data_len,
+                                CK_BYTE_PTR encrypted_data,
+                                CK_ULONG_PTR encrypted_data_len)
+{
+       return_val_if_fail (encrypted_data_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_EncryptUpdate__invalid_handle (CK_SESSION_HANDLE session,
+                                      CK_BYTE_PTR part,
+                                      CK_ULONG part_len,
+                                      CK_BYTE_PTR encrypted_part,
+                                      CK_ULONG_PTR encrypted_part_len)
+{
+       return_val_if_fail (encrypted_part_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_EncryptFinal__invalid_handle (CK_SESSION_HANDLE session,
+                                     CK_BYTE_PTR last_part,
+                                     CK_ULONG_PTR last_part_len)
+{
+       return_val_if_fail (last_part_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_DecryptInit__invalid_handle (CK_SESSION_HANDLE session,
+                                    CK_MECHANISM_PTR mechanism,
+                                    CK_OBJECT_HANDLE key)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_Decrypt__invalid_handle (CK_SESSION_HANDLE session,
+                                CK_BYTE_PTR enc_data,
+                                CK_ULONG enc_data_len,
+                                CK_BYTE_PTR data,
+                                CK_ULONG_PTR data_len)
+{
+       return_val_if_fail (data_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_DecryptUpdate__invalid_handle (CK_SESSION_HANDLE session,
+                                      CK_BYTE_PTR enc_part,
+                                      CK_ULONG enc_part_len,
+                                      CK_BYTE_PTR part,
+                                      CK_ULONG_PTR part_len)
+{
+       return_val_if_fail (part_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_DecryptFinal__invalid_handle (CK_SESSION_HANDLE session,
+                                     CK_BYTE_PTR last_part,
+                                     CK_ULONG_PTR last_part_len)
+{
+       return_val_if_fail (last_part_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_DigestInit__invalid_handle (CK_SESSION_HANDLE session,
+                                   CK_MECHANISM_PTR mechanism)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_Digest__invalid_handle (CK_SESSION_HANDLE session,
+                               CK_BYTE_PTR data,
+                               CK_ULONG data_len,
+                               CK_BYTE_PTR digest,
+                               CK_ULONG_PTR digest_len)
+{
+       return_val_if_fail (digest_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_DigestUpdate__invalid_handle (CK_SESSION_HANDLE session,
+                                     CK_BYTE_PTR part,
+                                     CK_ULONG part_len)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_DigestKey__invalid_handle (CK_SESSION_HANDLE session,
+                                  CK_OBJECT_HANDLE key)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_DigestFinal__invalid_handle (CK_SESSION_HANDLE session,
+                                    CK_BYTE_PTR digest,
+                                    CK_ULONG_PTR digest_len)
+{
+       return_val_if_fail (digest_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_SignInit__invalid_handle (CK_SESSION_HANDLE session,
+                                 CK_MECHANISM_PTR mechanism,
+                                 CK_OBJECT_HANDLE key)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_Sign__invalid_handle (CK_SESSION_HANDLE session,
+                             CK_BYTE_PTR data,
+                             CK_ULONG data_len,
+                             CK_BYTE_PTR signature,
+                             CK_ULONG_PTR signature_len)
+{
+       return_val_if_fail (signature_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_SignUpdate__invalid_handle (CK_SESSION_HANDLE session,
+                                   CK_BYTE_PTR part,
+                                   CK_ULONG part_len)
+{
+       return_val_if_fail (part_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_SignFinal__invalid_handle (CK_SESSION_HANDLE session,
+                                  CK_BYTE_PTR signature,
+                                  CK_ULONG_PTR signature_len)
+{
+       return_val_if_fail (signature_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_SignRecoverInit__invalid_handle (CK_SESSION_HANDLE session,
+                                        CK_MECHANISM_PTR mechanism,
+                                        CK_OBJECT_HANDLE key)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_SignRecover__invalid_handle (CK_SESSION_HANDLE session,
+                                    CK_BYTE_PTR data,
+                                    CK_ULONG data_len,
+                                    CK_BYTE_PTR signature,
+                                    CK_ULONG_PTR signature_len)
+{
+       return_val_if_fail (signature_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_VerifyInit__invalid_handle (CK_SESSION_HANDLE session,
+                                   CK_MECHANISM_PTR mechanism,
+                                   CK_OBJECT_HANDLE key)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_Verify__invalid_handle (CK_SESSION_HANDLE session,
+                               CK_BYTE_PTR data,
+                               CK_ULONG data_len,
+                               CK_BYTE_PTR signature,
+                               CK_ULONG signature_len)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_VerifyUpdate__invalid_handle (CK_SESSION_HANDLE session,
+                                     CK_BYTE_PTR part,
+                                     CK_ULONG part_len)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_VerifyFinal__invalid_handle (CK_SESSION_HANDLE session,
+                                    CK_BYTE_PTR signature,
+                                    CK_ULONG signature_len)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_VerifyRecoverInit__invalid_handle (CK_SESSION_HANDLE session,
+                                          CK_MECHANISM_PTR mechanism,
+                                          CK_OBJECT_HANDLE key)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_VerifyRecover__invalid_handle (CK_SESSION_HANDLE session,
+                                      CK_BYTE_PTR signature,
+                                      CK_ULONG signature_len,
+                                      CK_BYTE_PTR data,
+                                      CK_ULONG_PTR data_len)
+{
+       return_val_if_fail (data_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_DigestEncryptUpdate__invalid_handle (CK_SESSION_HANDLE session,
+                                            CK_BYTE_PTR part,
+                           CK_ULONG part_len, CK_BYTE_PTR enc_part,
+                           CK_ULONG_PTR enc_part_len)
+{
+       return_val_if_fail (enc_part_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_DecryptDigestUpdate__invalid_handle (CK_SESSION_HANDLE session,
+                                            CK_BYTE_PTR enc_part,
+                                            CK_ULONG enc_part_len,
+                                            CK_BYTE_PTR part,
+                                            CK_ULONG_PTR part_len)
+{
+       return_val_if_fail (part_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_SignEncryptUpdate__invalid_handle (CK_SESSION_HANDLE session,
+                                          CK_BYTE_PTR part,
+                                          CK_ULONG part_len,
+                                          CK_BYTE_PTR enc_part,
+                                          CK_ULONG_PTR enc_part_len)
+{
+       return_val_if_fail (enc_part_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_DecryptVerifyUpdate__invalid_handle (CK_SESSION_HANDLE session,
+                                            CK_BYTE_PTR enc_part,
+                                            CK_ULONG enc_part_len,
+                                            CK_BYTE_PTR part,
+                                            CK_ULONG_PTR part_len)
+{
+       return_val_if_fail (part_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_GenerateKey__invalid_handle (CK_SESSION_HANDLE session,
+                                    CK_MECHANISM_PTR mechanism,
+                                    CK_ATTRIBUTE_PTR template,
+                                    CK_ULONG count,
+                                    CK_OBJECT_HANDLE_PTR key)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_GenerateKeyPair__invalid_handle (CK_SESSION_HANDLE session,
+                                        CK_MECHANISM_PTR mechanism,
+                                        CK_ATTRIBUTE_PTR pub_template,
+                                        CK_ULONG pub_count,
+                                        CK_ATTRIBUTE_PTR priv_template,
+                                        CK_ULONG priv_count,
+                                        CK_OBJECT_HANDLE_PTR pub_key,
+                                        CK_OBJECT_HANDLE_PTR priv_key)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_WrapKey__invalid_handle (CK_SESSION_HANDLE session,
+                                CK_MECHANISM_PTR mechanism,
+                                CK_OBJECT_HANDLE wrapping_key,
+                                CK_OBJECT_HANDLE key,
+                                CK_BYTE_PTR wrapped_key,
+                                CK_ULONG_PTR wrapped_key_len)
+{
+       return_val_if_fail (wrapped_key_len, CKR_ARGUMENTS_BAD);
+
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_UnwrapKey__invalid_handle (CK_SESSION_HANDLE session,
+                                  CK_MECHANISM_PTR mechanism,
+                                  CK_OBJECT_HANDLE unwrapping_key,
+                                  CK_BYTE_PTR wrapped_key,
+                                  CK_ULONG wrapped_key_len,
+                                  CK_ATTRIBUTE_PTR template,
+                                  CK_ULONG count,
+                                  CK_OBJECT_HANDLE_PTR key)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_DeriveKey__invalid_handle (CK_SESSION_HANDLE session,
+                                  CK_MECHANISM_PTR mechanism,
+                                  CK_OBJECT_HANDLE base_key,
+                                  CK_ATTRIBUTE_PTR template,
+                                  CK_ULONG count,
+                                  CK_OBJECT_HANDLE_PTR key)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_SeedRandom__invalid_handle (CK_SESSION_HANDLE session,
+                                   CK_BYTE_PTR seed,
+                                   CK_ULONG seed_len)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV
+mock_C_GenerateRandom__invalid_handle (CK_SESSION_HANDLE session,
+                                       CK_BYTE_PTR random_data,
+                                       CK_ULONG random_len)
+{
+       return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_FUNCTION_LIST mock_module_no_slots = {
+       { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },  /* version */
+       mock_C_Initialize,
+       mock_C_Finalize,
+       mock_C_GetInfo,
+       mock_C_GetFunctionList,
+       mock_C_GetSlotList__no_tokens,
+       mock_C_GetSlotInfo__invalid_slotid,
+       mock_C_GetTokenInfo__invalid_slotid,
+       mock_C_GetMechanismList__invalid_slotid,
+       mock_C_GetMechanismInfo__invalid_slotid,
+       mock_C_InitToken__invalid_slotid,
+       mock_C_InitPIN__invalid_handle,
+       mock_C_SetPIN__invalid_handle,
+       mock_C_OpenSession__invalid_slotid,
+       mock_C_CloseSession__invalid_handle,
+       mock_C_CloseAllSessions__invalid_slotid,
+       mock_C_GetSessionInfo__invalid_handle,
+       mock_C_GetOperationState__invalid_handle,
+       mock_C_SetOperationState__invalid_handle,
+       mock_C_Login__invalid_handle,
+       mock_C_Logout__invalid_handle,
+       mock_C_CreateObject__invalid_handle,
+       mock_C_CopyObject__invalid_handle,
+       mock_C_DestroyObject__invalid_handle,
+       mock_C_GetObjectSize__invalid_handle,
+       mock_C_GetAttributeValue__invalid_handle,
+       mock_C_SetAttributeValue__invalid_handle,
+       mock_C_FindObjectsInit__invalid_handle,
+       mock_C_FindObjects__invalid_handle,
+       mock_C_FindObjectsFinal__invalid_handle,
+       mock_C_EncryptInit__invalid_handle,
+       mock_C_Encrypt__invalid_handle,
+       mock_C_EncryptUpdate__invalid_handle,
+       mock_C_EncryptFinal__invalid_handle,
+       mock_C_DecryptInit__invalid_handle,
+       mock_C_Decrypt__invalid_handle,
+       mock_C_DecryptUpdate__invalid_handle,
+       mock_C_DecryptFinal__invalid_handle,
+       mock_C_DigestInit__invalid_handle,
+       mock_C_Digest__invalid_handle,
+       mock_C_DigestUpdate__invalid_handle,
+       mock_C_DigestKey__invalid_handle,
+       mock_C_DigestFinal__invalid_handle,
+       mock_C_SignInit__invalid_handle,
+       mock_C_Sign__invalid_handle,
+       mock_C_SignUpdate__invalid_handle,
+       mock_C_SignFinal__invalid_handle,
+       mock_C_SignRecoverInit__invalid_handle,
+       mock_C_SignRecover__invalid_handle,
+       mock_C_VerifyInit__invalid_handle,
+       mock_C_Verify__invalid_handle,
+       mock_C_VerifyUpdate__invalid_handle,
+       mock_C_VerifyFinal__invalid_handle,
+       mock_C_VerifyRecoverInit__invalid_handle,
+       mock_C_VerifyRecover__invalid_handle,
+       mock_C_DigestEncryptUpdate__invalid_handle,
+       mock_C_DecryptDigestUpdate__invalid_handle,
+       mock_C_SignEncryptUpdate__invalid_handle,
+       mock_C_DecryptVerifyUpdate__invalid_handle,
+       mock_C_GenerateKey__invalid_handle,
+       mock_C_GenerateKeyPair__invalid_handle,
+       mock_C_WrapKey__invalid_handle,
+       mock_C_UnwrapKey__invalid_handle,
+       mock_C_DeriveKey__invalid_handle,
+       mock_C_SeedRandom__invalid_handle,
+       mock_C_GenerateRandom__invalid_handle,
+       mock_C_GetFunctionStatus__not_parallel,
+       mock_C_CancelFunction__not_parallel,
+       mock_C_WaitForSlotEvent__no_event,
+};
diff --git a/tests/mock-module.h b/tests/mock-module.h
new file mode 100644 (file)
index 0000000..f198e46
--- /dev/null
@@ -0,0 +1,336 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* mock-module.c - a mock PKCS#11 module
+
+   Copyright (C) 2011 Collabora Ltd.
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stefw@collabora.co.uk>
+*/
+
+#ifndef __MOCK_MODULE_H__
+#define __MOCK_MODULE_H__
+
+#include "pkcs11.h"
+
+CK_FUNCTION_LIST    mock_module_no_slots;
+
+
+CK_RV       mock_C_Initialize                             (CK_VOID_PTR init_args);
+
+CK_RV       mock_C_Finalize                               (CK_VOID_PTR reserved);
+
+CK_RV       mock_C_GetInfo                                (CK_INFO_PTR info);
+
+CK_RV       mock_C_GetFunctionList                        (CK_FUNCTION_LIST_PTR_PTR list);
+
+CK_RV       mock_C_GetSlotList__no_tokens                 (CK_BBOOL token_present,
+                                                           CK_SLOT_ID_PTR slot_list,
+                                                           CK_ULONG_PTR count);
+
+CK_RV       mock_C_GetSlotInfo__invalid_slotid            (CK_SLOT_ID id,
+                                                           CK_SLOT_INFO_PTR info);
+
+CK_RV       mock_C_GetTokenInfo__invalid_slotid           (CK_SLOT_ID id,
+                                                           CK_TOKEN_INFO_PTR info);
+
+CK_RV       mock_C_GetMechanismList__invalid_slotid       (CK_SLOT_ID id,
+                                                           CK_MECHANISM_TYPE_PTR mechanism_list,
+                                                           CK_ULONG_PTR count);
+
+CK_RV       mock_C_GetMechanismInfo__invalid_slotid       (CK_SLOT_ID id,
+                                                           CK_MECHANISM_TYPE type,
+                                                           CK_MECHANISM_INFO_PTR info);
+
+CK_RV       mock_C_InitToken__invalid_slotid              (CK_SLOT_ID id,
+                                                           CK_UTF8CHAR_PTR pin,
+                                                           CK_ULONG pin_len,
+                                                           CK_UTF8CHAR_PTR label);
+
+CK_RV       mock_C_WaitForSlotEvent__no_event             (CK_FLAGS flags,
+                                                           CK_SLOT_ID_PTR slot,
+                                                           CK_VOID_PTR reserved);
+
+CK_RV       mock_C_OpenSession__invalid_slotid            (CK_SLOT_ID id,
+                                                           CK_FLAGS flags,
+                                                           CK_VOID_PTR user_data,
+                                                           CK_NOTIFY callback,
+                                                           CK_SESSION_HANDLE_PTR session);
+
+CK_RV       mock_C_CloseSession__invalid_handle           (CK_SESSION_HANDLE session);
+
+CK_RV       mock_C_CloseAllSessions__invalid_slotid       (CK_SLOT_ID id);
+
+CK_RV       mock_C_GetFunctionStatus__not_parallel        (CK_SESSION_HANDLE session);
+
+CK_RV       mock_C_CancelFunction__not_parallel           (CK_SESSION_HANDLE session);
+
+CK_RV       mock_C_GetSessionInfo__invalid_handle         (CK_SESSION_HANDLE session,
+                                                           CK_SESSION_INFO_PTR info);
+
+CK_RV       mock_C_InitPIN__invalid_handle                (CK_SESSION_HANDLE session,
+                                                           CK_UTF8CHAR_PTR pin,
+                                                           CK_ULONG pin_len);
+
+CK_RV       mock_C_SetPIN__invalid_handle                 (CK_SESSION_HANDLE session,
+                                                           CK_UTF8CHAR_PTR old_pin,
+                                                           CK_ULONG old_pin_len,
+                                                           CK_UTF8CHAR_PTR new_pin,
+                                                           CK_ULONG new_pin_len);
+
+CK_RV       mock_C_GetOperationState__invalid_handle      (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR operation_state,
+                                                           CK_ULONG_PTR operation_state_len);
+
+CK_RV       mock_C_SetOperationState__invalid_handle      (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR operation_state,
+                                                           CK_ULONG operation_state_len,
+                                                           CK_OBJECT_HANDLE encryption_key,
+                                                           CK_OBJECT_HANDLE authentication_key);
+
+CK_RV       mock_C_Login__invalid_handle                  (CK_SESSION_HANDLE session,
+                                                           CK_USER_TYPE user_type,
+                                                           CK_UTF8CHAR_PTR pin,
+                                                           CK_ULONG pin_len);
+
+CK_RV       mock_C_Logout__invalid_handle                 (CK_SESSION_HANDLE session);
+
+CK_RV       mock_C_CreateObject__invalid_handle           (CK_SESSION_HANDLE session,
+                                                           CK_ATTRIBUTE_PTR template,
+                                                           CK_ULONG count,
+                                                           CK_OBJECT_HANDLE_PTR new_object);
+
+CK_RV       mock_C_CopyObject__invalid_handle             (CK_SESSION_HANDLE session,
+                                                           CK_OBJECT_HANDLE object,
+                                                           CK_ATTRIBUTE_PTR template,
+                                                           CK_ULONG count,
+                                                           CK_OBJECT_HANDLE_PTR new_object);
+
+CK_RV       mock_C_DestroyObject__invalid_handle          (CK_SESSION_HANDLE session,
+                                                           CK_OBJECT_HANDLE object);
+
+CK_RV       mock_C_GetObjectSize__invalid_handle          (CK_SESSION_HANDLE session,
+                                                           CK_OBJECT_HANDLE object,
+                                                           CK_ULONG_PTR size);
+
+CK_RV       mock_C_GetAttributeValue__invalid_handle      (CK_SESSION_HANDLE session,
+                                                           CK_OBJECT_HANDLE object,
+                                                           CK_ATTRIBUTE_PTR template,
+                                                           CK_ULONG count);
+
+CK_RV       mock_C_SetAttributeValue__invalid_handle      (CK_SESSION_HANDLE session,
+                                                           CK_OBJECT_HANDLE object,
+                                                           CK_ATTRIBUTE_PTR template,
+                                                           CK_ULONG count);
+
+CK_RV       mock_C_FindObjectsInit__invalid_handle        (CK_SESSION_HANDLE session,
+                                                           CK_ATTRIBUTE_PTR template,
+                                                           CK_ULONG count);
+
+CK_RV       mock_C_FindObjects__invalid_handle            (CK_SESSION_HANDLE session,
+                                                           CK_OBJECT_HANDLE_PTR objects,
+                                                           CK_ULONG max_count,
+                                                           CK_ULONG_PTR count);
+
+CK_RV       mock_C_FindObjectsFinal__invalid_handle       (CK_SESSION_HANDLE session);
+
+CK_RV       mock_C_EncryptInit__invalid_handle            (CK_SESSION_HANDLE session,
+                                                           CK_MECHANISM_PTR mechanism,
+                                                           CK_OBJECT_HANDLE key);
+
+CK_RV       mock_C_Encrypt__invalid_handle                (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR data,
+                                                           CK_ULONG data_len,
+                                                           CK_BYTE_PTR encrypted_data,
+                                                           CK_ULONG_PTR encrypted_data_len);
+
+CK_RV       mock_C_EncryptUpdate__invalid_handle          (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR part,
+                                                           CK_ULONG part_len,
+                                                           CK_BYTE_PTR encrypted_part,
+                                                           CK_ULONG_PTR encrypted_part_len);
+
+CK_RV       mock_C_EncryptFinal__invalid_handle           (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR last_part,
+                                                           CK_ULONG_PTR last_part_len);
+
+CK_RV       mock_C_DecryptInit__invalid_handle            (CK_SESSION_HANDLE session,
+                                                           CK_MECHANISM_PTR mechanism,
+                                                           CK_OBJECT_HANDLE key);
+
+CK_RV       mock_C_Decrypt__invalid_handle                (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR enc_data,
+                                                           CK_ULONG enc_data_len,
+                                                           CK_BYTE_PTR data,
+                                                           CK_ULONG_PTR data_len);
+
+CK_RV       mock_C_DecryptUpdate__invalid_handle          (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR enc_part,
+                                                           CK_ULONG enc_part_len,
+                                                           CK_BYTE_PTR part,
+                                                           CK_ULONG_PTR part_len);
+
+CK_RV       mock_C_DecryptFinal__invalid_handle           (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR last_part,
+                                                           CK_ULONG_PTR last_part_len);
+
+CK_RV       mock_C_DigestInit__invalid_handle             (CK_SESSION_HANDLE session,
+                                                           CK_MECHANISM_PTR mechanism);
+
+CK_RV       mock_C_Digest__invalid_handle                 (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR data,
+                                                           CK_ULONG data_len,
+                                                           CK_BYTE_PTR digest,
+                                                           CK_ULONG_PTR digest_len);
+
+CK_RV       mock_C_DigestUpdate__invalid_handle           (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR part,
+                                                           CK_ULONG part_len);
+
+CK_RV       mock_C_DigestKey__invalid_handle              (CK_SESSION_HANDLE session,
+                                                           CK_OBJECT_HANDLE key);
+
+CK_RV       mock_C_DigestFinal__invalid_handle            (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR digest,
+                                                           CK_ULONG_PTR digest_len);
+
+CK_RV       mock_C_SignInit__invalid_handle               (CK_SESSION_HANDLE session,
+                                                           CK_MECHANISM_PTR mechanism,
+                                                           CK_OBJECT_HANDLE key);
+
+CK_RV       mock_C_Sign__invalid_handle                   (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR data,
+                                                           CK_ULONG data_len,
+                                                           CK_BYTE_PTR signature,
+                                                           CK_ULONG_PTR signature_len);
+
+CK_RV       mock_C_SignUpdate__invalid_handle             (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR part,
+                                                           CK_ULONG part_len);
+
+CK_RV       mock_C_SignFinal__invalid_handle              (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR signature,
+                                                           CK_ULONG_PTR signature_len);
+
+CK_RV       mock_C_SignRecoverInit__invalid_handle        (CK_SESSION_HANDLE session,
+                                                           CK_MECHANISM_PTR mechanism,
+                                                           CK_OBJECT_HANDLE key);
+
+CK_RV       mock_C_SignRecover__invalid_handle            (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR data,
+                                                           CK_ULONG data_len,
+                                                           CK_BYTE_PTR signature,
+                                                           CK_ULONG_PTR signature_len);
+
+CK_RV       mock_C_VerifyInit__invalid_handle             (CK_SESSION_HANDLE session,
+                                                           CK_MECHANISM_PTR mechanism,
+                                                           CK_OBJECT_HANDLE key);
+
+CK_RV       mock_C_Verify__invalid_handle                 (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR data,
+                                                           CK_ULONG data_len,
+                                                           CK_BYTE_PTR signature,
+                                                           CK_ULONG signature_len);
+
+CK_RV       mock_C_VerifyUpdate__invalid_handle           (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR part,
+                                                           CK_ULONG part_len);
+
+CK_RV       mock_C_VerifyFinal__invalid_handle            (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR signature,
+                                                           CK_ULONG signature_len);
+
+CK_RV       mock_C_VerifyRecoverInit__invalid_handle      (CK_SESSION_HANDLE session,
+                                                           CK_MECHANISM_PTR mechanism,
+                                                           CK_OBJECT_HANDLE key);
+
+CK_RV       mock_C_VerifyRecover__invalid_handle          (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR signature,
+                                                           CK_ULONG signature_len,
+                                                           CK_BYTE_PTR data,
+                                                           CK_ULONG_PTR data_len);
+
+CK_RV       mock_C_DigestEncryptUpdate__invalid_handle    (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR part,
+                                                           CK_ULONG part_len,
+                                                           CK_BYTE_PTR enc_part,
+                                                           CK_ULONG_PTR enc_part_len);
+
+CK_RV       mock_C_DecryptDigestUpdate__invalid_handle    (CK_SESSION_HANDLE session,
+                                                           CK_BYTE_PTR enc_part,
+                                                           CK_ULONG enc_part_len,
+                                                           CK_BYTE_PTR part,
+                                                           CK_ULONG_PTR part_len);
+
+CK_RV       mock_C_SignEncryptUpdate__invalid_handle       (CK_SESSION_HANDLE session,
+                                                            CK_BYTE_PTR part,
+                                                            CK_ULONG part_len,
+                                                            CK_BYTE_PTR enc_part,
+                                                            CK_ULONG_PTR enc_part_len);
+
+CK_RV       mock_C_DecryptVerifyUpdate__invalid_handle     (CK_SESSION_HANDLE session,
+                                                            CK_BYTE_PTR enc_part,
+                                                            CK_ULONG enc_part_len,
+                                                            CK_BYTE_PTR part,
+                                                            CK_ULONG_PTR part_len);
+
+CK_RV       mock_C_GenerateKey__invalid_handle             (CK_SESSION_HANDLE session,
+                                                            CK_MECHANISM_PTR mechanism,
+                                                            CK_ATTRIBUTE_PTR template,
+                                                            CK_ULONG count,
+                                                            CK_OBJECT_HANDLE_PTR key);
+
+CK_RV       mock_C_GenerateKeyPair__invalid_handle         (CK_SESSION_HANDLE session,
+                                                            CK_MECHANISM_PTR mechanism,
+                                                            CK_ATTRIBUTE_PTR pub_template,
+                                                            CK_ULONG pub_count,
+                                                            CK_ATTRIBUTE_PTR priv_template,
+                                                            CK_ULONG priv_count,
+                                                            CK_OBJECT_HANDLE_PTR pub_key,
+                                                            CK_OBJECT_HANDLE_PTR priv_key);
+
+CK_RV       mock_C_WrapKey__invalid_handle                 (CK_SESSION_HANDLE session,
+                                                            CK_MECHANISM_PTR mechanism,
+                                                            CK_OBJECT_HANDLE wrapping_key,
+                                                            CK_OBJECT_HANDLE key,
+                                                            CK_BYTE_PTR wrapped_key,
+                                                            CK_ULONG_PTR wrapped_key_len);
+
+CK_RV       mock_C_UnwrapKey__invalid_handle               (CK_SESSION_HANDLE session,
+                                                            CK_MECHANISM_PTR mechanism,
+                                                            CK_OBJECT_HANDLE unwrapping_key,
+                                                            CK_BYTE_PTR wrapped_key,
+                                                            CK_ULONG wrapped_key_len,
+                                                            CK_ATTRIBUTE_PTR template,
+                                                            CK_ULONG count,
+                                                            CK_OBJECT_HANDLE_PTR key);
+
+CK_RV       mock_C_DeriveKey__invalid_handle               (CK_SESSION_HANDLE session,
+                                                            CK_MECHANISM_PTR mechanism,
+                                                            CK_OBJECT_HANDLE base_key,
+                                                            CK_ATTRIBUTE_PTR template,
+                                                            CK_ULONG count,
+                                                            CK_OBJECT_HANDLE_PTR key);
+
+CK_RV       mock_C_SeedRandom__invalid_handle              (CK_SESSION_HANDLE session,
+                                                            CK_BYTE_PTR seed,
+                                                            CK_ULONG seed_len);
+
+CK_RV       mock_C_GenerateRandom__invalid_handle          (CK_SESSION_HANDLE session,
+                                                            CK_BYTE_PTR random_data,
+                                                            CK_ULONG random_len);
+
+#endif /* __MOCK_MODULE_H__ */
diff --git a/tests/p11-test.c b/tests/p11-test.c
new file mode 100644 (file)
index 0000000..fcdcbe9
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011, Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *     * Redistributions of source code must retain the above
+ *       copyright notice, this list of conditions and the
+ *       following disclaimer.
+ *     * Redistributions in binary form must reproduce the
+ *       above copyright notice, this list of conditions and
+ *       the following disclaimer in the documentation and/or
+ *       other materials provided with the distribution.
+ *     * The names of contributors to this software may not be
+ *       used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "p11-kit/p11-kit.h"
+
+#include "mock-module.h"
+
+static CK_RV
+mock_C_Initialize__with_fork (CK_VOID_PTR init_args)
+{
+       CK_RV rv;
+       pid_t child;
+       pid_t ret;
+       int status;
+
+       rv = mock_C_Initialize (init_args);
+       assert (rv == CKR_OK);
+
+       /* Fork during the initialization */
+       child = fork ();
+       if (child == 0) {
+               sleep (1);
+               exit (66);
+       }
+
+       ret = waitpid (child, &status, 0);
+       assert (ret == child);
+       assert (WIFEXITED (status));
+       assert (WEXITSTATUS (status) == 66);
+
+       return CKR_OK;
+}
+
+static void
+test_fork_initialization (CuTest *tc)
+{
+       CK_FUNCTION_LIST module;
+       CK_RV rv;
+
+       /* Build up our own function list */
+       memcpy (&module, &mock_module_no_slots, sizeof (CK_FUNCTION_LIST));
+       module.C_Initialize = mock_C_Initialize__with_fork;
+
+       rv = p11_kit_initialize_module (&module);
+       CuAssertTrue (tc, rv == CKR_OK);
+
+       rv = p11_kit_finalize_module (&module);
+       CuAssertTrue (tc, rv == CKR_OK);
+}
+
+int
+main (void)
+{
+       CuString *output = CuStringNew ();
+       CuSuite* suite = CuSuiteNew ();
+       int ret;
+
+       SUITE_ADD_TEST (suite, test_fork_initialization);
+
+       CuSuiteRun (suite);
+       CuSuiteSummary (suite, output);
+       CuSuiteDetails (suite, output);
+       printf ("%s\n", output->buffer);
+       ret = suite->failCount;
+       CuSuiteDelete (suite);
+       CuStringDelete (output);
+
+       return ret;
+}
+
+#include "CuTest.c"