Add reference counting on certifiates, push out CK_SESSION_HANDLE from slot.

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@17588 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2006-05-27 10:58:07 +00:00
parent 8b2a7cf875
commit 4abe3b3bce

View File

@@ -50,7 +50,6 @@ struct p11_module {
#define P11_SESSION 1 #define P11_SESSION 1
#define P11_LOGIN_REQ 2 #define P11_LOGIN_REQ 2
#define P11_LOGIN_DONE 4 #define P11_LOGIN_DONE 4
CK_SESSION_HANDLE session;
CK_SLOT_ID id; CK_SLOT_ID id;
CK_BBOOL token; CK_BBOOL token;
char *name; char *name;
@@ -59,11 +58,15 @@ struct p11_module {
} slot; } slot;
}; };
#define P11SESSION(module) ((module)->session)
#define P11FUNC(module,f,args) (*(module)->funcs->C_##f)args #define P11FUNC(module,f,args) (*(module)->funcs->C_##f)args
static int p11_get_session(struct p11_module *, struct p11_slot *, hx509_lock); static int p11_get_session(struct p11_module *,
static int p11_put_session(struct p11_module *, struct p11_slot *); struct p11_slot *,
hx509_lock,
CK_SESSION_HANDLE *);
static int p11_put_session(struct p11_module *,
struct p11_slot *,
CK_SESSION_HANDLE);
static void p11_release_module(struct p11_module *); static void p11_release_module(struct p11_module *);
/* /*
@@ -107,6 +110,7 @@ p11_rsa_private_encrypt(int flen,
{ {
struct p11_rsa *p11rsa = RSA_get_app_data(rsa); struct p11_rsa *p11rsa = RSA_get_app_data(rsa);
CK_OBJECT_HANDLE key = p11rsa->private_key; CK_OBJECT_HANDLE key = p11rsa->private_key;
CK_SESSION_HANDLE session;
CK_MECHANISM mechanism; CK_MECHANISM mechanism;
CK_ULONG ck_sigsize; CK_ULONG ck_sigsize;
int ret; int ret;
@@ -119,24 +123,22 @@ p11_rsa_private_encrypt(int flen,
ck_sigsize = RSA_size(rsa); ck_sigsize = RSA_size(rsa);
ret = p11_get_session(p11rsa->p, p11rsa->slot, NULL); ret = p11_get_session(p11rsa->p, p11rsa->slot, NULL, &session);
if (ret) if (ret)
return -1; return -1;
ret = P11FUNC(p11rsa->p, SignInit, ret = P11FUNC(p11rsa->p, SignInit, (session, &mechanism, key));
(P11SESSION(p11rsa->slot), &mechanism, key));
if (ret != CKR_OK) { if (ret != CKR_OK) {
p11_put_session(p11rsa->p, p11rsa->slot); p11_put_session(p11rsa->p, p11rsa->slot, session);
return -1; return -1;
} }
ret = P11FUNC(p11rsa->p, Sign, ret = P11FUNC(p11rsa->p, Sign,
(P11SESSION(p11rsa->slot), (CK_BYTE *)from, (session, (CK_BYTE *)from, flen, to, &ck_sigsize));
flen, to, &ck_sigsize));
if (ret != CKR_OK) if (ret != CKR_OK)
return -1; return -1;
p11_put_session(p11rsa->p, p11rsa->slot); p11_put_session(p11rsa->p, p11rsa->slot, session);
return ck_sigsize; return ck_sigsize;
} }
@@ -147,6 +149,7 @@ p11_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
{ {
struct p11_rsa *p11rsa = RSA_get_app_data(rsa); struct p11_rsa *p11rsa = RSA_get_app_data(rsa);
CK_OBJECT_HANDLE key = p11rsa->private_key; CK_OBJECT_HANDLE key = p11rsa->private_key;
CK_SESSION_HANDLE session;
CK_MECHANISM mechanism; CK_MECHANISM mechanism;
CK_ULONG ck_sigsize; CK_ULONG ck_sigsize;
int ret; int ret;
@@ -159,24 +162,22 @@ p11_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
ck_sigsize = RSA_size(rsa); ck_sigsize = RSA_size(rsa);
ret = p11_get_session(p11rsa->p, p11rsa->slot, NULL); ret = p11_get_session(p11rsa->p, p11rsa->slot, NULL, &session);
if (ret) if (ret)
return -1; return -1;
ret = P11FUNC(p11rsa->p, DecryptInit, ret = P11FUNC(p11rsa->p, DecryptInit, (session, &mechanism, key));
(P11SESSION(p11rsa->slot), &mechanism, key));
if (ret != CKR_OK) { if (ret != CKR_OK) {
p11_put_session(p11rsa->p, p11rsa->slot); p11_put_session(p11rsa->p, p11rsa->slot, session);
return -1; return -1;
} }
ret = P11FUNC(p11rsa->p, Decrypt, ret = P11FUNC(p11rsa->p, Decrypt,
(P11SESSION(p11rsa->slot), (CK_BYTE *)from, (session, (CK_BYTE *)from, flen, to, &ck_sigsize));
flen, to, &ck_sigsize));
if (ret != CKR_OK) if (ret != CKR_OK)
return -1; return -1;
p11_put_session(p11rsa->p, p11rsa->slot); p11_put_session(p11rsa->p, p11rsa->slot, session);
return ck_sigsize; return ck_sigsize;
} }
@@ -257,8 +258,10 @@ p11_init_slot(struct p11_module *p, CK_SLOT_ID id, struct p11_slot *slot)
static int static int
p11_get_session(struct p11_module *p, p11_get_session(struct p11_module *p,
struct p11_slot *slot, struct p11_slot *slot,
hx509_lock lock) hx509_lock lock,
CK_SESSION_HANDLE *psession)
{ {
CK_SESSION_HANDLE session;
CK_RV ret; CK_RV ret;
if (slot->flags & P11_SESSION) if (slot->flags & P11_SESSION)
@@ -268,7 +271,7 @@ p11_get_session(struct p11_module *p,
CKF_SERIAL_SESSION, CKF_SERIAL_SESSION,
NULL, NULL,
NULL, NULL,
&slot->session)); &session));
if (ret != CKR_OK) if (ret != CKR_OK)
return EINVAL; return EINVAL;
@@ -316,16 +319,16 @@ p11_get_session(struct p11_module *p,
strlcpy(pin, slot->pin, sizeof(pin)); strlcpy(pin, slot->pin, sizeof(pin));
} }
ret = P11FUNC(p, Login, (P11SESSION(slot), CKU_USER, ret = P11FUNC(p, Login, (session, CKU_USER,
(unsigned char*)pin, strlen(pin))); (unsigned char*)pin, strlen(pin)));
if (ret != CKR_OK) { if (ret != CKR_OK) {
p11_put_session(p, slot); p11_put_session(p, slot, session);
return EINVAL; return EINVAL;
} }
if (slot->pin == NULL) { if (slot->pin == NULL) {
slot->pin = strdup(pin); slot->pin = strdup(pin);
if (slot->pin == NULL) { if (slot->pin == NULL) {
p11_put_session(p, slot); p11_put_session(p, slot, session);
return EINVAL; return EINVAL;
} }
} }
@@ -333,11 +336,15 @@ p11_get_session(struct p11_module *p,
} else } else
slot->flags |= P11_LOGIN_DONE; slot->flags |= P11_LOGIN_DONE;
*psession = session;
return 0; return 0;
} }
static int static int
p11_put_session(struct p11_module *p, struct p11_slot *slot) p11_put_session(struct p11_module *p,
struct p11_slot *slot,
CK_SESSION_HANDLE session)
{ {
int ret; int ret;
@@ -345,7 +352,7 @@ p11_put_session(struct p11_module *p, struct p11_slot *slot)
_hx509_abort("slot not in session"); _hx509_abort("slot not in session");
slot->flags &= ~P11_SESSION; slot->flags &= ~P11_SESSION;
ret = P11FUNC(p, CloseSession, (P11SESSION(slot))); ret = P11FUNC(p, CloseSession, (session));
if (ret != CKR_OK) if (ret != CKR_OK)
return EINVAL; return EINVAL;
@@ -354,9 +361,11 @@ p11_put_session(struct p11_module *p, struct p11_slot *slot)
static int static int
iterate_entries(struct p11_module *p, struct p11_slot *slot, iterate_entries(struct p11_module *p, struct p11_slot *slot,
CK_SESSION_HANDLE session,
CK_ATTRIBUTE *search_data, int num_search_data, CK_ATTRIBUTE *search_data, int num_search_data,
CK_ATTRIBUTE *query, int num_query, CK_ATTRIBUTE *query, int num_query,
int (*func)(struct p11_module *, struct p11_slot *, int (*func)(struct p11_module *, struct p11_slot *,
CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object, CK_OBJECT_HANDLE object,
void *, CK_ATTRIBUTE *, int), void *ptr) void *, CK_ATTRIBUTE *, int), void *ptr)
{ {
@@ -364,14 +373,12 @@ iterate_entries(struct p11_module *p, struct p11_slot *slot,
CK_ULONG object_count; CK_ULONG object_count;
int ret, i; int ret, i;
ret = P11FUNC(p, FindObjectsInit, ret = P11FUNC(p, FindObjectsInit, (session, search_data, num_search_data));
(P11SESSION(slot), search_data, num_search_data));
if (ret != CKR_OK) { if (ret != CKR_OK) {
return -1; return -1;
} }
while (1) { while (1) {
ret = P11FUNC(p, FindObjects, ret = P11FUNC(p, FindObjects, (session, &object, 1, &object_count));
(P11SESSION(slot), &object, 1, &object_count));
if (ret != CKR_OK) { if (ret != CKR_OK) {
return -1; return -1;
} }
@@ -382,7 +389,7 @@ iterate_entries(struct p11_module *p, struct p11_slot *slot,
query[i].pValue = NULL; query[i].pValue = NULL;
ret = P11FUNC(p, GetAttributeValue, ret = P11FUNC(p, GetAttributeValue,
(P11SESSION(slot), object, query, num_query)); (session, object, query, num_query));
if (ret != CKR_OK) { if (ret != CKR_OK) {
return -1; return -1;
} }
@@ -394,13 +401,13 @@ iterate_entries(struct p11_module *p, struct p11_slot *slot,
} }
} }
ret = P11FUNC(p, GetAttributeValue, ret = P11FUNC(p, GetAttributeValue,
(P11SESSION(slot), object, query, num_query)); (session, object, query, num_query));
if (ret != CKR_OK) { if (ret != CKR_OK) {
ret = -1; ret = -1;
goto out; goto out;
} }
ret = (*func)(p, slot, object, ptr, query, num_query); ret = (*func)(p, slot, session, object, ptr, query, num_query);
if (ret) if (ret)
goto out; goto out;
@@ -418,7 +425,7 @@ iterate_entries(struct p11_module *p, struct p11_slot *slot,
query[i].pValue = NULL; query[i].pValue = NULL;
} }
ret = P11FUNC(p, FindObjectsFinal, (P11SESSION(slot))); ret = P11FUNC(p, FindObjectsFinal, (session));
if (ret != CKR_OK) { if (ret != CKR_OK) {
return -2; return -2;
} }
@@ -428,8 +435,11 @@ iterate_entries(struct p11_module *p, struct p11_slot *slot,
} }
static BIGNUM * static BIGNUM *
getattr_bn(struct p11_module *p, struct p11_slot *slot, getattr_bn(struct p11_module *p,
CK_OBJECT_HANDLE object, unsigned int type) struct p11_slot *slot,
CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object,
unsigned int type)
{ {
CK_ATTRIBUTE query; CK_ATTRIBUTE query;
BIGNUM *bn; BIGNUM *bn;
@@ -440,14 +450,14 @@ getattr_bn(struct p11_module *p, struct p11_slot *slot,
query.ulValueLen = 0; query.ulValueLen = 0;
ret = P11FUNC(p, GetAttributeValue, ret = P11FUNC(p, GetAttributeValue,
(P11SESSION(slot), object, &query, 1)); (session, object, &query, 1));
if (ret != CKR_OK) if (ret != CKR_OK)
return NULL; return NULL;
query.pValue = malloc(query.ulValueLen); query.pValue = malloc(query.ulValueLen);
ret = P11FUNC(p, GetAttributeValue, ret = P11FUNC(p, GetAttributeValue,
(P11SESSION(slot), object, &query, 1)); (session, object, &query, 1));
if (ret != CKR_OK) { if (ret != CKR_OK) {
free(query.pValue); free(query.pValue);
return NULL; return NULL;
@@ -465,6 +475,7 @@ struct p11_collector {
static int static int
collect_private_key(struct p11_module *p, struct p11_slot *slot, collect_private_key(struct p11_module *p, struct p11_slot *slot,
CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object, CK_OBJECT_HANDLE object,
void *ptr, CK_ATTRIBUTE *query, int num_query) void *ptr, CK_ATTRIBUTE *query, int num_query)
{ {
@@ -489,10 +500,10 @@ collect_private_key(struct p11_module *p, struct p11_slot *slot,
if (rsa == NULL) if (rsa == NULL)
_hx509_abort("out of memory"); _hx509_abort("out of memory");
rsa->n = getattr_bn(p, slot, object, CKA_MODULUS); rsa->n = getattr_bn(p, slot, session, object, CKA_MODULUS);
if (rsa->n == NULL) if (rsa->n == NULL)
_hx509_abort("CKA_MODULUS missing"); _hx509_abort("CKA_MODULUS missing");
rsa->e = getattr_bn(p, slot, object, CKA_PUBLIC_EXPONENT); rsa->e = getattr_bn(p, slot, session, object, CKA_PUBLIC_EXPONENT);
if (rsa->e == NULL) if (rsa->e == NULL)
_hx509_abort("CKA_PUBLIC_EXPONENT missing"); _hx509_abort("CKA_PUBLIC_EXPONENT missing");
@@ -528,8 +539,17 @@ collect_private_key(struct p11_module *p, struct p11_slot *slot,
return 0; return 0;
} }
static void
p11_cert_release(hx509_cert cert, void *ctx)
{
struct p11_module *p = ctx;
p11_release_module(p);
}
static int static int
collect_cert(struct p11_module *p, struct p11_slot *slot, collect_cert(struct p11_module *p, struct p11_slot *slot,
CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object, CK_OBJECT_HANDLE object,
void *ptr, CK_ATTRIBUTE *query, int num_query) void *ptr, CK_ATTRIBUTE *query, int num_query)
{ {
@@ -552,6 +572,13 @@ collect_cert(struct p11_module *p, struct p11_slot *slot,
if (ret) if (ret)
return ret; return ret;
p->refcount++;
if (p->refcount == 0)
_hx509_abort("pkcs11 refcount to high");
_hx509_cert_set_release(cert, p11_cert_release, p);
_hx509_set_cert_attribute(ctx->context, _hx509_set_cert_attribute(ctx->context,
cert, cert,
oid_id_pkcs_9_at_localKeyId(), oid_id_pkcs_9_at_localKeyId(),
@@ -571,6 +598,7 @@ static int
p11_list_keys(hx509_context context, p11_list_keys(hx509_context context,
struct p11_module *p, struct p11_module *p,
struct p11_slot *slot, struct p11_slot *slot,
CK_SESSION_HANDLE session,
hx509_lock lock, hx509_lock lock,
hx509_certs *certs) hx509_certs *certs)
{ {
@@ -595,7 +623,7 @@ p11_list_keys(hx509_context context,
return ENOMEM; return ENOMEM;
key_class = CKO_PRIVATE_KEY; key_class = CKO_PRIVATE_KEY;
ret = iterate_entries(p, slot, ret = iterate_entries(p, slot, session,
search_data, 1, search_data, 1,
query_data, 1, query_data, 1,
collect_private_key, &ctx); collect_private_key, &ctx);
@@ -603,7 +631,7 @@ p11_list_keys(hx509_context context,
goto out; goto out;
key_class = CKO_CERTIFICATE; key_class = CKO_CERTIFICATE;
ret = iterate_entries(p, slot, ret = iterate_entries(p, slot, session,
search_data, 1, search_data, 1,
query_data, 2, query_data, 2,
collect_cert, &ctx); collect_cert, &ctx);
@@ -709,10 +737,12 @@ p11_init(hx509_context context,
} }
{ {
CK_SESSION_HANDLE session;
CK_SLOT_ID_PTR slot_ids; CK_SLOT_ID_PTR slot_ids;
slot_ids = malloc(p->num_slots * sizeof(*slot_ids)); slot_ids = malloc(p->num_slots * sizeof(*slot_ids));
if (slot_ids == NULL) { if (slot_ids == NULL) {
hx509_clear_error_string(context);
ret = ENOMEM; ret = ENOMEM;
goto out; goto out;
} }
@@ -720,20 +750,32 @@ p11_init(hx509_context context,
ret = P11FUNC(p, GetSlotList, (FALSE, slot_ids, &p->num_slots)); ret = P11FUNC(p, GetSlotList, (FALSE, slot_ids, &p->num_slots));
if (ret) { if (ret) {
free(slot_ids); free(slot_ids);
hx509_set_error_string(context, 0, EINVAL,
"Failed getting slot-list from "
"PKCS11 module");
ret = EINVAL; ret = EINVAL;
goto out; goto out;
} }
ret = p11_init_slot(p, slot_ids[p->selected_slot], &p->slot); ret = p11_init_slot(p, slot_ids[p->selected_slot], &p->slot);
free(slot_ids); free(slot_ids);
if (ret) if (ret) {
hx509_set_error_string(context, 0, ret,
"Failed to init PKCS11 slot %d",
p->selected_slot);
goto out; goto out;
}
ret = p11_get_session(p, &p->slot, lock); ret = p11_get_session(p, &p->slot, lock, &session);
if (ret) if (ret) {
hx509_set_error_string(context, 0, ret,
"Failed to get session PKCS11 slot %d",
p->selected_slot);
goto out; goto out;
ret = p11_list_keys(context, p, &p->slot, NULL, &p->slot.certs); }
p11_put_session(p, &p->slot); ret = p11_list_keys(context, p, &p->slot, session,
NULL, &p->slot.certs);
p11_put_session(p, &p->slot, session);
} }
*data = p; *data = p;