pkcs11: when importing a public key, import it's data as well (version 2 fix)
[gnutls:gnutls.git] / lib / pkcs11.c
1 /*
2  * GnuTLS PKCS#11 support
3  * Copyright (C) 2010-2014 Free Software Foundation, Inc.
4  * Copyright (C) 2008 Joe Orton <joe@manyfish.co.uk>
5  * Copyright (C) 2013 Nikos Mavrogiannopoulos
6  * Copyright (C) 2014 Red Hat
7  * 
8  * Authors: Nikos Mavrogiannopoulos, Stef Walter
9  *
10  * Inspired and some parts (pkcs11_login) based on neon PKCS #11 support 
11  * by Joe Orton. More ideas came from the pkcs11-helper library by 
12  * Alon Bar-Lev.
13  *
14  * GnuTLS is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Lesser General Public License
16  * as published by the Free Software Foundation; either version 2.1 of
17  * the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with this program.  If not, see <http://www.gnu.org/licenses/>
26  */
27
28 #include <gnutls_int.h>
29 #include <gnutls/pkcs11.h>
30 #include <string.h>
31 #include <gnutls_errors.h>
32 #include <gnutls_datum.h>
33 #include <x509/common.h>
34 #include <locks.h>
35
36 #include <pin.h>
37 #include <pkcs11_int.h>
38 #include <p11-kit/p11-kit.h>
39 #include "pkcs11x.h"
40 #include <p11-kit/pin.h>
41 #include <system-keys.h>
42
43 #include <atfork.h>
44
45 #define MAX_PROVIDERS 16
46
47 #define MAX_SLOTS 48
48
49 extern void *_gnutls_pkcs11_mutex;
50
51 struct gnutls_pkcs11_provider_st {
52         struct ck_function_list *module;
53         unsigned active;
54         unsigned trusted; /* in the sense of p11-kit trusted:
55                            * it can be used for verification */
56         struct ck_info info;
57 };
58
59 struct find_flags_data_st {
60         struct p11_kit_uri *info;
61         unsigned int slot_flags;
62         unsigned int trusted;
63 };
64
65 struct find_url_data_st {
66         gnutls_pkcs11_obj_t obj;
67 };
68
69 struct find_obj_data_st {
70         gnutls_pkcs11_obj_t *p_list;
71         unsigned int current;
72         unsigned int flags;
73         struct p11_kit_uri *info;
74 };
75
76 struct find_token_num {
77         struct p11_kit_uri *info;
78         unsigned int seq;       /* which one we are looking for */
79         unsigned int current;   /* which one are we now */
80 };
81
82 struct find_pkey_list_st {
83         gnutls_buffer_st *key_ids;
84         size_t key_ids_size;
85 };
86
87 struct find_cert_st {
88         gnutls_datum_t dn;
89         gnutls_datum_t issuer_dn;
90         gnutls_datum_t key_id;
91         gnutls_datum_t serial;
92
93         unsigned need_import;
94         gnutls_pkcs11_obj_t obj;
95         gnutls_x509_crt_t crt; /* used when compare flag is specified */
96         unsigned flags;
97 };
98
99
100 static struct gnutls_pkcs11_provider_st providers[MAX_PROVIDERS];
101 static unsigned int active_providers = 0;
102 static unsigned int providers_initialized = 0;
103 static unsigned int dfork = 0;
104
105 gnutls_pkcs11_token_callback_t _gnutls_token_func;
106 void *_gnutls_token_data;
107
108 int pkcs11_rv_to_err(ck_rv_t rv)
109 {
110         switch (rv) {
111         case CKR_OK:
112                 return 0;
113         case CKR_HOST_MEMORY:
114                 return GNUTLS_E_MEMORY_ERROR;
115         case CKR_SLOT_ID_INVALID:
116                 return GNUTLS_E_PKCS11_SLOT_ERROR;
117         case CKR_ARGUMENTS_BAD:
118         case CKR_MECHANISM_PARAM_INVALID:
119                 return GNUTLS_E_INVALID_REQUEST;
120         case CKR_NEED_TO_CREATE_THREADS:
121         case CKR_CANT_LOCK:
122         case CKR_FUNCTION_NOT_PARALLEL:
123         case CKR_MUTEX_BAD:
124         case CKR_MUTEX_NOT_LOCKED:
125                 return GNUTLS_E_LOCKING_ERROR;
126         case CKR_ATTRIBUTE_READ_ONLY:
127         case CKR_ATTRIBUTE_SENSITIVE:
128         case CKR_ATTRIBUTE_TYPE_INVALID:
129         case CKR_ATTRIBUTE_VALUE_INVALID:
130                 return GNUTLS_E_PKCS11_ATTRIBUTE_ERROR;
131         case CKR_DEVICE_ERROR:
132         case CKR_DEVICE_MEMORY:
133         case CKR_DEVICE_REMOVED:
134                 return GNUTLS_E_PKCS11_DEVICE_ERROR;
135         case CKR_DATA_INVALID:
136         case CKR_DATA_LEN_RANGE:
137         case CKR_ENCRYPTED_DATA_INVALID:
138         case CKR_ENCRYPTED_DATA_LEN_RANGE:
139         case CKR_OBJECT_HANDLE_INVALID:
140                 return GNUTLS_E_PKCS11_DATA_ERROR;
141         case CKR_FUNCTION_NOT_SUPPORTED:
142         case CKR_MECHANISM_INVALID:
143                 return GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR;
144         case CKR_KEY_HANDLE_INVALID:
145         case CKR_KEY_SIZE_RANGE:
146         case CKR_KEY_TYPE_INCONSISTENT:
147         case CKR_KEY_NOT_NEEDED:
148         case CKR_KEY_CHANGED:
149         case CKR_KEY_NEEDED:
150         case CKR_KEY_INDIGESTIBLE:
151         case CKR_KEY_FUNCTION_NOT_PERMITTED:
152         case CKR_KEY_NOT_WRAPPABLE:
153         case CKR_KEY_UNEXTRACTABLE:
154                 return GNUTLS_E_PKCS11_KEY_ERROR;
155         case CKR_PIN_INCORRECT:
156         case CKR_PIN_INVALID:
157         case CKR_PIN_LEN_RANGE:
158                 return GNUTLS_E_PKCS11_PIN_ERROR;
159         case CKR_PIN_EXPIRED:
160                 return GNUTLS_E_PKCS11_PIN_EXPIRED;
161         case CKR_PIN_LOCKED:
162                 return GNUTLS_E_PKCS11_PIN_LOCKED;
163         case CKR_SESSION_CLOSED:
164         case CKR_SESSION_COUNT:
165         case CKR_SESSION_HANDLE_INVALID:
166         case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
167         case CKR_SESSION_READ_ONLY:
168         case CKR_SESSION_EXISTS:
169         case CKR_SESSION_READ_ONLY_EXISTS:
170         case CKR_SESSION_READ_WRITE_SO_EXISTS:
171                 return GNUTLS_E_PKCS11_SESSION_ERROR;
172         case CKR_SIGNATURE_INVALID:
173         case CKR_SIGNATURE_LEN_RANGE:
174                 return GNUTLS_E_PKCS11_SIGNATURE_ERROR;
175         case CKR_TOKEN_NOT_PRESENT:
176         case CKR_TOKEN_NOT_RECOGNIZED:
177         case CKR_TOKEN_WRITE_PROTECTED:
178                 return GNUTLS_E_PKCS11_TOKEN_ERROR;
179         case CKR_USER_ALREADY_LOGGED_IN:
180         case CKR_USER_NOT_LOGGED_IN:
181         case CKR_USER_PIN_NOT_INITIALIZED:
182         case CKR_USER_TYPE_INVALID:
183         case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
184         case CKR_USER_TOO_MANY_TYPES:
185                 return GNUTLS_E_PKCS11_USER_ERROR;
186         case CKR_BUFFER_TOO_SMALL:
187                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
188         default:
189                 return GNUTLS_E_PKCS11_ERROR;
190         }
191 }
192
193
194 static int scan_slots(struct gnutls_pkcs11_provider_st *p,
195                       ck_slot_id_t * slots, unsigned long *nslots)
196 {
197         ck_rv_t rv;
198
199         rv = pkcs11_get_slot_list(p->module, 1, slots, nslots);
200         if (rv != CKR_OK) {
201                 gnutls_assert();
202                 return pkcs11_rv_to_err(rv);
203         }
204         return 0;
205 }
206
207 static int
208 pkcs11_add_module(const char* name, struct ck_function_list *module, const char *params)
209 {
210         unsigned int i;
211         struct ck_info info;
212
213         if (active_providers >= MAX_PROVIDERS) {
214                 gnutls_assert();
215                 return GNUTLS_E_CONSTRAINT_ERROR;
216         }
217
218         memset(&info, 0, sizeof(info));
219         pkcs11_get_module_info(module, &info);
220
221         /* initially check if this module is a duplicate */
222         for (i = 0; i < active_providers; i++) {
223                 /* already loaded, skip the rest */
224                 if (module == providers[i].module) {
225                         _gnutls_debug_log("p11: module %s is already loaded.\n", name);
226                         return GNUTLS_E_INT_RET_0;
227                 }
228         }
229
230         active_providers++;
231         providers[active_providers - 1].module = module;
232         providers[active_providers - 1].active = 1;
233
234         if (p11_kit_module_get_flags(module) & P11_KIT_MODULE_TRUSTED ||
235                 (params != NULL && strstr(params, "trusted") != 0))
236                 providers[active_providers - 1].trusted = 1;
237
238         memcpy(&providers[active_providers - 1].info, &info, sizeof(info));
239
240         return 0;
241 }
242
243 /* Returns:
244  *  - negative error code on error,
245  *  - 0 on success
246  *  - 1 on success (and a fork was detected)
247  */
248 int _gnutls_pkcs11_check_init(void)
249 {
250         int ret;
251
252         ret = gnutls_mutex_lock(&_gnutls_pkcs11_mutex);
253         if (ret != 0)
254                 return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
255
256         if (providers_initialized != 0) {
257                 ret = 0;
258
259                 if (_gnutls_fork_detected(&dfork)) {
260                         /* if we are initialized but a fork is detected */
261                         ret = gnutls_pkcs11_reinit();
262                         if (ret == 0)
263                                 ret = 1;
264                 }
265
266                 gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
267                 return ret;
268         }
269
270         providers_initialized = 1;
271         _gnutls_debug_log("Initializing PKCS #11 modules\n");
272         ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO, NULL);
273
274         gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
275
276         if (ret < 0)
277                 return gnutls_assert_val(ret);
278
279         return 0;
280 }
281
282
283 /**
284  * gnutls_pkcs11_add_provider:
285  * @name: The filename of the module
286  * @params: should be NULL
287  *
288  * This function will load and add a PKCS 11 module to the module
289  * list used in gnutls. After this function is called the module will
290  * be used for PKCS 11 operations.
291  *
292  * When loading a module to be used for certificate verification,
293  * use the string 'trusted' as @params.
294  *
295  * Note that this function is not thread safe.
296  *
297  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
298  *   negative error value.
299  *
300  * Since: 2.12.0
301  **/
302 int gnutls_pkcs11_add_provider(const char *name, const char *params)
303 {
304         struct ck_function_list *module;
305         int ret;
306
307         module = p11_kit_module_load(name, P11_KIT_MODULE_CRITICAL);
308         if (module == NULL) {
309                 gnutls_assert();
310                 _gnutls_debug_log("p11: Cannot load provider %s\n", name);
311                 return GNUTLS_E_PKCS11_LOAD_ERROR;
312         }
313
314         _gnutls_debug_log
315                     ("p11: Initializing module: %s\n", name);
316
317         ret = p11_kit_module_initialize(module);
318         if (ret != CKR_OK) {
319                 p11_kit_module_release(module);
320                 gnutls_assert();
321                 return pkcs11_rv_to_err(ret);
322         }
323
324         ret = pkcs11_add_module(name, module, params);
325         if (ret != 0) {
326                 if (ret == GNUTLS_E_INT_RET_0)
327                         ret = 0;
328                 p11_kit_module_finalize(module);
329                 p11_kit_module_release(module);
330                 gnutls_assert();
331         }
332
333         return ret;
334 }
335
336
337 /**
338  * gnutls_pkcs11_obj_get_info:
339  * @obj: should contain a #gnutls_pkcs11_obj_t structure
340  * @itype: Denotes the type of information requested
341  * @output: where output will be stored
342  * @output_size: contains the maximum size of the output and will be overwritten with actual
343  *
344  * This function will return information about the PKCS11 certificate
345  * such as the label, id as well as token information where the key is
346  * stored. When output is text it returns null terminated string
347  * although @output_size contains the size of the actual data only.
348  *
349  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
350  *
351  * Since: 2.12.0
352  **/
353 int
354 gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t obj,
355                            gnutls_pkcs11_obj_info_t itype,
356                            void *output, size_t * output_size)
357 {
358         return pkcs11_get_info(obj->info, itype, output, output_size);
359 }
360
361 int
362 pkcs11_get_info(struct p11_kit_uri *info,
363                 gnutls_pkcs11_obj_info_t itype, void *output,
364                 size_t * output_size)
365 {
366         struct ck_attribute *attr = NULL;
367         struct ck_version *version = NULL;
368         const uint8_t *str = NULL;
369         size_t str_max = 0;
370         int terminate = 0;
371         int hexify = 0;
372         size_t length = 0;
373         const char *data = NULL;
374         char buf[32];
375
376         /*
377          * Either attr, str or version is valid by the time switch
378          * finishes
379          */
380
381         switch (itype) {
382         case GNUTLS_PKCS11_OBJ_ID:
383                 attr = p11_kit_uri_get_attribute(info, CKA_ID);
384                 break;
385         case GNUTLS_PKCS11_OBJ_ID_HEX:
386                 attr = p11_kit_uri_get_attribute(info, CKA_ID);
387                 hexify = 1;
388                 terminate = 1;
389                 break;
390         case GNUTLS_PKCS11_OBJ_LABEL:
391                 attr = p11_kit_uri_get_attribute(info, CKA_LABEL);
392                 terminate = 1;
393                 break;
394         case GNUTLS_PKCS11_OBJ_TOKEN_LABEL:
395                 str = p11_kit_uri_get_token_info(info)->label;
396                 str_max = 32;
397                 break;
398         case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL:
399                 str = p11_kit_uri_get_token_info(info)->serial_number;
400                 str_max = 16;
401                 break;
402         case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER:
403                 str = p11_kit_uri_get_token_info(info)->manufacturer_id;
404                 str_max = 32;
405                 break;
406         case GNUTLS_PKCS11_OBJ_TOKEN_MODEL:
407                 str = p11_kit_uri_get_token_info(info)->model;
408                 str_max = 16;
409                 break;
410         case GNUTLS_PKCS11_OBJ_LIBRARY_DESCRIPTION:
411                 str =
412                     p11_kit_uri_get_module_info(info)->library_description;
413                 str_max = 32;
414                 break;
415         case GNUTLS_PKCS11_OBJ_LIBRARY_VERSION:
416                 version =
417                     &p11_kit_uri_get_module_info(info)->library_version;
418                 break;
419         case GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER:
420                 str = p11_kit_uri_get_module_info(info)->manufacturer_id;
421                 str_max = 32;
422                 break;
423         default:
424                 gnutls_assert();
425                 return GNUTLS_E_INVALID_REQUEST;
426         }
427
428         if (attr != NULL) {
429                 data = attr->value;
430                 length = attr->value_len;
431         } else if (str != NULL) {
432                 data = (void *) str;
433                 length = p11_kit_space_strlen(str, str_max);
434                 terminate = 1;
435         } else if (version != NULL) {
436                 data = buf;
437                 length =
438                     snprintf(buf, sizeof(buf), "%d.%d",
439                              (int) version->major, (int) version->minor);
440                 terminate = 1;
441         } else {
442                 *output_size = 0;
443                 if (output)
444                         ((uint8_t *) output)[0] = 0;
445                 return 0;
446         }
447
448         if (hexify) {
449                 /* terminate is assumed with hexify */
450                 if (*output_size < length * 3) {
451                         *output_size = length * 3;
452                         return GNUTLS_E_SHORT_MEMORY_BUFFER;
453                 }
454                 if (output && length > 0)
455                         _gnutls_bin2hex(data, length, output, *output_size,
456                                         ":");
457                 *output_size = length * 3;
458                 return 0;
459         } else {
460                 if (*output_size < length + terminate) {
461                         *output_size = length + terminate;
462                         return GNUTLS_E_SHORT_MEMORY_BUFFER;
463                 }
464                 if (output) {
465                         memcpy(output, data, length);
466                         if (terminate)
467                                 ((unsigned char *) output)[length] = '\0';
468                 }
469                 *output_size = length + terminate;
470         }
471
472         return 0;
473 }
474
475 static int init = 0;
476
477 /* tries to load modules from /etc/gnutls/pkcs11.conf if it exists
478  */
479 static void compat_load(const char *configfile)
480 {
481         FILE *fp;
482         int ret;
483         char line[512];
484         const char *library;
485
486         if (configfile == NULL)
487                 configfile = "/etc/gnutls/pkcs11.conf";
488
489         fp = fopen(configfile, "r");
490         if (fp == NULL) {
491                 gnutls_assert();
492                 return;
493         }
494
495         _gnutls_debug_log("Loading PKCS #11 libraries from %s\n",
496                           configfile);
497         while (fgets(line, sizeof(line), fp) != NULL) {
498                 if (strncmp(line, "load", sizeof("load") - 1) == 0) {
499                         char *p;
500                         p = strchr(line, '=');
501                         if (p == NULL)
502                                 continue;
503
504                         library = ++p;
505                         p = strchr(line, '\n');
506                         if (p != NULL)
507                                 *p = 0;
508
509                         ret = gnutls_pkcs11_add_provider(library, NULL);
510                         if (ret < 0) {
511                                 gnutls_assert();
512                                 _gnutls_debug_log
513                                     ("Cannot load provider: %s\n",
514                                      library);
515                                 continue;
516                         }
517                 }
518         }
519         fclose(fp);
520
521         return;
522 }
523
524 static int auto_load(void)
525 {
526         struct ck_function_list **modules;
527         int i, ret;
528         char* name;
529
530         modules = p11_kit_modules_load_and_initialize(0);
531         if (modules == NULL) {
532                 gnutls_assert();
533                 _gnutls_debug_log
534                     ("Cannot initialize registered modules: %s\n",
535                      p11_kit_message());
536                 return GNUTLS_E_PKCS11_LOAD_ERROR;
537         }
538
539         for (i = 0; modules[i] != NULL; i++) {
540                 name = p11_kit_module_get_name(modules[i]);
541                 _gnutls_debug_log
542                             ("p11: Initializing module: %s\n", name);
543
544                 ret = pkcs11_add_module(name, modules[i], NULL);
545                 if (ret < 0) {
546                         gnutls_assert();
547                         _gnutls_debug_log
548                             ("Cannot load PKCS #11 module: %s\n", name);
549                 }
550                 free(name);
551         }
552
553         /* Shallow free */
554         free(modules);
555         return 0;
556 }
557
558 /**
559  * gnutls_pkcs11_init:
560  * @flags: An ORed sequence of %GNUTLS_PKCS11_FLAG_*
561  * @deprecated_config_file: either NULL or the location of a deprecated
562  *     configuration file
563  *
564  * This function will initialize the PKCS 11 subsystem in gnutls. It will
565  * read configuration files if %GNUTLS_PKCS11_FLAG_AUTO is used or allow
566  * you to independently load PKCS 11 modules using gnutls_pkcs11_add_provider()
567  * if %GNUTLS_PKCS11_FLAG_MANUAL is specified.
568  *
569  * Normally you don't need to call this function since it is being called
570  * when the first PKCS 11 operation is requested using the %GNUTLS_PKCS11_FLAG_AUTO
571  * flag. If another flags are required then it must be called independently
572  * prior to any PKCS 11 operation.
573  *
574  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
575  *   negative error value.
576  *
577  * Since: 2.12.0
578  **/
579 int
580 gnutls_pkcs11_init(unsigned int flags, const char *deprecated_config_file)
581 {
582         int ret = 0;
583
584         if (init != 0) {
585                 init++;
586                 return 0;
587         }
588         init++;
589
590         _gnutls_fork_set_val(&dfork);
591
592         p11_kit_pin_register_callback(P11_KIT_PIN_FALLBACK,
593                                       p11_kit_pin_file_callback, NULL,
594                                       NULL);
595
596         if (flags == GNUTLS_PKCS11_FLAG_MANUAL)
597                 return 0;
598         else if (flags & GNUTLS_PKCS11_FLAG_AUTO) {
599                 if (deprecated_config_file == NULL)
600                         ret = auto_load();
601
602                 compat_load(deprecated_config_file);
603
604                 return ret;
605         }
606
607         return 0;
608 }
609
610 /**
611  * gnutls_pkcs11_reinit:
612  *
613  * This function will reinitialize the PKCS 11 subsystem in gnutls. 
614  * This is required by PKCS 11 when an application uses fork(). The
615  * reinitialization function must be called on the child.
616  *
617  * Note that since GnuTLS 3.3.0, the reinitialization of the PKCS #11
618  * subsystem occurs automatically after fork.
619  *
620  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
621  *   negative error value.
622  *
623  * Since: 3.0
624  **/
625 int gnutls_pkcs11_reinit(void)
626 {
627         unsigned i;
628         ck_rv_t rv;
629
630         /* make sure that we don't call more than once after a fork */
631         if (_gnutls_fork_detected(&dfork) == 0)
632                 return 0;
633
634         for (i = 0; i < active_providers; i++) {
635                 if (providers[i].module != NULL) {
636                         rv = p11_kit_module_initialize(providers
637                                                        [i].module);
638                         if (rv == CKR_OK || rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) {
639                                 providers[i].active = 1;
640                         } else {
641                                 providers[i].active = 0;
642                                 _gnutls_debug_log
643                                     ("Cannot re-initialize registered module '%.*s': %s\n",
644                                      (int)32, providers[i].info.library_description,
645                                      p11_kit_strerror(rv));
646                         }
647                 }
648         }
649
650         return 0;
651 }
652
653 /**
654  * gnutls_pkcs11_deinit:
655  *
656  * This function will deinitialize the PKCS 11 subsystem in gnutls.
657  * This function is only needed if you need to deinitialize the
658  * subsystem without calling gnutls_global_deinit().
659  *
660  * Since: 2.12.0
661  **/
662 void gnutls_pkcs11_deinit(void)
663 {
664         unsigned int i;
665
666         if (init == 0)
667                 return;
668
669         init--;
670         if (init > 0)
671                 return;
672
673         for (i = 0; i < active_providers; i++) {
674                 if (providers[i].active)
675                         p11_kit_module_finalize(providers[i].module);
676                 p11_kit_module_release(providers[i].module);
677         }
678         active_providers = 0;
679         providers_initialized = 0;
680
681         gnutls_pkcs11_set_pin_function(NULL, NULL);
682         gnutls_pkcs11_set_token_function(NULL, NULL);
683         p11_kit_pin_unregister_callback(P11_KIT_PIN_FALLBACK,
684                                         p11_kit_pin_file_callback, NULL);
685 }
686
687 /**
688  * gnutls_pkcs11_set_token_function:
689  * @fn: The token callback
690  * @userdata: data to be supplied to callback
691  *
692  * This function will set a callback function to be used when a token
693  * needs to be inserted to continue PKCS 11 operations.
694  *
695  * Since: 2.12.0
696  **/
697 void
698 gnutls_pkcs11_set_token_function(gnutls_pkcs11_token_callback_t fn,
699                                  void *userdata)
700 {
701         _gnutls_token_func = fn;
702         _gnutls_token_data = userdata;
703 }
704
705 int pkcs11_url_to_info(const char *url, struct p11_kit_uri **info, unsigned flags)
706 {
707         int allocated = 0;
708         int ret;
709
710         if (*info == NULL) {
711                 *info = p11_kit_uri_new();
712                 if (*info == NULL) {
713                         gnutls_assert();
714                         return GNUTLS_E_MEMORY_ERROR;
715                 }
716                 allocated = 1;
717         }
718
719         ret = p11_kit_uri_parse(url, P11_KIT_URI_FOR_ANY, *info);
720         if (ret < 0) {
721                 if (allocated) {
722                         p11_kit_uri_free(*info);
723                         *info = NULL;
724                 }
725                 gnutls_assert();
726                 return ret == P11_KIT_URI_NO_MEMORY ?
727                     GNUTLS_E_MEMORY_ERROR : GNUTLS_E_PARSING_ERROR;
728         }
729
730         /* check for incomplete URIs */
731         if (p11_kit_uri_get_attribute (*info, CKA_CLASS) == NULL) {
732                 struct ck_attribute at;
733                 ck_object_class_t klass;
734
735                 if (flags & GNUTLS_PKCS11_OBJ_FLAG_EXPECT_CERT) {
736                         klass = CKO_CERTIFICATE;
737                         at.type = CKA_CLASS;
738                         at.value = &klass;
739                         at.value_len = sizeof (klass);
740                         p11_kit_uri_set_attribute (*info, &at);
741                 } else if (flags & GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY) {
742                         klass = CKO_PRIVATE_KEY;
743                         at.type = CKA_CLASS;
744                         at.value = &klass;
745                         at.value_len = sizeof (klass);
746                         p11_kit_uri_set_attribute (*info, &at);
747                 }
748         }
749
750         return 0;
751 }
752
753 int
754 pkcs11_info_to_url(struct p11_kit_uri *info,
755                    gnutls_pkcs11_url_type_t detailed, char **url)
756 {
757         p11_kit_uri_type_t type = 0;
758         int ret;
759
760         switch (detailed) {
761         case GNUTLS_PKCS11_URL_GENERIC:
762                 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN;
763                 break;
764         case GNUTLS_PKCS11_URL_LIB:
765                 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE;
766                 break;
767         case GNUTLS_PKCS11_URL_LIB_VERSION:
768                 type =
769                     P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE |
770                     P11_KIT_URI_FOR_MODULE_WITH_VERSION;
771                 break;
772         }
773
774         ret = p11_kit_uri_format(info, type, url);
775         if (ret < 0) {
776                 gnutls_assert();
777                 return ret == P11_KIT_URI_NO_MEMORY ?
778                     GNUTLS_E_MEMORY_ERROR : GNUTLS_E_INTERNAL_ERROR;
779         }
780
781         return 0;
782 }
783
784 /**
785  * gnutls_pkcs11_obj_init:
786  * @obj: The structure to be initialized
787  *
788  * This function will initialize a pkcs11 certificate structure.
789  *
790  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
791  *   negative error value.
792  *
793  * Since: 2.12.0
794  **/
795 int gnutls_pkcs11_obj_init(gnutls_pkcs11_obj_t * obj)
796 {
797         *obj = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_obj_st));
798         if (*obj == NULL) {
799                 gnutls_assert();
800                 return GNUTLS_E_MEMORY_ERROR;
801         }
802
803         (*obj)->info = p11_kit_uri_new();
804         if ((*obj)->info == NULL) {
805                 gnutls_free(*obj);
806                 *obj = NULL;
807                 gnutls_assert();
808                 return GNUTLS_E_MEMORY_ERROR;
809         }
810
811         return 0;
812 }
813
814 /**
815  * gnutls_pkcs11_obj_set_pin_function:
816  * @obj: The object structure
817  * @fn: the callback
818  * @userdata: data associated with the callback
819  *
820  * This function will set a callback function to be used when
821  * required to access the object. This function overrides the global
822  * set using gnutls_pkcs11_set_pin_function().
823  *
824  * Since: 3.1.0
825  **/
826 void
827 gnutls_pkcs11_obj_set_pin_function(gnutls_pkcs11_obj_t obj,
828                                    gnutls_pin_callback_t fn,
829                                    void *userdata)
830 {
831         obj->pin.cb = fn;
832         obj->pin.data = userdata;
833 }
834
835 /**
836  * gnutls_pkcs11_obj_deinit:
837  * @obj: The structure to be initialized
838  *
839  * This function will deinitialize a certificate structure.
840  *
841  * Since: 2.12.0
842  **/
843 void gnutls_pkcs11_obj_deinit(gnutls_pkcs11_obj_t obj)
844 {
845         _gnutls_free_datum(&obj->raw);
846         p11_kit_uri_free(obj->info);
847         free(obj);
848 }
849
850 /**
851  * gnutls_pkcs11_obj_export:
852  * @obj: Holds the object
853  * @output_data: will contain the object data
854  * @output_data_size: holds the size of output_data (and will be
855  *   replaced by the actual size of parameters)
856  *
857  * This function will export the PKCS11 object data.  It is normal for
858  * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
859  * will be returned.
860  *
861  * If the buffer provided is not long enough to hold the output, then
862  * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
863  * be returned.
864  *
865  * Returns: In case of failure a negative error code will be
866  *   returned, and %GNUTLS_E_SUCCESS (0) on success.
867  *
868  * Since: 2.12.0
869  **/
870 int
871 gnutls_pkcs11_obj_export(gnutls_pkcs11_obj_t obj,
872                          void *output_data, size_t * output_data_size)
873 {
874         if (obj == NULL || obj->raw.data == NULL) {
875                 gnutls_assert();
876                 return GNUTLS_E_INVALID_REQUEST;
877         }
878
879         if (output_data == NULL || *output_data_size < obj->raw.size) {
880                 *output_data_size = obj->raw.size;
881                 gnutls_assert();
882                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
883         }
884         *output_data_size = obj->raw.size;
885
886         memcpy(output_data, obj->raw.data, obj->raw.size);
887         return 0;
888 }
889
890 /**
891  * gnutls_pkcs11_obj_export2:
892  * @obj: Holds the object
893  * @out: will contain the object data
894  *
895  * This function will export the PKCS11 object data.  It is normal for
896  * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
897  * will be returned.
898  *
899  * The output buffer is allocated using gnutls_malloc().
900  *
901  * Returns: In case of failure a negative error code will be
902  *   returned, and %GNUTLS_E_SUCCESS (0) on success.
903  *
904  * Since: 3.1.3
905  **/
906 int
907 gnutls_pkcs11_obj_export2(gnutls_pkcs11_obj_t obj, gnutls_datum_t * out)
908 {
909         if (obj == NULL || obj->raw.data == NULL) {
910                 gnutls_assert();
911                 return GNUTLS_E_INVALID_REQUEST;
912         }
913
914         return _gnutls_set_datum(out, obj->raw.data, obj->raw.size);
915 }
916
917 /**
918  * gnutls_pkcs11_obj_export3:
919  * @obj: Holds the object
920  * @out: will contain the object data
921  * @fmt: The format of the exported data
922  *
923  * This function will export the PKCS11 object data.  It is normal for
924  * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
925  * will be returned.
926  *
927  * The output buffer is allocated using gnutls_malloc().
928  *
929  * Returns: In case of failure a negative error code will be
930  *   returned, and %GNUTLS_E_SUCCESS (0) on success.
931  *
932  * Since: 3.2.7
933  **/
934 int
935 gnutls_pkcs11_obj_export3(gnutls_pkcs11_obj_t obj,
936                           gnutls_x509_crt_fmt_t fmt, gnutls_datum_t * out)
937 {
938         int ret;
939
940         if (obj == NULL || obj->raw.data == NULL) {
941                 gnutls_assert();
942                 return GNUTLS_E_INVALID_REQUEST;
943         }
944
945         if (fmt == GNUTLS_X509_FMT_DER)
946                 return _gnutls_set_datum(out, obj->raw.data,
947                                          obj->raw.size);
948         else if (fmt == GNUTLS_X509_FMT_PEM) {
949                 switch (obj->type) {
950                 case GNUTLS_PKCS11_OBJ_X509_CRT:
951                         return
952                             gnutls_pem_base64_encode_alloc(PEM_X509_CERT2,
953                                                            &obj->raw, out);
954                 case GNUTLS_PKCS11_OBJ_PUBKEY:{
955                                 gnutls_pubkey_t pubkey;
956                                 /* more complex */
957                                 ret = gnutls_pubkey_init(&pubkey);
958                                 if (ret < 0)
959                                         return gnutls_assert_val(ret);
960
961                                 ret =
962                                     gnutls_pubkey_import_pkcs11(pubkey,
963                                                                 obj, 0);
964                                 if (ret < 0) {
965                                         gnutls_assert();
966                                         goto pcleanup;
967                                 }
968
969                                 ret =
970                                     gnutls_pubkey_export2(pubkey, fmt,
971                                                           out);
972
973                               pcleanup:
974                                 gnutls_pubkey_deinit(pubkey);
975                                 return ret;
976                         }
977                 default:
978                         return gnutls_pem_base64_encode_alloc("DATA",
979                                                               &obj->raw,
980                                                               out);
981                 }
982         } else
983                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
984 }
985
986
987 int
988 pkcs11_find_slot(struct ck_function_list **module, ck_slot_id_t * slot,
989                  struct p11_kit_uri *info,
990                  struct ck_token_info *_tinfo,
991                  struct ck_slot_info *_slot_info)
992 {
993         unsigned int x, z;
994         int ret;
995         unsigned long nslots;
996         ck_slot_id_t slots[MAX_SLOTS];
997
998         for (x = 0; x < active_providers; x++) {
999                 if (providers[x].active == 0)
1000                         continue;
1001
1002                 nslots = sizeof(slots) / sizeof(slots[0]);
1003                 ret = scan_slots(&providers[x], slots, &nslots);
1004                 if (ret < 0) {
1005                         gnutls_assert();
1006                         continue;
1007                 }
1008
1009                 for (z = 0; z < nslots; z++) {
1010                         struct ck_token_info tinfo;
1011                         struct ck_slot_info sinfo;
1012
1013                         if (pkcs11_get_token_info
1014                             (providers[x].module, slots[z],
1015                              &tinfo) != CKR_OK) {
1016                                 continue;
1017                         }
1018
1019                         if (pkcs11_get_slot_info
1020                             (providers[x].module, slots[z],
1021                              &sinfo) != CKR_OK) {
1022                                 continue;
1023                         }
1024
1025                         if (!p11_kit_uri_match_token_info
1026                             (info, &tinfo)
1027                             || !p11_kit_uri_match_module_info(info,
1028                                                               &providers
1029                                                               [x].info)) {
1030                                 continue;
1031                         }
1032
1033                         /* ok found */
1034                         *module = providers[x].module;
1035                         *slot = slots[z];
1036
1037                         if (_tinfo != NULL)
1038                                 memcpy(_tinfo, &tinfo, sizeof(tinfo));
1039
1040                         if (_slot_info != NULL)
1041                                 memcpy(_slot_info, &sinfo, sizeof(sinfo));
1042
1043                         return 0;
1044                 }
1045         }
1046
1047         gnutls_assert();
1048         return GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE;
1049 }
1050
1051 int
1052 pkcs11_open_session(struct pkcs11_session_info *sinfo,
1053                     struct pin_info_st *pin_info,
1054                     struct p11_kit_uri *info, unsigned int flags)
1055 {
1056         ck_rv_t rv;
1057         int ret;
1058         ck_session_handle_t pks = 0;
1059         struct ck_function_list *module;
1060         ck_slot_id_t slot;
1061         struct ck_token_info tinfo;
1062
1063         ret = pkcs11_find_slot(&module, &slot, info, &tinfo, &sinfo->slot_info);
1064         if (ret < 0) {
1065                 gnutls_assert();
1066                 return ret;
1067         }
1068
1069         rv = (module)->C_OpenSession(slot, ((flags & SESSION_WRITE)
1070                                             ? CKF_RW_SESSION : 0) |
1071                                      CKF_SERIAL_SESSION, NULL, NULL, &pks);
1072         if (rv != CKR_OK) {
1073                 gnutls_assert();
1074                 return pkcs11_rv_to_err(rv);
1075         }
1076
1077         /* ok found */
1078         sinfo->pks = pks;
1079         sinfo->module = module;
1080         sinfo->sid = slot;
1081         sinfo->init = 1;
1082         memcpy(&sinfo->tinfo, &tinfo, sizeof(sinfo->tinfo));
1083
1084         if (flags & SESSION_LOGIN) {
1085                 ret =
1086                     pkcs11_login(sinfo, pin_info, info,
1087                                  (flags & SESSION_SO) ? 1 : 0, 0);
1088                 if (ret < 0) {
1089                         gnutls_assert();
1090                         pkcs11_close_session(sinfo);
1091                         return ret;
1092                 }
1093         }
1094
1095         return 0;
1096 }
1097
1098
1099 int
1100 _pkcs11_traverse_tokens(find_func_t find_func, void *input,
1101                         struct p11_kit_uri *info,
1102                         struct pin_info_st *pin_info, unsigned int flags)
1103 {
1104         ck_rv_t rv;
1105         unsigned int found = 0, x, z;
1106         int ret;
1107         ck_session_handle_t pks = 0;
1108         struct pkcs11_session_info sinfo;
1109         struct ck_function_list *module = NULL;
1110         unsigned long nslots;
1111         ck_slot_id_t slots[MAX_SLOTS];
1112
1113         for (x = 0; x < active_providers; x++) {
1114                 if (providers[x].active == 0)
1115                         continue;
1116
1117                 if (flags & SESSION_TRUSTED && providers[x].trusted == 0)
1118                         continue;
1119
1120                 nslots = sizeof(slots) / sizeof(slots[0]);
1121                 ret = scan_slots(&providers[x], slots, &nslots);
1122                 if (ret < 0) {
1123                         gnutls_assert();
1124                         continue;
1125                 }
1126
1127                 module = providers[x].module;
1128                 for (z = 0; z < nslots; z++) {
1129                         struct ck_token_info l_tinfo;
1130                         struct ck_slot_info l_sinfo;
1131
1132                         if (pkcs11_get_token_info(module, slots[z],
1133                                                   &l_tinfo) != CKR_OK) {
1134                                 continue;
1135                         }
1136
1137                         if (pkcs11_get_slot_info(module, slots[z],
1138                                                  &l_sinfo) != CKR_OK) {
1139                                 continue;
1140                         }
1141
1142                         if (info != NULL) {
1143                             if (!p11_kit_uri_match_token_info
1144                                 (info, &l_tinfo)
1145                                 || !p11_kit_uri_match_module_info(info,
1146                                                               &providers
1147                                                               [x].info)) {
1148                                 continue;
1149                             }
1150                         }
1151
1152                         rv = (module)->C_OpenSession(slots[z],
1153                                                      ((flags & SESSION_WRITE) ? CKF_RW_SESSION : 0)
1154                                                      | CKF_SERIAL_SESSION,
1155                                                      NULL, NULL, &pks);
1156                         if (rv != CKR_OK) {
1157                                 continue;
1158                         }
1159
1160                         sinfo.module = module;
1161                         sinfo.pks = pks;
1162                         sinfo.sid = slots[z];
1163                         memcpy(&sinfo.tinfo, &l_tinfo, sizeof(sinfo.tinfo));
1164                         memcpy(&sinfo.slot_info, &l_sinfo, sizeof(sinfo.slot_info));
1165
1166                         if (flags & SESSION_LOGIN) {
1167                                 ret =
1168                                     pkcs11_login(&sinfo, pin_info,
1169                                                  info, (flags & SESSION_SO) ? 1 : 0,
1170                                                  0);
1171                                 if (ret < 0) {
1172                                         gnutls_assert();
1173                                         return ret;
1174                                 }
1175                         }
1176
1177                         ret =
1178                             find_func(&sinfo, &l_tinfo, &providers[x].info, input);
1179
1180                         if (ret == 0) {
1181                                 found = 1;
1182                                 goto finish;
1183                         } else {
1184                                 pkcs11_close_session(&sinfo);
1185                                 pks = 0;
1186                         }
1187                 }
1188         }
1189
1190       finish:
1191         /* final call */
1192
1193         if (found == 0) {
1194                 if (module) {
1195                         sinfo.module = module;
1196                         sinfo.pks = pks;
1197                         ret = find_func(&sinfo, NULL, NULL, input);
1198                 } else
1199                         ret =
1200                             gnutls_assert_val
1201                             (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1202         } else {
1203                 ret = 0;
1204         }
1205
1206         if (pks != 0 && module != NULL) {
1207                 pkcs11_close_session(&sinfo);
1208         }
1209
1210         return ret;
1211 }
1212
1213 ck_object_class_t pkcs11_type_to_class(gnutls_pkcs11_obj_type_t type)
1214 {
1215         switch (type) {
1216         case GNUTLS_PKCS11_OBJ_X509_CRT:
1217                 return CKO_CERTIFICATE;
1218         case GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION:
1219                 return CKO_X_CERTIFICATE_EXTENSION;
1220         case GNUTLS_PKCS11_OBJ_PUBKEY:
1221                 return CKO_PUBLIC_KEY;
1222         case GNUTLS_PKCS11_OBJ_PRIVKEY:
1223                 return CKO_PRIVATE_KEY;
1224         case GNUTLS_PKCS11_OBJ_SECRET_KEY:
1225                 return CKO_SECRET_KEY;
1226         case GNUTLS_PKCS11_OBJ_DATA:
1227                 return CKO_DATA;
1228         default:
1229                 return -1;
1230         }
1231 }
1232
1233 static gnutls_pkcs11_obj_type_t pkcs11_class_to_type(ck_object_class_t class)
1234 {
1235         switch (class) {
1236         case CKO_CERTIFICATE:
1237                 return GNUTLS_PKCS11_OBJ_X509_CRT;
1238         case CKO_X_CERTIFICATE_EXTENSION:
1239                 return GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION;
1240         case CKO_PUBLIC_KEY:
1241                 return GNUTLS_PKCS11_OBJ_PUBKEY;
1242         case CKO_PRIVATE_KEY:
1243                 return GNUTLS_PKCS11_OBJ_PRIVKEY;
1244         case CKO_SECRET_KEY:
1245                 return GNUTLS_PKCS11_OBJ_SECRET_KEY;
1246         case CKO_DATA:
1247                 return GNUTLS_PKCS11_OBJ_DATA;
1248         default:
1249                 _gnutls_debug_log("unknown pkcs11 object class %x\n", (unsigned)class);
1250                 return GNUTLS_PKCS11_OBJ_UNKNOWN;
1251         }
1252 }
1253
1254 /* imports an object from a token to a pkcs11_obj_t structure.
1255  */
1256 static int
1257 pkcs11_obj_import(ck_object_class_t class, gnutls_pkcs11_obj_t obj,
1258                   const gnutls_datum_t * data,
1259                   const gnutls_datum_t * id,
1260                   const gnutls_datum_t * label,
1261                   struct ck_token_info *tinfo, struct ck_info *lib_info)
1262 {
1263         struct ck_attribute attr;
1264         int ret;
1265
1266         obj->type = pkcs11_class_to_type(class);
1267
1268         attr.type = CKA_CLASS;
1269         attr.value = &class;
1270         attr.value_len = sizeof(class);
1271         ret = p11_kit_uri_set_attribute(obj->info, &attr);
1272         if (ret < 0) {
1273                 gnutls_assert();
1274                 return GNUTLS_E_MEMORY_ERROR;
1275         }
1276
1277         if (data && data->data) {
1278                 ret = _gnutls_set_datum(&obj->raw, data->data, data->size);
1279                 if (ret < 0) {
1280                         gnutls_assert();
1281                         return ret;
1282                 }
1283         }
1284
1285         /* copy the token and library info into the uri */
1286         memcpy(p11_kit_uri_get_token_info(obj->info), tinfo,
1287                sizeof(struct ck_token_info));
1288         memcpy(p11_kit_uri_get_module_info(obj->info), lib_info,
1289                sizeof(struct ck_info));
1290
1291         if (label && label->data) {
1292                 attr.type = CKA_LABEL;
1293                 attr.value = label->data;
1294                 attr.value_len = label->size;
1295                 ret = p11_kit_uri_set_attribute(obj->info, &attr);
1296                 if (ret < 0) {
1297                         gnutls_assert();
1298                         return GNUTLS_E_MEMORY_ERROR;
1299                 }
1300         }
1301
1302         if (id && id->data) {
1303                 attr.type = CKA_ID;
1304                 attr.value = id->data;
1305                 attr.value_len = id->size;
1306                 ret = p11_kit_uri_set_attribute(obj->info, &attr);
1307                 if (ret < 0) {
1308                         gnutls_assert();
1309                         return GNUTLS_E_MEMORY_ERROR;
1310                 }
1311         }
1312
1313         return 0;
1314 }
1315
1316 #define MAX_PK_PARAM_SIZE 2048
1317
1318 int pkcs11_read_pubkey(struct ck_function_list *module,
1319                        ck_session_handle_t pks, ck_object_handle_t obj,
1320                        ck_key_type_t key_type, gnutls_datum_t * pubkey)
1321 {
1322         struct ck_attribute a[4];
1323         uint8_t *tmp1;
1324         uint8_t *tmp2 = NULL;
1325         size_t tmp1_size, tmp2_size;
1326         int ret;
1327         ck_rv_t rv;
1328
1329         tmp1_size = tmp2_size = MAX_PK_PARAM_SIZE;
1330         tmp1 = gnutls_malloc(tmp1_size);
1331         if (tmp1 == NULL)
1332                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1333
1334         tmp2 = gnutls_malloc(tmp2_size);
1335         if (tmp2 == NULL) {
1336                 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1337                 goto cleanup;
1338         }
1339
1340         switch (key_type) {
1341         case CKK_RSA:
1342                 a[0].type = CKA_MODULUS;
1343                 a[0].value = tmp1;
1344                 a[0].value_len = tmp1_size;
1345                 a[1].type = CKA_PUBLIC_EXPONENT;
1346                 a[1].value = tmp2;
1347                 a[1].value_len = tmp2_size;
1348
1349                 if (pkcs11_get_attribute_value(module, pks, obj, a, 2) ==
1350                     CKR_OK) {
1351
1352                         pubkey[0].data = a[0].value;
1353                         pubkey[0].size = a[0].value_len;
1354
1355                         pubkey[1].data = a[1].value;
1356                         pubkey[1].size = a[1].value_len;
1357                 } else {
1358                         gnutls_assert();
1359                         ret = GNUTLS_E_PKCS11_ERROR;
1360                         goto cleanup;
1361                 }
1362                 break;
1363         case CKK_DSA:
1364                 a[0].type = CKA_PRIME;
1365                 a[0].value = tmp1;
1366                 a[0].value_len = tmp1_size;
1367                 a[1].type = CKA_SUBPRIME;
1368                 a[1].value = tmp2;
1369                 a[1].value_len = tmp2_size;
1370
1371                 if ((rv = pkcs11_get_attribute_value(module, pks, obj, a, 2)) ==
1372                     CKR_OK) {
1373                         ret =
1374                             _gnutls_set_datum(&pubkey[0], a[0].value,
1375                                               a[0].value_len);
1376
1377                         if (ret >= 0)
1378                                 ret =
1379                                     _gnutls_set_datum(&pubkey
1380                                                       [1], a[1].value,
1381                                                       a[1].value_len);
1382
1383                         if (ret < 0) {
1384                                 gnutls_assert();
1385                                 _gnutls_free_datum(&pubkey[1]);
1386                                 _gnutls_free_datum(&pubkey[0]);
1387                                 ret = GNUTLS_E_MEMORY_ERROR;
1388                                 goto cleanup;
1389                         }
1390                 } else {
1391                         gnutls_assert();
1392                         ret = pkcs11_rv_to_err(rv);
1393                         goto cleanup;
1394                 }
1395
1396                 a[0].type = CKA_BASE;
1397                 a[0].value = tmp1;
1398                 a[0].value_len = tmp1_size;
1399                 a[1].type = CKA_VALUE;
1400                 a[1].value = tmp2;
1401                 a[1].value_len = tmp2_size;
1402
1403                 if ((rv = pkcs11_get_attribute_value(module, pks, obj, a, 2)) ==
1404                     CKR_OK) {
1405                         pubkey[2].data = a[0].value;
1406                         pubkey[2].size = a[0].value_len;
1407
1408                         pubkey[3].data = a[1].value;
1409                         pubkey[3].size = a[1].value_len;
1410
1411                 } else {
1412                         gnutls_assert();
1413                         ret = pkcs11_rv_to_err(rv);
1414                         goto cleanup;
1415                 }
1416                 break;
1417         case CKK_ECDSA:
1418                 a[0].type = CKA_EC_PARAMS;
1419                 a[0].value = tmp1;
1420                 a[0].value_len = tmp1_size;
1421
1422                 a[1].type = CKA_EC_POINT;
1423                 a[1].value = tmp2;
1424                 a[1].value_len = tmp2_size;
1425
1426                 if ((rv = pkcs11_get_attribute_value(module, pks, obj, a, 2)) ==
1427                     CKR_OK) {
1428
1429                         pubkey[0].data = a[0].value;
1430                         pubkey[0].size = a[0].value_len;
1431
1432                         pubkey[1].data = a[1].value;
1433                         pubkey[1].size = a[1].value_len;
1434                 } else {
1435                         gnutls_assert();
1436
1437                         ret = pkcs11_rv_to_err(rv);
1438                         goto cleanup;
1439                 }
1440
1441                 break;
1442         default:
1443                 _gnutls_debug_log("requested reading public key of unsupported type %u\n", (unsigned)key_type);
1444                 ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1445                 goto cleanup;
1446         }
1447
1448         return 0;
1449
1450 cleanup:
1451         gnutls_free(tmp1);
1452         gnutls_free(tmp2);
1453
1454         return ret;
1455 }
1456
1457 static int
1458 pkcs11_obj_import_pubkey(struct ck_function_list *module,
1459                          ck_session_handle_t pks,
1460                          ck_object_handle_t obj,
1461                          gnutls_pkcs11_obj_t crt,
1462                          gnutls_datum_t *data,
1463                          const gnutls_datum_t *id,
1464                          const gnutls_datum_t *label,
1465                          struct ck_token_info *tinfo,
1466                          struct ck_info *lib_info)
1467 {
1468         struct ck_attribute a[4];
1469         ck_key_type_t key_type;
1470         int ret;
1471         ck_bool_t tval;
1472
1473         a[0].type = CKA_KEY_TYPE;
1474         a[0].value = &key_type;
1475         a[0].value_len = sizeof(key_type);
1476
1477         if (pkcs11_get_attribute_value(module, pks, obj, a, 1) == CKR_OK) {
1478                 crt->pk_algorithm = mech_to_pk(key_type);
1479
1480                 ret =
1481                     pkcs11_read_pubkey(module, pks, obj, key_type,
1482                                        crt->pubkey);
1483                 if (ret < 0)
1484                         return gnutls_assert_val(ret);
1485         }
1486
1487         /* read key usage flags */
1488         a[0].type = CKA_ENCRYPT;
1489         a[0].value = &tval;
1490         a[0].value_len = sizeof(tval);
1491
1492         if (pkcs11_get_attribute_value(module, pks, obj, a, 1) == CKR_OK) {
1493                 if (tval != 0) {
1494                         crt->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
1495                 }
1496         }
1497
1498         a[0].type = CKA_VERIFY;
1499         a[0].value = &tval;
1500         a[0].value_len = sizeof(tval);
1501
1502         if (pkcs11_get_attribute_value(module, pks, obj, a, 1) == CKR_OK) {
1503                 if (tval != 0) {
1504                         crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1505                             GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1506                             | GNUTLS_KEY_NON_REPUDIATION;
1507                 }
1508         }
1509
1510         a[0].type = CKA_VERIFY_RECOVER;
1511         a[0].value = &tval;
1512         a[0].value_len = sizeof(tval);
1513
1514         if (pkcs11_get_attribute_value(module, pks, obj, a, 1) == CKR_OK) {
1515                 if (tval != 0) {
1516                         crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1517                             GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1518                             | GNUTLS_KEY_NON_REPUDIATION;
1519                 }
1520         }
1521
1522         a[0].type = CKA_DERIVE;
1523         a[0].value = &tval;
1524         a[0].value_len = sizeof(tval);
1525
1526         if (pkcs11_get_attribute_value(module, pks, obj, a, 1) == CKR_OK) {
1527                 if (tval != 0) {
1528                         crt->key_usage |= GNUTLS_KEY_KEY_AGREEMENT;
1529                 }
1530         }
1531
1532         a[0].type = CKA_WRAP;
1533         a[0].value = &tval;
1534         a[0].value_len = sizeof(tval);
1535
1536         if (pkcs11_get_attribute_value(module, pks, obj, a, 1) == CKR_OK) {
1537                 if (tval != 0) {
1538                         crt->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
1539                 }
1540         }
1541
1542         ret = pkcs11_obj_import(CKO_PUBLIC_KEY, crt, data, id, label,
1543                                  tinfo, lib_info);
1544         return ret;
1545 }
1546
1547 static int
1548 pkcs11_import_object(ck_object_handle_t obj, ck_object_class_t class,
1549                      struct pkcs11_session_info *sinfo,
1550                      struct ck_token_info *tinfo, struct ck_info *lib_info,
1551                      gnutls_pkcs11_obj_t fobj)
1552 {
1553         ck_bool_t b;
1554         int rv, ret;
1555         struct ck_attribute a[4];
1556         unsigned long category = 0;
1557         char label_tmp[PKCS11_LABEL_SIZE];
1558         char id_tmp[PKCS11_ID_SIZE];
1559         gnutls_datum_t id, label, data = {NULL, 0};
1560
1561         /* now figure out flags */
1562         fobj->flags = 0;
1563         a[0].type = CKA_WRAP;
1564         a[0].value = &b;
1565         a[0].value_len = sizeof(b);
1566
1567         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1568         if (rv == CKR_OK && b != 0)
1569                 fobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP;
1570
1571         a[0].type = CKA_UNWRAP;
1572         a[0].value = &b;
1573         a[0].value_len = sizeof(b);
1574
1575         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1576         if (rv == CKR_OK && b != 0)
1577                 fobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP;
1578
1579         a[0].type = CKA_PRIVATE;
1580         a[0].value = &b;
1581         a[0].value_len = sizeof(b);
1582
1583         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1584         if (rv == CKR_OK && b != 0)
1585                 fobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE;
1586
1587         a[0].type = CKA_TRUSTED;
1588         a[0].value = &b;
1589         a[0].value_len = sizeof(b);
1590
1591         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1592         if (rv == CKR_OK && b != 0)
1593                 fobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED;
1594
1595         a[0].type = CKA_SENSITIVE;
1596         a[0].value = &b;
1597         a[0].value_len = sizeof(b);
1598
1599         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1600         if (rv == CKR_OK && b != 0)
1601                 fobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE;
1602
1603         a[0].type = CKA_EXTRACTABLE;
1604         a[0].value = &b;
1605         a[0].value_len = sizeof(b);
1606
1607         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1608         if (rv == CKR_OK && b != 0)
1609                 fobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_EXTRACTABLE;
1610
1611         a[0].type = CKA_NEVER_EXTRACTABLE;
1612         a[0].value = &b;
1613         a[0].value_len = sizeof(b);
1614
1615         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1616         if (rv == CKR_OK && b != 0)
1617                 fobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_NEVER_EXTRACTABLE;
1618
1619         a[0].type = CKA_CERTIFICATE_CATEGORY;
1620         a[0].value = &category;
1621         a[0].value_len = sizeof(category);
1622
1623         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1624         if (rv == CKR_OK && category == 2)
1625                 fobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_CA;
1626
1627         a[0].type = CKA_ALWAYS_AUTHENTICATE;
1628         a[0].value = &b;
1629         a[0].value_len = sizeof(b);
1630
1631         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1632         if (rv == CKR_OK && b != 0)
1633                 fobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH;
1634
1635         /* now recover the object label/id */
1636         a[0].type = CKA_LABEL;
1637         a[0].value = label_tmp;
1638         a[0].value_len = sizeof(label_tmp);
1639         rv = pkcs11_get_attribute_value
1640             (sinfo->module, sinfo->pks, obj, a, 1);
1641         if (rv != CKR_OK) {
1642                 gnutls_assert();
1643                 label.data = NULL;
1644                 label.size = 0;
1645         } else {
1646                 label.data = a[0].value;
1647                 label.size = a[0].value_len;
1648         }
1649
1650         a[0].type = CKA_ID;
1651         a[0].value = id_tmp;
1652         a[0].value_len = sizeof(id_tmp);
1653         rv = pkcs11_get_attribute_value
1654             (sinfo->module, sinfo->pks, obj, a, 1);
1655         if (rv != CKR_OK) {
1656                 gnutls_assert();
1657                 id.data = NULL;
1658                 id.size = 0;
1659         } else {
1660                 id.data = a[0].value;
1661                 id.size = a[0].value_len;
1662         }
1663
1664         if (label.data == NULL && id.data == NULL)
1665                 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1666
1667         rv = pkcs11_get_attribute_avalue
1668             (sinfo->module, sinfo->pks, obj, CKA_VALUE, &data);
1669         if (rv != CKR_OK) {
1670                 gnutls_assert();
1671                 /* data will be null */
1672         }
1673
1674         if (class == CKO_PUBLIC_KEY) {
1675                 ret =
1676                     pkcs11_obj_import_pubkey(sinfo->module,
1677                                              sinfo->pks,
1678                                              obj,
1679                                              fobj,
1680                                              &data,
1681                                              &id, &label,
1682                                              tinfo,
1683                                              lib_info);
1684         } else {
1685                 ret =
1686                     pkcs11_obj_import(class,
1687                                       fobj,
1688                                       &data, &id, &label,
1689                                       tinfo,
1690                                       lib_info);
1691         }
1692         if (ret < 0) {
1693                 gnutls_assert();
1694                 goto cleanup;
1695         }
1696
1697         ret = 0;
1698  cleanup:
1699         gnutls_free(data.data);
1700         return ret;
1701 }
1702
1703 static int
1704 find_obj_url_cb(struct pkcs11_session_info *sinfo,
1705              struct ck_token_info *tinfo, struct ck_info *lib_info,
1706              void *input)
1707 {
1708         struct find_url_data_st *find_data = input;
1709         struct ck_attribute a[4];
1710         struct ck_attribute *attr;
1711         ck_object_class_t class = -1;
1712         ck_certificate_type_t type = (ck_certificate_type_t) - 1;
1713         ck_rv_t rv;
1714         ck_object_handle_t obj;
1715         unsigned long count, a_vals;
1716         int found = 0, ret;
1717
1718         if (tinfo == NULL) {    /* we don't support multiple calls */
1719                 gnutls_assert();
1720                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1721         }
1722
1723         /* do not bother reading the token if basic fields do not match
1724          */
1725         if (!p11_kit_uri_match_token_info
1726             (find_data->obj->info, tinfo)
1727             || !p11_kit_uri_match_module_info(find_data->obj->info,
1728                                               lib_info)) {
1729                 gnutls_assert();
1730                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1731         }
1732
1733         a_vals = 0;
1734         attr = p11_kit_uri_get_attribute(find_data->obj->info, CKA_ID);
1735         if (attr) {
1736                 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1737                 a_vals++;
1738         }
1739
1740         attr = p11_kit_uri_get_attribute(find_data->obj->info, CKA_LABEL);
1741         if (attr) {
1742                 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1743                 a_vals++;
1744         }
1745
1746         if (!a_vals) {
1747                 gnutls_assert();
1748                 return GNUTLS_E_INVALID_REQUEST;
1749         }
1750
1751         /* Find objects with given class and type */
1752         attr = p11_kit_uri_get_attribute(find_data->obj->info, CKA_CLASS);
1753         if (attr) {
1754                 if (attr->value
1755                     && attr->value_len == sizeof(ck_object_class_t))
1756                         class = *((ck_object_class_t *) attr->value);
1757                 if (class == CKO_CERTIFICATE)
1758                         type = CKC_X_509;
1759                 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1760                 a_vals++;
1761         }
1762
1763         if (type != (ck_certificate_type_t) - 1) {
1764                 a[a_vals].type = CKA_CERTIFICATE_TYPE;
1765                 a[a_vals].value = &type;
1766                 a[a_vals].value_len = sizeof type;
1767                 a_vals++;
1768         }
1769
1770
1771         rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
1772                                       a_vals);
1773         if (rv != CKR_OK) {
1774                 gnutls_assert();
1775                 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
1776                 ret = pkcs11_rv_to_err(rv);
1777                 goto cleanup;
1778         }
1779
1780         if (pkcs11_find_objects(sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK &&
1781             count == 1) {
1782                 ret = pkcs11_import_object(obj, class, sinfo, tinfo, lib_info, find_data->obj);
1783                 if (ret >= 0) {
1784                         found = 1;
1785                 }
1786         } else {
1787                 _gnutls_debug_log
1788                     ("p11: Skipped object, missing attrs.\n");
1789         }
1790
1791         if (found == 0) {
1792                 gnutls_assert();
1793                 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1794         } else {
1795                 ret = 0;
1796         }
1797
1798       cleanup:
1799         pkcs11_find_objects_final(sinfo);
1800
1801         return ret;
1802 }
1803
1804 unsigned int pkcs11_obj_flags_to_int(unsigned int flags)
1805 {
1806         unsigned int ret_flags = 0;
1807
1808         if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN)
1809                 ret_flags |= SESSION_LOGIN;
1810         if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO)
1811                 ret_flags |= SESSION_LOGIN | SESSION_SO;
1812         if (flags & GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE)
1813                 ret_flags |= SESSION_TRUSTED;
1814
1815         return ret_flags;
1816 }
1817
1818 /**
1819  * gnutls_pkcs11_obj_import_url:
1820  * @obj: The structure to store the object
1821  * @url: a PKCS 11 url identifying the key
1822  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
1823  *
1824  * This function will "import" a PKCS 11 URL identifying an object (e.g. certificate)
1825  * to the #gnutls_pkcs11_obj_t structure. This does not involve any
1826  * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is
1827  * format agnostic. Only data are transferred.
1828  *
1829  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1830  *   negative error value.
1831  *
1832  * Since: 2.12.0
1833  **/
1834 int
1835 gnutls_pkcs11_obj_import_url(gnutls_pkcs11_obj_t obj, const char *url,
1836                              unsigned int flags)
1837 {
1838         int ret;
1839         struct find_url_data_st find_data;
1840
1841         PKCS11_CHECK_INIT;
1842         memset(&find_data, 0, sizeof(find_data));
1843
1844         /* fill in the find data structure */
1845         find_data.obj = obj;
1846
1847         ret = pkcs11_url_to_info(url, &obj->info, flags);
1848         if (ret < 0) {
1849                 gnutls_assert();
1850                 return ret;
1851         }
1852
1853         ret =
1854             _pkcs11_traverse_tokens(find_obj_url_cb, &find_data, obj->info,
1855                                     &obj->pin,
1856                                     pkcs11_obj_flags_to_int(flags));
1857         if (ret < 0) {
1858                 gnutls_assert();
1859                 return ret;
1860         }
1861
1862         return 0;
1863 }
1864
1865 static int
1866 find_token_num_cb(struct pkcs11_session_info *sinfo,
1867                struct ck_token_info *tinfo,
1868                struct ck_info *lib_info, void *input)
1869 {
1870         struct find_token_num *find_data = input;
1871
1872         if (tinfo == NULL) {    /* we don't support multiple calls */
1873                 gnutls_assert();
1874                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1875         }
1876
1877         if (find_data->current == find_data->seq) {
1878                 memcpy(p11_kit_uri_get_token_info(find_data->info),
1879                        tinfo, sizeof(struct ck_token_info));
1880                 memcpy(p11_kit_uri_get_module_info(find_data->info),
1881                        lib_info, sizeof(struct ck_info));
1882                 return 0;
1883         }
1884
1885         find_data->current++;
1886         /* search the token for the id */
1887
1888
1889         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;   /* non zero is enough */
1890 }
1891
1892 /**
1893  * gnutls_pkcs11_token_get_url:
1894  * @seq: sequence number starting from 0
1895  * @detailed: non zero if a detailed URL is required
1896  * @url: will contain an allocated url
1897  *
1898  * This function will return the URL for each token available
1899  * in system. The url has to be released using gnutls_free()
1900  *
1901  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
1902  * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if the sequence number
1903  * exceeds the available tokens, otherwise a negative error value.
1904  *
1905  * Since: 2.12.0
1906  **/
1907 int
1908 gnutls_pkcs11_token_get_url(unsigned int seq,
1909                             gnutls_pkcs11_url_type_t detailed, char **url)
1910 {
1911         int ret;
1912         struct find_token_num tn;
1913
1914         PKCS11_CHECK_INIT;
1915
1916         memset(&tn, 0, sizeof(tn));
1917         tn.seq = seq;
1918         tn.info = p11_kit_uri_new();
1919
1920         ret = _pkcs11_traverse_tokens(find_token_num_cb, &tn, NULL, NULL, 0);
1921         if (ret < 0) {
1922                 p11_kit_uri_free(tn.info);
1923                 gnutls_assert();
1924                 return ret;
1925         }
1926
1927         ret = pkcs11_info_to_url(tn.info, detailed, url);
1928         p11_kit_uri_free(tn.info);
1929
1930         if (ret < 0) {
1931                 gnutls_assert();
1932                 return ret;
1933         }
1934
1935         return 0;
1936
1937 }
1938
1939 /**
1940  * gnutls_pkcs11_token_get_info:
1941  * @url: should contain a PKCS 11 URL
1942  * @ttype: Denotes the type of information requested
1943  * @output: where output will be stored
1944  * @output_size: contains the maximum size of the output and will be overwritten with actual
1945  *
1946  * This function will return information about the PKCS 11 token such
1947  * as the label, id, etc.
1948  *
1949  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code
1950  * on error.
1951  *
1952  * Since: 2.12.0
1953  **/
1954 int
1955 gnutls_pkcs11_token_get_info(const char *url,
1956                              gnutls_pkcs11_token_info_t ttype,
1957                              void *output, size_t * output_size)
1958 {
1959         struct p11_kit_uri *info = NULL;
1960         const uint8_t *str;
1961         size_t str_max;
1962         size_t len;
1963         int ret;
1964
1965         PKCS11_CHECK_INIT;
1966
1967         ret = pkcs11_url_to_info(url, &info, 0);
1968         if (ret < 0) {
1969                 gnutls_assert();
1970                 return ret;
1971         }
1972
1973         switch (ttype) {
1974         case GNUTLS_PKCS11_TOKEN_LABEL:
1975                 str = p11_kit_uri_get_token_info(info)->label;
1976                 str_max = 32;
1977                 break;
1978         case GNUTLS_PKCS11_TOKEN_SERIAL:
1979                 str = p11_kit_uri_get_token_info(info)->serial_number;
1980                 str_max = 16;
1981                 break;
1982         case GNUTLS_PKCS11_TOKEN_MANUFACTURER:
1983                 str = p11_kit_uri_get_token_info(info)->manufacturer_id;
1984                 str_max = 32;
1985                 break;
1986         case GNUTLS_PKCS11_TOKEN_MODEL:
1987                 str = p11_kit_uri_get_token_info(info)->model;
1988                 str_max = 16;
1989                 break;
1990         default:
1991                 p11_kit_uri_free(info);
1992                 gnutls_assert();
1993                 return GNUTLS_E_INVALID_REQUEST;
1994         }
1995
1996         len = p11_kit_space_strlen(str, str_max);
1997
1998         if (len + 1 > *output_size) {
1999                 *output_size = len + 1;
2000                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
2001         }
2002
2003         memcpy(output, str, len);
2004         ((char *) output)[len] = '\0';
2005
2006         *output_size = len;
2007
2008         ret = 0;
2009
2010         p11_kit_uri_free(info);
2011         return ret;
2012 }
2013
2014 /**
2015  * gnutls_pkcs11_obj_export_url:
2016  * @obj: Holds the PKCS 11 certificate
2017  * @detailed: non zero if a detailed URL is required
2018  * @url: will contain an allocated url
2019  *
2020  * This function will export a URL identifying the given certificate.
2021  *
2022  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2023  *   negative error value.
2024  *
2025  * Since: 2.12.0
2026  **/
2027 int
2028 gnutls_pkcs11_obj_export_url(gnutls_pkcs11_obj_t obj,
2029                              gnutls_pkcs11_url_type_t detailed, char **url)
2030 {
2031         int ret;
2032
2033         ret = pkcs11_info_to_url(obj->info, detailed, url);
2034         if (ret < 0) {
2035                 gnutls_assert();
2036                 return ret;
2037         }
2038
2039         return 0;
2040 }
2041
2042 /**
2043  * gnutls_pkcs11_obj_get_type:
2044  * @obj: Holds the PKCS 11 object
2045  *
2046  * This function will return the type of the object being
2047  * stored in the structure.
2048  *
2049  * Returns: The type of the object
2050  *
2051  * Since: 2.12.0
2052  **/
2053 gnutls_pkcs11_obj_type_t
2054 gnutls_pkcs11_obj_get_type(gnutls_pkcs11_obj_t obj)
2055 {
2056         return obj->type;
2057 }
2058
2059 static int
2060 retrieve_pin_from_source(const char *pinfile,
2061                          struct ck_token_info *token_info, int attempts,
2062                          ck_user_type_t user_type,
2063                          struct p11_kit_pin **pin)
2064 {
2065         unsigned int flags = 0;
2066         struct p11_kit_uri *token_uri;
2067         struct p11_kit_pin *result;
2068         char *label;
2069
2070         label =
2071             p11_kit_space_strdup(token_info->label,
2072                                  sizeof(token_info->label));
2073         if (label == NULL) {
2074                 gnutls_assert();
2075                 return GNUTLS_E_MEMORY_ERROR;
2076         }
2077
2078         token_uri = p11_kit_uri_new();
2079         if (token_uri == NULL) {
2080                 free(label);
2081                 gnutls_assert();
2082                 return GNUTLS_E_MEMORY_ERROR;
2083         }
2084
2085         memcpy(p11_kit_uri_get_token_info(token_uri), token_info,
2086                sizeof(struct ck_token_info));
2087
2088         if (attempts)
2089                 flags |= P11_KIT_PIN_FLAGS_RETRY;
2090         if (user_type == CKU_USER) {
2091                 flags |= P11_KIT_PIN_FLAGS_USER_LOGIN;
2092                 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
2093                         flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
2094                 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
2095                         flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
2096         } else if (user_type == CKU_SO) {
2097                 flags |= P11_KIT_PIN_FLAGS_SO_LOGIN;
2098                 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
2099                         flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
2100                 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
2101                         flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
2102         } else if (user_type == CKU_CONTEXT_SPECIFIC) {
2103                 flags |= P11_KIT_PIN_FLAGS_CONTEXT_LOGIN;
2104         }
2105
2106         result = p11_kit_pin_request(pinfile, token_uri, label, flags);
2107         p11_kit_uri_free(token_uri);
2108         free(label);
2109
2110         if (result == NULL) {
2111                 gnutls_assert();
2112                 return GNUTLS_E_PKCS11_PIN_ERROR;
2113         }
2114
2115         *pin = result;
2116         return 0;
2117 }
2118
2119 static int
2120 retrieve_pin_from_callback(const struct pin_info_st *pin_info,
2121                            struct ck_token_info *token_info,
2122                            int attempts, ck_user_type_t user_type,
2123                            struct p11_kit_pin **pin)
2124 {
2125         char pin_value[GNUTLS_PKCS11_MAX_PIN_LEN];
2126         unsigned int flags = 0;
2127         char *token_str;
2128         char *label;
2129         struct p11_kit_uri *token_uri;
2130         int ret = 0;
2131
2132         label =
2133             p11_kit_space_strdup(token_info->label,
2134                                  sizeof(token_info->label));
2135         if (label == NULL) {
2136                 gnutls_assert();
2137                 return GNUTLS_E_MEMORY_ERROR;
2138         }
2139
2140         token_uri = p11_kit_uri_new();
2141         if (token_uri == NULL) {
2142                 free(label);
2143                 gnutls_assert();
2144                 return GNUTLS_E_MEMORY_ERROR;
2145         }
2146
2147         memcpy(p11_kit_uri_get_token_info(token_uri), token_info,
2148                sizeof(struct ck_token_info));
2149         ret = pkcs11_info_to_url(token_uri, 1, &token_str);
2150         p11_kit_uri_free(token_uri);
2151
2152         if (ret < 0) {
2153                 free(label);
2154                 gnutls_assert();
2155                 return GNUTLS_E_MEMORY_ERROR;
2156         }
2157
2158         if (user_type == CKU_USER || user_type == CKU_CONTEXT_SPECIFIC) {
2159                 flags |= GNUTLS_PIN_USER;
2160
2161                 if (user_type == CKU_CONTEXT_SPECIFIC)
2162                         flags |= GNUTLS_PIN_CONTEXT_SPECIFIC;
2163                 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
2164                         flags |= GNUTLS_PIN_COUNT_LOW;
2165                 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
2166                         flags |= GNUTLS_PIN_FINAL_TRY;
2167         } else if (user_type == CKU_SO) {
2168                 flags |= GNUTLS_PIN_SO;
2169                 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
2170                         flags |= GNUTLS_PIN_COUNT_LOW;
2171                 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
2172                         flags |= GNUTLS_PIN_FINAL_TRY;
2173         }
2174
2175         if (attempts > 0)
2176                 flags |= GNUTLS_PIN_WRONG;
2177
2178         if (pin_info && pin_info->cb)
2179                 ret =
2180                     pin_info->cb(pin_info->data, attempts,
2181                                  (char *) token_str, label, flags,
2182                                  pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2183         else if (_gnutls_pin_func)
2184                 ret =
2185                     _gnutls_pin_func(_gnutls_pin_data, attempts,
2186                                      (char *) token_str, label, flags,
2187                                      pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2188         else
2189                 ret = gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2190
2191         free(token_str);
2192         free(label);
2193
2194         if (ret < 0)
2195                 return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2196
2197         *pin = p11_kit_pin_new_for_string(pin_value);
2198
2199         if (*pin == NULL)
2200                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2201
2202         return 0;
2203 }
2204
2205 static int
2206 retrieve_pin(struct pin_info_st *pin_info, struct p11_kit_uri *info,
2207              struct ck_token_info *token_info, int attempts,
2208              ck_user_type_t user_type, struct p11_kit_pin **pin)
2209 {
2210         const char *pinfile;
2211         int ret = GNUTLS_E_PKCS11_PIN_ERROR;
2212
2213         if (pin) {
2214                 *pin = NULL;
2215
2216                 /* Check if a pinfile is specified, and use that if possible */
2217                 pinfile = p11_kit_uri_get_pin_source(info);
2218                 if (pinfile != NULL) {
2219                         _gnutls_debug_log("p11: Using pinfile to retrieve PIN\n");
2220                         ret =
2221                             retrieve_pin_from_source(pinfile, token_info, attempts,
2222                                                      user_type, pin);
2223                 }
2224         }
2225
2226         /* The global gnutls pin callback */
2227         if (ret < 0)
2228                 ret =
2229                     retrieve_pin_from_callback(pin_info, token_info,
2230                                                attempts, user_type, pin);
2231
2232         /* Otherwise, PIN entry is necessary for login, so fail if there's
2233          * no callback. */
2234
2235         if (ret < 0) {
2236                 gnutls_assert();
2237                 _gnutls_debug_log
2238                     ("p11: No suitable pin callback but login required.\n");
2239         }
2240
2241         return ret;
2242 }
2243
2244 int
2245 pkcs11_login(struct pkcs11_session_info *sinfo,
2246              struct pin_info_st *pin_info,
2247              struct p11_kit_uri *info,
2248              unsigned so,
2249              unsigned reauth)
2250 {
2251         struct ck_session_info session_info;
2252         int attempt = 0, ret;
2253         ck_user_type_t user_type;
2254         ck_rv_t rv;
2255
2256         if (so == 0) {
2257                 if (reauth == 0)
2258                         user_type = CKU_USER;
2259                 else
2260                         user_type = CKU_CONTEXT_SPECIFIC;
2261         } else
2262                 user_type = CKU_SO;
2263
2264         if (so == 0 && (sinfo->tinfo.flags & CKF_LOGIN_REQUIRED) == 0) {
2265                 gnutls_assert();
2266                 _gnutls_debug_log("p11: No login required.\n");
2267                 return 0;
2268         }
2269
2270         /* For a token with a "protected" (out-of-band) authentication
2271          * path, calling login with a NULL username is all that is
2272          * required. */
2273         if (sinfo->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
2274                 rv = (sinfo->module)->C_Login(sinfo->pks,
2275                                               user_type,
2276                                               NULL, 0);
2277                 if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) {
2278                         return 0;
2279                 } else {
2280                         gnutls_assert();
2281                         _gnutls_debug_log
2282                             ("p11: Protected login failed.\n");
2283                         ret = GNUTLS_E_PKCS11_ERROR;
2284                         goto cleanup;
2285                 }
2286         }
2287
2288         do {
2289                 struct p11_kit_pin *pin;
2290                 struct ck_token_info tinfo;
2291
2292                 memcpy(&tinfo, &sinfo->tinfo, sizeof(tinfo));
2293
2294                 /* Check whether the session is already logged in, and if so, just skip */
2295                 rv = (sinfo->module)->C_GetSessionInfo(sinfo->pks,
2296                                                        &session_info);
2297                 if (rv == CKR_OK && reauth == 0 &&
2298                     (session_info.state == CKS_RO_USER_FUNCTIONS
2299                         || session_info.state == CKS_RW_USER_FUNCTIONS)) {
2300                         ret = 0;
2301                         goto cleanup;
2302                 }
2303
2304                 /* If login has been attempted once already, check the token
2305                  * status again, the flags might change. */
2306                 if (attempt) {
2307                         if (pkcs11_get_token_info
2308                             (sinfo->module, sinfo->sid,
2309                              &tinfo) != CKR_OK) {
2310                                 gnutls_assert();
2311                                 _gnutls_debug_log
2312                                     ("p11: GetTokenInfo failed\n");
2313                                 ret = GNUTLS_E_PKCS11_ERROR;
2314                                 goto cleanup;
2315                         }
2316                 }
2317
2318                 ret =
2319                     retrieve_pin(pin_info, info, &tinfo, attempt++,
2320                                  user_type, &pin);
2321                 if (ret < 0) {
2322                         gnutls_assert();
2323                         goto cleanup;
2324                 }
2325
2326                 rv = (sinfo->module)->C_Login(sinfo->pks, user_type,
2327                                               (unsigned char *)
2328                                               p11_kit_pin_get_value(pin,
2329                                                                     NULL),
2330                                               p11_kit_pin_get_length(pin));
2331
2332                 p11_kit_pin_unref(pin);
2333         }
2334         while (rv == CKR_PIN_INCORRECT);
2335
2336         _gnutls_debug_log("p11: Login result = %lu\n", rv);
2337
2338
2339         ret = (rv == CKR_OK
2340                || rv ==
2341                CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err(rv);
2342
2343       cleanup:
2344         return ret;
2345 }
2346
2347 int pkcs11_call_token_func(struct p11_kit_uri *info, const unsigned retry)
2348 {
2349         struct ck_token_info *tinfo;
2350         char *label;
2351         int ret = 0;
2352
2353         tinfo = p11_kit_uri_get_token_info(info);
2354         label = p11_kit_space_strdup(tinfo->label, sizeof(tinfo->label));
2355         ret = (_gnutls_token_func) (_gnutls_token_data, label, retry);
2356         free(label);
2357
2358         return ret;
2359 }
2360
2361
2362 static int
2363 find_privkeys(struct pkcs11_session_info *sinfo,
2364               struct ck_token_info *tinfo, struct find_pkey_list_st *list)
2365 {
2366         struct ck_attribute a[3];
2367         ck_object_class_t class;
2368         ck_rv_t rv;
2369         ck_object_handle_t obj;
2370         unsigned long count, current;
2371         char certid_tmp[PKCS11_ID_SIZE];
2372
2373         class = CKO_PRIVATE_KEY;
2374
2375         /* Find an object with private key class and a certificate ID
2376          * which matches the certificate. */
2377         /* FIXME: also match the cert subject. */
2378         a[0].type = CKA_CLASS;
2379         a[0].value = &class;
2380         a[0].value_len = sizeof class;
2381
2382         rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 1);
2383         if (rv != CKR_OK) {
2384                 gnutls_assert();
2385                 return pkcs11_rv_to_err(rv);
2386         }
2387
2388         list->key_ids_size = 0;
2389         while (pkcs11_find_objects
2390                (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK
2391                && count == 1) {
2392                 list->key_ids_size++;
2393         }
2394
2395         pkcs11_find_objects_final(sinfo);
2396
2397         if (list->key_ids_size == 0) {
2398                 gnutls_assert();
2399                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2400         }
2401
2402         list->key_ids =
2403             gnutls_malloc(sizeof(gnutls_buffer_st) * list->key_ids_size);
2404         if (list->key_ids == NULL) {
2405                 gnutls_assert();
2406                 return GNUTLS_E_MEMORY_ERROR;
2407         }
2408
2409         /* actual search */
2410         a[0].type = CKA_CLASS;
2411         a[0].value = &class;
2412         a[0].value_len = sizeof class;
2413
2414         rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 1);
2415         if (rv != CKR_OK) {
2416                 gnutls_assert();
2417                 return pkcs11_rv_to_err(rv);
2418         }
2419
2420         current = 0;
2421         while (pkcs11_find_objects
2422                (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK
2423                && count == 1) {
2424
2425                 a[0].type = CKA_ID;
2426                 a[0].value = certid_tmp;
2427                 a[0].value_len = sizeof(certid_tmp);
2428
2429                 _gnutls_buffer_init(&list->key_ids[current]);
2430
2431                 if (pkcs11_get_attribute_value
2432                     (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK) {
2433                         _gnutls_buffer_append_data(&list->key_ids[current],
2434                                                    a[0].value,
2435                                                    a[0].value_len);
2436                         current++;
2437                 }
2438
2439                 if (current > list->key_ids_size)
2440                         break;
2441         }
2442
2443         pkcs11_find_objects_final(sinfo);
2444
2445         list->key_ids_size = current - 1;
2446
2447         return 0;
2448 }
2449
2450 /* Recover certificate list from tokens */
2451
2452 #define OBJECTS_A_TIME 8*1024
2453
2454 static int
2455 find_objs_cb(struct pkcs11_session_info *sinfo,
2456           struct ck_token_info *tinfo, struct ck_info *lib_info, void *input)
2457 {
2458         struct find_obj_data_st *find_data = input;
2459         struct ck_attribute a[16];
2460         struct ck_attribute *attr;
2461         ck_object_class_t class = (ck_object_class_t) -1;
2462         ck_certificate_type_t type = (ck_certificate_type_t) -1;
2463         ck_bool_t trusted;
2464         unsigned long category;
2465         ck_rv_t rv;
2466         ck_object_handle_t *objs = NULL;
2467         unsigned long count;
2468         char certid_tmp[PKCS11_ID_SIZE];
2469         int ret;
2470         struct find_pkey_list_st plist; /* private key holder */
2471         unsigned int i, tot_values = 0, class_set = 0;
2472
2473         if (tinfo == NULL) {
2474                 gnutls_assert();
2475                 return 0;
2476         }
2477
2478         /* do not bother reading the token if basic fields do not match
2479          */
2480         if (!p11_kit_uri_match_token_info(find_data->info, tinfo) ||
2481             !p11_kit_uri_match_module_info(find_data->info, lib_info)) {
2482                 gnutls_assert();
2483                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2484         }
2485
2486         memset(&plist, 0, sizeof(plist));
2487
2488         if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_WITH_PRIVKEY) {
2489                 ret = find_privkeys(sinfo, tinfo, &plist);
2490                 if (ret < 0) {
2491                         gnutls_assert();
2492                         return ret;
2493                 }
2494
2495                 if (plist.key_ids_size == 0) {
2496                         gnutls_assert();
2497                         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2498                 }
2499         }
2500
2501         /* Find objects with given class and type */
2502         attr = p11_kit_uri_get_attribute(find_data->info, CKA_CLASS);
2503         if (attr) {
2504                 if (attr->value
2505                     && attr->value_len == sizeof(ck_object_class_t))
2506                         class = *((ck_object_class_t *) attr->value);
2507                 if (class == CKO_CERTIFICATE)
2508                         type = CKC_X_509;
2509         }
2510
2511
2512         if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_CRT) {
2513                 class = CKO_CERTIFICATE;
2514
2515                 a[tot_values].type = CKA_CLASS;
2516                 a[tot_values].value = &class;
2517                 a[tot_values].value_len = sizeof class;
2518                 tot_values++;
2519                 class_set = 1;
2520
2521                 type = CKC_X_509;
2522                 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2523                 a[tot_values].value = &type;
2524                 a[tot_values].value_len = sizeof type;
2525                 tot_values++;
2526                 _gnutls_assert_log("p11 attrs: CKA_CLASS (CERT), CKA_CERTIFICATE_TYPE\n");
2527         }
2528
2529         if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_PUBKEY) {
2530                 class = CKO_PUBLIC_KEY;
2531
2532                 a[tot_values].type = CKA_CLASS;
2533                 a[tot_values].value = &class;
2534                 a[tot_values].value_len = sizeof class;
2535                 tot_values++;
2536                 class_set = 1;
2537                 _gnutls_assert_log("p11 attrs: CKA_CLASS (PUBLIC KEY)\n");
2538         }
2539
2540         if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY) {
2541                 class = CKO_PRIVATE_KEY;
2542
2543                 a[tot_values].type = CKA_CLASS;
2544                 a[tot_values].value = &class;
2545                 a[tot_values].value_len = sizeof class;
2546                 tot_values++;
2547                 class_set = 1;
2548                 _gnutls_assert_log("p11 attrs: CKA_CLASS (PRIVATE KEY)\n");
2549         }
2550
2551         if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
2552                 trusted = 1;
2553                 a[tot_values].type = CKA_TRUSTED;
2554                 a[tot_values].value = &trusted;
2555                 a[tot_values].value_len = sizeof trusted;
2556                 tot_values++;
2557                 _gnutls_assert_log("p11 attrs: CKA_TRUSTED\n");
2558         }
2559
2560         if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA) {
2561                 category = 2;
2562                 a[tot_values].type = CKA_CERTIFICATE_CATEGORY;
2563                 a[tot_values].value = &category;
2564                 a[tot_values].value_len = sizeof category;
2565                 tot_values++;
2566                 _gnutls_assert_log("p11 attrs: CKA_CERTIFICATE_CATEGORY=CA\n");
2567         }
2568
2569         if (class_set == 0 && class != (ck_object_class_t)-1) {
2570                 a[tot_values].type = CKA_CLASS;
2571                 a[tot_values].value = &class;
2572                 a[tot_values].value_len = sizeof class;
2573                 tot_values++;
2574                 class_set = 1;
2575                 _gnutls_assert_log("p11 attrs: CKA_CLASS\n");
2576         }
2577
2578         attr = p11_kit_uri_get_attribute(find_data->info, CKA_ID);
2579         if (attr) {
2580                 a[tot_values].type = CKA_ID;
2581                 a[tot_values].value = attr->value;
2582                 a[tot_values].value_len = attr->value_len;
2583                 tot_values++;
2584                 _gnutls_assert_log("p11 attrs: CKA_ID\n");
2585         }
2586
2587         attr = p11_kit_uri_get_attribute(find_data->info, CKA_LABEL);
2588         if (attr) {
2589                 a[tot_values].type = CKA_LABEL;
2590                 a[tot_values].value = attr->value;
2591                 a[tot_values].value_len = attr->value_len;
2592                 tot_values++;
2593                 _gnutls_assert_log("p11 attrs: CKA_LABEL\n");
2594         }
2595
2596         rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
2597                                       tot_values);
2598         if (rv != CKR_OK) {
2599                 gnutls_assert();
2600                 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
2601                 return pkcs11_rv_to_err(rv);
2602         }
2603
2604         objs = gnutls_malloc(OBJECTS_A_TIME*sizeof(objs[0]));
2605         if (objs == NULL) {
2606                 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2607                 goto fail;
2608         }
2609
2610         while (pkcs11_find_objects
2611                (sinfo->module, sinfo->pks, objs, OBJECTS_A_TIME, &count) == CKR_OK
2612                && count > 0) {
2613                 unsigned j;
2614                 gnutls_datum_t id;
2615
2616                 find_data->p_list = gnutls_realloc_fast(find_data->p_list, (find_data->current+count)*sizeof(find_data->p_list[0]));
2617                 if (find_data->p_list == NULL) {
2618                         ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2619                         goto fail;
2620                 }
2621
2622                 for (j=0;j<count;j++) {
2623                         a[0].type = CKA_ID;
2624                         a[0].value = certid_tmp;
2625                         a[0].value_len = sizeof certid_tmp;
2626
2627                         if (pkcs11_get_attribute_value
2628                             (sinfo->module, sinfo->pks, objs[j], a, 1) == CKR_OK) {
2629                                 id.data = a[0].value;
2630                                 id.size = a[0].value_len;
2631                         } else {
2632                                 id.data = NULL;
2633                                 id.size = 0;
2634                         }
2635
2636                         if (class_set == 0) {
2637                                 a[0].type = CKA_CLASS;
2638                                 a[0].value = &class;
2639                                 a[0].value_len = sizeof class;
2640
2641                                 rv = pkcs11_get_attribute_value(sinfo->module,
2642                                                            sinfo->pks, objs[j], a, 1);
2643                                 if (rv != CKR_OK) {
2644                                         class = -1;
2645                                 }
2646                         }
2647
2648                         if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_WITH_PRIVKEY) {
2649                                 for (i = 0; i < plist.key_ids_size; i++) {
2650                                         if (plist.key_ids[i].length !=
2651                                             id.size
2652                                             || memcmp(plist.key_ids[i].data,
2653                                                       id.data,
2654                                                       id.size) != 0) {
2655                                                 /* not found */
2656                                                 continue;
2657                                         }
2658                                 }
2659                         }
2660
2661                         ret =
2662                             gnutls_pkcs11_obj_init(&find_data->p_list
2663                                                    [find_data->current]);
2664                         if (ret < 0) {
2665                                 gnutls_assert();
2666                                 goto fail;
2667                         }
2668
2669                         ret = pkcs11_import_object(objs[j], class, sinfo,
2670                                              tinfo, lib_info,
2671                                              find_data->p_list[find_data->current]);
2672                         if (ret < 0) {
2673                                 gnutls_assert();
2674                                 /* skip the failed object */
2675                                 continue;
2676                         }
2677
2678                         find_data->current++;
2679                 }
2680         }
2681
2682         gnutls_free(objs);
2683         pkcs11_find_objects_final(sinfo);
2684
2685         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;   /* continue until all tokens have been checked */
2686
2687       fail:
2688         gnutls_free(objs);
2689         pkcs11_find_objects_final(sinfo);
2690         if (plist.key_ids != NULL) {
2691                 for (i = 0; i < plist.key_ids_size; i++) {
2692                         _gnutls_buffer_clear(&plist.key_ids[i]);
2693                 }
2694                 gnutls_free(plist.key_ids);
2695         }
2696         if (find_data->p_list != NULL) {
2697                 for (i = 0; i < find_data->current; i++) {
2698                         gnutls_pkcs11_obj_deinit(find_data->p_list[i]);
2699                 }
2700                 gnutls_free(find_data->p_list);
2701         }
2702         find_data->p_list = NULL;
2703         find_data->current = 0;
2704
2705         return ret;
2706 }
2707
2708 /**
2709  * gnutls_pkcs11_obj_list_import_url3:
2710  * @p_list: An uninitialized object list (may be NULL)
2711  * @n_list: initially should hold the maximum size of the list. Will contain the actual size.
2712  * @url: A PKCS 11 url identifying a set of objects
2713  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
2714  *
2715  * This function will initialize and set values to an object list
2716  * by using all objects identified by a PKCS 11 URL.
2717  *
2718  * The supported in this function @flags are %GNUTLS_PKCS11_OBJ_FLAG_LOGIN,
2719  * %GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO, %GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE,
2720  * %GNUTLS_PKCS11_OBJ_FLAG_CRT, %GNUTLS_PKCS11_OBJ_FLAG_PUBKEY, %GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY,
2721  * %GNUTLS_PKCS11_OBJ_FLAG_WITH_PRIVKEY, %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA,
2722  * %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED.
2723  *
2724  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2725  *   negative error value.
2726  *
2727  * Since: 3.4.0
2728  **/
2729 int
2730 gnutls_pkcs11_obj_list_import_url3(gnutls_pkcs11_obj_t * p_list,
2731                                   unsigned int *n_list,
2732                                   const char *url,
2733                                   unsigned int flags)
2734 {
2735         int ret;
2736         struct find_obj_data_st priv;
2737         unsigned i;
2738
2739         PKCS11_CHECK_INIT;
2740
2741         memset(&priv, 0, sizeof(priv));
2742
2743         /* fill in the find data structure */
2744         priv.flags = flags;
2745
2746         if (url == NULL || url[0] == 0) {
2747                 url = "pkcs11:";
2748         }
2749
2750         ret = pkcs11_url_to_info(url, &priv.info, flags);
2751         if (ret < 0) {
2752                 gnutls_assert();
2753                 return ret;
2754         }
2755
2756         ret =
2757             _pkcs11_traverse_tokens(find_objs_cb, &priv, priv.info,
2758                                     NULL, pkcs11_obj_flags_to_int(flags));
2759         p11_kit_uri_free(priv.info);
2760
2761         if (ret < 0) {
2762                 gnutls_assert();
2763                 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2764                         *n_list = 0;
2765                         ret = 0;
2766                 }
2767                 return ret;
2768         }
2769
2770         if (priv.current > *n_list) {
2771                 *n_list = priv.current;
2772                 for (i=0;i<priv.current;i++) {
2773                         gnutls_pkcs11_obj_deinit(priv.p_list[i]);
2774                 }
2775                 gnutls_free(priv.p_list);
2776                 return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
2777         }
2778
2779         *n_list = priv.current;
2780         memcpy(p_list, priv.p_list, priv.current*sizeof(p_list[0]));
2781         gnutls_free(priv.p_list);
2782
2783         return 0;
2784 }
2785
2786 /**
2787  * gnutls_pkcs11_obj_list_import_url4:
2788  * @p_list: An uninitialized object list (may be NULL)
2789  * @n_list: It will contain the size of the list.
2790  * @url: A PKCS 11 url identifying a set of objects
2791  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
2792  *
2793  * This function will initialize and set values to an object list
2794  * by using all objects identified by the PKCS 11 URL. The output
2795  * is stored in @p_list, which will be initialized.
2796  *
2797  * All returned objects must be deinitialized using gnutls_pkcs11_obj_deinit(),
2798  * and @p_list must be free'd using gnutls_free().
2799  *
2800  * The supported in this function @flags are %GNUTLS_PKCS11_OBJ_FLAG_LOGIN,
2801  * %GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO, %GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE,
2802  * %GNUTLS_PKCS11_OBJ_FLAG_CRT, %GNUTLS_PKCS11_OBJ_FLAG_PUBKEY, %GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY,
2803  * %GNUTLS_PKCS11_OBJ_FLAG_WITH_PRIVKEY, %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA,
2804  * %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED.
2805  *
2806  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2807  *   negative error value.
2808  *
2809  * Since: 3.4.0
2810  **/
2811 int
2812 gnutls_pkcs11_obj_list_import_url4(gnutls_pkcs11_obj_t ** p_list,
2813                                    unsigned int *n_list,
2814                                    const char *url,
2815                                    unsigned int flags)
2816 {
2817         int ret;
2818         struct find_obj_data_st priv;
2819
2820         PKCS11_CHECK_INIT;
2821
2822         memset(&priv, 0, sizeof(priv));
2823
2824         /* fill in the find data structure */
2825         priv.flags = flags;
2826
2827         if (url == NULL || url[0] == 0) {
2828                 url = "pkcs11:";
2829         }
2830
2831         ret = pkcs11_url_to_info(url, &priv.info, flags);
2832         if (ret < 0) {
2833                 gnutls_assert();
2834                 return ret;
2835         }
2836
2837         ret =
2838             _pkcs11_traverse_tokens(find_objs_cb, &priv, priv.info,
2839                                     NULL, pkcs11_obj_flags_to_int(flags));
2840         p11_kit_uri_free(priv.info);
2841
2842         if (ret < 0) {
2843                 gnutls_assert();
2844                 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2845                         *n_list = 0;
2846                         ret = 0;
2847                 }
2848                 return ret;
2849         }
2850
2851         *n_list = priv.current;
2852         *p_list = priv.p_list;
2853
2854         return 0;
2855 }
2856
2857 /**
2858  * gnutls_x509_crt_import_pkcs11:
2859  * @crt: A certificate of type #gnutls_x509_crt_t
2860  * @pkcs11_crt: A PKCS 11 object that contains a certificate
2861  *
2862  * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t
2863  * structure.
2864  *
2865  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2866  *   negative error value.
2867  *
2868  * Since: 2.12.0
2869  **/
2870 int
2871 gnutls_x509_crt_import_pkcs11(gnutls_x509_crt_t crt,
2872                               gnutls_pkcs11_obj_t pkcs11_crt)
2873 {
2874         return gnutls_x509_crt_import(crt, &pkcs11_crt->raw,
2875                                       GNUTLS_X509_FMT_DER);
2876 }
2877
2878 /*-
2879  * _gnutls_x509_crt_import_pkcs11_url:
2880  * @crt: A certificate of type #gnutls_x509_crt_t
2881  * @url: A PKCS 11 url
2882  * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2883  *
2884  * This function will import a PKCS 11 certificate directly from a token