diff options
author | Stef Walter <stefw@collabora.co.uk> | 2011-01-22 14:45:57 -0600 |
---|---|---|
committer | Stef Walter <stefw@collabora.co.uk> | 2011-01-22 14:45:57 -0600 |
commit | c2a5aaf7baf4bcc006674a1938205f93028b8ab0 (patch) | |
tree | c6db4d82e1b673c33fdf8ee37c9dd434a40d72d3 /module | |
parent | a50ba779ff3e0a5d4f35fb2b6ab525a423575cc4 (diff) |
Rough idea of possible library functions.
Diffstat (limited to 'module')
-rw-r--r-- | module/p11-unity.c | 307 | ||||
-rw-r--r-- | module/p11-unity.h | 56 |
2 files changed, 310 insertions, 53 deletions
diff --git a/module/p11-unity.c b/module/p11-unity.c index e6ea668..35e8f53 100644 --- a/module/p11-unity.c +++ b/module/p11-unity.c @@ -37,11 +37,13 @@ #include "hash.h" #include "pkcs11.h" +#include "p11-unity.h" #include <sys/types.h> #include <assert.h> #include <dirent.h> #include <dlfcn.h> +#include <errno.h> #include <pthread.h> #include <stdarg.h> #include <stddef.h> @@ -66,6 +68,7 @@ typedef struct _Session { } Session; typedef struct _Module { + char *name; char *path; void *dl_module; CK_FUNCTION_LIST_PTR funcs; @@ -76,6 +79,12 @@ typedef struct _Module { /* Forward declaration */ static CK_FUNCTION_LIST unity_function_list; +/* + * This is the mutex that protects the global data of this library + * and the pkcs11 proxy module. Note that we *never* call into our + * underlying pkcs11 modules while holding this mutex. Therefore it + * doesn't have to be recursive and we can keep things simple. + */ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /* @@ -302,6 +311,45 @@ unload_module_unlocked (Module *module) } static CK_RV +finalize_unlocked (CK_VOID_PTR args) +{ + Module *module, *next; + hsh_index_t *iter; + + if (gl.initialize_count == 0) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + /* Finalize all the modules */ + for (module = gl.modules; module; module = next) { + next = module->next; + if (module->initialized) { + (module->funcs->C_Finalize) (args); + module->initialized = 0; + } + + unload_module_unlocked (module); + free (module); + } + gl.modules = NULL; + + /* No more mappings */ + free (gl.mappings); + gl.mappings = NULL; + gl.n_mappings = 0; + + /* no more sessions */ + if (gl.sessions) { + for (iter = hsh_first (gl.sessions); iter; iter = hsh_next (iter)) + free (hsh_this (iter, NULL, NULL)); + hsh_free (gl.sessions); + gl.sessions = NULL; + } + + --gl.initialize_count; + return CKR_OK; +} + +static CK_RV initialize_unlocked (CK_VOID_PTR init_args) { CK_SLOT_ID_PTR slots; @@ -311,6 +359,20 @@ initialize_unlocked (CK_VOID_PTR init_args) Module *module; CK_RV rv; + /* + * We bend the rules of PKCS#11 here. We never return the + * CKR_ALREADY_INITIALIZED error code, but just increase + * an initialization ref count. + * + * C_Finalize must be called the same amount of times as + * C_Initialize. + */ + + if (gl.initialize_count > 0) { + ++gl.initialize_count; + return CKR_OK; + } + assert (!gl.mappings); assert (gl.n_mappings == 0); assert (!gl.modules); @@ -389,46 +451,210 @@ initialize_unlocked (CK_VOID_PTR init_args) } gl.sessions = hsh_create (); + + /* + * In the case of failure, we just finalize the partially + * initialized stuff, which cleans everything up. That's + * why we increment initialize_count, as finalize will bring + * it back to zero. + */ + + gl.initialize_count = 1; + if (rv != CKR_OK) { + finalize_unlocked (NULL); + assert (gl.initialize_count == 0); + } + return rv; } static CK_RV -finalize_unlocked (CK_VOID_PTR args) +create_mutex (CK_VOID_PTR_PTR mut) { - Module *module, *next; - hsh_index_t *iter; + pthread_mutex_t *pmutex; + int err; - /* Finalize all the modules */ - for (module = gl.modules; module; module = next) { - next = module->next; - if (module->initialized) { - (module->funcs->C_Finalize) (args); - module->initialized = 0; - } + pmutex = malloc (sizeof (pthread_mutex_t)); + if (!pmutex) + return CKR_HOST_MEMORY; + err = pthread_mutex_init (pmutex, NULL); + if (err == ENOMEM) + return CKR_HOST_MEMORY; + else if (err != 0) + return CKR_GENERAL_ERROR; + *mut = pmutex; + return CKR_OK; +} - unload_module_unlocked (module); - free (module); - } - gl.modules = NULL; +static CK_RV +destroy_mutex (CK_VOID_PTR mut) +{ + pthread_mutex_t *pmutex = mut; + int err; - /* No more mappings */ - free (gl.mappings); - gl.mappings = NULL; - gl.n_mappings = 0; + err = pthread_mutex_destroy (pmutex); + if (err == EINVAL) + return CKR_MUTEX_BAD; + else if (err != 0) + return CKR_GENERAL_ERROR; + free (pmutex); + return CKR_OK; +} - /* no more sessions */ - if (gl.sessions) { - for (iter = hsh_first (gl.sessions); iter; iter = hsh_next (iter)) - free (hsh_this (iter, NULL, NULL)); - hsh_free (gl.sessions); - gl.sessions = NULL; - } +static CK_RV +lock_mutex (CK_VOID_PTR mut) +{ + pthread_mutex_t *pmutex = mut; + int err; + err = pthread_mutex_lock (pmutex); + if (err == EINVAL) + return CKR_MUTEX_BAD; + else if (err != 0) + return CKR_GENERAL_ERROR; + return CKR_OK; +} + +static CK_RV +unlock_mutex (CK_VOID_PTR mut) +{ + pthread_mutex_t *pmutex = mut; + int err; + + err = pthread_mutex_unlock (pmutex); + if (err == EINVAL) + return CKR_MUTEX_BAD; + else if (err == EPERM) + return CKR_MUTEX_NOT_LOCKED; + else if (err != 0) + return CKR_GENERAL_ERROR; return CKR_OK; } /* ----------------------------------------------------------------------------- - * PKCS#11 FUNCTIONS + * PUBLIC FUNCTIONALITY + */ + +CK_RV +p11_unity_initialize (void) +{ + CK_C_INITIALIZE_ARGS args; + CK_RV rv; + + memset (&args, 0, sizeof (args)); + args.CreateMutex = create_mutex; + args.DestroyMutex = destroy_mutex; + args.LockMutex = lock_mutex; + args.UnlockMutex = unlock_mutex; + args.flags = CKF_OS_LOCKING_OK; + + pthread_mutex_lock (&mutex); + + rv = initialize_unlocked (&args); + + pthread_mutex_unlock (&mutex); + + return rv; +} + +CK_RV +p11_unity_finalize (void) +{ + CK_RV rv; + + pthread_mutex_lock (&mutex); + + rv = finalize_unlocked (NULL); + + pthread_mutex_unlock (&mutex); + + return rv; +} + +char** +p11_unity_module_names (void) +{ + Module *module; + char **result; + int count, i; + + pthread_mutex_lock (&mutex); + + if (!gl.initialize_count) { + result = NULL; + } else { + for (module = gl.modules, count = 0; + module; module = module->next) + ++count; + result = calloc (count + 1, sizeof (char*)); + if (result) { + for (module = gl.modules, i = 0; + module; module = module->next, ++i) + result[i] = strdup (module->name); + } + } + + pthread_mutex_unlock (&mutex); + + return result; +} + +void +p11_unity_free_names (char **module_names) +{ + char **name; + for (name = module_names; *name; ++name) + free (name); +} + +CK_FUNCTION_LIST_PTR +p11_unity_module_functions (const char *module_name) +{ + CK_FUNCTION_LIST_PTR result; + Module *module; + + if (!module_name) + return NULL; + + pthread_mutex_lock (&mutex); + + if (gl.initialize_count) { + for (module = gl.modules; module; module = module->next) { + if (strcmp (module_name, module->name) == 0) { + result = module->funcs; + break; + } + } + } + + pthread_mutex_unlock (&mutex); + + return result; +} + +int +p11_unity_module_add (const char *module_name, CK_FUNCTION_LIST_PTR module) +{ + assert (0); + return -1; +} + +int +p11_unity_module_remove (const char *module_name) +{ + assert (0); + return -1; +} + +char* +p11_unity_config_get_option (const char *module_name, const char *field) +{ + assert (0); + return NULL; +} + +/* ----------------------------------------------------------------------------- + * PKCS#11 PROXY MODULE */ static CK_RV @@ -441,13 +667,7 @@ unity_C_Finalize (CK_VOID_PTR reserved) pthread_mutex_lock (&mutex); - if (gl.initialize_count == 0) { - rv = CKR_CRYPTOKI_NOT_INITIALIZED; - } else { - rv = finalize_unlocked (reserved); - if (rv == CKR_OK) - --gl.initialize_count; - } + rv = finalize_unlocked (reserved); pthread_mutex_unlock (&mutex); @@ -461,29 +681,10 @@ unity_C_Initialize (CK_VOID_PTR init_args) pthread_mutex_lock (&mutex); - /* - * We bend the rules of PKCS#11 here. We never return the - * CKR_ALREADY_INITIALIZED error code, but just increase - * an initialization ref count. - * - * C_Finalize must be called the same amount of times as - * C_Initialize. - */ - - if (gl.initialize_count > 0) { - ++gl.initialize_count; - rv = CKR_OK; - } else { - rv = initialize_unlocked (init_args); - gl.initialize_count = 1; - } + rv = initialize_unlocked (init_args); pthread_mutex_unlock (&mutex); - /* Finalize anything that was half initialized */ - if (rv != CKR_OK) - unity_C_Finalize (NULL); - return rv; } diff --git a/module/p11-unity.h b/module/p11-unity.h new file mode 100644 index 0000000..52855f3 --- /dev/null +++ b/module/p11-unity.h @@ -0,0 +1,56 @@ +/* + * 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> + */ + +#ifndef __P11_UNITY_H__ +#define __P11_UNITY_H__ + +CK_RV p11_unity_initialize (void); + +CK_RV p11_unity_finalize (void); + +char** p11_unity_module_names (void); + +void p11_unity_free_names (char **module_names); + +CK_FUNCTION_LIST_PTR p11_unity_module_functions (const char *module_name); + +int p11_unity_module_add (const char *module_name, + CK_FUNCTION_LIST_PTR module); + +int p11_unity_module_remove (const char *module_name); + +char* p11_unity_config_get_option (const char *module_name, + const char *field); + +#endif /* __P11_UNITY_H__ */ |