From: Nikos Mavrogiannopoulos Date: Sat, 9 Jun 2012 12:10:44 +0000 (+0200) Subject: In tokens that allow multiple sessions make the private key session persistent. X-Git-Tag: gnutls_3_0_21~47 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0e0c9260ff9c862f47598e9ee6bccbc024d280b4;p=thirdparty%2Fgnutls.git In tokens that allow multiple sessions make the private key session persistent. This prevents asking for PIN on every private key operation. --- diff --git a/lib/pkcs11.c b/lib/pkcs11.c index 9510a06f0d..0f9c1b0629 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -831,21 +831,18 @@ gnutls_pkcs11_obj_export (gnutls_pkcs11_obj_t obj, } int -pkcs11_find_object (struct ck_function_list ** _module, - ck_session_handle_t * _pks, +pkcs11_find_object (struct pkcs11_session_info* sinfo, ck_object_handle_t * _obj, struct p11_kit_uri *info, unsigned int flags) { int ret; - struct ck_function_list *module; - ck_session_handle_t pks; ck_object_handle_t obj; struct ck_attribute *attrs; unsigned long attr_count; unsigned long count; ck_rv_t rv; - ret = pkcs11_open_session (&module, &pks, info, flags & SESSION_LOGIN); + ret = pkcs11_open_session (sinfo, info, flags & SESSION_LOGIN); if (ret < 0) { gnutls_assert (); @@ -853,7 +850,7 @@ pkcs11_find_object (struct ck_function_list ** _module, } attrs = p11_kit_uri_get_attributes (info, &attr_count); - rv = pkcs11_find_objects_init (module, pks, attrs, attr_count); + rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, attrs, attr_count); if (rv != CKR_OK) { gnutls_assert (); @@ -862,19 +859,17 @@ pkcs11_find_object (struct ck_function_list ** _module, goto fail; } - if (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1) + if (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1) { *_obj = obj; - *_pks = pks; - *_module = module; - pkcs11_find_objects_final (module, pks); + pkcs11_find_objects_final (sinfo); return 0; } ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - pkcs11_find_objects_final (module, pks); + pkcs11_find_objects_final (sinfo); fail: - pkcs11_close_session (module, pks); + pkcs11_close_session (sinfo); return ret; } @@ -929,8 +924,8 @@ pkcs11_find_slot (struct ck_function_list ** module, ck_slot_id_t * slot, } int -pkcs11_open_session (struct ck_function_list ** _module, ck_session_handle_t * _pks, - struct p11_kit_uri *info, unsigned int flags) +pkcs11_open_session (struct pkcs11_session_info *sinfo, struct p11_kit_uri *info, + unsigned int flags) { ck_rv_t rv; int ret; @@ -956,20 +951,23 @@ pkcs11_open_session (struct ck_function_list ** _module, ck_session_handle_t * _ return pkcs11_rv_to_err (rv); } + /* ok found */ + sinfo->pks = pks; + sinfo->module = module; + sinfo->init = 1; + memcpy(&sinfo->tinfo, &tinfo.tinfo, sizeof(sinfo->tinfo)); + if (flags & SESSION_LOGIN) { - ret = pkcs11_login (module, pks, &tinfo, info, (flags & SESSION_SO) ? 1 : 0); + ret = pkcs11_login (sinfo, &tinfo, info, (flags & SESSION_SO) ? 1 : 0); if (ret < 0) { gnutls_assert (); - pkcs11_close_session (module, pks); + pkcs11_close_session (sinfo); return ret; } } - /* ok found */ - *_pks = pks; - *_module = module; return 0; } @@ -982,6 +980,7 @@ _pkcs11_traverse_tokens (find_func_t find_func, void *input, unsigned int found = 0, x, z; int ret; ck_session_handle_t pks = 0; + struct pkcs11_session_info sinfo; struct ck_function_list *module = NULL; for (x = 0; x < active_providers; x++) @@ -1015,10 +1014,13 @@ _pkcs11_traverse_tokens (find_func_t find_func, void *input, { continue; } + + sinfo.module = module; + sinfo.pks = pks; if (flags & SESSION_LOGIN) { - ret = pkcs11_login (module, pks, &tinfo, info, (flags & SESSION_SO) ? 1 : 0); + ret = pkcs11_login (&sinfo, &tinfo, info, (flags & SESSION_SO) ? 1 : 0); if (ret < 0) { gnutls_assert (); @@ -1026,7 +1028,7 @@ _pkcs11_traverse_tokens (find_func_t find_func, void *input, } } - ret = find_func (module, pks, &tinfo, &providers[x].info, input); + ret = find_func (&sinfo, &tinfo, &providers[x].info, input); if (ret == 0) { @@ -1035,7 +1037,7 @@ _pkcs11_traverse_tokens (find_func_t find_func, void *input, } else { - pkcs11_close_session (module, pks); + pkcs11_close_session (&sinfo); pks = 0; } } @@ -1047,7 +1049,11 @@ finish: if (found == 0) { if (module) - ret = find_func (module, pks, NULL, NULL, input); + { + sinfo.module = module; + sinfo.pks = pks; + ret = find_func (&sinfo, NULL, NULL, input); + } else ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); } @@ -1058,7 +1064,7 @@ finish: if (pks != 0 && module != NULL) { - pkcs11_close_session (module, pks); + pkcs11_close_session (&sinfo); } return ret; @@ -1401,7 +1407,7 @@ pkcs11_obj_import_pubkey (struct ck_function_list *module, } static int -find_obj_url (struct ck_function_list *module, ck_session_handle_t pks, +find_obj_url (struct pkcs11_session_info *sinfo, struct token_info *info, struct ck_info *lib_info, void *input) { struct url_find_data_st *find_data = input; @@ -1470,7 +1476,7 @@ find_obj_url (struct ck_function_list *module, ck_session_handle_t pks, a_vals++; } - rv = pkcs11_find_objects_init (module, pks, a, a_vals); + rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, a_vals); if (rv != CKR_OK) { gnutls_assert (); @@ -1479,7 +1485,7 @@ find_obj_url (struct ck_function_list *module, ck_session_handle_t pks, goto cleanup; } - while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1) + while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1) { a[0].type = CKA_VALUE; @@ -1489,7 +1495,7 @@ find_obj_url (struct ck_function_list *module, ck_session_handle_t pks, a[1].value = label_tmp; a[1].value_len = sizeof (label_tmp); - if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK) + if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 2) == CKR_OK) { gnutls_datum_t id; gnutls_datum_t data = { a[0].value, a[0].value_len }; @@ -1502,7 +1508,7 @@ find_obj_url (struct ck_function_list *module, ck_session_handle_t pks, if (class == CKO_PUBLIC_KEY) { ret = - pkcs11_obj_import_pubkey (module, pks, obj, + pkcs11_obj_import_pubkey (sinfo->module, sinfo->pks, obj, find_data->crt, &id, &label, &info->tinfo, lib_info); @@ -1542,7 +1548,7 @@ find_obj_url (struct ck_function_list *module, ck_session_handle_t pks, cleanup: gnutls_free (cert_data); - pkcs11_find_objects_final (module, pks); + pkcs11_find_objects_final (sinfo); return ret; } @@ -1614,8 +1620,7 @@ struct token_num }; static int -find_token_num (struct ck_function_list *module, - ck_session_handle_t pks, +find_token_num (struct pkcs11_session_info* sinfo, struct token_info *tinfo, struct ck_info *lib_info, void *input) { @@ -1987,7 +1992,7 @@ retrieve_pin (struct p11_kit_uri *info, struct ck_token_info *token_info, } int -pkcs11_login (struct ck_function_list * module, ck_session_handle_t pks, +pkcs11_login (struct pkcs11_session_info * sinfo, const struct token_info *tokinfo, struct p11_kit_uri *info, int so) { struct ck_session_info session_info; @@ -2008,7 +2013,7 @@ pkcs11_login (struct ck_function_list * module, ck_session_handle_t pks, * required. */ if (tokinfo->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) { - rv = (module)->C_Login (pks, (so == 0) ? CKU_USER : CKU_SO, NULL, 0); + rv = (sinfo->module)->C_Login (sinfo->pks, (so == 0) ? CKU_USER : CKU_SO, NULL, 0); if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) { return 0; @@ -2030,7 +2035,7 @@ pkcs11_login (struct ck_function_list * module, ck_session_handle_t pks, memcpy (&tinfo, &tokinfo->tinfo, sizeof(tinfo)); /* Check whether the session is already logged in, and if so, just skip */ - rv = (module)->C_GetSessionInfo (pks, &session_info); + rv = (sinfo->module)->C_GetSessionInfo (sinfo->pks, &session_info); if (rv == CKR_OK && (session_info.state == CKS_RO_USER_FUNCTIONS || session_info.state == CKS_RW_USER_FUNCTIONS)) { @@ -2059,7 +2064,7 @@ pkcs11_login (struct ck_function_list * module, ck_session_handle_t pks, goto cleanup; } - rv = (module)->C_Login (pks, user_type, + rv = (sinfo->module)->C_Login (sinfo->pks, user_type, (unsigned char *)p11_kit_pin_get_value (pin, NULL), p11_kit_pin_get_length (pin)); @@ -2094,7 +2099,7 @@ pkcs11_call_token_func (struct p11_kit_uri *info, const unsigned retry) static int -find_privkeys (struct ck_function_list *module, ck_session_handle_t pks, +find_privkeys (struct pkcs11_session_info* sinfo, struct token_info *info, struct pkey_list *list) { struct ck_attribute a[3]; @@ -2113,7 +2118,7 @@ find_privkeys (struct ck_function_list *module, ck_session_handle_t pks, a[0].value = &class; a[0].value_len = sizeof class; - rv = pkcs11_find_objects_init (module, pks, a, 1); + rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, 1); if (rv != CKR_OK) { gnutls_assert (); @@ -2121,12 +2126,12 @@ find_privkeys (struct ck_function_list *module, ck_session_handle_t pks, } list->key_ids_size = 0; - while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1) + while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1) { list->key_ids_size++; } - pkcs11_find_objects_final (module, pks); + pkcs11_find_objects_final (sinfo); if (list->key_ids_size == 0) { @@ -2147,7 +2152,7 @@ find_privkeys (struct ck_function_list *module, ck_session_handle_t pks, a[0].value = &class; a[0].value_len = sizeof class; - rv = pkcs11_find_objects_init (module, pks, a, 1); + rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, 1); if (rv != CKR_OK) { gnutls_assert (); @@ -2155,7 +2160,7 @@ find_privkeys (struct ck_function_list *module, ck_session_handle_t pks, } current = 0; - while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1) + while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1) { a[0].type = CKA_ID; @@ -2164,7 +2169,7 @@ find_privkeys (struct ck_function_list *module, ck_session_handle_t pks, _gnutls_buffer_init (&list->key_ids[current]); - if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK) + if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK) { _gnutls_buffer_append_data (&list->key_ids[current], a[0].value, a[0].value_len); @@ -2175,7 +2180,7 @@ find_privkeys (struct ck_function_list *module, ck_session_handle_t pks, break; } - pkcs11_find_objects_final (module, pks); + pkcs11_find_objects_final (sinfo); list->key_ids_size = current - 1; @@ -2186,7 +2191,7 @@ find_privkeys (struct ck_function_list *module, ck_session_handle_t pks, static int -find_objs (struct ck_function_list * module, ck_session_handle_t pks, +find_objs (struct pkcs11_session_info* sinfo, struct token_info *info, struct ck_info *lib_info, void *input) { struct crt_find_data_st *find_data = input; @@ -2230,7 +2235,7 @@ find_objs (struct ck_function_list * module, ck_session_handle_t pks, if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) { - ret = find_privkeys (module, pks, info, &plist); + ret = find_privkeys (sinfo, info, &plist); if (ret < 0) { gnutls_assert (); @@ -2339,7 +2344,7 @@ find_objs (struct ck_function_list * module, ck_session_handle_t pks, tot_values++; } - rv = pkcs11_find_objects_init (module, pks, a, tot_values); + rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, tot_values); if (rv != CKR_OK) { gnutls_assert (); @@ -2347,7 +2352,7 @@ find_objs (struct ck_function_list * module, ck_session_handle_t pks, return pkcs11_rv_to_err (rv); } - while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1) + while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1) { gnutls_datum_t label, id, value; @@ -2355,7 +2360,7 @@ find_objs (struct ck_function_list * module, ck_session_handle_t pks, a[0].value = label_tmp; a[0].value_len = sizeof label_tmp; - if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK) + if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK) { label.data = a[0].value; label.size = a[0].value_len; @@ -2370,7 +2375,7 @@ find_objs (struct ck_function_list * module, ck_session_handle_t pks, a[0].value = certid_tmp; a[0].value_len = sizeof certid_tmp; - if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK) + if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK) { id.data = a[0].value; id.size = a[0].value_len; @@ -2384,7 +2389,7 @@ find_objs (struct ck_function_list * module, ck_session_handle_t pks, a[0].type = CKA_VALUE; a[0].value = cert_data; a[0].value_len = MAX_CERT_SIZE; - if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK) + if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK) { value.data = a[0].value; value.size = a[0].value_len; @@ -2401,7 +2406,7 @@ find_objs (struct ck_function_list * module, ck_session_handle_t pks, a[0].value = &class; a[0].value_len = sizeof class; - pkcs11_get_attribute_value (module, pks, obj, a, 1); + pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1); } if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) @@ -2432,7 +2437,7 @@ find_objs (struct ck_function_list * module, ck_session_handle_t pks, if (class == CKO_PUBLIC_KEY) { ret = - pkcs11_obj_import_pubkey (module, pks, obj, + pkcs11_obj_import_pubkey (sinfo->module, sinfo->pks, obj, find_data->p_list [find_data->current], &id, &label, @@ -2459,13 +2464,13 @@ find_objs (struct ck_function_list * module, ck_session_handle_t pks, } gnutls_free (cert_data); - pkcs11_find_objects_final (module, pks); + pkcs11_find_objects_final (sinfo); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* continue until all tokens have been checked */ fail: gnutls_free (cert_data); - pkcs11_find_objects_final (module, pks); + pkcs11_find_objects_final (sinfo); if (plist.key_ids != NULL) { for (i = 0; i < plist.key_ids_size; i++) @@ -2725,7 +2730,7 @@ cleanup: } static int -find_flags (struct ck_function_list * module, ck_session_handle_t pks, +find_flags (struct pkcs11_session_info* sinfo, struct token_info *info, struct ck_info *lib_info, void *input) { struct flags_find_data_st *find_data = input; @@ -2943,17 +2948,16 @@ pkcs11_find_objects (struct ck_function_list *module, } ck_rv_t -pkcs11_find_objects_final (struct ck_function_list *module, - ck_session_handle_t sess) +pkcs11_find_objects_final (struct pkcs11_session_info* sinfo) { - return (module)->C_FindObjectsFinal (sess); + return (sinfo->module)->C_FindObjectsFinal (sinfo->pks); } ck_rv_t -pkcs11_close_session (struct ck_function_list *module, - ck_session_handle_t sess) +pkcs11_close_session (struct pkcs11_session_info * sinfo) { - return (module)->C_CloseSession (sess); + sinfo->init = 0; + return (sinfo->module)->C_CloseSession (sinfo->pks); } ck_rv_t diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h index 36d53671e3..538da55fe3 100644 --- a/lib/pkcs11_int.h +++ b/lib/pkcs11_int.h @@ -34,6 +34,13 @@ #include typedef unsigned char ck_bool_t; +struct pkcs11_session_info { + struct ck_function_list * module; + struct ck_token_info tinfo; + ck_session_handle_t pks; + unsigned int init; +}; + struct token_info { struct ck_token_info tinfo; @@ -58,8 +65,7 @@ struct gnutls_pkcs11_obj_st * function. Once everything is traversed it is called with NULL tinfo. * It should return 0 if found what it was looking for. */ -typedef int (*find_func_t) (struct ck_function_list *module, - ck_session_handle_t pks, +typedef int (*find_func_t) (struct pkcs11_session_info*, struct token_info * tinfo, struct ck_info *, void *input); @@ -72,8 +78,8 @@ pkcs11_find_slot (struct ck_function_list ** module, ck_slot_id_t * slot, int pkcs11_get_info (struct p11_kit_uri *info, gnutls_pkcs11_obj_info_t itype, void *output, size_t * output_size); -int pkcs11_login (struct ck_function_list * module, ck_session_handle_t pks, - const struct token_info *tinfo, struct p11_kit_uri *info, int admin); +int pkcs11_login (struct pkcs11_session_info * sinfo, + const struct token_info *tokinfo, struct p11_kit_uri *info, int so); int pkcs11_call_token_func (struct p11_kit_uri *info, const unsigned retry); @@ -87,7 +93,7 @@ int pkcs11_info_to_url (struct p11_kit_uri *info, #define SESSION_WRITE (1<<0) #define SESSION_LOGIN (1<<1) #define SESSION_SO (1<<2) /* security officer session */ -int pkcs11_open_session (struct ck_function_list **_module, ck_session_handle_t * _pks, +int pkcs11_open_session (struct pkcs11_session_info* sinfo, struct p11_kit_uri *info, unsigned int flags); int _pkcs11_traverse_tokens (find_func_t find_func, void *input, struct p11_kit_uri *info, unsigned int flags); @@ -98,10 +104,9 @@ int pkcs11_token_matches_info (struct p11_kit_uri *info, struct ck_info *lib_info); /* flags are SESSION_* */ -int pkcs11_find_object (struct ck_function_list ** _module, - ck_session_handle_t * _pks, - ck_object_handle_t * _obj, - struct p11_kit_uri *info, unsigned int flags); +int pkcs11_find_object (struct pkcs11_session_info* sinfo, + ck_object_handle_t * _obj, + struct p11_kit_uri *info, unsigned int flags); unsigned int pkcs11_obj_flags_to_int (unsigned int flags); @@ -192,12 +197,10 @@ pkcs11_find_objects (struct ck_function_list *module, unsigned long *object_count); ck_rv_t -pkcs11_find_objects_final (struct ck_function_list *module, - ck_session_handle_t sess); +pkcs11_find_objects_final (struct pkcs11_session_info*); ck_rv_t -pkcs11_close_session (struct ck_function_list *module, - ck_session_handle_t sess); +pkcs11_close_session (struct pkcs11_session_info *); ck_rv_t pkcs11_get_attribute_value(struct ck_function_list *module, diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c index afbd8e402a..b0bee57fc9 100644 --- a/lib/pkcs11_privkey.c +++ b/lib/pkcs11_privkey.c @@ -35,6 +35,9 @@ struct gnutls_pkcs11_privkey_st struct p11_kit_uri *info; gnutls_pkcs11_pin_callback_t pin_func; void *pin_data; + + struct pkcs11_session_info sinfo; + ck_object_handle_t obj; /* the key in the session */ }; /** @@ -77,6 +80,8 @@ void gnutls_pkcs11_privkey_deinit (gnutls_pkcs11_privkey_t key) { p11_kit_uri_free (key->info); + if (key->sinfo.init != 0) + pkcs11_close_session (&key->sinfo); gnutls_free (key); } @@ -123,12 +128,12 @@ gnutls_pkcs11_privkey_get_info (gnutls_pkcs11_privkey_t pkey, } -#define FIND_OBJECT(module, pks, obj, key) \ +#define FIND_OBJECT(sinfo, obj, key) \ do { \ int retries = 0; \ int rret; \ - ret = pkcs11_find_object (&module, &pks, &obj, key->info, \ - SESSION_LOGIN); \ + ret = pkcs11_find_object (sinfo, &obj, key->info, \ + SESSION_LOGIN); \ if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \ if (token_func) \ { \ @@ -163,11 +168,21 @@ _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key, int ret; struct ck_mechanism mech; unsigned long siglen; - struct ck_function_list *module; - ck_session_handle_t pks; + struct pkcs11_session_info _sinfo; + struct pkcs11_session_info *sinfo; ck_object_handle_t obj; - FIND_OBJECT (module, pks, obj, key); + if (key->sinfo.init != 0) + { + sinfo = &key->sinfo; + obj = key->obj; + } + else + { + sinfo = &_sinfo; + memset(sinfo, 0, sizeof(*sinfo)); + FIND_OBJECT (sinfo, obj, key); + } mech.mechanism = pk_to_mech(key->pk_algorithm); mech.parameter = NULL; @@ -175,7 +190,7 @@ _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key, /* Initialize signing operation; using the private key discovered * earlier. */ - rv = pkcs11_sign_init (module, pks, &mech, obj); + rv = pkcs11_sign_init (sinfo->module, sinfo->pks, &mech, obj); if (rv != CKR_OK) { gnutls_assert (); @@ -184,7 +199,7 @@ _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key, } /* Work out how long the signature must be: */ - rv = pkcs11_sign (module, pks, hash->data, hash->size, NULL, &siglen); + rv = pkcs11_sign (sinfo->module, sinfo->pks, hash->data, hash->size, NULL, &siglen); if (rv != CKR_OK) { gnutls_assert (); @@ -195,7 +210,7 @@ _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key, signature->data = gnutls_malloc (siglen); signature->size = siglen; - rv = pkcs11_sign (module, pks, hash->data, hash->size, signature->data, &siglen); + rv = pkcs11_sign (sinfo->module, sinfo->pks, hash->data, hash->size, signature->data, &siglen); if (rv != CKR_OK) { gnutls_free (signature->data); @@ -209,7 +224,8 @@ _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key, ret = 0; cleanup: - pkcs11_close_session (module, pks); + if (sinfo != &key->sinfo) + pkcs11_close_session (sinfo); return ret; } @@ -233,12 +249,13 @@ gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey, const char *url, unsigned int flags) { int ret; - struct ck_function_list *module; struct ck_attribute *attr; - ck_session_handle_t pks; ck_object_handle_t obj; struct ck_attribute a[4]; ck_key_type_t key_type; + struct pkcs11_session_info sinfo; + + memset(&sinfo, 0, sizeof(sinfo)); ret = pkcs11_url_to_info (url, &pkey->info); if (ret < 0) @@ -264,12 +281,13 @@ gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey, return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } - FIND_OBJECT (module, pks, obj, pkey); + FIND_OBJECT (&sinfo, obj, pkey); + a[0].type = CKA_KEY_TYPE; a[0].value = &key_type; a[0].value_len = sizeof (key_type); - if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK) + if (pkcs11_get_attribute_value (sinfo.module, sinfo.pks, obj, a, 1) == CKR_OK) { pkey->pk_algorithm = mech_to_pk(key_type); if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) @@ -281,9 +299,22 @@ gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey, } ret = 0; + + if (pkey->sinfo.init) + pkcs11_close_session (&pkey->sinfo); + + if (sinfo.tinfo.max_session_count != 1) + { + /* We do not keep the session open in tokens that can + * only support a single session. + */ + memcpy(&pkey->sinfo, &sinfo, sizeof(pkey->sinfo)); + pkey->obj = obj; + return ret; + } cleanup: - pkcs11_close_session (module, pks); + pkcs11_close_session (&sinfo); return ret; } @@ -311,11 +342,21 @@ _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key, int ret; struct ck_mechanism mech; unsigned long siglen; - struct ck_function_list *module; - ck_session_handle_t pks; ck_object_handle_t obj; + struct pkcs11_session_info _sinfo; + struct pkcs11_session_info *sinfo; - FIND_OBJECT (module, pks, obj, key); + if (key->sinfo.init != 0) + { + sinfo = &key->sinfo; + obj = key->obj; + } + else + { + sinfo = &_sinfo; + memset(sinfo, 0, sizeof(*sinfo)); + FIND_OBJECT (sinfo, obj, key); + } if (key->pk_algorithm != GNUTLS_PK_RSA) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); @@ -326,7 +367,7 @@ _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key, /* Initialize signing operation; using the private key discovered * earlier. */ - rv = pkcs11_decrypt_init (module, pks, &mech, obj); + rv = pkcs11_decrypt_init (sinfo->module, sinfo->pks, &mech, obj); if (rv != CKR_OK) { gnutls_assert (); @@ -335,7 +376,7 @@ _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key, } /* Work out how long the plaintext must be: */ - rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size, + rv = pkcs11_decrypt (sinfo->module, sinfo->pks, ciphertext->data, ciphertext->size, NULL, &siglen); if (rv != CKR_OK) { @@ -347,7 +388,7 @@ _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key, plaintext->data = gnutls_malloc (siglen); plaintext->size = siglen; - rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size, + rv = pkcs11_decrypt (sinfo->module, sinfo->pks, ciphertext->data, ciphertext->size, plaintext->data, &siglen); if (rv != CKR_OK) { @@ -362,7 +403,8 @@ _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key, ret = 0; cleanup: - pkcs11_close_session (module, pks); + if (key->sinfo.init == 0) + pkcs11_close_session (sinfo); return ret; } @@ -421,8 +463,7 @@ gnutls_pkcs11_privkey_generate (const char* url, int ret; const ck_bool_t tval = 1; const ck_bool_t fval = 0; - struct ck_function_list *module; - ck_session_handle_t pks = 0; + struct pkcs11_session_info sinfo; struct p11_kit_uri *info = NULL; ck_rv_t rv; struct ck_attribute a[10], p[10]; @@ -431,6 +472,8 @@ gnutls_pkcs11_privkey_generate (const char* url, int a_val, p_val; struct ck_mechanism mech; + memset(&sinfo, 0, sizeof(sinfo)); + ret = pkcs11_url_to_info (url, &info); if (ret < 0) { @@ -439,7 +482,7 @@ gnutls_pkcs11_privkey_generate (const char* url, } ret = - pkcs11_open_session (&module, &pks, info, + pkcs11_open_session (&sinfo, info, SESSION_WRITE | pkcs11_obj_flags_to_int (flags)); p11_kit_uri_free (info); @@ -572,7 +615,7 @@ gnutls_pkcs11_privkey_generate (const char* url, p_val++; } - rv = pkcs11_generate_key_pair( module, pks, &mech, a, a_val, p, p_val, &pub, &priv); + rv = pkcs11_generate_key_pair( sinfo.module, sinfo.pks, &mech, a, a_val, p, p_val, &pub, &priv); if (rv != CKR_OK) { gnutls_assert (); @@ -583,8 +626,8 @@ gnutls_pkcs11_privkey_generate (const char* url, cleanup: - if (pks != 0) - pkcs11_close_session (module, pks); + if (sinfo.pks != 0) + pkcs11_close_session (&sinfo); return ret; } diff --git a/lib/pkcs11_secret.c b/lib/pkcs11_secret.c index 54205f741e..10d39c7855 100644 --- a/lib/pkcs11_secret.c +++ b/lib/pkcs11_secret.c @@ -50,8 +50,6 @@ gnutls_pkcs11_copy_secret_key (const char *token_url, gnutls_datum_t * key, /* GNUTLS_PKCS11_OBJ_FLAG_* */ ) { int ret; - struct ck_function_list *module; - ck_session_handle_t pks; struct p11_kit_uri *info = NULL; ck_rv_t rv; struct ck_attribute a[12]; @@ -61,6 +59,9 @@ gnutls_pkcs11_copy_secret_key (const char *token_url, gnutls_datum_t * key, ck_bool_t tval = 1; int a_val; uint8_t id[16]; + struct pkcs11_session_info sinfo; + + memset(&sinfo, 0, sizeof(sinfo)); ret = pkcs11_url_to_info (token_url, &info); if (ret < 0) @@ -78,7 +79,7 @@ gnutls_pkcs11_copy_secret_key (const char *token_url, gnutls_datum_t * key, } ret = - pkcs11_open_session (&module, &pks, info, + pkcs11_open_session (&sinfo, info, SESSION_WRITE | pkcs11_obj_flags_to_int (flags)); p11_kit_uri_free (info); @@ -129,7 +130,7 @@ gnutls_pkcs11_copy_secret_key (const char *token_url, gnutls_datum_t * key, a[a_val].value_len = sizeof (tval); a_val++; - rv = pkcs11_create_object (module, pks, a, a_val, &obj); + rv = pkcs11_create_object (sinfo.module, sinfo.pks, a, a_val, &obj); if (rv != CKR_OK) { gnutls_assert (); @@ -144,7 +145,7 @@ gnutls_pkcs11_copy_secret_key (const char *token_url, gnutls_datum_t * key, ret = 0; cleanup: - pkcs11_close_session (module, pks); + pkcs11_close_session (&sinfo); return ret; diff --git a/lib/pkcs11_write.c b/lib/pkcs11_write.c index aa474a6694..ca72c8fe78 100644 --- a/lib/pkcs11_write.c +++ b/lib/pkcs11_write.c @@ -50,8 +50,6 @@ gnutls_pkcs11_copy_x509_crt (const char *token_url, unsigned int flags) { int ret; - struct ck_function_list *module; - ck_session_handle_t pks; struct p11_kit_uri *info = NULL; ck_rv_t rv; size_t der_size, id_size; @@ -63,6 +61,9 @@ gnutls_pkcs11_copy_x509_crt (const char *token_url, ck_object_handle_t obj; int a_val; gnutls_datum_t subject = { NULL, 0 }; + struct pkcs11_session_info sinfo; + + memset(&sinfo, 0, sizeof(sinfo)); ret = pkcs11_url_to_info (token_url, &info); if (ret < 0) @@ -72,7 +73,7 @@ gnutls_pkcs11_copy_x509_crt (const char *token_url, } ret = - pkcs11_open_session (&module, &pks, info, + pkcs11_open_session (&sinfo, info, SESSION_WRITE | pkcs11_obj_flags_to_int (flags)); p11_kit_uri_free (info); @@ -182,7 +183,7 @@ gnutls_pkcs11_copy_x509_crt (const char *token_url, } } - rv = pkcs11_create_object (module, pks, a, a_val, &obj); + rv = pkcs11_create_object (sinfo.module, sinfo.pks, a, a_val, &obj); if (rv != CKR_OK) { gnutls_assert (); @@ -198,7 +199,7 @@ gnutls_pkcs11_copy_x509_crt (const char *token_url, cleanup: gnutls_free (der); - pkcs11_close_session (module, pks); + pkcs11_close_session (&sinfo); _gnutls_free_datum(&subject); return ret; @@ -228,8 +229,6 @@ gnutls_pkcs11_copy_x509_privkey (const char *token_url, unsigned int key_usage, unsigned int flags) { int ret; - struct ck_function_list *module; - ck_session_handle_t pks = 0; struct p11_kit_uri *info = NULL; ck_rv_t rv; size_t id_size; @@ -242,6 +241,9 @@ gnutls_pkcs11_copy_x509_privkey (const char *token_url, gnutls_pk_algorithm_t pk; gnutls_datum_t p, q, g, y, x; gnutls_datum_t m, e, d, u, exp1, exp2; + struct pkcs11_session_info sinfo; + + memset(&sinfo, 0, sizeof(sinfo)); memset(&p, 0, sizeof(p)); memset(&q, 0, sizeof(q)); @@ -272,7 +274,7 @@ gnutls_pkcs11_copy_x509_privkey (const char *token_url, } ret = - pkcs11_open_session (&module, &pks, info, + pkcs11_open_session (&sinfo, info, SESSION_WRITE | pkcs11_obj_flags_to_int (flags)); p11_kit_uri_free (info); @@ -474,7 +476,7 @@ gnutls_pkcs11_copy_x509_privkey (const char *token_url, goto cleanup; } - rv = pkcs11_create_object (module, pks, a, a_val, &obj); + rv = pkcs11_create_object (sinfo.module, sinfo.pks, a, a_val, &obj); if (rv != CKR_OK) { gnutls_assert (); @@ -521,8 +523,8 @@ cleanup: break; } - if (pks != 0) - pkcs11_close_session (module, pks); + if (sinfo.pks != 0) + pkcs11_close_session (&sinfo); return ret; @@ -535,8 +537,7 @@ struct delete_data_st }; static int -delete_obj_url (struct ck_function_list *module, - ck_session_handle_t pks, +delete_obj_url (struct pkcs11_session_info * sinfo, struct token_info *info, struct ck_info *lib_info, void *input) { @@ -550,7 +551,6 @@ delete_obj_url (struct ck_function_list *module, unsigned long count, a_vals; int found = 0, ret; - if (info == NULL) { /* we don't support multiple calls */ gnutls_assert (); @@ -606,7 +606,7 @@ delete_obj_url (struct ck_function_list *module, a_vals++; } - rv = pkcs11_find_objects_init (module, pks, a, a_vals); + rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, a_vals); if (rv != CKR_OK) { gnutls_assert (); @@ -615,9 +615,9 @@ delete_obj_url (struct ck_function_list *module, goto cleanup; } - while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1) + while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1) { - rv = pkcs11_destroy_object (module, pks, obj); + rv = pkcs11_destroy_object (sinfo->module, sinfo->pks, obj); if (rv != CKR_OK) { _gnutls_debug_log @@ -642,7 +642,7 @@ delete_obj_url (struct ck_function_list *module, } cleanup: - pkcs11_find_objects_final (module, pks); + pkcs11_find_objects_final (sinfo); return ret; } @@ -770,11 +770,12 @@ gnutls_pkcs11_token_set_pin (const char *token_url, const char *newpin, unsigned int flags) { int ret; - struct ck_function_list *module; - ck_session_handle_t pks; struct p11_kit_uri *info = NULL; ck_rv_t rv; unsigned int ses_flags; + struct pkcs11_session_info sinfo; + + memset(&sinfo, 0, sizeof(sinfo)); ret = pkcs11_url_to_info (token_url, &info); if (ret < 0) @@ -789,7 +790,7 @@ gnutls_pkcs11_token_set_pin (const char *token_url, else ses_flags = SESSION_WRITE | SESSION_LOGIN; - ret = pkcs11_open_session (&module, &pks, info, ses_flags); + ret = pkcs11_open_session (&sinfo, info, ses_flags); p11_kit_uri_free (info); if (ret < 0) @@ -800,7 +801,7 @@ gnutls_pkcs11_token_set_pin (const char *token_url, if (oldpin == NULL) { - rv = pkcs11_init_pin (module, pks, (uint8_t *) newpin, strlen (newpin)); + rv = pkcs11_init_pin (sinfo.module, sinfo.pks, (uint8_t *) newpin, strlen (newpin)); if (rv != CKR_OK) { gnutls_assert (); @@ -811,7 +812,7 @@ gnutls_pkcs11_token_set_pin (const char *token_url, } else { - rv = pkcs11_set_pin (module, pks, + rv = pkcs11_set_pin (sinfo.module, sinfo.pks, oldpin, strlen (oldpin), newpin, strlen (newpin)); if (rv != CKR_OK) @@ -826,7 +827,7 @@ gnutls_pkcs11_token_set_pin (const char *token_url, ret = 0; finish: - pkcs11_close_session (module, pks); + pkcs11_close_session (&sinfo); return ret; }