- remove dependence on a specific threading library

- add two new structures: sc_thread_context_t which let
  the user specify the mutex functions to use and
  sc_context_param_t to specify parameters for the sc_context_t
  creation (including mutex functions) using sc_create_context()
- add new function sc_context_create()  
- remove timestamp code from libopensc


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@2829 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
nils 2006-02-01 22:59:42 +00:00
parent 670c0ee063
commit 5c3aed1189
12 changed files with 446 additions and 240 deletions

View File

@ -13,7 +13,7 @@ bin_SCRIPTS = opensc-config
lib_LTLIBRARIES = libopensc.la
libopensc_la_SOURCES = \
sc.c ctx.c ui.c log.c errors.c portability.c \
sc.c ctx.c ui.c log.c errors.c \
asn1.c base64.c sec.c card.c iso7816.c dir.c padding.c apdu.c \
\
pkcs15.c pkcs15-cert.c pkcs15-data.c pkcs15-pin.c \

View File

@ -11,7 +11,7 @@ HEADERS = \
HEADERSDIR = $(TOPDIR)\src\include\opensc
OBJECTS = \
sc.obj ctx.obj ui.obj log.obj errors.obj portability.obj \
sc.obj ctx.obj ui.obj log.obj errors.obj \
asn1.obj base64.obj sec.obj card.obj iso7816.obj dir.obj padding.obj \
apdu.obj \
\

View File

@ -48,10 +48,13 @@ void sc_format_apdu(sc_card_t *card, sc_apdu_t *apdu,
apdu->p2 = (u8) p2;
}
static sc_card_t * sc_card_new(void)
static sc_card_t * sc_card_new(sc_context_t *ctx)
{
sc_card_t *card;
if (ctx == NULL)
return NULL;
card = (sc_card_t *) calloc(1, sizeof(struct sc_card));
if (card == NULL)
return NULL;
@ -60,10 +63,17 @@ static sc_card_t * sc_card_new(void)
free(card);
return NULL;
}
card->ctx = ctx;
if (sc_mutex_create(ctx, &card->mutex) != SC_SUCCESS) {
free(card->ops);
free(card);
return NULL;
}
card->type = -1;
card->app_count = -1;
card->magic = SC_CARD_MAGIC;
card->mutex = sc_mutex_new();
return card;
}
@ -77,28 +87,30 @@ static void sc_card_free(sc_card_t *card)
free(card->ops);
if (card->algorithms != NULL)
free(card->algorithms);
sc_mutex_free(card->mutex);
if (card->mutex != NULL)
sc_mutex_destroy(card->ctx, card->mutex);
sc_mem_clear(card, sizeof(*card));
free(card);
}
int sc_connect_card(sc_reader_t *reader, int slot_id,
sc_card_t **card_out)
int sc_connect_card(sc_reader_t *reader, int slot_id, sc_card_t **card_out)
{
sc_card_t *card;
sc_context_t *ctx = reader->ctx;
sc_context_t *ctx;
sc_slot_info_t *slot = _sc_get_slot_info(reader, slot_id);
struct sc_card_driver *driver;
int i, r = 0, idx, connected = 0;
assert(card_out != NULL);
if (card_out == NULL || reader == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
ctx = reader->ctx;
SC_FUNC_CALLED(ctx, 1);
if (reader->ops->connect == NULL)
SC_FUNC_RETURN(ctx, 0, SC_ERROR_NOT_SUPPORTED);
if (slot == NULL)
SC_FUNC_RETURN(ctx, 0, SC_ERROR_SLOT_NOT_FOUND);
card = sc_card_new();
card = sc_card_new(ctx);
if (card == NULL)
SC_FUNC_RETURN(ctx, 1, SC_ERROR_OUT_OF_MEMORY);
r = reader->ops->connect(reader, slot);
@ -238,8 +250,11 @@ int sc_lock(sc_card_t *card)
{
int r = 0;
assert(card != NULL);
sc_mutex_lock(card->mutex);
if (card == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
r = sc_mutex_lock(card->ctx, card->mutex);
if (r != SC_SUCCESS)
return r;
if (card->lock_count == 0) {
SC_FUNC_CALLED(card->ctx, 3);
if (card->reader->ops->lock != NULL)
@ -249,7 +264,7 @@ int sc_lock(sc_card_t *card)
}
if (r == 0)
card->lock_count++;
sc_mutex_unlock(card->mutex);
r = sc_mutex_unlock(card->ctx, card->mutex);
return r;
}
@ -257,18 +272,28 @@ int sc_unlock(sc_card_t *card)
{
int r = 0;
assert(card != NULL);
sc_mutex_lock(card->mutex);
if (card == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
r = sc_mutex_lock(card->ctx, card->mutex);
if (r != SC_SUCCESS)
return r;
assert(card->lock_count >= 1);
if (card->lock_count == 1) {
SC_FUNC_CALLED(card->ctx, 3);
memset(&card->cache, 0, sizeof(card->cache));
card->cache_valid = 0;
if (card->ops->logout != NULL) {
sc_mutex_unlock(card->mutex);
/*XXX*/
r = sc_mutex_unlock(card->ctx, card->mutex);
if (r != SC_SUCCESS) {
sc_error(card->ctx, "unable to release lock\n");
return r;
}
sc_debug(card->ctx, "Calling card logout function\n");
card->ops->logout(card);
sc_mutex_lock(card->mutex);
r = sc_mutex_lock(card->ctx, card->mutex);
if (r != SC_SUCCESS)
return r;
}
}
/* Check again, lock count may have changed
@ -278,7 +303,7 @@ int sc_unlock(sc_card_t *card)
r = card->reader->ops->unlock(card->reader, card->slot);
}
card->lock_count--;
sc_mutex_unlock(card->mutex);
r = sc_mutex_unlock(card->ctx, card->mutex);
return r;
}

View File

@ -178,12 +178,14 @@ ctbcs_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
dummy_card.reader = reader;
dummy_card.slot = slot;
dummy_card.ctx = reader->ctx;
dummy_card.mutex = sc_mutex_new();
r = sc_mutex_create(reader->ctx, &dummy_card.mutex);
if (r != SC_SUCCESS)
return r;
dummy_card.ops = &ops;
card = &dummy_card;
r = sc_transmit_apdu(card, &apdu);
sc_mutex_free(card->mutex);
sc_mutex_destroy(reader->ctx, card->mutex);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
/* Check CTBCS status word */

View File

@ -678,23 +678,49 @@ void sc_ctx_suppress_errors_off(sc_context_t *ctx)
int sc_establish_context(sc_context_t **ctx_out, const char *app_name)
{
const char *default_app = "default";
sc_context_t *ctx;
struct _sc_ctx_options opts;
sc_context_param_t ctx_param;
assert(ctx_out != NULL);
ctx = (sc_context_t *) calloc(1, sizeof(sc_context_t));
memset(&ctx_param, 0, sizeof(sc_context_param_t));
ctx_param.ver = 0;
ctx_param.app_name = app_name;
return sc_context_create(ctx_out, &ctx_param);
}
int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm)
{
sc_context_t *ctx;
struct _sc_ctx_options opts;
int r;
if (ctx_out == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
ctx = calloc(1, sizeof(sc_context_t));
if (ctx == NULL)
return SC_ERROR_OUT_OF_MEMORY;
memset(&opts, 0, sizeof(opts));
set_defaults(ctx, &opts);
ctx->app_name = app_name ? strdup(app_name) : strdup(default_app);
/* set the application name if set in the parameter options */
if (parm != NULL && parm->app_name != NULL)
ctx->app_name = strdup(parm->app_name);
else
ctx->app_name = strdup("default");
if (ctx->app_name == NULL) {
sc_release_context(ctx);
return SC_ERROR_OUT_OF_MEMORY;
}
/* set thread context and create mutex object (if specified) */
if (parm != NULL && parm->thread_ctx != NULL)
ctx->thread_ctx = parm->thread_ctx;
r = sc_mutex_create(ctx, &ctx->mutex);
if (r != SC_SUCCESS) {
sc_release_context(ctx);
return r;
}
process_config_file(ctx, &opts);
ctx->mutex = sc_mutex_new();
sc_debug(ctx, "===================================\n"); /* first thing in the log */
sc_debug(ctx, "opensc version: %s\n", sc_get_version());
@ -755,12 +781,14 @@ int sc_release_context(sc_context_t *ctx)
fclose(ctx->debug_file);
if (ctx->error_file && ctx->error_file != stderr)
fclose(ctx->error_file);
if (ctx->preferred_language)
if (ctx->preferred_language != NULL)
free(ctx->preferred_language);
if (ctx->conf)
if (ctx->conf != NULL)
scconf_free(ctx->conf);
sc_mutex_free(ctx->mutex);
free(ctx->app_name);
if (ctx->mutex != NULL)
sc_mutex_destroy(ctx, ctx->mutex);
if (ctx->app_name != NULL)
free(ctx->app_name);
sc_mem_clear(ctx, sizeof(*ctx));
free(ctx);
return SC_SUCCESS;
@ -770,7 +798,7 @@ int sc_set_card_driver(sc_context_t *ctx, const char *short_name)
{
int i = 0, match = 0;
sc_mutex_lock(ctx->mutex);
sc_mutex_lock(ctx, ctx->mutex);
if (short_name == NULL) {
ctx->forced_driver = NULL;
match = 1;
@ -784,7 +812,7 @@ int sc_set_card_driver(sc_context_t *ctx, const char *short_name)
}
i++;
}
sc_mutex_unlock(ctx->mutex);
sc_mutex_unlock(ctx, ctx->mutex);
if (match == 0)
return SC_ERROR_OBJECT_NOT_FOUND; /* FIXME: invent error */
return SC_SUCCESS;

View File

@ -40,6 +40,13 @@ extern "C" {
#define SC_CARD_MAGIC 0x27182818
#define SC_CTX_MAGIC 0x0A550335
#ifndef _WIN32
#define msleep(t) usleep((t) * 1000)
#else
#define msleep(t) Sleep(t)
#define sleep(t) Sleep((t) * 1000)
#endif
struct sc_atr_table {
/* The atr fields are required to
* be in aa:bb:cc hex format. */
@ -105,6 +112,51 @@ int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags,
const u8 *in, size_t in_len, u8 *out, size_t *out_len, size_t mod_len);
int sc_strip_zero_padding(const u8 *in,size_t in_len, u8 *out, size_t *out_len);
/********************************************************************/
/* mutex functions */
/********************************************************************/
/**
* Creates a new sc_mutex object. Note: unless sc_mutex_set_mutex_funcs()
* this function does nothing and always returns SC_SUCCESS.
* @param ctx sc_context_t object with the thread context
* @param mutex pointer for the newly created mutex object
* @return SC_SUCCESS on success and an error code otherwise
*/
int sc_mutex_create(const sc_context_t *ctx, void **mutex);
/**
* Tries to acquire a lock for a sc_mutex object. Note: Unless
* sc_mutex_set_mutex_funcs() has been called before this
* function does nothing and always returns SUCCESS.
* @param ctx sc_context_t object with the thread context
* @param mutex mutex object to lock
* @return SC_SUCCESS on success and an error code otherwise
*/
int sc_mutex_lock(const sc_context_t *ctx, void *mutex);
/**
* Unlocks a sc_mutex object. Note: Unless sc_mutex_set_mutex_funcs()
* has been called before this function does nothing and always returns
* SC_SUCCESS.
* @param ctx sc_context_t object with the thread context
* @param mutex mutex object to unlock
* @return SC_SUCCESS on success and an error code otherwise
*/
int sc_mutex_unlock(const sc_context_t *ctx, void *mutex);
/**
* Destroys a sc_mutex object. Note: Unless sc_mutex_set_mutex_funcs()
* has been called before this function does nothing and always returns
* SC_SUCCESS.
* @param ctx sc_context_t object with the thread context
* @param mutex mutex object to be destroyed
*/
void sc_mutex_destroy(const sc_context_t *ctx, void *mutex);
/**
* Returns a unique id for every thread.
* @param ctx sc_context_t object with the thread context
* @return unsigned long with the unique id or 0 if not supported
*/
unsigned long sc_thread_id(const sc_context_t *ctx);
#ifdef __cplusplus
}
#endif

View File

@ -192,16 +192,6 @@ extern "C" {
#define SC_ALGORITHM_RSA_HASH_MD5_SHA1 0x00000080
#define SC_ALGORITHM_RSA_HASH_RIPEMD160 0x00000100
/* A 64-bit uint, used in sc_current_time() */
#ifndef _WIN32
typedef unsigned long long sc_timestamp_t;
#define msleep(t) usleep((t) * 1000)
#else
typedef unsigned __int64 sc_timestamp_t;
#define msleep(t) Sleep(t)
#define sleep(t) Sleep((t) * 1000)
#endif
/* Event masks for sc_wait_for_event() */
#define SC_EVENT_CARD_INSERTED 0x0001
#define SC_EVENT_CARD_REMOVED 0x0002
@ -419,17 +409,6 @@ struct sc_reader_operations {
int timeout);
};
/* Mutexes - this is just a dummy struct used for type
* safety; internally we use objects defined by the
* underlying thread model
*/
typedef struct sc_mutex sc_mutex_t;
struct sc_mutex *sc_mutex_new(void);
void sc_mutex_lock(struct sc_mutex *p);
void sc_mutex_unlock(struct sc_mutex *p);
void sc_mutex_free(struct sc_mutex *p);
/*
* Card flags
*
@ -511,7 +490,7 @@ typedef struct sc_card {
sc_serial_number_t serialnr;
sc_mutex_t *mutex;
void *mutex;
unsigned int magic;
} sc_card_t;
@ -642,6 +621,26 @@ typedef struct sc_card_driver {
void *dll;
} sc_card_driver_t;
/**
* @struct sc_thread_context_t
* Structure for the locking function to use when using libopensc
* in a multi-threaded application.
*/
typedef struct {
/** the version number of this structure (0 for this version) */
unsigned int ver;
/** creates a mutex object */
int (*create_mutex)(void **);
/** locks a mutex object (blocks until the lock has been acquired) */
int (*lock_mutex)(void *);
/** unlocks a mutex object */
int (*unlock_mutex)(void *);
/** destroys a mutex object */
void (*destroy_mutex)(void *);
/** returns unique identifier for the thread (can be NULL) */
unsigned long (*thread_id)(void);
} sc_thread_context_t;
typedef struct sc_context {
scconf_context *conf;
scconf_block *conf_blocks[3];
@ -661,7 +660,8 @@ typedef struct sc_context {
struct sc_card_driver *card_drivers[SC_MAX_CARD_DRIVERS];
struct sc_card_driver *forced_driver;
sc_mutex_t *mutex;
sc_thread_context_t *thread_ctx;
void *mutex;
unsigned int magic;
} sc_context_t;
@ -684,13 +684,42 @@ void sc_format_apdu(sc_card_t *card, sc_apdu_t *apdu, int cse, int ins,
/********************************************************************/
/**
* Establishes an OpenSC context
* Establishes an OpenSC context. Note: this function is deprecated,
* please use sc_context_create() instead.
* @param ctx A pointer to a pointer that will receive the allocated context
* @param app_name A string that identifies the application, used primarily
* in finding application-specific configuration data. Can be NULL.
*/
int sc_establish_context(sc_context_t **ctx, const char *app_name);
/**
* @struct sc_context_t initialization parameters
* Structure to supply additional parameters, for example
* mutex information, to the sc_context_t creation.
*/
typedef struct {
/** version number of this structure (0 for this version) */
unsigned int ver;
/** name of the application (used for finding application
* dependend configuration data). If NULL the name "default"
* will be used. */
const char *app_name;
/** flags, currently unused */
unsigned long flags;
/** mutex functions to use (optional) */
sc_thread_context_t *thread_ctx;
} sc_context_param_t;
/**
* Creates a new sc_context_t object.
* @param ctx pointer to a sc_context_t pointer for the newly
* created sc_context_t object.
* @param parm parameters for the sc_context_t creation (see
* sc_context_param_t for a description of the supported
* options). This parameter is optional and can be NULL.
* @return SC_SUCCESS on success and an error code otherwise.
*/
int sc_context_create(sc_context_t **ctx, const sc_context_param_t *parm);
/**
* Releases an established OpenSC context
* @param ctx A pointer to the context structure to be released
@ -737,8 +766,7 @@ int sc_set_card_driver(sc_context_t *ctx, const char *short_name);
* @param reader Reader structure
* @param slot_id Slot ID to connect to
* @param card The allocated card object will go here */
int sc_connect_card(sc_reader_t *reader, int slot_id,
sc_card_t **card);
int sc_connect_card(sc_reader_t *reader, int slot_id, sc_card_t **card);
/**
* Disconnects from a card, and frees the card structure. Any locks
* made by the application must be released before calling this function.
@ -997,9 +1025,6 @@ int sc_base64_encode(const u8 *in, size_t inlen, u8 *out, size_t outlen,
size_t linelength);
int sc_base64_decode(const char *in, u8 *out, size_t outlen);
/* Returns the current time in milliseconds */
sc_timestamp_t sc_current_time(void);
/**
* Clears a memory buffer (note: when OpenSSL is used this is
* currently a wrapper for OPENSSL_cleanse() ).

View File

@ -1,147 +0,0 @@
/*
* portability.c: Miscellaneous stuff needed for porting to other platforms
*
* Copyright (C) 2003, Olaf Kirch <okir@lst.de>
*
* 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
*/
#include "internal.h"
#include <assert.h>
#include <stdlib.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#if defined(HAVE_PTHREAD)
#include <pthread.h>
sc_mutex_t *
sc_mutex_new(void)
{
pthread_mutex_t *mutex;
mutex = (pthread_mutex_t *) malloc(sizeof(*mutex));
assert(mutex);
pthread_mutex_init(mutex, NULL);
return (sc_mutex_t *) mutex;
}
void
sc_mutex_lock(sc_mutex_t *p)
{
pthread_mutex_lock((pthread_mutex_t *) p);
}
void
sc_mutex_unlock(sc_mutex_t *p)
{
pthread_mutex_unlock((pthread_mutex_t *) p);
}
void
sc_mutex_free(sc_mutex_t *p)
{
pthread_mutex_destroy((pthread_mutex_t *) p);
free(p);
}
#elif defined(_WIN32)
sc_mutex_t *
sc_mutex_new(void)
{
CRITICAL_SECTION *mutex;
mutex = (CRITICAL_SECTION *) malloc(sizeof(*mutex));
assert(mutex);
InitializeCriticalSection(mutex);
return (sc_mutex_t *) mutex;
}
void
sc_mutex_lock(sc_mutex_t *p)
{
EnterCriticalSection((CRITICAL_SECTION *) p);
}
void
sc_mutex_unlock(sc_mutex_t *p)
{
LeaveCriticalSection((CRITICAL_SECTION *) p);
}
void
sc_mutex_free(sc_mutex_t *p)
{
DeleteCriticalSection((CRITICAL_SECTION *) p);
free(p);
}
#else
sc_mutex_t *
sc_mutex_new(void)
{
return (sc_mutex_t *) NULL;
}
void
sc_mutex_lock(sc_mutex_t *p)
{
/* NOP */
}
void
sc_mutex_unlock(sc_mutex_t *p)
{
/* NOP */
}
void
sc_mutex_free(sc_mutex_t *p)
{
/* NOP */
}
#endif
#ifndef _WIN32
sc_timestamp_t sc_current_time(void)
{
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;
return curr;
}
#else
sc_timestamp_t sc_current_time(void)
{
struct _timeb time_buf;
sc_timestamp_t curr;
_ftime(&time_buf);
curr = time_buf.time;
curr *= 1000;
curr += time_buf.millitm;
return curr;
}
#endif

View File

@ -672,3 +672,52 @@ void sc_mem_clear(void *ptr, size_t len)
memset(ptr, 0, len);
#endif
}
/**************************** mutex functions ************************/
int sc_mutex_create(const sc_context_t *ctx, void **mutex)
{
if (ctx == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
if (ctx->thread_ctx != NULL && ctx->thread_ctx->create_mutex != NULL)
return ctx->thread_ctx->create_mutex(mutex);
else
return SC_SUCCESS;
}
int sc_mutex_lock(const sc_context_t *ctx, void *mutex)
{
if (ctx == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
if (ctx->thread_ctx != NULL && ctx->thread_ctx->lock_mutex != NULL)
return ctx->thread_ctx->lock_mutex(mutex);
else
return SC_SUCCESS;
}
int sc_mutex_unlock(const sc_context_t *ctx, void *mutex)
{
if (ctx == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
if (ctx->thread_ctx != NULL && ctx->thread_ctx->unlock_mutex != NULL)
return ctx->thread_ctx->unlock_mutex(mutex);
else
return SC_SUCCESS;
}
void sc_mutex_destroy(const sc_context_t *ctx, void *mutex)
{
if (ctx == NULL || ctx->thread_ctx == NULL ||
ctx->thread_ctx->destroy_mutex == NULL)
return;
ctx->thread_ctx->destroy_mutex(mutex);
}
unsigned long sc_thread_id(const sc_context_t *ctx)
{
if (ctx == NULL || ctx->thread_ctx == NULL ||
ctx->thread_ctx->thread_id == NULL)
return 0UL;
else
return ctx->thread_ctx->thread_id();
}

View File

@ -18,8 +18,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include "sc-pkcs11.h"
sc_context_t *context = NULL;
@ -30,16 +37,156 @@ struct sc_pkcs11_config sc_pkcs11_conf;
extern CK_FUNCTION_LIST pkcs11_function_list;
#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;
m = (CRITICAL_SECTION *) malloc(sizeof(*mutex));
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
static CK_C_INITIALIZE_ARGS_PTR _locking;
static void * _lock = NULL;
#if (defined(HAVE_PTHREAD) || defined(_WIN32)) && defined(PKCS11_THREAD_LOCKING)
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)
{
if (_locking == NULL)
return SC_SUCCESS;
if (_locking->CreateMutex(m) == CKR_OK)
return SC_SUCCESS;
else
return SC_ERROR_INTERNAL;
}
static int sc_lock_mutex(void *m)
{
if (_locking == NULL)
return SC_SUCCESS;
if (_locking->LockMutex(m) == CKR_OK)
return SC_SUCCESS;
else
return SC_ERROR_INTERNAL;
}
static int sc_unlock_mutex(void *m)
{
if (_locking == NULL)
return SC_SUCCESS;
if (_locking->UnlockMutex(m) == CKR_OK)
return SC_SUCCESS;
else
return SC_ERROR_INTERNAL;
}
static void sc_destroy_mutex(void *m)
{
if (_locking == NULL)
return;
_locking->DestroyMutex(m);
}
static sc_thread_context_t sc_thread_ctx = {
0, sc_create_mutex, sc_lock_mutex,
sc_unlock_mutex, sc_destroy_mutex, NULL
};
CK_RV C_Initialize(CK_VOID_PTR pReserved)
{
int i, rc, rv;
sc_context_param_t ctx_opts;
if (context != NULL) {
sc_error(context, "C_Initialize(): Cryptoki already initialized\n");
return CKR_CRYPTOKI_ALREADY_INITIALIZED;
}
rc = sc_establish_context(&context, "opensc-pkcs11");
if (rc != 0) {
rv = sc_pkcs11_init_lock((CK_C_INITIALIZE_ARGS_PTR) pReserved);
if (rv != CKR_OK) {
sc_release_context(context);
context = NULL;
}
/* 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) {
rv = CKR_DEVICE_ERROR;
goto out;
}
@ -57,12 +204,6 @@ CK_RV C_Initialize(CK_VOID_PTR pReserved)
/* Detect any card, but do not flag "insert" events */
__card_detect_all(0);
rv = sc_pkcs11_init_lock((CK_C_INITIALIZE_ARGS_PTR) pReserved);
if (rv != CKR_OK) {
sc_release_context(context);
context = NULL;
}
out:
if (context != NULL)
sc_debug(context, "C_Initialize: result = %d\n", rv);
@ -190,6 +331,33 @@ out: sc_pkcs11_unlock();
return rv;
}
static sc_timestamp_t get_current_time(void)
{
#ifndef _WIN32
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;
timestamp_t curr;
_ftime(&time_buf);
curr = time_buf.time;
curr *= 1000;
curr += time_buf.millitm;
#endif
return curr;
}
CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
{
struct sc_pkcs11_slot *slot;
@ -209,7 +377,7 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
rv = slot_get_slot(slotID, &slot);
if (rv == CKR_OK){
now = sc_current_time();
now = get_current_time();
if (now >= card_table[slot->reader].slot_state_expires || now == 0) {
/* Update slot status */
rv = card_detect(slot->reader);
@ -418,9 +586,6 @@ out: sc_pkcs11_unlock();
* Locking functions
*/
static CK_C_INITIALIZE_ARGS_PTR _locking;
static void * _lock = NULL;
CK_RV
sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR args)
{
@ -441,7 +606,7 @@ sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR args)
*/
_locking = NULL;
if (args->flags & CKF_OS_LOCKING_OK) {
#if (defined(HAVE_PTHREAD) && !defined(PKCS11_THREAD_LOCKING))
#if defined(HAVE_PTHREAD) && !defined(PKCS11_THREAD_LOCKING)
/* FIXME:
* Mozilla uses the CKF_OS_LOCKING_OK flag in C_Initialize().
* The result is that the Mozilla process doesn't end when
@ -457,16 +622,15 @@ sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR args)
*/
return CKR_OK;
#endif
if (!(_lock = sc_mutex_new()))
rv = CKR_CANT_LOCK;
} else
if (args->CreateMutex
&& args->DestroyMutex
&& args->LockMutex
&& args->UnlockMutex) {
rv = args->CreateMutex(&_lock);
if (rv == CKR_OK)
_locking = args;
_locking = default_mutex_funcs;
} else if (args->CreateMutex && args->DestroyMutex &&
args->LockMutex && args->UnlockMutex) {
_locking = args;
}
if (_locking != NULL) {
/* create mutex */
rv = _locking->CreateMutex(&_lock);
}
return rv;
@ -483,9 +647,7 @@ sc_pkcs11_lock()
if (_locking) {
while (_locking->LockMutex(_lock) != CKR_OK)
;
} else {
sc_mutex_lock((sc_mutex_t *) _lock);
}
}
return CKR_OK;
}
@ -498,9 +660,7 @@ __sc_pkcs11_unlock(void *lock)
if (_locking) {
while (_locking->UnlockMutex(lock) != CKR_OK)
;
} else {
sc_mutex_unlock((sc_mutex_t *) lock);
}
}
}
void
@ -532,8 +692,6 @@ sc_pkcs11_free_lock()
if (_locking)
_locking->DestroyMutex(tempLock);
else
sc_mutex_free((sc_mutex_t *) tempLock);
_locking = NULL;
}

View File

@ -184,6 +184,12 @@ struct sc_pkcs11_framework_ops {
* PKCS#11 Slot (used to access card with specific framework data)
*/
#ifndef _WIN32
typedef unsigned long long sc_timestamp_t;
#else
typedef unsigned __int64 sc_timestamp_t;
#endif
struct sc_pkcs11_card {
int reader;
struct sc_card *card;

View File

@ -483,6 +483,14 @@ gpk_store_key(sc_profile_t *profile, sc_card_t *card,
return r;
}
/* this could be removed once we include libopensc/internal.h */
#ifndef _WIN32
#define msleep(t) usleep((t) * 1000)
#else
#define msleep(t) Sleep(t)
#define sleep(t) Sleep((t) * 1000)
#endif
/*
* On-board key generation.
*/