Added enumerator for PKCS#11 tokens

This commit is contained in:
Martin Willi
2010-08-04 09:26:20 +02:00
parent fe876b24d9
commit 36c852a08b
3 changed files with 140 additions and 15 deletions
@@ -279,7 +279,7 @@ pkcs11_creds_t *pkcs11_creds_create(pkcs11_library_t *p11, CK_SLOT_ID slot)
if (!load_certificates(this)) if (!load_certificates(this))
{ {
free(this); destroy(this);
return NULL; return NULL;
} }
+120 -14
View File
@@ -58,8 +58,6 @@ struct private_pkcs11_manager_t {
typedef struct { typedef struct {
/* back reference to this */ /* back reference to this */
private_pkcs11_manager_t *this; private_pkcs11_manager_t *this;
/* friendly name */
char *name;
/* associated library path */ /* associated library path */
char *path; char *path;
/* loaded library */ /* loaded library */
@@ -178,14 +176,14 @@ static void handle_slot(lib_entry_t *entry, CK_SLOT_ID slot)
if (info.flags & CKF_TOKEN_PRESENT) if (info.flags & CKF_TOKEN_PRESENT)
{ {
DBG1(DBG_CFG, " found token in slot '%s':%lu (%s)", DBG1(DBG_CFG, " found token in slot '%s':%lu (%s)",
entry->name, slot, info.slotDescription); entry->lib->get_name(entry->lib), slot, info.slotDescription);
handle_token(entry, slot); handle_token(entry, slot);
entry->this->cb(entry->this->data, entry->lib, slot, TRUE); entry->this->cb(entry->this->data, entry->lib, slot, TRUE);
} }
else else
{ {
DBG1(DBG_CFG, "token removed from slot '%s':%lu (%s)", DBG1(DBG_CFG, "token removed from slot '%s':%lu (%s)",
entry->name, slot, info.slotDescription); entry->lib->get_name(entry->lib), slot, info.slotDescription);
entry->this->cb(entry->this->data, entry->lib, slot, FALSE); entry->this->cb(entry->this->data, entry->lib, slot, FALSE);
} }
} }
@@ -205,7 +203,7 @@ static job_requeue_t dispatch_slot_events(lib_entry_t *entry)
if (rv == CKR_FUNCTION_NOT_SUPPORTED || rv == CKR_NO_EVENT) if (rv == CKR_FUNCTION_NOT_SUPPORTED || rv == CKR_NO_EVENT)
{ {
DBG1(DBG_CFG, "module '%s' does not support hot-plugging, cancelled", DBG1(DBG_CFG, "module '%s' does not support hot-plugging, cancelled",
entry->name); entry->lib->get_name(entry->lib));
return JOB_REQUEUE_NONE; return JOB_REQUEUE_NONE;
} }
if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) if (rv == CKR_CRYPTOKI_NOT_INITIALIZED)
@@ -229,34 +227,131 @@ static void end_dispatch(lib_entry_t *entry)
entry->job = NULL; entry->job = NULL;
} }
/**
* Get the slot list of a library
*/
static CK_SLOT_ID_PTR get_slot_list(pkcs11_library_t *p11, CK_ULONG *out)
{
CK_SLOT_ID_PTR slots;
CK_ULONG count;
CK_RV rv;
rv = p11->f->C_GetSlotList(TRUE, NULL, &count);
if (rv != CKR_OK)
{
DBG1(DBG_CFG, "C_GetSlotList() failed: %N", ck_rv_names, rv);
return NULL;
}
if (count == 0)
{
return NULL;
}
slots = malloc(sizeof(CK_SLOT_ID) * count);
rv = p11->f->C_GetSlotList(TRUE, slots, &count);
if (rv != CKR_OK)
{
DBG1(DBG_CFG, "C_GetSlotList() failed: %N", ck_rv_names, rv);
free(slots);
return NULL;
}
*out = count;
return slots;
}
/** /**
* Query the slots for tokens * Query the slots for tokens
*/ */
static void query_slots(lib_entry_t *entry) static void query_slots(lib_entry_t *entry)
{ {
CK_ULONG token_count; CK_ULONG count;
CK_SLOT_ID_PTR slots; CK_SLOT_ID_PTR slots;
int i; int i;
if (entry->lib->f->C_GetSlotList(TRUE, NULL, &token_count) == CKR_OK) slots = get_slot_list(entry->lib, &count);
if (slots)
{ {
slots = malloc(sizeof(CK_SLOT_ID) * token_count); for (i = 0; i < count; i++)
if (entry->lib->f->C_GetSlotList(TRUE, slots, &token_count) == CKR_OK)
{ {
for (i = 0; i < token_count; i++) handle_slot(entry, slots[i]);
{
handle_slot(entry, slots[i]);
}
} }
free(slots); free(slots);
} }
} }
/**
* Token enumerator
*/
typedef struct {
/* implements enumerator */
enumerator_t public;
/* inner enumerator over PKCS#11 libraries */
enumerator_t *inner;
/* active library entry */
lib_entry_t *entry;
/* slot list with tokens */
CK_SLOT_ID_PTR slots;
/* number of slots */
CK_ULONG count;
/* current slot */
int current;
} token_enumerator_t;
METHOD(enumerator_t, enumerate_token, bool,
token_enumerator_t *this, pkcs11_library_t **out, CK_SLOT_ID *slot)
{
if (this->current >= this->count)
{
free(this->slots);
this->slots = NULL;
this->current = 0;
}
while (!this->slots)
{
if (!this->inner->enumerate(this->inner, &this->entry))
{
return FALSE;
}
this->slots = get_slot_list(this->entry->lib, &this->count);
}
*out = this->entry->lib;
*slot = this->slots[this->current++];
return TRUE;
}
METHOD(enumerator_t, destroy_token, void,
token_enumerator_t *this)
{
this->inner->destroy(this->inner);
free(this->slots);
free(this);
}
METHOD(pkcs11_manager_t, create_token_enumerator, enumerator_t*,
private_pkcs11_manager_t *this)
{
token_enumerator_t *enumerator;
INIT(enumerator,
.public = {
.enumerate = (void*)_enumerate_token,
.destroy = _destroy_token,
},
.inner = this->libs->create_enumerator(this->libs),
);
return &enumerator->public;
}
/**
* Singleton instance
*/
static private_pkcs11_manager_t *singleton = NULL;
METHOD(pkcs11_manager_t, destroy, void, METHOD(pkcs11_manager_t, destroy, void,
private_pkcs11_manager_t *this) private_pkcs11_manager_t *this)
{ {
this->libs->destroy_function(this->libs, (void*)lib_entry_destroy); this->libs->destroy_function(this->libs, (void*)lib_entry_destroy);
free(this); free(this);
singleton = NULL;
} }
/** /**
@@ -272,6 +367,7 @@ pkcs11_manager_t *pkcs11_manager_create(pkcs11_manager_token_event_t cb,
INIT(this, INIT(this,
.public = { .public = {
.create_token_enumerator = _create_token_enumerator,
.destroy = _destroy, .destroy = _destroy,
}, },
.libs = linked_list_create(), .libs = linked_list_create(),
@@ -285,7 +381,6 @@ pkcs11_manager_t *pkcs11_manager_create(pkcs11_manager_token_event_t cb,
{ {
INIT(entry, INIT(entry,
.this = this, .this = this,
.name = module,
); );
entry->path = lib->settings->get_str(lib->settings, entry->path = lib->settings->get_str(lib->settings,
@@ -310,5 +405,16 @@ pkcs11_manager_t *pkcs11_manager_create(pkcs11_manager_token_event_t cb,
charon->processor->queue_job(charon->processor, (job_t*)entry->job); charon->processor->queue_job(charon->processor, (job_t*)entry->job);
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
singleton = this;
return &this->public; return &this->public;
} }
/**
* See header
*/
pkcs11_manager_t *pkcs11_manager_get()
{
return (pkcs11_manager_t*)singleton;
}
@@ -44,6 +44,13 @@ typedef void (*pkcs11_manager_token_event_t)(void *data, pkcs11_library_t *p11,
*/ */
struct pkcs11_manager_t { struct pkcs11_manager_t {
/**
* Create an enumerator over all tokens.
*
* @return enumerator over (pkcs11_library_t*,CK_SLOT_ID)
*/
enumerator_t* (*create_token_enumerator)(pkcs11_manager_t *this);
/** /**
* Destroy a pkcs11_manager_t. * Destroy a pkcs11_manager_t.
*/ */
@@ -52,8 +59,20 @@ struct pkcs11_manager_t {
/** /**
* Create a pkcs11_manager instance. * Create a pkcs11_manager instance.
*
* @param cb token event callback function
* @param data user data to pass to token event callback
* @return instance
*/ */
pkcs11_manager_t *pkcs11_manager_create(pkcs11_manager_token_event_t cb, pkcs11_manager_t *pkcs11_manager_create(pkcs11_manager_token_event_t cb,
void *data); void *data);
/**
* Get the singleton instance of the manager
*
* @return instance, NULL if none available
*/
pkcs11_manager_t *pkcs11_manager_get();
#endif /** PKCS11_MANAGER_H_ @}*/ #endif /** PKCS11_MANAGER_H_ @}*/