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
|
|
|
|
*/
|
|
|
|
|
2010-03-04 08:14:36 +00:00
|
|
|
#include "config.h"
|
2006-02-01 22:59:42 +00:00
|
|
|
|
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
|
2010-03-04 08:14:36 +00:00
|
|
|
|
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-12-21 16:45:37 +00:00
|
|
|
struct sc_pkcs11_config sc_pkcs11_conf;
|
2010-01-24 20:45:02 +00:00
|
|
|
list_t sessions;
|
|
|
|
list_t virtual_slots;
|
2008-03-06 14:56:31 +00:00
|
|
|
#if !defined(_WIN32)
|
|
|
|
pid_t initialized_pid = (pid_t)-1;
|
|
|
|
#endif
|
2010-01-24 20:45:02 +00:00
|
|
|
static int in_finalize = 0;
|
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)
|
|
|
|
{
|
Do not cast the return value of malloc(3) and calloc(3)
From http://en.wikipedia.org/wiki/Malloc#Casting_and_type_safety
" Casting and type safety
malloc returns a void pointer (void *), which indicates that it is a
pointer to a region of unknown data type. One may "cast" (see type
conversion) this pointer to a specific type, as in
int *ptr = (int*)malloc(10 * sizeof (int));
When using C, this is considered bad practice; it is redundant under the
C standard. Moreover, putting in a cast may mask failure to include the
header stdlib.h, in which the prototype for malloc is found. In the
absence of a prototype for malloc, the C compiler will assume that
malloc returns an int, and will issue a warning in a context such as the
above, provided the error is not masked by a cast. On certain
architectures and data models (such as LP64 on 64 bit systems, where
long and pointers are 64 bit and int is 32 bit), this error can actually
result in undefined behavior, as the implicitly declared malloc returns
a 32 bit value whereas the actually defined function returns a 64 bit
value. Depending on calling conventions and memory layout, this may
result in stack smashing.
The returned pointer need not be explicitly cast to a more specific
pointer type, since ANSI C defines an implicit conversion between the
void pointer type and other pointers to objects. An explicit cast of
malloc's return value is sometimes performed because malloc originally
returned a char *, but this cast is unnecessary in standard C
code.[4][5] Omitting the cast, however, creates an incompatibility with
C++, which does require it.
The lack of a specific pointer type returned from malloc is type-unsafe
behaviour: malloc allocates based on byte count but not on type. This
distinguishes it from the C++ new operator that returns a pointer whose
type relies on the operand. (see C Type Safety). "
See also
http://www.opensc-project.org/pipermail/opensc-devel/2010-August/014586.html
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4636 c6295689-39f2-0310-b995-f0e70906c6a9
2010-08-18 15:08:51 +00:00
|
|
|
pthread_mutex_t *m = malloc(sizeof(*mutex));
|
2006-02-01 22:59:42 +00:00
|
|
|
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;
|
|
|
|
|
Do not cast the return value of malloc(3) and calloc(3)
From http://en.wikipedia.org/wiki/Malloc#Casting_and_type_safety
" Casting and type safety
malloc returns a void pointer (void *), which indicates that it is a
pointer to a region of unknown data type. One may "cast" (see type
conversion) this pointer to a specific type, as in
int *ptr = (int*)malloc(10 * sizeof (int));
When using C, this is considered bad practice; it is redundant under the
C standard. Moreover, putting in a cast may mask failure to include the
header stdlib.h, in which the prototype for malloc is found. In the
absence of a prototype for malloc, the C compiler will assume that
malloc returns an int, and will issue a warning in a context such as the
above, provided the error is not masked by a cast. On certain
architectures and data models (such as LP64 on 64 bit systems, where
long and pointers are 64 bit and int is 32 bit), this error can actually
result in undefined behavior, as the implicitly declared malloc returns
a 32 bit value whereas the actually defined function returns a 64 bit
value. Depending on calling conventions and memory layout, this may
result in stack smashing.
The returned pointer need not be explicitly cast to a more specific
pointer type, since ANSI C defines an implicit conversion between the
void pointer type and other pointers to objects. An explicit cast of
malloc's return value is sometimes performed because malloc originally
returned a char *, but this cast is unnecessary in standard C
code.[4][5] Omitting the cast, however, creates an incompatibility with
C++, which does require it.
The lack of a specific pointer type returned from malloc is type-unsafe
behaviour: malloc allocates based on byte count but not on type. This
distinguishes it from the C++ new operator that returns a pointer whose
type relies on the operand. (see C Type Safety). "
See also
http://www.opensc-project.org/pipermail/opensc-devel/2010-August/014586.html
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4636 c6295689-39f2-0310-b995-f0e70906c6a9
2010-08-18 15:08:51 +00:00
|
|
|
m = 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
|
|
|
|
};
|
|
|
|
|
2010-01-24 20:45:02 +00:00
|
|
|
/* simclist helpers to locate interesting objects by ID */
|
|
|
|
static int session_list_seeker(const void *el, const void *key) {
|
|
|
|
const struct sc_pkcs11_session *session = (struct sc_pkcs11_session *)el;
|
|
|
|
if ((el == NULL) || (key == NULL))
|
|
|
|
return 0;
|
|
|
|
if (session->handle == *(CK_SESSION_HANDLE*)key)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
static int slot_list_seeker(const void *el, const void *key) {
|
|
|
|
const struct sc_pkcs11_slot *slot = (struct sc_pkcs11_slot *)el;
|
|
|
|
if ((el == NULL) || (key == NULL))
|
|
|
|
return 0;
|
|
|
|
if (slot->id == *(CK_SLOT_ID *)key)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-10-02 17:26:48 +00:00
|
|
|
CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
|
2002-01-16 22:49:03 +00:00
|
|
|
{
|
2010-06-16 11:43:10 +00:00
|
|
|
CK_RV rv;
|
2008-03-06 14:56:31 +00:00
|
|
|
#if !defined(_WIN32)
|
|
|
|
pid_t current_pid = getpid();
|
|
|
|
#endif
|
2010-06-16 11:43:10 +00:00
|
|
|
int rc;
|
2009-10-22 09:18:16 +00:00
|
|
|
unsigned int i;
|
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;
|
2010-01-24 20:45:02 +00:00
|
|
|
in_finalize = 0;
|
2008-03-06 14:56:31 +00:00
|
|
|
#endif
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
if (context != NULL) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "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) {
|
2009-09-14 08:59:58 +00:00
|
|
|
rv = CKR_GENERAL_ERROR;
|
2003-02-17 14:21:38 +00:00
|
|
|
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);
|
|
|
|
|
2010-01-24 20:45:02 +00:00
|
|
|
/* List of sessions */
|
|
|
|
list_init(&sessions);
|
|
|
|
list_attributes_seeker(&sessions, session_list_seeker);
|
|
|
|
|
|
|
|
/* List of slots */
|
|
|
|
list_init(&virtual_slots);
|
|
|
|
list_attributes_seeker(&virtual_slots, slot_list_seeker);
|
|
|
|
|
|
|
|
/* Create a slot for a future "PnP" stuff. */
|
|
|
|
if (sc_pkcs11_conf.plug_and_play) {
|
|
|
|
create_slot(NULL);
|
|
|
|
}
|
|
|
|
/* Create slots for readers found on initialization */
|
|
|
|
for (i=0; i<sc_ctx_get_reader_count(context); i++) {
|
|
|
|
initialize_reader(sc_ctx_get_reader(context, i));
|
2008-03-06 15:04:29 +00:00
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2010-01-24 20:45:02 +00:00
|
|
|
/* Set initial event state on slots */
|
|
|
|
for (i=0; i<list_size(&virtual_slots); i++) {
|
|
|
|
sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
|
|
|
|
slot->events = 0; /* Initially there are no events */
|
|
|
|
}
|
2003-02-03 12:20:54 +00:00
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
out:
|
|
|
|
if (context != NULL)
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_Initialize() = %s", lookup_enum ( RV_T, 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;
|
2010-05-30 07:31:31 +00:00
|
|
|
void *p;
|
|
|
|
sc_pkcs11_slot_t *slot;
|
2003-02-19 13:44:36 +00:00
|
|
|
CK_RV rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2010-08-23 14:47:14 +00:00
|
|
|
if (pReserved != NULL_PTR)
|
|
|
|
return CKR_ARGUMENTS_BAD;
|
|
|
|
|
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;
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_Finalize()");
|
2010-01-24 20:45:02 +00:00
|
|
|
|
|
|
|
/* cancel pending calls */
|
|
|
|
in_finalize = 1;
|
2010-10-28 09:44:22 +00:00
|
|
|
#ifdef PCSC_CANCEL_OK
|
2010-01-24 20:45:02 +00:00
|
|
|
sc_cancel(context);
|
2010-10-28 09:44:22 +00:00
|
|
|
#endif
|
2010-01-24 20:45:02 +00:00
|
|
|
/* remove all cards from readers */
|
2005-09-16 10:18:55 +00:00
|
|
|
for (i=0; i < (int)sc_ctx_get_reader_count(context); i++)
|
2010-01-24 20:45:02 +00:00
|
|
|
card_removed(sc_ctx_get_reader(context, i));
|
2008-03-06 15:04:29 +00:00
|
|
|
|
2010-05-30 07:31:31 +00:00
|
|
|
while ((p = list_fetch(&sessions)))
|
|
|
|
free(p);
|
2010-01-24 20:45:02 +00:00
|
|
|
list_destroy(&sessions);
|
2010-05-30 07:31:31 +00:00
|
|
|
|
|
|
|
while ((slot = list_fetch(&virtual_slots))) {
|
|
|
|
list_destroy(&slot->objects);
|
|
|
|
free(slot);
|
|
|
|
}
|
2010-01-24 20:45:02 +00:00
|
|
|
list_destroy(&virtual_slots);
|
2010-05-30 07:31:31 +00:00
|
|
|
|
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
|
|
|
|
2010-08-23 14:47:14 +00:00
|
|
|
/* 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
|
|
|
|
2010-08-23 14:47:14 +00:00
|
|
|
if (pInfo == NULL_PTR)
|
|
|
|
return CKR_ARGUMENTS_BAD;
|
|
|
|
|
2003-02-19 13:44:36 +00:00
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_GetInfo()");
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
memset(pInfo, 0, sizeof(CK_INFO));
|
|
|
|
pInfo->cryptokiVersion.major = 2;
|
2009-01-23 09:14:15 +00:00
|
|
|
pInfo->cryptokiVersion.minor = 20;
|
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,
|
2010-01-24 20:45:02 +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
|
|
|
|
2010-08-23 14:47:14 +00:00
|
|
|
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;
|
2009-10-22 09:18:16 +00:00
|
|
|
unsigned 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;
|
|
|
|
|
2010-08-23 14:47:14 +00:00
|
|
|
if (pulCount == NULL_PTR)
|
|
|
|
return CKR_ARGUMENTS_BAD;
|
|
|
|
|
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
|
|
|
|
2010-06-16 13:42:59 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_GetSlotList(token=%d, %s)", tokenPresent,
|
|
|
|
(pSlotList==NULL_PTR && sc_pkcs11_conf.plug_and_play)? "plug-n-play":"refresh");
|
2010-01-24 20:45:02 +00:00
|
|
|
|
2009-01-19 12:06:38 +00:00
|
|
|
/* Slot list can only change in v2.20 */
|
2009-01-23 09:14:15 +00:00
|
|
|
if (pSlotList == NULL_PTR && sc_pkcs11_conf.plug_and_play) {
|
2010-01-24 20:45:02 +00:00
|
|
|
/* Trick NSS into updating the slot list by changing the hotplug slot ID */
|
|
|
|
sc_pkcs11_slot_t *hotplug_slot = list_get_at(&virtual_slots, 0);
|
|
|
|
hotplug_slot->id--;
|
|
|
|
sc_ctx_detect_readers(context);
|
2008-04-29 17:01:19 +00:00
|
|
|
}
|
2010-06-16 13:42:59 +00:00
|
|
|
|
2003-01-20 09:50:33 +00:00
|
|
|
card_detect_all();
|
2002-01-16 22:49:03 +00:00
|
|
|
|
Do not cast the return value of malloc(3) and calloc(3)
From http://en.wikipedia.org/wiki/Malloc#Casting_and_type_safety
" Casting and type safety
malloc returns a void pointer (void *), which indicates that it is a
pointer to a region of unknown data type. One may "cast" (see type
conversion) this pointer to a specific type, as in
int *ptr = (int*)malloc(10 * sizeof (int));
When using C, this is considered bad practice; it is redundant under the
C standard. Moreover, putting in a cast may mask failure to include the
header stdlib.h, in which the prototype for malloc is found. In the
absence of a prototype for malloc, the C compiler will assume that
malloc returns an int, and will issue a warning in a context such as the
above, provided the error is not masked by a cast. On certain
architectures and data models (such as LP64 on 64 bit systems, where
long and pointers are 64 bit and int is 32 bit), this error can actually
result in undefined behavior, as the implicitly declared malloc returns
a 32 bit value whereas the actually defined function returns a 64 bit
value. Depending on calling conventions and memory layout, this may
result in stack smashing.
The returned pointer need not be explicitly cast to a more specific
pointer type, since ANSI C defines an implicit conversion between the
void pointer type and other pointers to objects. An explicit cast of
malloc's return value is sometimes performed because malloc originally
returned a char *, but this cast is unnecessary in standard C
code.[4][5] Omitting the cast, however, creates an incompatibility with
C++, which does require it.
The lack of a specific pointer type returned from malloc is type-unsafe
behaviour: malloc allocates based on byte count but not on type. This
distinguishes it from the C++ new operator that returns a pointer whose
type relies on the operand. (see C Type Safety). "
See also
http://www.opensc-project.org/pipermail/opensc-devel/2010-August/014586.html
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4636 c6295689-39f2-0310-b995-f0e70906c6a9
2010-08-18 15:08:51 +00:00
|
|
|
found = malloc(list_size(&virtual_slots) * sizeof(CK_SLOT_ID));
|
2010-06-16 13:42:59 +00:00
|
|
|
|
|
|
|
if (found == NULL) {
|
|
|
|
rv = CKR_HOST_MEMORY;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2002-12-22 11:50:41 +00:00
|
|
|
numMatches = 0;
|
2010-06-16 13:43:10 +00:00
|
|
|
for (i=0; i<list_size(&virtual_slots); i++) {
|
2010-01-24 20:45:02 +00:00
|
|
|
slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
|
|
|
|
if (!tokenPresent || (slot->slot_info.flags & CKF_TOKEN_PRESENT))
|
|
|
|
found[numMatches++] = slot->id;
|
2003-01-03 11:40:11 +00:00
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
if (pSlotList == NULL_PTR) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "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) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "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
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "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
|
|
|
|
2010-08-23 14:47:14 +00:00
|
|
|
if (pInfo == NULL_PTR)
|
|
|
|
return CKR_ARGUMENTS_BAD;
|
|
|
|
|
2003-02-19 13:44:36 +00:00
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_GetSlotInfo(0x%lx)", 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){
|
2010-01-24 20:45:02 +00:00
|
|
|
if (slot->reader == NULL)
|
|
|
|
rv = CKR_TOKEN_NOT_PRESENT;
|
|
|
|
else {
|
|
|
|
now = get_current_time();
|
|
|
|
if (now >= slot->slot_state_expires || now == 0) {
|
|
|
|
/* Update slot status */
|
|
|
|
rv = card_detect(slot->reader);
|
|
|
|
/* Don't ask again within the next second */
|
|
|
|
slot->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));
|
|
|
|
|
2010-08-23 14:47:14 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_GetSlotInfo(0x%lx) = %s", slotID, lookup_enum ( RV_T, rv ));
|
2010-01-24 20:45:02 +00:00
|
|
|
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
|
|
|
|
2010-09-21 16:11:40 +00:00
|
|
|
if (pulCount == NULL_PTR)
|
|
|
|
return CKR_ARGUMENTS_BAD;
|
|
|
|
|
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
|
|
|
|
2010-08-23 14:47:14 +00:00
|
|
|
if (pInfo == NULL_PTR)
|
|
|
|
return CKR_ARGUMENTS_BAD;
|
|
|
|
|
2003-02-19 13:44:36 +00:00
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
|
|
|
|
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
|
|
|
|
2010-08-23 14:47:14 +00:00
|
|
|
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_session *session;
|
|
|
|
struct sc_pkcs11_slot *slot;
|
2005-01-19 18:15:43 +00:00
|
|
|
CK_RV rv;
|
2010-01-24 20:45:02 +00:00
|
|
|
unsigned int i;
|
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;
|
2010-01-24 20:45:02 +00:00
|
|
|
|
2002-04-05 15:02:18 +00:00
|
|
|
/* Make sure there's no open session for this token */
|
2010-01-24 20:45:02 +00:00
|
|
|
for (i=0; i<list_size(&sessions); i++) {
|
|
|
|
session = (struct sc_pkcs11_session*)list_get_at(&sessions, i);
|
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 */
|
|
|
|
{
|
2010-01-24 20:45:02 +00:00
|
|
|
sc_reader_t *found;
|
2003-02-03 12:20:54 +00:00
|
|
|
unsigned int mask, events;
|
2010-05-19 09:18:38 +00:00
|
|
|
void *reader_states = NULL;
|
|
|
|
CK_SLOT_ID slot_id;
|
2003-02-03 12:20:54 +00:00
|
|
|
CK_RV rv;
|
2010-06-16 11:32:21 +00:00
|
|
|
int r;
|
2010-01-24 20:45:02 +00:00
|
|
|
|
2010-05-19 09:18:38 +00:00
|
|
|
if (pReserved != NULL_PTR)
|
2010-01-24 20:45:02 +00:00
|
|
|
return CKR_ARGUMENTS_BAD;
|
2003-02-03 12:20:54 +00:00
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_WaitForSlotEvent(block=%d)", !(flags & CKF_DONT_BLOCK));
|
2010-01-24 20:45:02 +00:00
|
|
|
#if 0
|
|
|
|
/* pcsc-lite does not implement it in a threaded way */
|
2005-12-23 10:15:17 +00:00
|
|
|
if (!(flags & CKF_DONT_BLOCK))
|
|
|
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
2010-01-24 20:45:02 +00:00
|
|
|
#endif
|
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
|
|
|
|
2010-02-03 10:10:43 +00:00
|
|
|
mask = SC_EVENT_CARD_EVENTS;
|
2003-02-03 12:20:54 +00:00
|
|
|
|
2010-01-24 20:45:02 +00:00
|
|
|
/* Detect and add new slots for added readers v2.20 */
|
|
|
|
if (sc_pkcs11_conf.plug_and_play) {
|
2010-02-03 10:10:43 +00:00
|
|
|
mask |= SC_EVENT_READER_EVENTS;
|
2010-01-24 20:45:02 +00:00
|
|
|
}
|
|
|
|
|
2010-05-19 09:18:38 +00:00
|
|
|
rv = slot_find_changed(&slot_id, mask);
|
|
|
|
if ((rv == CKR_OK) || (flags & CKF_DONT_BLOCK))
|
2003-02-17 14:21:38 +00:00
|
|
|
goto out;
|
2003-02-03 12:20:54 +00:00
|
|
|
|
2003-04-11 14:22:52 +00:00
|
|
|
again:
|
2010-05-19 09:18:38 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_WaitForSlotEvent() reader_states:%p", reader_states);
|
2003-02-17 14:21:38 +00:00
|
|
|
sc_pkcs11_unlock();
|
2010-05-19 09:18:38 +00:00
|
|
|
r = sc_wait_for_event(context, mask, &found, &events, -1, &reader_states);
|
2010-01-24 20:45:02 +00:00
|
|
|
if (sc_pkcs11_conf.plug_and_play && events & SC_EVENT_READER_ATTACHED) {
|
|
|
|
/* NSS/Firefox Triggers a C_GetSlotList(NULL) only if a slot ID is returned that it does not know yet
|
2010-06-16 13:43:10 +00:00
|
|
|
Change the first hotplug slot id on every call to make this happen. */
|
2010-01-24 20:45:02 +00:00
|
|
|
sc_pkcs11_slot_t *hotplug_slot = list_get_at(&virtual_slots, 0);
|
|
|
|
*pSlot= hotplug_slot->id -1;
|
2010-05-19 09:18:38 +00:00
|
|
|
|
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
|
|
|
|
2010-01-24 20:45:02 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/* Was C_Finalize called ? */
|
|
|
|
if (in_finalize == 1)
|
2005-12-08 20:25:54 +00:00
|
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
2010-01-24 20:45:02 +00:00
|
|
|
|
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) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "sc_wait_for_event() returned %d\n", r);
|
2010-04-21 10:51:13 +00:00
|
|
|
rv = sc_to_cryptoki_error(r, "C_WaitForSlotEvent");
|
2003-02-17 14:21:38 +00:00
|
|
|
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 */
|
2010-05-19 09:18:38 +00:00
|
|
|
rv = slot_find_changed(&slot_id, mask);
|
|
|
|
if (rv != CKR_OK)
|
2003-04-11 14:22:52 +00:00
|
|
|
goto again;
|
2003-02-17 14:21:38 +00:00
|
|
|
|
2010-05-19 09:18:38 +00:00
|
|
|
out:
|
|
|
|
if (pSlot)
|
|
|
|
*pSlot = slot_id;
|
|
|
|
|
|
|
|
/* Free allocated readers states holder */
|
|
|
|
if (reader_states) {
|
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "free reader states");
|
|
|
|
sc_wait_for_event(context, 0, NULL, NULL, -1, &reader_states);
|
|
|
|
}
|
|
|
|
|
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_WaitForSlotEvent() = %s, event in 0x%lx", lookup_enum (RV_T, rv), *pSlot);
|
2010-01-24 20:45:02 +00:00
|
|
|
sc_pkcs11_unlock();
|
2003-02-17 14:21:38 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Locking functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
CK_RV
|
|
|
|
sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR args)
|
|
|
|
{
|
2010-06-16 11:43:10 +00:00
|
|
|
CK_RV rv = CKR_OK;
|
2003-02-17 14:21:38 +00:00
|
|
|
|
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
|
|
|
|
};
|