#include "config.h" #include "p11-tests.h" #include #include #include #include #include static void *module = NULL; CK_FUNCTION_LIST_PTR p11_funcs = NULL; static CK_C_INITIALIZE_ARGS init_args; static int is_initialized = 0; static CK_RV create_mutex(void **mutex) { pthread_mutex_t *mut; if(!mutex) { p11t_msg_print("null mutex passed to create_mutex"); return CKR_ARGUMENTS_BAD; } mut = malloc(sizeof(pthread_mutex_t)); assert(mut); if(pthread_mutex_init(mut, NULL) != 0) assert(0); *mutex = mut; return CKR_OK; } static CK_RV destroy_mutex (void *mutex) { int res; if(!mutex) { p11t_msg_print("destroying null mutex"); return CKR_MUTEX_BAD; } res = pthread_mutex_destroy(mutex); if(res != 0) { if(res == EBUSY) { p11t_msg_print("trying to destroy locked mutex"); return CKR_GENERAL_ERROR; } else if(res == EINVAL) { p11t_msg_print("destroying invalid mutex used"); return CKR_MUTEX_BAD; } else { p11t_msg_print("couldn't destroy mutex: %d", res); return CKR_GENERAL_ERROR; } } return CKR_OK; } static CK_RV lock_mutex (void *mutex) { int res; if (!mutex) { p11t_msg_print("locking null mutex"); return CKR_MUTEX_BAD; } res = pthread_mutex_lock(mutex); if(res != 0) { if(res == EDEADLK) { p11t_msg_print("locking mutex would deadlock"); return CKR_CANT_LOCK; } else if(res == EINVAL) { p11t_msg_print("locking invalid mutex used"); return CKR_MUTEX_BAD; } else { p11t_msg_print("couldn't lock mutex: %d", res); return CKR_GENERAL_ERROR; } } return CKR_OK; } static CK_RV unlock_mutex (void *mutex) { int res; if (!mutex) { p11t_msg_print("unlocking null mutex"); return CKR_MUTEX_BAD; } res = pthread_mutex_lock(mutex); if(res != 0) { if(res == EPERM) { p11t_msg_print("unlocking mutex without locked"); return CKR_MUTEX_NOT_LOCKED; } else if(res == EINVAL) { p11t_msg_print("unlocking invalid mutex used"); return CKR_MUTEX_BAD; } else { p11t_msg_print("couldn't unlock mutex: %d", res); return CKR_GENERAL_ERROR; } } else { free(mutex); } return CKR_OK; } void p11t_module_load(const char *filename) { CK_C_GetFunctionList get_function_list; CK_RV rv; module = dlopen(filename, RTLD_NOW); if(!module) p11t_msg_fatal("couldn't open library: %s: %s", filename, dlerror()); /* Lookup the appropriate function in library */ get_function_list = (CK_C_GetFunctionList)dlsym (module, "C_GetFunctionList"); if(!get_function_list) p11t_msg_fatal("couldn't find C_GetFunctionList function in library: %s: %s", filename, dlerror()); /* Get the function list */ rv = (get_function_list)(&p11_funcs); if(rv != CKR_OK) p11t_msg_fatal("couldn't get function list: %s", p11t_msg_rv(rv)); /* Make sure we have a compatible version */ if(p11_funcs->version.major != CRYPTOKI_VERSION_MAJOR) p11t_msg_fatal("incompatible version of pkcs11 module: %d.%d", (int)p11_funcs->version.major, (int)p11_funcs->version.minor); } static void initialize_common(const char *mode) { CK_RV rv; assert(p11_funcs); rv = (p11_funcs->C_Initialize) (&init_args); if (rv != CKR_OK) { if(rv != CKR_CANT_LOCK) p11t_msg_print("C_Initialize failed (%s): %s", mode, p11t_msg_rv(rv)); } else { is_initialized = 1; } } static void initialize_locking_1(const char *initstr) { memset(&init_args, 0, sizeof (init_args)); init_args.pReserved = (void*)initstr; initialize_common("locking mode 1: no threads"); } static void initialize_locking_2(const char *initstr) { memset(&init_args, 0, sizeof (init_args)); init_args.flags = CKF_OS_LOCKING_OK; init_args.pReserved = (void*)initstr; initialize_common("locking mode 2: os locking"); } static void initialize_locking_3(const char *initstr) { memset(&init_args, 0, sizeof (init_args)); init_args.flags = 0; init_args.CreateMutex = create_mutex; init_args.DestroyMutex = destroy_mutex; init_args.LockMutex = lock_mutex; init_args.UnlockMutex = unlock_mutex; init_args.pReserved = (void*)initstr; initialize_common("locking mode 3: app locking"); } static void initialize_locking_4(const char *initstr) { memset(&init_args, 0, sizeof (init_args)); init_args.flags = CKF_OS_LOCKING_OK; init_args.CreateMutex = create_mutex; init_args.DestroyMutex = destroy_mutex; init_args.LockMutex = lock_mutex; init_args.UnlockMutex = unlock_mutex; init_args.pReserved = (void*)initstr; initialize_common("locking mode 4: either locking"); } void p11t_module_initialize(const char *initstr) { CK_INFO info; CK_RV rv; assert(p11_funcs); /* Some invalid use without initializing */ rv = (p11_funcs->C_GetInfo)(&info); if(rv != CKR_CRYPTOKI_NOT_INITIALIZED) p11t_msg_print("shouldn't run without initialize: %s", p11t_msg_rv(rv)); /* The various different locking modes */ initialize_locking_1(initstr); p11t_module_finalize(); initialize_locking_2(initstr); p11t_module_finalize(); initialize_locking_3(initstr); p11t_module_finalize(); initialize_locking_4(initstr); if(!is_initialized) p11t_msg_fatal("liberal locking strategy failed, can't continue"); /* Double initialize */ rv = (p11_funcs->C_Initialize) (&init_args); if (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { p11t_msg_print("double initialize should return CKR_CRYPTOKI_ALREADY_INITIALIZED: %s", p11t_msg_rv(rv)); } else { is_initialized = 1; } } void p11t_module_finalize(void) { CK_RV rv; if(is_initialized) { assert(p11_funcs); rv = p11_funcs->C_Finalize(NULL); if(rv != CKR_OK) p11t_msg_print("C_Finalize failed: %s", p11t_msg_rv(rv)); is_initialized = 0; } } void p11t_module_unload(void) { if(module) dlclose(module); module = NULL; }