2002-01-16 22:49:03 +00:00
|
|
|
/*
|
|
|
|
* pkcs11-global.c: PKCS#11 module level functions and function table
|
|
|
|
*
|
2006-12-19 21:33:15 +00:00
|
|
|
* Copyright (C) 2002 Timo Teräs <timo.teras@iki.fi>
|
2002-01-16 22:49:03 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
2006-02-01 22:59:42 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2002-03-15 11:41:16 +00:00
|
|
|
#include <stdlib.h>
|
2002-03-21 09:36:38 +00:00
|
|
|
#include <string.h>
|
2006-02-01 22:59:42 +00:00
|
|
|
#ifdef HAVE_SYS_TIME_H
|
|
|
|
#include <sys/time.h>
|
|
|
|
#endif
|
2002-03-25 12:39:35 +00:00
|
|
|
#include "sc-pkcs11.h"
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2005-03-09 00:04:44 +00:00
|
|
|
sc_context_t *context = NULL;
|
2002-01-16 22:49:03 +00:00
|
|
|
struct sc_pkcs11_pool session_pool;
|
2008-03-06 15:04:29 +00:00
|
|
|
struct sc_pkcs11_slot *virtual_slots = NULL;
|
2009-01-16 16:44:35 +00:00
|
|
|
struct sc_pkcs11_card card_table[SC_MAX_READERS];
|
2002-12-21 16:45:37 +00:00
|
|
|
struct sc_pkcs11_config sc_pkcs11_conf;
|
2008-03-06 14:56:31 +00:00
|
|
|
#if !defined(_WIN32)
|
|
|
|
pid_t initialized_pid = (pid_t)-1;
|
|
|
|
#endif
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2002-04-19 14:23:31 +00:00
|
|
|
extern CK_FUNCTION_LIST pkcs11_function_list;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2006-02-01 22:59:42 +00:00
|
|
|
#if defined(HAVE_PTHREAD) && defined(PKCS11_THREAD_LOCKING)
|
|
|
|
#include <pthread.h>
|
|
|
|
CK_RV mutex_create(void **mutex)
|
|
|
|
{
|
|
|
|
pthread_mutex_t *m = (pthread_mutex_t *) malloc(sizeof(*mutex));
|
|
|
|
if (m == NULL)
|
|
|
|
return CKR_GENERAL_ERROR;;
|
|
|
|
pthread_mutex_init(m, NULL);
|
|
|
|
*mutex = m;
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV mutex_lock(void *p)
|
|
|
|
{
|
|
|
|
if (pthread_mutex_lock((pthread_mutex_t *) p) == 0)
|
|
|
|
return CKR_OK;
|
|
|
|
else
|
|
|
|
return CKR_GENERAL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV mutex_unlock(void *p)
|
|
|
|
{
|
|
|
|
if (pthread_mutex_unlock((pthread_mutex_t *) p) == 0)
|
|
|
|
return CKR_OK;
|
|
|
|
else
|
|
|
|
return CKR_GENERAL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV mutex_destroy(void *p)
|
|
|
|
{
|
|
|
|
pthread_mutex_destroy((pthread_mutex_t *) p);
|
|
|
|
free(p);
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static CK_C_INITIALIZE_ARGS _def_locks = {
|
|
|
|
mutex_create, mutex_destroy, mutex_lock, mutex_unlock, 0, NULL };
|
|
|
|
#elif defined(_WIN32) && defined (PKCS11_THREAD_LOCKING)
|
|
|
|
CK_RV mutex_create(void **mutex)
|
|
|
|
{
|
|
|
|
CRITICAL_SECTION *m;
|
|
|
|
|
2007-04-01 17:03:08 +00:00
|
|
|
m = (CRITICAL_SECTION *) malloc(sizeof(*m));
|
2006-02-01 22:59:42 +00:00
|
|
|
if (m == NULL)
|
|
|
|
return CKR_GENERAL_ERROR;
|
|
|
|
InitializeCriticalSection(m);
|
|
|
|
*mutex = m;
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV mutex_lock(void *p)
|
|
|
|
{
|
|
|
|
EnterCriticalSection((CRITICAL_SECTION *) p);
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CK_RV mutex_unlock(void *p)
|
|
|
|
{
|
|
|
|
LeaveCriticalSection((CRITICAL_SECTION *) p);
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CK_RV mutex_destroy(void *p)
|
|
|
|
{
|
|
|
|
DeleteCriticalSection((CRITICAL_SECTION *) p);
|
|
|
|
free(p);
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
static CK_C_INITIALIZE_ARGS _def_locks = {
|
|
|
|
mutex_create, mutex_destroy, mutex_lock, mutex_unlock, 0, NULL };
|
|
|
|
#endif
|
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
static CK_C_INITIALIZE_ARGS_PTR global_locking;
|
|
|
|
static void * global_lock = NULL;
|
2006-02-01 22:59:42 +00:00
|
|
|
#if (defined(HAVE_PTHREAD) || defined(_WIN32)) && defined(PKCS11_THREAD_LOCKING)
|
2006-10-02 17:26:48 +00:00
|
|
|
#define HAVE_OS_LOCKING
|
2006-02-01 22:59:42 +00:00
|
|
|
static CK_C_INITIALIZE_ARGS_PTR default_mutex_funcs = &_def_locks;
|
|
|
|
#else
|
|
|
|
static CK_C_INITIALIZE_ARGS_PTR default_mutex_funcs = NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* wrapper for the locking functions for libopensc */
|
|
|
|
static int sc_create_mutex(void **m)
|
|
|
|
{
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_locking == NULL)
|
2006-02-01 22:59:42 +00:00
|
|
|
return SC_SUCCESS;
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_locking->CreateMutex(m) == CKR_OK)
|
2006-02-01 22:59:42 +00:00
|
|
|
return SC_SUCCESS;
|
|
|
|
else
|
|
|
|
return SC_ERROR_INTERNAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sc_lock_mutex(void *m)
|
|
|
|
{
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_locking == NULL)
|
2006-02-01 22:59:42 +00:00
|
|
|
return SC_SUCCESS;
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_locking->LockMutex(m) == CKR_OK)
|
2006-02-01 22:59:42 +00:00
|
|
|
return SC_SUCCESS;
|
|
|
|
else
|
|
|
|
return SC_ERROR_INTERNAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sc_unlock_mutex(void *m)
|
|
|
|
{
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_locking == NULL)
|
2006-02-01 22:59:42 +00:00
|
|
|
return SC_SUCCESS;
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_locking->UnlockMutex(m) == CKR_OK)
|
2006-02-01 22:59:42 +00:00
|
|
|
return SC_SUCCESS;
|
|
|
|
else
|
|
|
|
return SC_ERROR_INTERNAL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-02-05 19:35:55 +00:00
|
|
|
static int sc_destroy_mutex(void *m)
|
2006-02-01 22:59:42 +00:00
|
|
|
{
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_locking == NULL)
|
2006-02-05 19:35:55 +00:00
|
|
|
return SC_SUCCESS;
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_locking->DestroyMutex(m) == CKR_OK)
|
2006-02-05 19:35:55 +00:00
|
|
|
return SC_SUCCESS;
|
|
|
|
else
|
|
|
|
return SC_ERROR_INTERNAL;
|
2006-02-01 22:59:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static sc_thread_context_t sc_thread_ctx = {
|
|
|
|
0, sc_create_mutex, sc_lock_mutex,
|
|
|
|
sc_unlock_mutex, sc_destroy_mutex, NULL
|
|
|
|
};
|
|
|
|
|
2006-10-02 17:26:48 +00:00
|
|
|
CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
|
2002-01-16 22:49:03 +00:00
|
|
|
{
|
2008-03-06 14:56:31 +00:00
|
|
|
#if !defined(_WIN32)
|
|
|
|
pid_t current_pid = getpid();
|
|
|
|
#endif
|
2003-02-17 14:21:38 +00:00
|
|
|
int i, rc, rv;
|
2006-02-01 22:59:42 +00:00
|
|
|
sc_context_param_t ctx_opts;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2008-03-06 14:56:31 +00:00
|
|
|
/* Handle fork() exception */
|
|
|
|
#if !defined(_WIN32)
|
|
|
|
if (current_pid != initialized_pid) {
|
|
|
|
C_Finalize(NULL_PTR);
|
|
|
|
}
|
|
|
|
initialized_pid = current_pid;
|
|
|
|
#endif
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
if (context != NULL) {
|
2003-08-25 14:21:18 +00:00
|
|
|
sc_error(context, "C_Initialize(): Cryptoki already initialized\n");
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_CRYPTOKI_ALREADY_INITIALIZED;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
2006-02-01 22:59:42 +00:00
|
|
|
|
2006-10-02 17:26:48 +00:00
|
|
|
rv = sc_pkcs11_init_lock((CK_C_INITIALIZE_ARGS_PTR) pInitArgs);
|
2008-03-06 15:04:29 +00:00
|
|
|
if (rv != CKR_OK)
|
|
|
|
goto out;
|
2006-02-01 22:59:42 +00:00
|
|
|
|
|
|
|
/* set context options */
|
|
|
|
memset(&ctx_opts, 0, sizeof(sc_context_param_t));
|
|
|
|
ctx_opts.ver = 0;
|
|
|
|
ctx_opts.app_name = "opensc-pkcs11";
|
|
|
|
ctx_opts.thread_ctx = &sc_thread_ctx;
|
|
|
|
|
|
|
|
rc = sc_context_create(&context, &ctx_opts);
|
|
|
|
if (rc != SC_SUCCESS) {
|
2003-02-17 14:21:38 +00:00
|
|
|
rv = CKR_DEVICE_ERROR;
|
|
|
|
goto out;
|
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2002-12-21 16:45:37 +00:00
|
|
|
/* Load configuration */
|
|
|
|
load_pkcs11_parameters(&sc_pkcs11_conf, context);
|
|
|
|
|
2003-02-14 16:59:23 +00:00
|
|
|
first_free_slot = 0;
|
2008-04-04 16:21:08 +00:00
|
|
|
virtual_slots = (struct sc_pkcs11_slot *)malloc(
|
2009-01-16 16:44:35 +00:00
|
|
|
sizeof (*virtual_slots) * sc_pkcs11_conf.max_virtual_slots
|
2008-04-04 16:21:08 +00:00
|
|
|
);
|
2008-03-06 15:04:29 +00:00
|
|
|
if (virtual_slots == NULL) {
|
|
|
|
rv = CKR_HOST_MEMORY;
|
|
|
|
goto out;
|
|
|
|
}
|
2005-02-11 20:09:34 +00:00
|
|
|
pool_initialize(&session_pool, POOL_TYPE_SESSION);
|
2009-01-16 16:44:35 +00:00
|
|
|
for (i=0; i<sc_pkcs11_conf.max_virtual_slots; i++)
|
2005-02-11 20:09:34 +00:00
|
|
|
slot_initialize(i, &virtual_slots[i]);
|
2009-01-16 16:44:35 +00:00
|
|
|
for (i=0; i<SC_MAX_READERS; i++)
|
2005-02-11 20:09:34 +00:00
|
|
|
card_initialize(i);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-03 12:20:54 +00:00
|
|
|
/* Detect any card, but do not flag "insert" events */
|
|
|
|
__card_detect_all(0);
|
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
out:
|
|
|
|
if (context != NULL)
|
2003-08-25 14:21:18 +00:00
|
|
|
sc_debug(context, "C_Initialize: result = %d\n", rv);
|
2008-03-06 15:04:29 +00:00
|
|
|
|
|
|
|
if (rv != CKR_OK) {
|
|
|
|
if (context != NULL) {
|
|
|
|
sc_release_context(context);
|
|
|
|
context = NULL;
|
|
|
|
}
|
|
|
|
/* Release and destroy the mutex */
|
|
|
|
sc_pkcs11_free_lock();
|
|
|
|
}
|
|
|
|
|
2003-02-17 14:21:38 +00:00
|
|
|
return rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV C_Finalize(CK_VOID_PTR pReserved)
|
|
|
|
{
|
|
|
|
int i;
|
2003-02-19 13:44:36 +00:00
|
|
|
CK_RV rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2008-03-06 14:56:31 +00:00
|
|
|
if (context == NULL)
|
|
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
|
|
|
2003-02-19 13:44:36 +00:00
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
|
|
|
|
2006-10-02 17:26:48 +00:00
|
|
|
if (pReserved != NULL_PTR) {
|
2003-02-23 19:38:50 +00:00
|
|
|
rv = CKR_ARGUMENTS_BAD;
|
|
|
|
goto out;
|
|
|
|
}
|
2003-02-17 14:21:38 +00:00
|
|
|
|
2003-08-25 14:21:18 +00:00
|
|
|
sc_debug(context, "Shutting down Cryptoki\n");
|
2005-09-16 10:18:55 +00:00
|
|
|
for (i=0; i < (int)sc_ctx_get_reader_count(context); i++)
|
2005-01-19 18:15:43 +00:00
|
|
|
card_removed(i);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2008-03-06 15:04:29 +00:00
|
|
|
if (virtual_slots) {
|
|
|
|
free(virtual_slots);
|
|
|
|
virtual_slots = NULL;
|
|
|
|
}
|
|
|
|
|
2002-03-24 14:12:38 +00:00
|
|
|
sc_release_context(context);
|
2002-04-05 15:02:18 +00:00
|
|
|
context = NULL;
|
2003-03-03 13:07:28 +00:00
|
|
|
|
|
|
|
out: /* Release and destroy the mutex */
|
2003-02-17 14:21:38 +00:00
|
|
|
sc_pkcs11_free_lock();
|
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
return rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV C_GetInfo(CK_INFO_PTR pInfo)
|
|
|
|
{
|
2003-02-21 15:40:06 +00:00
|
|
|
CK_RV rv = CKR_OK;
|
2003-02-19 13:44:36 +00:00
|
|
|
|
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
|
|
|
|
2003-02-19 21:10:39 +00:00
|
|
|
if (pInfo == NULL_PTR) {
|
|
|
|
rv = CKR_ARGUMENTS_BAD;
|
|
|
|
goto out;
|
|
|
|
}
|
2003-02-17 14:21:38 +00:00
|
|
|
|
2003-08-25 14:21:18 +00:00
|
|
|
sc_debug(context, "Cryptoki info query\n");
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
memset(pInfo, 0, sizeof(CK_INFO));
|
|
|
|
pInfo->cryptokiVersion.major = 2;
|
2009-01-19 12:06:38 +00:00
|
|
|
pInfo->cryptokiVersion.minor = sc_pkcs11_conf.v2_20_mode ? 20 : 11;
|
2002-01-17 12:05:44 +00:00
|
|
|
strcpy_bp(pInfo->manufacturerID,
|
2006-09-14 08:55:06 +00:00
|
|
|
"OpenSC (www.opensc-project.org)",
|
2002-01-16 22:49:03 +00:00
|
|
|
sizeof(pInfo->manufacturerID));
|
2002-01-17 12:05:44 +00:00
|
|
|
strcpy_bp(pInfo->libraryDescription,
|
2005-06-16 19:35:31 +00:00
|
|
|
"smart card PKCS#11 API",
|
2002-01-16 22:49:03 +00:00
|
|
|
sizeof(pInfo->libraryDescription));
|
2009-01-20 08:42:47 +00:00
|
|
|
pInfo->libraryVersion.major = 0;
|
|
|
|
pInfo->libraryVersion.minor = 0; /* FIXME: use 0.116 for 0.11.6 from autoconf */
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-19 21:10:39 +00:00
|
|
|
out: sc_pkcs11_unlock();
|
2005-01-19 18:15:43 +00:00
|
|
|
return rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
|
|
|
|
{
|
2003-02-19 13:44:36 +00:00
|
|
|
if (ppFunctionList == NULL_PTR)
|
|
|
|
return CKR_ARGUMENTS_BAD;
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
*ppFunctionList = &pkcs11_function_list;
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token present */
|
|
|
|
CK_SLOT_ID_PTR pSlotList, /* receives the array of slot IDs */
|
|
|
|
CK_ULONG_PTR pulCount) /* receives the number of slots */
|
|
|
|
{
|
2008-04-04 16:21:08 +00:00
|
|
|
CK_SLOT_ID_PTR found = NULL;
|
2005-01-19 18:15:43 +00:00
|
|
|
int i;
|
2004-12-22 10:17:00 +00:00
|
|
|
CK_ULONG numMatches;
|
2003-01-03 11:40:11 +00:00
|
|
|
sc_pkcs11_slot_t *slot;
|
2003-02-17 14:21:38 +00:00
|
|
|
CK_RV rv;
|
|
|
|
|
2008-04-04 16:21:08 +00:00
|
|
|
if ((rv = sc_pkcs11_lock()) != CKR_OK) {
|
2003-02-19 13:44:36 +00:00
|
|
|
return rv;
|
2008-04-04 16:21:08 +00:00
|
|
|
}
|
2003-02-19 13:44:36 +00:00
|
|
|
|
2003-02-19 21:10:39 +00:00
|
|
|
if (pulCount == NULL_PTR) {
|
|
|
|
rv = CKR_ARGUMENTS_BAD;
|
|
|
|
goto out;
|
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2008-04-04 16:21:08 +00:00
|
|
|
if (
|
|
|
|
(found = (CK_SLOT_ID_PTR)malloc (
|
2009-01-16 16:44:35 +00:00
|
|
|
sizeof (*found) * sc_pkcs11_conf.max_virtual_slots
|
2008-04-04 16:21:08 +00:00
|
|
|
)) == NULL
|
|
|
|
) {
|
|
|
|
rv = CKR_HOST_MEMORY;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2003-08-25 14:21:18 +00:00
|
|
|
sc_debug(context, "Getting slot listing\n");
|
2009-01-19 12:06:38 +00:00
|
|
|
/* Slot list can only change in v2.20 */
|
|
|
|
if (pSlotList == NULL_PTR && sc_pkcs11_conf.v2_20_mode) {
|
2008-04-29 17:01:19 +00:00
|
|
|
sc_ctx_detect_readers(context);
|
|
|
|
}
|
2003-01-20 09:50:33 +00:00
|
|
|
card_detect_all();
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2002-12-22 11:50:41 +00:00
|
|
|
numMatches = 0;
|
2009-01-16 16:44:35 +00:00
|
|
|
for (i=0; i<sc_pkcs11_conf.max_virtual_slots; i++) {
|
2003-01-03 11:40:11 +00:00
|
|
|
slot = &virtual_slots[i];
|
|
|
|
|
2003-01-13 21:38:43 +00:00
|
|
|
if (!tokenPresent || (slot->slot_info.flags & CKF_TOKEN_PRESENT))
|
|
|
|
found[numMatches++] = i;
|
2003-01-03 11:40:11 +00:00
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
if (pSlotList == NULL_PTR) {
|
2003-08-25 14:21:18 +00:00
|
|
|
sc_debug(context, "was only a size inquiry (%d)\n", numMatches);
|
2002-01-16 22:49:03 +00:00
|
|
|
*pulCount = numMatches;
|
2005-01-19 18:15:43 +00:00
|
|
|
rv = CKR_OK;
|
2003-02-17 14:21:38 +00:00
|
|
|
goto out;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (*pulCount < numMatches) {
|
2003-08-25 14:21:18 +00:00
|
|
|
sc_debug(context, "buffer was too small (needed %d)\n", numMatches);
|
2002-01-16 22:49:03 +00:00
|
|
|
*pulCount = numMatches;
|
2005-01-19 18:15:43 +00:00
|
|
|
rv = CKR_BUFFER_TOO_SMALL;
|
2003-02-17 14:21:38 +00:00
|
|
|
goto out;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2003-01-03 11:40:11 +00:00
|
|
|
memcpy(pSlotList, found, numMatches * sizeof(CK_SLOT_ID));
|
2002-01-16 22:49:03 +00:00
|
|
|
*pulCount = numMatches;
|
2003-02-17 14:21:38 +00:00
|
|
|
rv = CKR_OK;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-08-25 14:21:18 +00:00
|
|
|
sc_debug(context, "returned %d slots\n", numMatches);
|
2003-02-17 14:21:38 +00:00
|
|
|
|
2008-04-04 16:21:08 +00:00
|
|
|
out:
|
|
|
|
if (found != NULL) {
|
|
|
|
free (found);
|
|
|
|
found = NULL;
|
|
|
|
}
|
|
|
|
sc_pkcs11_unlock();
|
2005-01-19 18:15:43 +00:00
|
|
|
return rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2006-02-01 22:59:42 +00:00
|
|
|
static sc_timestamp_t get_current_time(void)
|
|
|
|
{
|
2008-03-06 16:06:59 +00:00
|
|
|
#if HAVE_GETTIMEOFDAY
|
2006-02-01 22:59:42 +00:00
|
|
|
struct timeval tv;
|
|
|
|
struct timezone tz;
|
|
|
|
sc_timestamp_t curr;
|
|
|
|
|
|
|
|
if (gettimeofday(&tv, &tz) != 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
curr = tv.tv_sec;
|
|
|
|
curr *= 1000;
|
|
|
|
curr += tv.tv_usec / 1000;
|
|
|
|
#else
|
|
|
|
struct _timeb time_buf;
|
2006-02-23 11:02:24 +00:00
|
|
|
sc_timestamp_t curr;
|
2006-02-01 22:59:42 +00:00
|
|
|
|
|
|
|
_ftime(&time_buf);
|
|
|
|
|
|
|
|
curr = time_buf.time;
|
|
|
|
curr *= 1000;
|
|
|
|
curr += time_buf.millitm;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return curr;
|
|
|
|
}
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
|
|
|
|
{
|
|
|
|
struct sc_pkcs11_slot *slot;
|
2003-08-18 14:54:37 +00:00
|
|
|
sc_timestamp_t now;
|
2005-01-19 18:15:43 +00:00
|
|
|
CK_RV rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-19 13:44:36 +00:00
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
|
|
|
|
2003-02-19 21:10:39 +00:00
|
|
|
if (pInfo == NULL_PTR) {
|
|
|
|
rv = CKR_ARGUMENTS_BAD;
|
|
|
|
goto out;
|
|
|
|
}
|
2003-02-17 14:21:38 +00:00
|
|
|
|
2003-08-25 14:21:18 +00:00
|
|
|
sc_debug(context, "Getting info about slot %d\n", slotID);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-17 14:21:38 +00:00
|
|
|
rv = slot_get_slot(slotID, &slot);
|
2003-04-02 06:59:19 +00:00
|
|
|
if (rv == CKR_OK){
|
2006-02-01 22:59:42 +00:00
|
|
|
now = get_current_time();
|
2003-04-18 11:58:11 +00:00
|
|
|
if (now >= card_table[slot->reader].slot_state_expires || now == 0) {
|
2003-04-02 06:59:19 +00:00
|
|
|
/* Update slot status */
|
|
|
|
rv = card_detect(slot->reader);
|
2005-02-11 20:09:34 +00:00
|
|
|
/* Don't ask again within the next second */
|
2003-04-18 11:58:11 +00:00
|
|
|
card_table[slot->reader].slot_state_expires = now + 1000;
|
2003-04-02 06:59:19 +00:00
|
|
|
}
|
|
|
|
}
|
2003-04-11 14:22:52 +00:00
|
|
|
if (rv == CKR_TOKEN_NOT_PRESENT || rv == CKR_TOKEN_NOT_RECOGNIZED)
|
2003-02-23 19:38:50 +00:00
|
|
|
rv = CKR_OK;
|
2002-01-22 14:44:56 +00:00
|
|
|
|
2003-02-17 14:21:38 +00:00
|
|
|
if (rv == CKR_OK)
|
|
|
|
memcpy(pInfo, &slot->slot_info, sizeof(CK_SLOT_INFO));
|
|
|
|
|
2003-02-19 21:10:39 +00:00
|
|
|
out: sc_pkcs11_unlock();
|
2003-02-17 14:21:38 +00:00
|
|
|
return rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
|
|
|
|
{
|
|
|
|
struct sc_pkcs11_slot *slot;
|
2005-01-19 18:15:43 +00:00
|
|
|
CK_RV rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-19 13:44:36 +00:00
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
|
|
|
|
2003-02-19 21:10:39 +00:00
|
|
|
if (pInfo == NULL_PTR) {
|
|
|
|
rv = CKR_ARGUMENTS_BAD;
|
|
|
|
goto out;
|
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-08-25 14:21:18 +00:00
|
|
|
sc_debug(context, "Getting info about token in slot %d\n", slotID);
|
2003-02-17 14:21:38 +00:00
|
|
|
|
|
|
|
rv = slot_get_token(slotID, &slot);
|
|
|
|
if (rv == CKR_OK)
|
|
|
|
memcpy(pInfo, &slot->token_info, sizeof(CK_TOKEN_INFO));
|
|
|
|
|
2003-02-19 21:10:39 +00:00
|
|
|
out: sc_pkcs11_unlock();
|
2003-02-17 14:21:38 +00:00
|
|
|
return rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV C_GetMechanismList(CK_SLOT_ID slotID,
|
|
|
|
CK_MECHANISM_TYPE_PTR pMechanismList,
|
|
|
|
CK_ULONG_PTR pulCount)
|
|
|
|
{
|
|
|
|
struct sc_pkcs11_slot *slot;
|
2005-01-19 18:15:43 +00:00
|
|
|
CK_RV rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-19 13:44:36 +00:00
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
2003-02-17 14:21:38 +00:00
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
rv = slot_get_token(slotID, &slot);
|
2003-02-17 14:21:38 +00:00
|
|
|
if (rv == CKR_OK)
|
|
|
|
rv = sc_pkcs11_get_mechanism_list(slot->card, pMechanismList, pulCount);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-17 14:21:38 +00:00
|
|
|
sc_pkcs11_unlock();
|
|
|
|
return rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
|
|
|
|
CK_MECHANISM_TYPE type,
|
|
|
|
CK_MECHANISM_INFO_PTR pInfo)
|
|
|
|
{
|
|
|
|
struct sc_pkcs11_slot *slot;
|
2005-01-19 18:15:43 +00:00
|
|
|
CK_RV rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-19 13:44:36 +00:00
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
|
|
|
|
2003-02-19 21:10:39 +00:00
|
|
|
if (pInfo == NULL_PTR) {
|
|
|
|
rv = CKR_ARGUMENTS_BAD;
|
|
|
|
goto out;
|
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
rv = slot_get_token(slotID, &slot);
|
2003-02-17 14:21:38 +00:00
|
|
|
if (rv == CKR_OK)
|
|
|
|
rv = sc_pkcs11_get_mechanism_info(slot->card, type, pInfo);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-19 21:10:39 +00:00
|
|
|
out: sc_pkcs11_unlock();
|
2003-02-17 14:21:38 +00:00
|
|
|
return rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV C_InitToken(CK_SLOT_ID slotID,
|
|
|
|
CK_CHAR_PTR pPin,
|
|
|
|
CK_ULONG ulPinLen,
|
|
|
|
CK_CHAR_PTR pLabel)
|
|
|
|
{
|
2002-04-05 15:02:18 +00:00
|
|
|
struct sc_pkcs11_pool_item *item;
|
|
|
|
struct sc_pkcs11_session *session;
|
|
|
|
struct sc_pkcs11_slot *slot;
|
2005-01-19 18:15:43 +00:00
|
|
|
CK_RV rv;
|
2002-04-05 15:02:18 +00:00
|
|
|
|
2003-02-19 13:44:36 +00:00
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
2003-02-17 14:21:38 +00:00
|
|
|
|
2002-04-05 15:02:18 +00:00
|
|
|
rv = slot_get_token(slotID, &slot);
|
|
|
|
if (rv != CKR_OK)
|
2003-02-17 14:21:38 +00:00
|
|
|
goto out;
|
2002-04-05 15:02:18 +00:00
|
|
|
|
|
|
|
/* Make sure there's no open session for this token */
|
|
|
|
for (item = session_pool.head; item; item = item->next) {
|
|
|
|
session = (struct sc_pkcs11_session*) item->item;
|
2003-02-17 14:21:38 +00:00
|
|
|
if (session->slot == slot) {
|
|
|
|
rv = CKR_SESSION_EXISTS;
|
|
|
|
goto out;
|
|
|
|
}
|
2002-04-05 15:02:18 +00:00
|
|
|
}
|
|
|
|
|
2003-02-23 19:38:50 +00:00
|
|
|
if (slot->card->framework->init_token == NULL) {
|
|
|
|
rv = CKR_FUNCTION_NOT_SUPPORTED;
|
|
|
|
goto out;
|
|
|
|
}
|
2002-04-08 15:51:19 +00:00
|
|
|
rv = slot->card->framework->init_token(slot->card,
|
2002-04-05 15:02:18 +00:00
|
|
|
slot->fw_data, pPin, ulPinLen, pLabel);
|
|
|
|
|
2003-02-17 14:21:38 +00:00
|
|
|
if (rv == CKR_OK) {
|
|
|
|
/* Now we should re-bind all tokens so they get the
|
|
|
|
* corresponding function vector and flags */
|
|
|
|
}
|
2002-04-05 15:02:18 +00:00
|
|
|
|
2003-02-17 14:21:38 +00:00
|
|
|
out: sc_pkcs11_unlock();
|
|
|
|
return rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV C_WaitForSlotEvent(CK_FLAGS flags, /* blocking/nonblocking flag */
|
|
|
|
CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
|
|
|
|
CK_VOID_PTR pReserved) /* reserved. Should be NULL_PTR */
|
|
|
|
{
|
2005-03-09 00:04:44 +00:00
|
|
|
sc_reader_t *reader, *readers[SC_MAX_SLOTS * SC_MAX_READERS];
|
2003-02-03 12:20:54 +00:00
|
|
|
int slots[SC_MAX_SLOTS * SC_MAX_READERS];
|
|
|
|
int i, j, k, r, found;
|
|
|
|
unsigned int mask, events;
|
|
|
|
CK_RV rv;
|
|
|
|
|
2006-10-02 17:26:48 +00:00
|
|
|
/* Firefox 1.5 (NSS 3.10) calls this function (blocking) from a seperate thread,
|
2005-12-23 10:15:17 +00:00
|
|
|
* which gives 2 problems:
|
|
|
|
* - on Windows/Mac: this waiting thread will log to a NULL context
|
|
|
|
* after the 'main' thread does a C_Finalize() and sets the ctx to NULL.
|
|
|
|
* - on Linux, things just hang (at least on Debian 'sid')
|
|
|
|
* So we just return CKR_FUNCTION_NOT_SUPPORTED on a blocking call,
|
2006-10-02 17:26:48 +00:00
|
|
|
* in which case FF just seems to default to polling in the main thread
|
|
|
|
* as earlier NSS versions.
|
2005-12-23 10:15:17 +00:00
|
|
|
*/
|
|
|
|
if (!(flags & CKF_DONT_BLOCK))
|
|
|
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
|
|
|
|
2003-02-19 13:44:36 +00:00
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
2003-02-17 14:21:38 +00:00
|
|
|
|
2003-02-19 21:10:39 +00:00
|
|
|
if (pReserved != NULL_PTR) {
|
|
|
|
rv = CKR_ARGUMENTS_BAD;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2003-02-03 12:20:54 +00:00
|
|
|
mask = SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED;
|
|
|
|
|
|
|
|
if ((rv = slot_find_changed(pSlot, mask)) == CKR_OK
|
|
|
|
|| (flags & CKF_DONT_BLOCK))
|
2003-02-17 14:21:38 +00:00
|
|
|
goto out;
|
2003-02-03 12:20:54 +00:00
|
|
|
|
2005-09-16 10:18:55 +00:00
|
|
|
for (i = k = 0; i < (int)sc_ctx_get_reader_count(context); i++) {
|
|
|
|
reader = sc_ctx_get_reader(context, i);
|
|
|
|
if (reader == NULL) {
|
|
|
|
rv = CKR_GENERAL_ERROR;
|
|
|
|
goto out;
|
|
|
|
}
|
2003-02-03 12:20:54 +00:00
|
|
|
for (j = 0; j < reader->slot_count; j++, k++) {
|
|
|
|
readers[k] = reader;
|
|
|
|
slots[k] = j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-04-11 14:22:52 +00:00
|
|
|
again:
|
2005-12-08 20:25:54 +00:00
|
|
|
/* Check if C_Finalize() has been called in another thread */
|
|
|
|
if (context == NULL)
|
|
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
|
|
|
2003-02-17 14:21:38 +00:00
|
|
|
sc_pkcs11_unlock();
|
2003-02-03 12:20:54 +00:00
|
|
|
r = sc_wait_for_event(readers, slots, k, mask, &found, &events, -1);
|
2003-03-03 13:07:28 +00:00
|
|
|
|
|
|
|
/* There may have been a C_Finalize while we slept */
|
2005-12-08 20:25:54 +00:00
|
|
|
if (context == NULL)
|
|
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
2003-03-03 13:07:28 +00:00
|
|
|
if ((rv = sc_pkcs11_lock()) != CKR_OK)
|
|
|
|
return rv;
|
2003-02-17 14:21:38 +00:00
|
|
|
|
2003-02-03 12:20:54 +00:00
|
|
|
if (r != SC_SUCCESS) {
|
2003-08-25 14:21:18 +00:00
|
|
|
sc_error(context, "sc_wait_for_event() returned %d\n", r);
|
2003-02-17 14:21:38 +00:00
|
|
|
rv = sc_to_cryptoki_error(r, -1);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2003-04-11 14:22:52 +00:00
|
|
|
/* If no changed slot was found (maybe an unsupported card
|
|
|
|
* was inserted/removed) then go waiting again */
|
2003-02-17 14:21:38 +00:00
|
|
|
if ((rv = slot_find_changed(pSlot, mask)) != CKR_OK)
|
2003-04-11 14:22:52 +00:00
|
|
|
goto again;
|
2003-02-17 14:21:38 +00:00
|
|
|
|
|
|
|
out: sc_pkcs11_unlock();
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Locking functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
CK_RV
|
|
|
|
sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR args)
|
|
|
|
{
|
|
|
|
int rv = CKR_OK;
|
|
|
|
|
2006-10-02 17:26:48 +00:00
|
|
|
int applock = 0;
|
|
|
|
int oslock = 0;
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_lock)
|
2003-02-17 14:21:38 +00:00
|
|
|
return CKR_OK;
|
|
|
|
|
|
|
|
/* No CK_C_INITIALIZE_ARGS pointer, no locking */
|
|
|
|
if (!args)
|
|
|
|
return CKR_OK;
|
|
|
|
|
2006-10-02 17:26:48 +00:00
|
|
|
if (args->pReserved != NULL_PTR)
|
2003-02-17 14:21:38 +00:00
|
|
|
return CKR_ARGUMENTS_BAD;
|
|
|
|
|
|
|
|
/* If the app tells us OS locking is okay,
|
|
|
|
* use that. Otherwise use the supplied functions.
|
|
|
|
*/
|
2008-03-06 16:06:59 +00:00
|
|
|
global_locking = NULL;
|
2006-10-02 17:26:48 +00:00
|
|
|
if (args->CreateMutex && args->DestroyMutex &&
|
2006-02-01 22:59:42 +00:00
|
|
|
args->LockMutex && args->UnlockMutex) {
|
2006-10-02 17:26:48 +00:00
|
|
|
applock = 1;
|
|
|
|
}
|
|
|
|
if ((args->flags & CKF_OS_LOCKING_OK)) {
|
|
|
|
oslock = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Based on PKCS#11 v2.11 11.4 */
|
|
|
|
if (applock && oslock) {
|
|
|
|
/* Shall be used in threaded environment, prefer app provided locking */
|
2008-03-06 16:06:59 +00:00
|
|
|
global_locking = args;
|
2006-10-02 17:26:48 +00:00
|
|
|
} else if (!applock && oslock) {
|
|
|
|
/* Shall be used in threaded environment, must use operating system locking */
|
2008-03-06 16:06:59 +00:00
|
|
|
global_locking = default_mutex_funcs;
|
2006-10-02 17:26:48 +00:00
|
|
|
} else if (applock && !oslock) {
|
|
|
|
/* Shall be used in threaded envirnoment, must use app provided locking */
|
2008-03-06 16:06:59 +00:00
|
|
|
global_locking = args;
|
2006-10-02 17:26:48 +00:00
|
|
|
} else if (!applock && !oslock) {
|
2009-01-19 12:06:38 +00:00
|
|
|
/* Shall not be used in threaded environment, use operating system locking */
|
2008-03-06 16:06:59 +00:00
|
|
|
global_locking = default_mutex_funcs;
|
2006-02-01 22:59:42 +00:00
|
|
|
}
|
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_locking != NULL) {
|
2006-02-01 22:59:42 +00:00
|
|
|
/* create mutex */
|
2008-03-06 16:06:59 +00:00
|
|
|
rv = global_locking->CreateMutex(&global_lock);
|
2003-02-03 12:20:54 +00:00
|
|
|
}
|
|
|
|
|
2003-02-17 14:21:38 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2007-06-21 12:01:39 +00:00
|
|
|
CK_RV sc_pkcs11_lock(void)
|
2003-02-17 14:21:38 +00:00
|
|
|
{
|
2003-02-19 13:44:36 +00:00
|
|
|
if (context == NULL)
|
|
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
if (!global_lock)
|
2003-02-19 13:44:36 +00:00
|
|
|
return CKR_OK;
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_locking) {
|
|
|
|
while (global_locking->LockMutex(global_lock) != CKR_OK)
|
2003-02-17 14:21:38 +00:00
|
|
|
;
|
2006-02-01 22:59:42 +00:00
|
|
|
}
|
2003-02-19 13:44:36 +00:00
|
|
|
|
|
|
|
return CKR_OK;
|
2003-02-17 14:21:38 +00:00
|
|
|
}
|
2003-02-03 12:20:54 +00:00
|
|
|
|
2003-03-03 13:07:28 +00:00
|
|
|
static void
|
|
|
|
__sc_pkcs11_unlock(void *lock)
|
2003-02-17 14:21:38 +00:00
|
|
|
{
|
2003-03-03 13:07:28 +00:00
|
|
|
if (!lock)
|
2003-02-17 14:21:38 +00:00
|
|
|
return;
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_locking) {
|
|
|
|
while (global_locking->UnlockMutex(lock) != CKR_OK)
|
2003-02-17 14:21:38 +00:00
|
|
|
;
|
2006-02-01 22:59:42 +00:00
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2007-06-21 12:01:39 +00:00
|
|
|
void sc_pkcs11_unlock(void)
|
2003-03-03 13:07:28 +00:00
|
|
|
{
|
2008-03-06 16:06:59 +00:00
|
|
|
__sc_pkcs11_unlock(global_lock);
|
2003-03-03 13:07:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Free the lock - note the lock must be held when
|
|
|
|
* you come here
|
|
|
|
*/
|
2007-06-21 12:01:39 +00:00
|
|
|
void sc_pkcs11_free_lock(void)
|
2003-03-03 13:07:28 +00:00
|
|
|
{
|
|
|
|
void *tempLock;
|
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
if (!(tempLock = global_lock))
|
2003-03-03 13:07:28 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* Clear the global lock pointer - once we've
|
|
|
|
* unlocked the mutex it's as good as gone */
|
2008-03-06 16:06:59 +00:00
|
|
|
global_lock = NULL;
|
2003-03-03 13:07:28 +00:00
|
|
|
|
|
|
|
/* Now unlock. On SMP machines the synchronization
|
2005-02-11 20:09:34 +00:00
|
|
|
* primitives should take care of flushing out
|
2003-03-03 13:07:28 +00:00
|
|
|
* all changed data to RAM */
|
|
|
|
__sc_pkcs11_unlock(tempLock);
|
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
if (global_locking)
|
|
|
|
global_locking->DestroyMutex(tempLock);
|
|
|
|
global_locking = NULL;
|
2003-03-03 13:07:28 +00:00
|
|
|
}
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
CK_FUNCTION_LIST pkcs11_function_list = {
|
2009-01-19 12:06:38 +00:00
|
|
|
{ 2, 11 }, /* Note: NSS/Firefox ignores this version number and uses C_GetInfo() */
|
2002-01-16 22:49:03 +00:00
|
|
|
C_Initialize,
|
|
|
|
C_Finalize,
|
|
|
|
C_GetInfo,
|
|
|
|
C_GetFunctionList,
|
|
|
|
C_GetSlotList,
|
|
|
|
C_GetSlotInfo,
|
|
|
|
C_GetTokenInfo,
|
|
|
|
C_GetMechanismList,
|
|
|
|
C_GetMechanismInfo,
|
|
|
|
C_InitToken,
|
|
|
|
C_InitPIN,
|
|
|
|
C_SetPIN,
|
|
|
|
C_OpenSession,
|
|
|
|
C_CloseSession,
|
|
|
|
C_CloseAllSessions,
|
|
|
|
C_GetSessionInfo,
|
|
|
|
C_GetOperationState,
|
|
|
|
C_SetOperationState,
|
|
|
|
C_Login,
|
|
|
|
C_Logout,
|
|
|
|
C_CreateObject,
|
|
|
|
C_CopyObject,
|
|
|
|
C_DestroyObject,
|
|
|
|
C_GetObjectSize,
|
|
|
|
C_GetAttributeValue,
|
|
|
|
C_SetAttributeValue,
|
|
|
|
C_FindObjectsInit,
|
|
|
|
C_FindObjects,
|
|
|
|
C_FindObjectsFinal,
|
|
|
|
C_EncryptInit,
|
|
|
|
C_Encrypt,
|
|
|
|
C_EncryptUpdate,
|
|
|
|
C_EncryptFinal,
|
|
|
|
C_DecryptInit,
|
|
|
|
C_Decrypt,
|
|
|
|
C_DecryptUpdate,
|
|
|
|
C_DecryptFinal,
|
2005-01-19 18:15:43 +00:00
|
|
|
C_DigestInit,
|
2002-01-16 22:49:03 +00:00
|
|
|
C_Digest,
|
|
|
|
C_DigestUpdate,
|
|
|
|
C_DigestKey,
|
|
|
|
C_DigestFinal,
|
|
|
|
C_SignInit,
|
|
|
|
C_Sign,
|
|
|
|
C_SignUpdate,
|
|
|
|
C_SignFinal,
|
|
|
|
C_SignRecoverInit,
|
|
|
|
C_SignRecover,
|
|
|
|
C_VerifyInit,
|
|
|
|
C_Verify,
|
|
|
|
C_VerifyUpdate,
|
|
|
|
C_VerifyFinal,
|
|
|
|
C_VerifyRecoverInit,
|
|
|
|
C_VerifyRecover,
|
|
|
|
C_DigestEncryptUpdate,
|
|
|
|
C_DecryptDigestUpdate,
|
|
|
|
C_SignEncryptUpdate,
|
|
|
|
C_DecryptVerifyUpdate,
|
|
|
|
C_GenerateKey,
|
|
|
|
C_GenerateKeyPair,
|
|
|
|
C_WrapKey,
|
|
|
|
C_UnwrapKey,
|
|
|
|
C_DeriveKey,
|
|
|
|
C_SeedRandom,
|
|
|
|
C_GenerateRandom,
|
|
|
|
C_GetFunctionStatus,
|
2005-01-19 18:15:43 +00:00
|
|
|
C_CancelFunction,
|
2002-01-16 22:49:03 +00:00
|
|
|
C_WaitForSlotEvent
|
|
|
|
};
|