]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
In tokens that allow multiple sessions make the private key session persistent.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 9 Jun 2012 12:10:44 +0000 (14:10 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 9 Jun 2012 12:10:44 +0000 (14:10 +0200)
This prevents asking for PIN on every private key operation.

lib/pkcs11.c
lib/pkcs11_int.h
lib/pkcs11_privkey.c
lib/pkcs11_secret.c
lib/pkcs11_write.c

index 9510a06f0d210340694735512f3ec16d8ce89b30..0f9c1b0629101d5ee0f1997ba3863d069edf5f92 100644 (file)
@@ -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
index 36d53671e39621215415dcf279e002fe123e4525..538da55fe3298a209ee29dfdf229c92b6b25c2c0 100644 (file)
 #include <p11-kit/uri.h>
 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,
index afbd8e402a645fc8aeec6969547e4f3afba4712c..b0bee57fc9c07620fc65998423e19ebe6dd21901 100644 (file)
@@ -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;
 }
index 54205f741e2db907bae23acbb59659cc48d5c1c3..10d39c785500b61f30666fa675cb74bc267ebda8 100644 (file)
@@ -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;
 
index aa474a6694beea484fae6a1cd4f3c445a43fa079..ca72c8fe782af8bfd7ff699ed6df94c2afe96457 100644 (file)
@@ -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;
 
 }