From 4abe3b3bced6300e69c9c10dc0d9db767c022982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Love=20H=C3=B6rnquist=20=C3=85strand?= Date: Sat, 27 May 2006 10:58:07 +0000 Subject: [PATCH] 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 --- lib/hx509/ks_p11.c | 138 +++++++++++++++++++++++++++++---------------- 1 file changed, 90 insertions(+), 48 deletions(-) diff --git a/lib/hx509/ks_p11.c b/lib/hx509/ks_p11.c index 8bb7de0dd..17187d42b 100644 --- a/lib/hx509/ks_p11.c +++ b/lib/hx509/ks_p11.c @@ -50,7 +50,6 @@ struct p11_module { #define P11_SESSION 1 #define P11_LOGIN_REQ 2 #define P11_LOGIN_DONE 4 - CK_SESSION_HANDLE session; CK_SLOT_ID id; CK_BBOOL token; char *name; @@ -59,11 +58,15 @@ struct p11_module { } slot; }; -#define P11SESSION(module) ((module)->session) #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_put_session(struct p11_module *, struct p11_slot *); +static int p11_get_session(struct p11_module *, + 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 *); /* @@ -107,6 +110,7 @@ p11_rsa_private_encrypt(int flen, { struct p11_rsa *p11rsa = RSA_get_app_data(rsa); CK_OBJECT_HANDLE key = p11rsa->private_key; + CK_SESSION_HANDLE session; CK_MECHANISM mechanism; CK_ULONG ck_sigsize; int ret; @@ -119,24 +123,22 @@ p11_rsa_private_encrypt(int flen, 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) return -1; - ret = P11FUNC(p11rsa->p, SignInit, - (P11SESSION(p11rsa->slot), &mechanism, key)); + ret = P11FUNC(p11rsa->p, SignInit, (session, &mechanism, key)); if (ret != CKR_OK) { - p11_put_session(p11rsa->p, p11rsa->slot); + p11_put_session(p11rsa->p, p11rsa->slot, session); return -1; } - ret = P11FUNC(p11rsa->p, Sign, - (P11SESSION(p11rsa->slot), (CK_BYTE *)from, - flen, to, &ck_sigsize)); + ret = P11FUNC(p11rsa->p, Sign, + (session, (CK_BYTE *)from, flen, to, &ck_sigsize)); if (ret != CKR_OK) return -1; - p11_put_session(p11rsa->p, p11rsa->slot); + p11_put_session(p11rsa->p, p11rsa->slot, session); 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); CK_OBJECT_HANDLE key = p11rsa->private_key; + CK_SESSION_HANDLE session; CK_MECHANISM mechanism; CK_ULONG ck_sigsize; int ret; @@ -159,24 +162,22 @@ p11_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to, 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) return -1; - ret = P11FUNC(p11rsa->p, DecryptInit, - (P11SESSION(p11rsa->slot), &mechanism, key)); + ret = P11FUNC(p11rsa->p, DecryptInit, (session, &mechanism, key)); if (ret != CKR_OK) { - p11_put_session(p11rsa->p, p11rsa->slot); + p11_put_session(p11rsa->p, p11rsa->slot, session); return -1; } - ret = P11FUNC(p11rsa->p, Decrypt, - (P11SESSION(p11rsa->slot), (CK_BYTE *)from, - flen, to, &ck_sigsize)); + ret = P11FUNC(p11rsa->p, Decrypt, + (session, (CK_BYTE *)from, flen, to, &ck_sigsize)); if (ret != CKR_OK) return -1; - p11_put_session(p11rsa->p, p11rsa->slot); + p11_put_session(p11rsa->p, p11rsa->slot, session); return ck_sigsize; } @@ -257,8 +258,10 @@ p11_init_slot(struct p11_module *p, CK_SLOT_ID id, struct p11_slot *slot) static int p11_get_session(struct p11_module *p, struct p11_slot *slot, - hx509_lock lock) + hx509_lock lock, + CK_SESSION_HANDLE *psession) { + CK_SESSION_HANDLE session; CK_RV ret; if (slot->flags & P11_SESSION) @@ -268,7 +271,7 @@ p11_get_session(struct p11_module *p, CKF_SERIAL_SESSION, NULL, NULL, - &slot->session)); + &session)); if (ret != CKR_OK) return EINVAL; @@ -316,16 +319,16 @@ p11_get_session(struct p11_module *p, 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))); if (ret != CKR_OK) { - p11_put_session(p, slot); + p11_put_session(p, slot, session); return EINVAL; } if (slot->pin == NULL) { slot->pin = strdup(pin); if (slot->pin == NULL) { - p11_put_session(p, slot); + p11_put_session(p, slot, session); return EINVAL; } } @@ -333,11 +336,15 @@ p11_get_session(struct p11_module *p, } else slot->flags |= P11_LOGIN_DONE; + *psession = session; + return 0; } 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; @@ -345,7 +352,7 @@ p11_put_session(struct p11_module *p, struct p11_slot *slot) _hx509_abort("slot not in session"); slot->flags &= ~P11_SESSION; - ret = P11FUNC(p, CloseSession, (P11SESSION(slot))); + ret = P11FUNC(p, CloseSession, (session)); if (ret != CKR_OK) return EINVAL; @@ -354,9 +361,11 @@ p11_put_session(struct p11_module *p, struct p11_slot *slot) static int iterate_entries(struct p11_module *p, struct p11_slot *slot, + CK_SESSION_HANDLE session, CK_ATTRIBUTE *search_data, int num_search_data, CK_ATTRIBUTE *query, int num_query, int (*func)(struct p11_module *, struct p11_slot *, + CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, void *, CK_ATTRIBUTE *, int), void *ptr) { @@ -364,14 +373,12 @@ iterate_entries(struct p11_module *p, struct p11_slot *slot, CK_ULONG object_count; int ret, i; - ret = P11FUNC(p, FindObjectsInit, - (P11SESSION(slot), search_data, num_search_data)); + ret = P11FUNC(p, FindObjectsInit, (session, search_data, num_search_data)); if (ret != CKR_OK) { return -1; } while (1) { - ret = P11FUNC(p, FindObjects, - (P11SESSION(slot), &object, 1, &object_count)); + ret = P11FUNC(p, FindObjects, (session, &object, 1, &object_count)); if (ret != CKR_OK) { return -1; } @@ -382,7 +389,7 @@ iterate_entries(struct p11_module *p, struct p11_slot *slot, query[i].pValue = NULL; ret = P11FUNC(p, GetAttributeValue, - (P11SESSION(slot), object, query, num_query)); + (session, object, query, num_query)); if (ret != CKR_OK) { return -1; } @@ -394,13 +401,13 @@ iterate_entries(struct p11_module *p, struct p11_slot *slot, } } ret = P11FUNC(p, GetAttributeValue, - (P11SESSION(slot), object, query, num_query)); + (session, object, query, num_query)); if (ret != CKR_OK) { ret = -1; goto out; } - ret = (*func)(p, slot, object, ptr, query, num_query); + ret = (*func)(p, slot, session, object, ptr, query, num_query); if (ret) goto out; @@ -418,7 +425,7 @@ iterate_entries(struct p11_module *p, struct p11_slot *slot, query[i].pValue = NULL; } - ret = P11FUNC(p, FindObjectsFinal, (P11SESSION(slot))); + ret = P11FUNC(p, FindObjectsFinal, (session)); if (ret != CKR_OK) { return -2; } @@ -428,8 +435,11 @@ iterate_entries(struct p11_module *p, struct p11_slot *slot, } static BIGNUM * -getattr_bn(struct p11_module *p, struct p11_slot *slot, - CK_OBJECT_HANDLE object, unsigned int type) +getattr_bn(struct p11_module *p, + struct p11_slot *slot, + CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + unsigned int type) { CK_ATTRIBUTE query; BIGNUM *bn; @@ -440,14 +450,14 @@ getattr_bn(struct p11_module *p, struct p11_slot *slot, query.ulValueLen = 0; ret = P11FUNC(p, GetAttributeValue, - (P11SESSION(slot), object, &query, 1)); + (session, object, &query, 1)); if (ret != CKR_OK) return NULL; query.pValue = malloc(query.ulValueLen); ret = P11FUNC(p, GetAttributeValue, - (P11SESSION(slot), object, &query, 1)); + (session, object, &query, 1)); if (ret != CKR_OK) { free(query.pValue); return NULL; @@ -465,6 +475,7 @@ struct p11_collector { static int collect_private_key(struct p11_module *p, struct p11_slot *slot, + CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, 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) _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) _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) _hx509_abort("CKA_PUBLIC_EXPONENT missing"); @@ -528,8 +539,17 @@ collect_private_key(struct p11_module *p, struct p11_slot *slot, return 0; } +static void +p11_cert_release(hx509_cert cert, void *ctx) +{ + struct p11_module *p = ctx; + p11_release_module(p); +} + + static int collect_cert(struct p11_module *p, struct p11_slot *slot, + CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, void *ptr, CK_ATTRIBUTE *query, int num_query) { @@ -552,6 +572,13 @@ collect_cert(struct p11_module *p, struct p11_slot *slot, if (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, cert, oid_id_pkcs_9_at_localKeyId(), @@ -571,6 +598,7 @@ static int p11_list_keys(hx509_context context, struct p11_module *p, struct p11_slot *slot, + CK_SESSION_HANDLE session, hx509_lock lock, hx509_certs *certs) { @@ -595,7 +623,7 @@ p11_list_keys(hx509_context context, return ENOMEM; key_class = CKO_PRIVATE_KEY; - ret = iterate_entries(p, slot, + ret = iterate_entries(p, slot, session, search_data, 1, query_data, 1, collect_private_key, &ctx); @@ -603,7 +631,7 @@ p11_list_keys(hx509_context context, goto out; key_class = CKO_CERTIFICATE; - ret = iterate_entries(p, slot, + ret = iterate_entries(p, slot, session, search_data, 1, query_data, 2, collect_cert, &ctx); @@ -709,10 +737,12 @@ p11_init(hx509_context context, } { + CK_SESSION_HANDLE session; CK_SLOT_ID_PTR slot_ids; slot_ids = malloc(p->num_slots * sizeof(*slot_ids)); if (slot_ids == NULL) { + hx509_clear_error_string(context); ret = ENOMEM; goto out; } @@ -720,20 +750,32 @@ p11_init(hx509_context context, ret = P11FUNC(p, GetSlotList, (FALSE, slot_ids, &p->num_slots)); if (ret) { free(slot_ids); + hx509_set_error_string(context, 0, EINVAL, + "Failed getting slot-list from " + "PKCS11 module"); ret = EINVAL; goto out; } ret = p11_init_slot(p, slot_ids[p->selected_slot], &p->slot); 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; + } - ret = p11_get_session(p, &p->slot, lock); - if (ret) + ret = p11_get_session(p, &p->slot, lock, &session); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to get session PKCS11 slot %d", + p->selected_slot); 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;