- 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:
parent
670c0ee063
commit
5c3aed1189
@ -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 \
|
||||
|
@ -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 \
|
||||
\
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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() ).
|
||||
|
@ -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
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user