Fix CVE-2017-6891 in minitasn1 code
[platform/upstream/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 #ifdef HAVE_GETPID
42 # include <unistd.h>
43 #endif
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         bool overwrite_exts; /* only valid if looking for a certificate */
68 };
69
70 struct find_obj_data_st {
71         gnutls_pkcs11_obj_t *p_list;
72         unsigned int current;
73         gnutls_pkcs11_obj_attr_t flags;
74         struct p11_kit_uri *info;
75 };
76
77 struct find_token_num {
78         struct p11_kit_uri *info;
79         unsigned int seq;       /* which one we are looking for */
80         unsigned int current;   /* which one are we now */
81 };
82
83 struct find_pkey_list_st {
84         gnutls_buffer_st *key_ids;
85         size_t key_ids_size;
86 };
87
88 struct find_cert_st {
89         gnutls_datum_t dn;
90         gnutls_datum_t issuer_dn;
91         gnutls_datum_t key_id;
92         gnutls_datum_t serial;
93
94         unsigned need_import;
95         gnutls_pkcs11_obj_t obj;
96         gnutls_x509_crt_t crt; /* used when compare flag is specified */
97         unsigned flags;
98 };
99
100
101 static struct gnutls_pkcs11_provider_st providers[MAX_PROVIDERS];
102 static unsigned int active_providers = 0;
103 static unsigned int providers_initialized = 0;
104 #ifdef HAVE_GETPID
105 static pid_t init_pid = -1;
106 #endif
107
108 gnutls_pkcs11_token_callback_t _gnutls_token_func;
109 void *_gnutls_token_data;
110
111 int pkcs11_rv_to_err(ck_rv_t rv)
112 {
113         switch (rv) {
114         case CKR_OK:
115                 return 0;
116         case CKR_HOST_MEMORY:
117                 return GNUTLS_E_MEMORY_ERROR;
118         case CKR_SLOT_ID_INVALID:
119                 return GNUTLS_E_PKCS11_SLOT_ERROR;
120         case CKR_ARGUMENTS_BAD:
121         case CKR_MECHANISM_PARAM_INVALID:
122                 return GNUTLS_E_INVALID_REQUEST;
123         case CKR_NEED_TO_CREATE_THREADS:
124         case CKR_CANT_LOCK:
125         case CKR_FUNCTION_NOT_PARALLEL:
126         case CKR_MUTEX_BAD:
127         case CKR_MUTEX_NOT_LOCKED:
128                 return GNUTLS_E_LOCKING_ERROR;
129         case CKR_ATTRIBUTE_READ_ONLY:
130         case CKR_ATTRIBUTE_SENSITIVE:
131         case CKR_ATTRIBUTE_TYPE_INVALID:
132         case CKR_ATTRIBUTE_VALUE_INVALID:
133                 return GNUTLS_E_PKCS11_ATTRIBUTE_ERROR;
134         case CKR_DEVICE_ERROR:
135         case CKR_DEVICE_MEMORY:
136         case CKR_DEVICE_REMOVED:
137                 return GNUTLS_E_PKCS11_DEVICE_ERROR;
138         case CKR_DATA_INVALID:
139         case CKR_DATA_LEN_RANGE:
140         case CKR_ENCRYPTED_DATA_INVALID:
141         case CKR_ENCRYPTED_DATA_LEN_RANGE:
142         case CKR_OBJECT_HANDLE_INVALID:
143                 return GNUTLS_E_PKCS11_DATA_ERROR;
144         case CKR_FUNCTION_NOT_SUPPORTED:
145         case CKR_MECHANISM_INVALID:
146                 return GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR;
147         case CKR_KEY_HANDLE_INVALID:
148         case CKR_KEY_SIZE_RANGE:
149         case CKR_KEY_TYPE_INCONSISTENT:
150         case CKR_KEY_NOT_NEEDED:
151         case CKR_KEY_CHANGED:
152         case CKR_KEY_NEEDED:
153         case CKR_KEY_INDIGESTIBLE:
154         case CKR_KEY_FUNCTION_NOT_PERMITTED:
155         case CKR_KEY_NOT_WRAPPABLE:
156         case CKR_KEY_UNEXTRACTABLE:
157                 return GNUTLS_E_PKCS11_KEY_ERROR;
158         case CKR_PIN_INCORRECT:
159         case CKR_PIN_INVALID:
160         case CKR_PIN_LEN_RANGE:
161                 return GNUTLS_E_PKCS11_PIN_ERROR;
162         case CKR_PIN_EXPIRED:
163                 return GNUTLS_E_PKCS11_PIN_EXPIRED;
164         case CKR_PIN_LOCKED:
165                 return GNUTLS_E_PKCS11_PIN_LOCKED;
166         case CKR_SESSION_CLOSED:
167         case CKR_SESSION_COUNT:
168         case CKR_SESSION_HANDLE_INVALID:
169         case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
170         case CKR_SESSION_READ_ONLY:
171         case CKR_SESSION_EXISTS:
172         case CKR_SESSION_READ_ONLY_EXISTS:
173         case CKR_SESSION_READ_WRITE_SO_EXISTS:
174                 return GNUTLS_E_PKCS11_SESSION_ERROR;
175         case CKR_SIGNATURE_INVALID:
176         case CKR_SIGNATURE_LEN_RANGE:
177                 return GNUTLS_E_PKCS11_SIGNATURE_ERROR;
178         case CKR_TOKEN_NOT_PRESENT:
179         case CKR_TOKEN_NOT_RECOGNIZED:
180         case CKR_TOKEN_WRITE_PROTECTED:
181                 return GNUTLS_E_PKCS11_TOKEN_ERROR;
182         case CKR_USER_ALREADY_LOGGED_IN:
183         case CKR_USER_NOT_LOGGED_IN:
184         case CKR_USER_PIN_NOT_INITIALIZED:
185         case CKR_USER_TYPE_INVALID:
186         case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
187         case CKR_USER_TOO_MANY_TYPES:
188                 return GNUTLS_E_PKCS11_USER_ERROR;
189         case CKR_BUFFER_TOO_SMALL:
190                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
191         default:
192                 return GNUTLS_E_PKCS11_ERROR;
193         }
194 }
195
196
197 static int scan_slots(struct gnutls_pkcs11_provider_st *p,
198                       ck_slot_id_t * slots, unsigned long *nslots)
199 {
200         ck_rv_t rv;
201
202         rv = pkcs11_get_slot_list(p->module, 1, slots, nslots);
203         if (rv != CKR_OK) {
204                 gnutls_assert();
205                 return pkcs11_rv_to_err(rv);
206         }
207         return 0;
208 }
209
210 static int
211 pkcs11_add_module(const char* name, struct ck_function_list *module, const char *params)
212 {
213         unsigned int i;
214         struct ck_info info;
215
216         if (active_providers >= MAX_PROVIDERS) {
217                 gnutls_assert();
218                 return GNUTLS_E_CONSTRAINT_ERROR;
219         }
220
221         memset(&info, 0, sizeof(info));
222         pkcs11_get_module_info(module, &info);
223
224         /* initially check if this module is a duplicate */
225         for (i = 0; i < active_providers; i++) {
226                 /* already loaded, skip the rest */
227                 if (module == providers[i].module) {
228                         _gnutls_debug_log("p11: module %s is already loaded.\n", name);
229                         return GNUTLS_E_INT_RET_0;
230                 }
231         }
232
233         active_providers++;
234         providers[active_providers - 1].module = module;
235         providers[active_providers - 1].active = 1;
236
237         if (p11_kit_module_get_flags(module) & P11_KIT_MODULE_TRUSTED ||
238                 (params != NULL && strstr(params, "trusted") != 0))
239                 providers[active_providers - 1].trusted = 1;
240
241         memcpy(&providers[active_providers - 1].info, &info, sizeof(info));
242
243         return 0;
244 }
245
246 /* Returns:
247  *  - negative error code on error,
248  *  - 0 on success
249  *  - 1 on success (and a fork was detected)
250  */
251 int _gnutls_pkcs11_check_init(void)
252 {
253         int ret;
254
255         ret = gnutls_mutex_lock(&_gnutls_pkcs11_mutex);
256         if (ret != 0)
257                 return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
258
259 #ifdef HAVE_GETPID
260         if (init_pid == 0)
261                 init_pid = getpid();
262 #endif
263
264         if (providers_initialized != 0) {
265                 ret = 0;
266 #ifdef HAVE_GETPID
267                 if (init_pid != getpid()) {
268                         /* if we are initialized but a fork is detected */
269                         ret = gnutls_pkcs11_reinit();
270                         if (ret == 0)
271                                 ret = 1;
272                 }
273 #endif
274
275                 gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
276                 return ret;
277         }
278
279 #ifdef HAVE_GETPID
280         init_pid = getpid();
281 #endif
282
283         providers_initialized = 1;
284         _gnutls_debug_log("Initializing PKCS #11 modules\n");
285         ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO, NULL);
286
287         gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
288
289         if (ret < 0)
290                 return gnutls_assert_val(ret);
291
292         return 0;
293 }
294
295
296 /**
297  * gnutls_pkcs11_add_provider:
298  * @name: The filename of the module
299  * @params: should be NULL
300  *
301  * This function will load and add a PKCS 11 module to the module
302  * list used in gnutls. After this function is called the module will
303  * be used for PKCS 11 operations.
304  *
305  * When loading a module to be used for certificate verification,
306  * use the string 'trusted' as @params.
307  *
308  * Note that this function is not thread safe.
309  *
310  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
311  *   negative error value.
312  *
313  * Since: 2.12.0
314  **/
315 int gnutls_pkcs11_add_provider(const char *name, const char *params)
316 {
317         struct ck_function_list *module;
318         int ret;
319
320         module = p11_kit_module_load(name, P11_KIT_MODULE_CRITICAL);
321         if (module == NULL) {
322                 gnutls_assert();
323                 _gnutls_debug_log("p11: Cannot load provider %s\n", name);
324                 return GNUTLS_E_PKCS11_LOAD_ERROR;
325         }
326
327         _gnutls_debug_log
328                     ("p11: Initializing module: %s\n", name);
329
330         ret = p11_kit_module_initialize(module);
331         if (ret != CKR_OK) {
332                 p11_kit_module_release(module);
333                 gnutls_assert();
334                 return pkcs11_rv_to_err(ret);
335         }
336
337         ret = pkcs11_add_module(name, module, params);
338         if (ret != 0) {
339                 if (ret == GNUTLS_E_INT_RET_0)
340                         ret = 0;
341                 p11_kit_module_finalize(module);
342                 p11_kit_module_release(module);
343                 gnutls_assert();
344         }
345
346         return ret;
347 }
348
349
350 /**
351  * gnutls_pkcs11_obj_set_info:
352  * @obj: should contain a #gnutls_pkcs11_obj_t structure
353  * @itype: Denotes the type of information to be set
354  * @data: the data to set
355  * @data_size: the size of data
356  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
357  *
358  * This function will set attributes on the provided object.
359  * Available options for @itype are %GNUTLS_PKCS11_OBJ_LABEL,
360  * %GNUTLS_PKCS11_OBJ_ID_HEX, and %GNUTLS_PKCS11_OBJ_ID.
361  *
362  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
363  *
364  * Since: 3.3.26
365  **/
366 int
367 gnutls_pkcs11_obj_set_info(gnutls_pkcs11_obj_t obj,
368                            gnutls_pkcs11_obj_info_t itype,
369                            const void *data, size_t data_size,
370                            unsigned flags)
371 {
372         struct p11_kit_uri *info = obj->info;
373         struct pkcs11_session_info sinfo;
374         struct ck_attribute *attr;
375         struct ck_attribute a[4];
376         ck_certificate_type_t type = -1;
377         ck_object_class_t class = CKO_CERTIFICATE;
378         ck_object_handle_t pkobj[2];
379         unsigned long count;
380         size_t size;
381         unsigned a_vals;
382         char tmp[128];
383         ck_rv_t rv;
384         int ret;
385
386         PKCS11_CHECK_INIT;
387
388         ret =
389             pkcs11_open_session(&sinfo, NULL, info,
390                                 SESSION_WRITE |
391                                 pkcs11_obj_flags_to_int(flags));
392         if (ret < 0) {
393                 gnutls_assert();
394                 return ret;
395         }
396
397         /* find the object that matches the URL */
398         a_vals = 0;
399         attr = p11_kit_uri_get_attribute(info, CKA_ID);
400         if (attr) {
401                 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
402                 a_vals++;
403         }
404
405         attr = p11_kit_uri_get_attribute(info, CKA_LABEL);
406         if (attr) {
407                 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
408                 a_vals++;
409         }
410
411         if (!a_vals) {
412                 gnutls_assert();
413                 ret = GNUTLS_E_INVALID_REQUEST;
414                 goto cleanup;
415         }
416
417         /* Find objects with given class and type */
418         attr = p11_kit_uri_get_attribute(info, CKA_CLASS);
419         if (attr) {
420                 if (attr->value
421                     && attr->value_len == sizeof(ck_object_class_t))
422                         class = *((ck_object_class_t *) attr->value);
423                 if (class == CKO_CERTIFICATE)
424                         type = CKC_X_509;
425                 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
426                 a_vals++;
427         }
428
429         if (type != (ck_certificate_type_t) - 1) {
430                 a[a_vals].type = CKA_CERTIFICATE_TYPE;
431                 a[a_vals].value = &type;
432                 a[a_vals].value_len = sizeof type;
433                 a_vals++;
434         }
435
436         rv = pkcs11_find_objects_init(sinfo.module, sinfo.pks, a,
437                                       a_vals);
438         if (rv != CKR_OK) {
439                 gnutls_assert();
440                 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
441                 ret = pkcs11_rv_to_err(rv);
442                 goto cleanup;
443         }
444
445         rv = pkcs11_find_objects(sinfo.module, sinfo.pks, pkobj, 2, &count);
446         if (rv != CKR_OK) {
447                 gnutls_assert();
448                 _gnutls_debug_log("p11: FindObjects failed.\n");
449                 ret = pkcs11_rv_to_err(rv);
450                 goto cleanup;
451         }
452
453         if (count > 1 || count == 0) {
454                 gnutls_assert();
455                 if (count > 1)
456                         _gnutls_debug_log("p11: More than one objects match (%d)\n", (int)count);
457                 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
458                 goto cleanup;
459         }
460
461         switch (itype) {
462         case GNUTLS_PKCS11_OBJ_ID_HEX:
463                 size = sizeof(tmp);
464                 ret = _gnutls_hex2bin(data, data_size, (uint8_t*)tmp, &size);
465                 if (ret < 0) {
466                         gnutls_assert();
467                         goto cleanup;
468                 }
469                 data = tmp;
470                 data_size = size;
471                 /* fallthrough */
472         case GNUTLS_PKCS11_OBJ_ID:
473                 a[0].type = CKA_ID;
474                 a[0].value = (void*)data;
475                 a[0].value_len = data_size;
476
477                 rv = pkcs11_set_attribute_value(sinfo.module, sinfo.pks, pkobj[0], a, 1);
478                 if (rv != CKR_OK) {
479                         gnutls_assert();
480                         _gnutls_debug_log("p11: set_attribute_value failed.\n");
481                         ret = pkcs11_rv_to_err(rv);
482                         goto cleanup;
483                 }
484
485                 break;
486         case GNUTLS_PKCS11_OBJ_LABEL:
487                 a[0].type = CKA_LABEL;
488                 a[0].value = (void*)data;
489                 a[0].value_len = data_size;
490
491                 rv = pkcs11_set_attribute_value(sinfo.module, sinfo.pks, pkobj[0], a, 1);
492                 if (rv != CKR_OK) {
493                         gnutls_assert();
494                         _gnutls_debug_log("p11: set_attribute_value failed.\n");
495                         ret = pkcs11_rv_to_err(rv);
496                         goto cleanup;
497                 }
498
499                 break;
500         default:
501                 gnutls_assert();
502                 return GNUTLS_E_INVALID_REQUEST;
503         }
504
505         ret = 0;
506  cleanup:
507         pkcs11_close_session(&sinfo);
508         return ret;
509 }
510
511 /**
512  * gnutls_pkcs11_obj_get_info:
513  * @obj: should contain a #gnutls_pkcs11_obj_t structure
514  * @itype: Denotes the type of information requested
515  * @output: where output will be stored
516  * @output_size: contains the maximum size of the output and will be overwritten with actual
517  *
518  * This function will return information about the PKCS11 certificate
519  * such as the label, id as well as token information where the key is
520  * stored. When output is text it returns null terminated string
521  * although @output_size contains the size of the actual data only.
522  *
523  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
524  *
525  * Since: 2.12.0
526  **/
527 int
528 gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t obj,
529                            gnutls_pkcs11_obj_info_t itype,
530                            void *output, size_t * output_size)
531 {
532         return pkcs11_get_info(obj->info, itype, output, output_size);
533 }
534
535 int
536 pkcs11_get_info(struct p11_kit_uri *info,
537                 gnutls_pkcs11_obj_info_t itype, void *output,
538                 size_t * output_size)
539 {
540         struct ck_attribute *attr = NULL;
541         struct ck_version *version = NULL;
542         const uint8_t *str = NULL;
543         size_t str_max = 0;
544         int terminate = 0;
545         int hexify = 0;
546         size_t length = 0;
547         const char *data = NULL;
548         char buf[32];
549
550         /*
551          * Either attr, str or version is valid by the time switch
552          * finishes
553          */
554
555         switch (itype) {
556         case GNUTLS_PKCS11_OBJ_ID:
557                 attr = p11_kit_uri_get_attribute(info, CKA_ID);
558                 break;
559         case GNUTLS_PKCS11_OBJ_ID_HEX:
560                 attr = p11_kit_uri_get_attribute(info, CKA_ID);
561                 hexify = 1;
562                 terminate = 1;
563                 break;
564         case GNUTLS_PKCS11_OBJ_LABEL:
565                 attr = p11_kit_uri_get_attribute(info, CKA_LABEL);
566                 terminate = 1;
567                 break;
568         case GNUTLS_PKCS11_OBJ_TOKEN_LABEL:
569                 str = p11_kit_uri_get_token_info(info)->label;
570                 str_max = 32;
571                 break;
572         case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL:
573                 str = p11_kit_uri_get_token_info(info)->serial_number;
574                 str_max = 16;
575                 break;
576         case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER:
577                 str = p11_kit_uri_get_token_info(info)->manufacturer_id;
578                 str_max = 32;
579                 break;
580         case GNUTLS_PKCS11_OBJ_TOKEN_MODEL:
581                 str = p11_kit_uri_get_token_info(info)->model;
582                 str_max = 16;
583                 break;
584         case GNUTLS_PKCS11_OBJ_LIBRARY_DESCRIPTION:
585                 str =
586                     p11_kit_uri_get_module_info(info)->library_description;
587                 str_max = 32;
588                 break;
589         case GNUTLS_PKCS11_OBJ_LIBRARY_VERSION:
590                 version =
591                     &p11_kit_uri_get_module_info(info)->library_version;
592                 break;
593         case GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER:
594                 str = p11_kit_uri_get_module_info(info)->manufacturer_id;
595                 str_max = 32;
596                 break;
597         default:
598                 gnutls_assert();
599                 return GNUTLS_E_INVALID_REQUEST;
600         }
601
602         if (attr != NULL) {
603                 data = attr->value;
604                 length = attr->value_len;
605         } else if (str != NULL) {
606                 data = (void *) str;
607                 length = p11_kit_space_strlen(str, str_max);
608                 terminate = 1;
609         } else if (version != NULL) {
610                 data = buf;
611                 length =
612                     snprintf(buf, sizeof(buf), "%d.%d",
613                              (int) version->major, (int) version->minor);
614                 terminate = 1;
615         } else {
616                 *output_size = 0;
617                 if (output)
618                         ((uint8_t *) output)[0] = 0;
619                 return 0;
620         }
621
622         if (hexify) {
623                 /* terminate is assumed with hexify */
624                 if (*output_size < length * 3) {
625                         *output_size = length * 3;
626                         return GNUTLS_E_SHORT_MEMORY_BUFFER;
627                 }
628                 if (output && length > 0)
629                         _gnutls_bin2hex(data, length, output, *output_size,
630                                         ":");
631                 *output_size = length * 3;
632                 return 0;
633         } else {
634                 if (*output_size < length + terminate) {
635                         *output_size = length + terminate;
636                         return GNUTLS_E_SHORT_MEMORY_BUFFER;
637                 }
638                 if (output) {
639                         memcpy(output, data, length);
640                         if (terminate)
641                                 ((unsigned char *) output)[length] = '\0';
642                 }
643                 *output_size = length + terminate;
644         }
645
646         return 0;
647 }
648
649 static int init = 0;
650
651 /* tries to load modules from /etc/gnutls/pkcs11.conf if it exists
652  */
653 static void compat_load(const char *configfile)
654 {
655         FILE *fp;
656         int ret;
657         char line[512];
658         const char *library;
659
660         if (configfile == NULL)
661                 configfile = "/etc/gnutls/pkcs11.conf";
662
663         fp = fopen(configfile, "r");
664         if (fp == NULL) {
665                 gnutls_assert();
666                 return;
667         }
668
669         _gnutls_debug_log("Loading PKCS #11 libraries from %s\n",
670                           configfile);
671         while (fgets(line, sizeof(line), fp) != NULL) {
672                 if (strncmp(line, "load", sizeof("load") - 1) == 0) {
673                         char *p;
674                         p = strchr(line, '=');
675                         if (p == NULL)
676                                 continue;
677
678                         library = ++p;
679                         p = strchr(line, '\n');
680                         if (p != NULL)
681                                 *p = 0;
682
683                         ret = gnutls_pkcs11_add_provider(library, NULL);
684                         if (ret < 0) {
685                                 gnutls_assert();
686                                 _gnutls_debug_log
687                                     ("Cannot load provider: %s\n",
688                                      library);
689                                 continue;
690                         }
691                 }
692         }
693         fclose(fp);
694
695         return;
696 }
697
698 static int auto_load(void)
699 {
700         struct ck_function_list **modules;
701         int i, ret;
702         char* name;
703
704         modules = p11_kit_modules_load_and_initialize(0);
705         if (modules == NULL) {
706                 gnutls_assert();
707                 _gnutls_debug_log
708                     ("Cannot initialize registered modules: %s\n",
709                      p11_kit_message());
710                 return GNUTLS_E_PKCS11_LOAD_ERROR;
711         }
712
713         for (i = 0; modules[i] != NULL; i++) {
714                 name = p11_kit_module_get_name(modules[i]);
715                 _gnutls_debug_log
716                             ("p11: Initializing module: %s\n", name);
717
718                 ret = pkcs11_add_module(name, modules[i], NULL);
719                 if (ret < 0) {
720                         gnutls_assert();
721                         _gnutls_debug_log
722                             ("Cannot load PKCS #11 module: %s\n", name);
723                 }
724                 free(name);
725         }
726
727         /* Shallow free */
728         free(modules);
729         return 0;
730 }
731
732 /**
733  * gnutls_pkcs11_init:
734  * @flags: An ORed sequence of %GNUTLS_PKCS11_FLAG_*
735  * @deprecated_config_file: either NULL or the location of a deprecated
736  *     configuration file
737  *
738  * This function will initialize the PKCS 11 subsystem in gnutls. It will
739  * read configuration files if %GNUTLS_PKCS11_FLAG_AUTO is used or allow
740  * you to independently load PKCS 11 modules using gnutls_pkcs11_add_provider()
741  * if %GNUTLS_PKCS11_FLAG_MANUAL is specified.
742  *
743  * Normally you don't need to call this function since it is being called
744  * when the first PKCS 11 operation is requested using the %GNUTLS_PKCS11_FLAG_AUTO
745  * flag. If another flags are required then it must be called independently
746  * prior to any PKCS 11 operation.
747  *
748  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
749  *   negative error value.
750  *
751  * Since: 2.12.0
752  **/
753 int
754 gnutls_pkcs11_init(unsigned int flags, const char *deprecated_config_file)
755 {
756         int ret = 0;
757
758         if (init != 0) {
759                 init++;
760                 return 0;
761         }
762         init++;
763
764         p11_kit_pin_register_callback(P11_KIT_PIN_FALLBACK,
765                                       p11_kit_pin_file_callback, NULL,
766                                       NULL);
767
768         if (flags == GNUTLS_PKCS11_FLAG_MANUAL)
769                 return 0;
770         else if (flags & GNUTLS_PKCS11_FLAG_AUTO) {
771                 if (deprecated_config_file == NULL)
772                         ret = auto_load();
773
774                 compat_load(deprecated_config_file);
775
776                 return ret;
777         }
778
779         return 0;
780 }
781
782 /**
783  * gnutls_pkcs11_reinit:
784  *
785  * This function will reinitialize the PKCS 11 subsystem in gnutls. 
786  * This is required by PKCS 11 when an application uses fork(). The
787  * reinitialization function must be called on the child.
788  *
789  * Note that since GnuTLS 3.3.0, the reinitialization of the PKCS #11
790  * subsystem occurs automatically after fork.
791  *
792  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
793  *   negative error value.
794  *
795  * Since: 3.0
796  **/
797 int gnutls_pkcs11_reinit(void)
798 {
799         unsigned i;
800         ck_rv_t rv;
801
802         /* make sure that we don't call more than once after a fork */
803         if (init_pid == getpid())
804                 return 0;
805
806         for (i = 0; i < active_providers; i++) {
807                 if (providers[i].module != NULL) {
808                         rv = p11_kit_module_initialize(providers
809                                                        [i].module);
810                         if (rv == CKR_OK || rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) {
811                                 providers[i].active = 1;
812                         } else {
813                                 providers[i].active = 0;
814                                 _gnutls_debug_log
815                                     ("Cannot re-initialize registered module '%.*s': %s\n",
816                                      (int)32, providers[i].info.library_description,
817                                      p11_kit_strerror(rv));
818                         }
819                 }
820         }
821 #ifdef HAVE_GETPID
822         init_pid = getpid();
823 #endif
824
825         return 0;
826 }
827
828 /**
829  * gnutls_pkcs11_deinit:
830  *
831  * This function will deinitialize the PKCS 11 subsystem in gnutls.
832  * This function is only needed if you need to deinitialize the
833  * subsystem without calling gnutls_global_deinit().
834  *
835  * Since: 2.12.0
836  **/
837 void gnutls_pkcs11_deinit(void)
838 {
839         unsigned int i;
840
841         if (init == 0)
842                 return;
843
844         init--;
845         if (init > 0)
846                 return;
847
848         for (i = 0; i < active_providers; i++) {
849                 if (providers[i].active)
850                         p11_kit_module_finalize(providers[i].module);
851                 p11_kit_module_release(providers[i].module);
852         }
853         active_providers = 0;
854         providers_initialized = 0;
855
856         gnutls_pkcs11_set_pin_function(NULL, NULL);
857         gnutls_pkcs11_set_token_function(NULL, NULL);
858         p11_kit_pin_unregister_callback(P11_KIT_PIN_FALLBACK,
859                                         p11_kit_pin_file_callback, NULL);
860 }
861
862 /**
863  * gnutls_pkcs11_set_token_function:
864  * @fn: The token callback
865  * @userdata: data to be supplied to callback
866  *
867  * This function will set a callback function to be used when a token
868  * needs to be inserted to continue PKCS 11 operations.
869  *
870  * Since: 2.12.0
871  **/
872 void
873 gnutls_pkcs11_set_token_function(gnutls_pkcs11_token_callback_t fn,
874                                  void *userdata)
875 {
876         _gnutls_token_func = fn;
877         _gnutls_token_data = userdata;
878 }
879
880 int pkcs11_url_to_info(const char *url, struct p11_kit_uri **info, unsigned flags)
881 {
882         int allocated = 0;
883         int ret;
884
885         if (*info == NULL) {
886                 *info = p11_kit_uri_new();
887                 if (*info == NULL) {
888                         gnutls_assert();
889                         return GNUTLS_E_MEMORY_ERROR;
890                 }
891                 allocated = 1;
892         }
893
894         ret = p11_kit_uri_parse(url, P11_KIT_URI_FOR_ANY, *info);
895         if (ret < 0) {
896                 if (allocated) {
897                         p11_kit_uri_free(*info);
898                         *info = NULL;
899                 }
900                 gnutls_assert();
901                 return ret == P11_KIT_URI_NO_MEMORY ?
902                     GNUTLS_E_MEMORY_ERROR : GNUTLS_E_PARSING_ERROR;
903         }
904
905         /* check for incomplete URIs */
906         if (p11_kit_uri_get_attribute (*info, CKA_CLASS) == NULL) {
907                 struct ck_attribute at;
908                 ck_object_class_t klass;
909
910                 if (flags & GNUTLS_PKCS11_OBJ_FLAG_EXPECT_CERT) {
911                         klass = CKO_CERTIFICATE;
912                         at.type = CKA_CLASS;
913                         at.value = &klass;
914                         at.value_len = sizeof (klass);
915                         p11_kit_uri_set_attribute (*info, &at);
916                 } else if (flags & GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY) {
917                         klass = CKO_PRIVATE_KEY;
918                         at.type = CKA_CLASS;
919                         at.value = &klass;
920                         at.value_len = sizeof (klass);
921                         p11_kit_uri_set_attribute (*info, &at);
922                 }
923         }
924
925         return 0;
926 }
927
928 int
929 pkcs11_info_to_url(struct p11_kit_uri *info,
930                    gnutls_pkcs11_url_type_t detailed, char **url)
931 {
932         p11_kit_uri_type_t type = 0;
933         int ret;
934
935         switch (detailed) {
936         case GNUTLS_PKCS11_URL_GENERIC:
937                 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN;
938                 break;
939         case GNUTLS_PKCS11_URL_LIB:
940                 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE;
941                 break;
942         case GNUTLS_PKCS11_URL_LIB_VERSION:
943                 type =
944                     P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE |
945                     P11_KIT_URI_FOR_MODULE_WITH_VERSION;
946                 break;
947         }
948
949         ret = p11_kit_uri_format(info, type, url);
950         if (ret < 0) {
951                 gnutls_assert();
952                 return ret == P11_KIT_URI_NO_MEMORY ?
953                     GNUTLS_E_MEMORY_ERROR : GNUTLS_E_INTERNAL_ERROR;
954         }
955
956         return 0;
957 }
958
959 /**
960  * gnutls_pkcs11_obj_init:
961  * @obj: The structure to be initialized
962  *
963  * This function will initialize a pkcs11 certificate structure.
964  *
965  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
966  *   negative error value.
967  *
968  * Since: 2.12.0
969  **/
970 int gnutls_pkcs11_obj_init(gnutls_pkcs11_obj_t * obj)
971 {
972         *obj = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_obj_st));
973         if (*obj == NULL) {
974                 gnutls_assert();
975                 return GNUTLS_E_MEMORY_ERROR;
976         }
977
978         (*obj)->info = p11_kit_uri_new();
979         if ((*obj)->info == NULL) {
980                 gnutls_free(*obj);
981                 *obj = NULL;
982                 gnutls_assert();
983                 return GNUTLS_E_MEMORY_ERROR;
984         }
985
986         return 0;
987 }
988
989 /**
990  * gnutls_pkcs11_obj_set_pin_function:
991  * @obj: The object structure
992  * @fn: the callback
993  * @userdata: data associated with the callback
994  *
995  * This function will set a callback function to be used when
996  * required to access the object. This function overrides the global
997  * set using gnutls_pkcs11_set_pin_function().
998  *
999  * Since: 3.1.0
1000  **/
1001 void
1002 gnutls_pkcs11_obj_set_pin_function(gnutls_pkcs11_obj_t obj,
1003                                    gnutls_pin_callback_t fn,
1004                                    void *userdata)
1005 {
1006         obj->pin.cb = fn;
1007         obj->pin.data = userdata;
1008 }
1009
1010 /**
1011  * gnutls_pkcs11_obj_deinit:
1012  * @obj: The structure to be initialized
1013  *
1014  * This function will deinitialize a certificate structure.
1015  *
1016  * Since: 2.12.0
1017  **/
1018 void gnutls_pkcs11_obj_deinit(gnutls_pkcs11_obj_t obj)
1019 {
1020         unsigned i;
1021         for (i=0;i<obj->pubkey_size;i++)
1022                 _gnutls_free_datum(&obj->pubkey[i]);
1023         _gnutls_free_datum(&obj->raw);
1024         p11_kit_uri_free(obj->info);
1025         free(obj);
1026 }
1027
1028 /**
1029  * gnutls_pkcs11_obj_export:
1030  * @obj: Holds the object
1031  * @output_data: will contain the object data
1032  * @output_data_size: holds the size of output_data (and will be
1033  *   replaced by the actual size of parameters)
1034  *
1035  * This function will export the PKCS11 object data.  It is normal for
1036  * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
1037  * will be returned.
1038  *
1039  * If the buffer provided is not long enough to hold the output, then
1040  * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
1041  * be returned.
1042  *
1043  * Returns: In case of failure a negative error code will be
1044  *   returned, and %GNUTLS_E_SUCCESS (0) on success.
1045  *
1046  * Since: 2.12.0
1047  **/
1048 int
1049 gnutls_pkcs11_obj_export(gnutls_pkcs11_obj_t obj,
1050                          void *output_data, size_t * output_data_size)
1051 {
1052         if (obj == NULL || obj->raw.data == NULL) {
1053                 gnutls_assert();
1054                 return GNUTLS_E_INVALID_REQUEST;
1055         }
1056
1057         if (output_data == NULL || *output_data_size < obj->raw.size) {
1058                 *output_data_size = obj->raw.size;
1059                 gnutls_assert();
1060                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
1061         }
1062         *output_data_size = obj->raw.size;
1063
1064         memcpy(output_data, obj->raw.data, obj->raw.size);
1065         return 0;
1066 }
1067
1068 /**
1069  * gnutls_pkcs11_obj_export2:
1070  * @obj: Holds the object
1071  * @out: will contain the object data
1072  *
1073  * This function will export the PKCS11 object data.  It is normal for
1074  * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
1075  * will be returned.
1076  *
1077  * The output buffer is allocated using gnutls_malloc().
1078  *
1079  * Returns: In case of failure a negative error code will be
1080  *   returned, and %GNUTLS_E_SUCCESS (0) on success.
1081  *
1082  * Since: 3.1.3
1083  **/
1084 int
1085 gnutls_pkcs11_obj_export2(gnutls_pkcs11_obj_t obj, gnutls_datum_t * out)
1086 {
1087         if (obj == NULL || obj->raw.data == NULL) {
1088                 gnutls_assert();
1089                 return GNUTLS_E_INVALID_REQUEST;
1090         }
1091
1092         return _gnutls_set_datum(out, obj->raw.data, obj->raw.size);
1093 }
1094
1095 /**
1096  * gnutls_pkcs11_obj_export3:
1097  * @obj: Holds the object
1098  * @out: will contain the object data
1099  * @fmt: The format of the exported data
1100  *
1101  * This function will export the PKCS11 object data.  It is normal for
1102  * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
1103  * will be returned.
1104  *
1105  * The output buffer is allocated using gnutls_malloc().
1106  *
1107  * Returns: In case of failure a negative error code will be
1108  *   returned, and %GNUTLS_E_SUCCESS (0) on success.
1109  *
1110  * Since: 3.2.7
1111  **/
1112 int
1113 gnutls_pkcs11_obj_export3(gnutls_pkcs11_obj_t obj,
1114                           gnutls_x509_crt_fmt_t fmt, gnutls_datum_t * out)
1115 {
1116         int ret;
1117
1118         if (obj == NULL || obj->raw.data == NULL) {
1119                 gnutls_assert();
1120                 return GNUTLS_E_INVALID_REQUEST;
1121         }
1122
1123         if (fmt == GNUTLS_X509_FMT_DER)
1124                 return _gnutls_set_datum(out, obj->raw.data,
1125                                          obj->raw.size);
1126         else if (fmt == GNUTLS_X509_FMT_PEM) {
1127                 switch (obj->type) {
1128                 case GNUTLS_PKCS11_OBJ_X509_CRT:
1129                         return
1130                             gnutls_pem_base64_encode_alloc(PEM_X509_CERT2,
1131                                                            &obj->raw, out);
1132                 case GNUTLS_PKCS11_OBJ_PUBKEY:{
1133                                 gnutls_pubkey_t pubkey;
1134                                 /* more complex */
1135                                 ret = gnutls_pubkey_init(&pubkey);
1136                                 if (ret < 0)
1137                                         return gnutls_assert_val(ret);
1138
1139                                 ret =
1140                                     gnutls_pubkey_import_pkcs11(pubkey,
1141                                                                 obj, 0);
1142                                 if (ret < 0) {
1143                                         gnutls_assert();
1144                                         goto pcleanup;
1145                                 }
1146
1147                                 ret =
1148                                     gnutls_pubkey_export2(pubkey, fmt,
1149                                                           out);
1150
1151                               pcleanup:
1152                                 gnutls_pubkey_deinit(pubkey);
1153                                 return ret;
1154                         }
1155                 default:
1156                         return gnutls_pem_base64_encode_alloc("DATA",
1157                                                               &obj->raw,
1158                                                               out);
1159                 }
1160         } else
1161                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1162 }
1163
1164
1165 int
1166 pkcs11_find_slot(struct ck_function_list **module, ck_slot_id_t * slot,
1167                  struct p11_kit_uri *info, struct token_info *_tinfo)
1168 {
1169         unsigned int x, z;
1170         int ret;
1171         unsigned long nslots;
1172         ck_slot_id_t slots[MAX_SLOTS];
1173
1174         for (x = 0; x < active_providers; x++) {
1175                 if (providers[x].active == 0)
1176                         continue;
1177
1178                 nslots = sizeof(slots) / sizeof(slots[0]);
1179                 ret = scan_slots(&providers[x], slots, &nslots);
1180                 if (ret < 0) {
1181                         gnutls_assert();
1182                         continue;
1183                 }
1184
1185                 for (z = 0; z < nslots; z++) {
1186                         struct token_info tinfo;
1187
1188                         if (pkcs11_get_token_info
1189                             (providers[x].module, slots[z],
1190                              &tinfo.tinfo) != CKR_OK) {
1191                                 continue;
1192                         }
1193                         tinfo.sid = slots[z];
1194                         tinfo.prov = &providers[x];
1195
1196                         if (pkcs11_get_slot_info
1197                             (providers[x].module, slots[z],
1198                              &tinfo.sinfo) != CKR_OK) {
1199                                 continue;
1200                         }
1201
1202                         if (!p11_kit_uri_match_token_info
1203                             (info, &tinfo.tinfo)
1204                             || !p11_kit_uri_match_module_info(info,
1205                                                               &providers
1206                                                               [x].info)) {
1207                                 continue;
1208                         }
1209
1210                         /* ok found */
1211                         *module = providers[x].module;
1212                         *slot = slots[z];
1213
1214                         if (_tinfo != NULL)
1215                                 memcpy(_tinfo, &tinfo, sizeof(tinfo));
1216
1217                         return 0;
1218                 }
1219         }
1220
1221         gnutls_assert();
1222         return GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE;
1223 }
1224
1225 int
1226 pkcs11_open_session(struct pkcs11_session_info *sinfo,
1227                     struct pin_info_st *pin_info,
1228                     struct p11_kit_uri *info, unsigned int flags)
1229 {
1230         ck_rv_t rv;
1231         int ret;
1232         ck_session_handle_t pks = 0;
1233         struct ck_function_list *module;
1234         ck_slot_id_t slot;
1235         struct token_info tinfo;
1236
1237         ret = pkcs11_find_slot(&module, &slot, info, &tinfo);
1238         if (ret < 0) {
1239                 gnutls_assert();
1240                 return ret;
1241         }
1242
1243         rv = (module)->C_OpenSession(slot, ((flags & SESSION_WRITE)
1244                                             ? CKF_RW_SESSION : 0) |
1245                                      CKF_SERIAL_SESSION, NULL, NULL, &pks);
1246         if (rv != CKR_OK) {
1247                 gnutls_assert();
1248                 return pkcs11_rv_to_err(rv);
1249         }
1250
1251         /* ok found */
1252         sinfo->pks = pks;
1253         sinfo->module = module;
1254         sinfo->sid = slot;
1255         sinfo->init = 1;
1256         memcpy(&sinfo->tinfo, &tinfo.tinfo, sizeof(sinfo->tinfo));
1257
1258         if (flags & SESSION_LOGIN) {
1259                 ret =
1260                     pkcs11_login(sinfo, pin_info, info,
1261                                  (flags & SESSION_SO) ? 1 : 0, 0);
1262                 if (ret < 0) {
1263                         gnutls_assert();
1264                         pkcs11_close_session(sinfo);
1265                         return ret;
1266                 }
1267         }
1268
1269         return 0;
1270 }
1271
1272
1273 int
1274 _pkcs11_traverse_tokens(find_func_t find_func, void *input,
1275                         struct p11_kit_uri *info,
1276                         struct pin_info_st *pin_info, unsigned int flags)
1277 {
1278         ck_rv_t rv;
1279         unsigned int found = 0, x, z;
1280         int ret;
1281         ck_session_handle_t pks = 0;
1282         struct pkcs11_session_info sinfo;
1283         struct ck_function_list *module = NULL;
1284         unsigned long nslots;
1285         ck_slot_id_t slots[MAX_SLOTS];
1286
1287         for (x = 0; x < active_providers; x++) {
1288                 if (providers[x].active == 0)
1289                         continue;
1290
1291                 if (flags & SESSION_TRUSTED && providers[x].trusted == 0)
1292                         continue;
1293
1294                 nslots = sizeof(slots) / sizeof(slots[0]);
1295                 ret = scan_slots(&providers[x], slots, &nslots);
1296                 if (ret < 0) {
1297                         gnutls_assert();
1298                         continue;
1299                 }
1300
1301                 module = providers[x].module;
1302                 for (z = 0; z < nslots; z++) {
1303                         struct token_info tinfo;
1304
1305                         if (pkcs11_get_token_info(module, slots[z],
1306                                                   &tinfo.tinfo) != CKR_OK) {
1307                                 continue;
1308                         }
1309                         tinfo.sid = slots[z];
1310                         tinfo.prov = &providers[x];
1311
1312                         if (pkcs11_get_slot_info(module, slots[z],
1313                                                  &tinfo.sinfo) != CKR_OK) {
1314                                 continue;
1315                         }
1316
1317                         if (info != NULL) {
1318                             if (!p11_kit_uri_match_token_info
1319                                 (info, &tinfo.tinfo)
1320                                 || !p11_kit_uri_match_module_info(info,
1321                                                               &providers
1322                                                               [x].info)) {
1323                                 continue;
1324                             }
1325                         }
1326
1327                         rv = (module)->C_OpenSession(slots[z],
1328                                                      ((flags & SESSION_WRITE) ? CKF_RW_SESSION : 0)
1329                                                      | CKF_SERIAL_SESSION,
1330                                                      NULL, NULL, &pks);
1331                         if (rv != CKR_OK) {
1332                                 continue;
1333                         }
1334
1335                         sinfo.module = module;
1336                         sinfo.pks = pks;
1337                         sinfo.sid = tinfo.sid;
1338                         memcpy(&sinfo.tinfo, &tinfo.tinfo, sizeof(sinfo.tinfo));
1339
1340                         if (flags & SESSION_LOGIN) {
1341                                 ret =
1342                                     pkcs11_login(&sinfo, pin_info,
1343                                                  info, (flags & SESSION_SO) ? 1 : 0,
1344                                                  0);
1345                                 if (ret < 0) {
1346                                         gnutls_assert();
1347                                         return ret;
1348                                 }
1349                         }
1350
1351                         ret =
1352                             find_func(&sinfo, &tinfo, &providers[x].info, input);
1353
1354                         if (ret == 0) {
1355                                 found = 1;
1356                                 goto finish;
1357                         } else {
1358                                 pkcs11_close_session(&sinfo);
1359                                 pks = 0;
1360                         }
1361                 }
1362         }
1363
1364       finish:
1365         /* final call */
1366
1367         if (found == 0) {
1368                 if (module) {
1369                         sinfo.module = module;
1370                         sinfo.pks = pks;
1371                         ret = find_func(&sinfo, NULL, NULL, input);
1372                 } else
1373                         ret =
1374                             gnutls_assert_val
1375                             (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1376         } else {
1377                 ret = 0;
1378         }
1379
1380         if (pks != 0 && module != NULL) {
1381                 pkcs11_close_session(&sinfo);
1382         }
1383
1384         return ret;
1385 }
1386
1387 /* imports an object from a token to a pkcs11_obj_t structure.
1388  */
1389 static int
1390 pkcs11_obj_import(ck_object_class_t class, gnutls_pkcs11_obj_t obj,
1391                   const gnutls_datum_t * data,
1392                   const gnutls_datum_t * id,
1393                   const gnutls_datum_t * label,
1394                   struct ck_token_info *tinfo, struct ck_info *lib_info)
1395 {
1396         struct ck_attribute attr;
1397         int ret;
1398
1399         switch (class) {
1400         case CKO_CERTIFICATE:
1401                 obj->type = GNUTLS_PKCS11_OBJ_X509_CRT;
1402                 break;
1403         case CKO_X_CERTIFICATE_EXTENSION:
1404                 obj->type = GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION;
1405                 break;
1406         case CKO_PUBLIC_KEY:
1407                 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1408                 break;
1409         case CKO_PRIVATE_KEY:
1410                 obj->type = GNUTLS_PKCS11_OBJ_PRIVKEY;
1411                 break;
1412         case CKO_SECRET_KEY:
1413                 obj->type = GNUTLS_PKCS11_OBJ_SECRET_KEY;
1414                 break;
1415         case CKO_DATA:
1416                 obj->type = GNUTLS_PKCS11_OBJ_DATA;
1417                 break;
1418         default:
1419                 _gnutls_debug_log("unknown pkcs11 object class %x\n", (unsigned)class);
1420                 obj->type = GNUTLS_PKCS11_OBJ_UNKNOWN;
1421         }
1422
1423         attr.type = CKA_CLASS;
1424         attr.value = &class;
1425         attr.value_len = sizeof(class);
1426         ret = p11_kit_uri_set_attribute(obj->info, &attr);
1427         if (ret < 0) {
1428                 gnutls_assert();
1429                 return GNUTLS_E_MEMORY_ERROR;
1430         }
1431
1432         if (data && data->data && data->size) {
1433                 ret = _gnutls_set_datum(&obj->raw, data->data, data->size);
1434                 if (ret < 0) {
1435                         gnutls_assert();
1436                         return ret;
1437                 }
1438         }
1439
1440         /* copy the token and library info into the uri */
1441         memcpy(p11_kit_uri_get_token_info(obj->info), tinfo,
1442                sizeof(struct ck_token_info));
1443         memcpy(p11_kit_uri_get_module_info(obj->info), lib_info,
1444                sizeof(struct ck_info));
1445
1446         if (label && label->data && label->size) {
1447                 attr.type = CKA_LABEL;
1448                 attr.value = label->data;
1449                 attr.value_len = label->size;
1450                 ret = p11_kit_uri_set_attribute(obj->info, &attr);
1451                 if (ret < 0) {
1452                         gnutls_assert();
1453                         return GNUTLS_E_MEMORY_ERROR;
1454                 }
1455         }
1456
1457         if (id && id->data && id->size) {
1458                 attr.type = CKA_ID;
1459                 attr.value = id->data;
1460                 attr.value_len = id->size;
1461                 ret = p11_kit_uri_set_attribute(obj->info, &attr);
1462                 if (ret < 0) {
1463                         gnutls_assert();
1464                         return GNUTLS_E_MEMORY_ERROR;
1465                 }
1466         }
1467
1468         return 0;
1469 }
1470
1471 #define MAX_PK_PARAM_SIZE 2048
1472
1473 int pkcs11_read_pubkey(struct ck_function_list *module,
1474                        ck_session_handle_t pks, ck_object_handle_t obj,
1475                        ck_key_type_t key_type, gnutls_pkcs11_obj_t pobj)
1476 {
1477         struct ck_attribute a[4];
1478         uint8_t *tmp1;
1479         uint8_t *tmp2 = NULL;
1480         size_t tmp1_size, tmp2_size;
1481         int ret;
1482         ck_rv_t rv;
1483
1484         tmp1_size = tmp2_size = MAX_PK_PARAM_SIZE;
1485         tmp1 = gnutls_malloc(tmp1_size);
1486         if (tmp1 == NULL)
1487                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1488
1489         tmp2 = gnutls_malloc(tmp2_size);
1490         if (tmp2 == NULL) {
1491                 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1492                 goto cleanup;
1493         }
1494
1495         switch (key_type) {
1496         case CKK_RSA:
1497                 a[0].type = CKA_MODULUS;
1498                 a[0].value = tmp1;
1499                 a[0].value_len = tmp1_size;
1500                 a[1].type = CKA_PUBLIC_EXPONENT;
1501                 a[1].value = tmp2;
1502                 a[1].value_len = tmp2_size;
1503
1504                 if (pkcs11_get_attribute_value(module, pks, obj, a, 2) ==
1505                     CKR_OK) {
1506
1507                         pobj->pubkey[0].data = a[0].value;
1508                         pobj->pubkey[0].size = a[0].value_len;
1509
1510                         pobj->pubkey[1].data = a[1].value;
1511                         pobj->pubkey[1].size = a[1].value_len;
1512
1513                         pobj->pubkey_size = 2;
1514                 } else {
1515                         gnutls_assert();
1516                         ret = GNUTLS_E_PKCS11_ERROR;
1517                         goto cleanup;
1518                 }
1519                 break;
1520         case CKK_DSA:
1521                 a[0].type = CKA_PRIME;
1522                 a[0].value = tmp1;
1523                 a[0].value_len = tmp1_size;
1524                 a[1].type = CKA_SUBPRIME;
1525                 a[1].value = tmp2;
1526                 a[1].value_len = tmp2_size;
1527
1528                 if ((rv = pkcs11_get_attribute_value(module, pks, obj, a, 2)) ==
1529                     CKR_OK) {
1530                         ret =
1531                             _gnutls_set_datum(&pobj->pubkey[0], a[0].value,
1532                                               a[0].value_len);
1533
1534                         if (ret >= 0)
1535                                 ret =
1536                                     _gnutls_set_datum(&pobj->pubkey
1537                                                       [1], a[1].value,
1538                                                       a[1].value_len);
1539
1540                         if (ret < 0) {
1541                                 gnutls_assert();
1542                                 _gnutls_free_datum(&pobj->pubkey[1]);
1543                                 _gnutls_free_datum(&pobj->pubkey[0]);
1544                                 ret = GNUTLS_E_MEMORY_ERROR;
1545                                 goto cleanup;
1546                         }
1547
1548                         pobj->pubkey_size = 2;
1549                 } else {
1550                         gnutls_assert();
1551                         ret = pkcs11_rv_to_err(rv);
1552                         goto cleanup;
1553                 }
1554
1555                 a[0].type = CKA_BASE;
1556                 a[0].value = tmp1;
1557                 a[0].value_len = tmp1_size;
1558                 a[1].type = CKA_VALUE;
1559                 a[1].value = tmp2;
1560                 a[1].value_len = tmp2_size;
1561
1562                 if ((rv = pkcs11_get_attribute_value(module, pks, obj, a, 2)) ==
1563                     CKR_OK) {
1564                         pobj->pubkey[2].data = a[0].value;
1565                         pobj->pubkey[2].size = a[0].value_len;
1566
1567                         pobj->pubkey[3].data = a[1].value;
1568                         pobj->pubkey[3].size = a[1].value_len;
1569
1570                         pobj->pubkey_size = 4;
1571                 } else {
1572                         gnutls_assert();
1573                         ret = pkcs11_rv_to_err(rv);
1574                         goto cleanup;
1575                 }
1576                 break;
1577         case CKK_ECDSA:
1578                 a[0].type = CKA_EC_PARAMS;
1579                 a[0].value = tmp1;
1580                 a[0].value_len = tmp1_size;
1581
1582                 a[1].type = CKA_EC_POINT;
1583                 a[1].value = tmp2;
1584                 a[1].value_len = tmp2_size;
1585
1586                 if ((rv = pkcs11_get_attribute_value(module, pks, obj, a, 2)) ==
1587                     CKR_OK) {
1588
1589                         pobj->pubkey[0].data = a[0].value;
1590                         pobj->pubkey[0].size = a[0].value_len;
1591
1592                         pobj->pubkey[1].data = a[1].value;
1593                         pobj->pubkey[1].size = a[1].value_len;
1594
1595                         pobj->pubkey_size = 2;
1596                 } else {
1597                         gnutls_assert();
1598
1599                         ret = pkcs11_rv_to_err(rv);
1600                         goto cleanup;
1601                 }
1602
1603                 break;
1604         default:
1605                 _gnutls_debug_log("requested reading public key of unsupported type %u\n", (unsigned)key_type);
1606                 ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1607                 goto cleanup;
1608         }
1609
1610         return 0;
1611
1612 cleanup:
1613         gnutls_free(tmp1);
1614         gnutls_free(tmp2);
1615
1616         return ret;
1617 }
1618
1619 static int
1620 pkcs11_obj_import_pubkey(struct ck_function_list *module,
1621                          ck_session_handle_t pks,
1622                          ck_object_handle_t ctx,
1623                          gnutls_pkcs11_obj_t pobj,
1624                          gnutls_datum_t *data,
1625                          const gnutls_datum_t *id,
1626                          const gnutls_datum_t *label,
1627                          struct ck_token_info *tinfo,
1628                          struct ck_info *lib_info)
1629 {
1630         struct ck_attribute a[4];
1631         ck_key_type_t key_type;
1632         int ret;
1633         ck_bool_t tval;
1634
1635         a[0].type = CKA_KEY_TYPE;
1636         a[0].value = &key_type;
1637         a[0].value_len = sizeof(key_type);
1638
1639         if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1640                 pobj->pk_algorithm = mech_to_pk(key_type);
1641
1642                 ret =
1643                     pkcs11_read_pubkey(module, pks, ctx, key_type,
1644                                        pobj);
1645                 if (ret < 0)
1646                         return gnutls_assert_val(ret);
1647         }
1648
1649         /* read key usage flags */
1650         a[0].type = CKA_ENCRYPT;
1651         a[0].value = &tval;
1652         a[0].value_len = sizeof(tval);
1653
1654         if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1655                 if (tval != 0) {
1656                         pobj->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
1657                 }
1658         }
1659
1660         a[0].type = CKA_VERIFY;
1661         a[0].value = &tval;
1662         a[0].value_len = sizeof(tval);
1663
1664         if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1665                 if (tval != 0) {
1666                         pobj->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1667                             GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1668                             | GNUTLS_KEY_NON_REPUDIATION;
1669                 }
1670         }
1671
1672         a[0].type = CKA_VERIFY_RECOVER;
1673         a[0].value = &tval;
1674         a[0].value_len = sizeof(tval);
1675
1676         if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1677                 if (tval != 0) {
1678                         pobj->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1679                             GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1680                             | GNUTLS_KEY_NON_REPUDIATION;
1681                 }
1682         }
1683
1684         a[0].type = CKA_DERIVE;
1685         a[0].value = &tval;
1686         a[0].value_len = sizeof(tval);
1687
1688         if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1689                 if (tval != 0) {
1690                         pobj->key_usage |= GNUTLS_KEY_KEY_AGREEMENT;
1691                 }
1692         }
1693
1694         a[0].type = CKA_WRAP;
1695         a[0].value = &tval;
1696         a[0].value_len = sizeof(tval);
1697
1698         if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1699                 if (tval != 0) {
1700                         pobj->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
1701                 }
1702         }
1703
1704         ret = pkcs11_obj_import(CKO_PUBLIC_KEY, pobj, data, id, label,
1705                                  tinfo, lib_info);
1706         return ret;
1707 }
1708
1709 static int
1710 pkcs11_import_object(ck_object_handle_t obj, ck_object_class_t class,
1711                      struct pkcs11_session_info *sinfo,
1712                      struct token_info *info, struct ck_info *lib_info,
1713                      gnutls_pkcs11_obj_t pobj)
1714 {
1715         ck_bool_t b;
1716         int rv, ret;
1717         struct ck_attribute a[4];
1718         unsigned long category = 0;
1719         char label_tmp[PKCS11_LABEL_SIZE];
1720         char id_tmp[PKCS11_ID_SIZE];
1721         gnutls_datum_t id, label, data = {NULL, 0};
1722
1723         /* now figure out flags */
1724         pobj->flags = 0;
1725         a[0].type = CKA_WRAP;
1726         a[0].value = &b;
1727         a[0].value_len = sizeof(b);
1728
1729         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1730         if (rv == CKR_OK && b != 0)
1731                 pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP;
1732
1733         a[0].type = CKA_UNWRAP;
1734         a[0].value = &b;
1735         a[0].value_len = sizeof(b);
1736
1737         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1738         if (rv == CKR_OK && b != 0)
1739                 pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP;
1740
1741         a[0].type = CKA_PRIVATE;
1742         a[0].value = &b;
1743         a[0].value_len = sizeof(b);
1744
1745         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1746         if (rv == CKR_OK && b != 0)
1747                 pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE;
1748
1749         a[0].type = CKA_TRUSTED;
1750         a[0].value = &b;
1751         a[0].value_len = sizeof(b);
1752
1753         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1754         if (rv == CKR_OK && b != 0)
1755                 pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED;
1756
1757         a[0].type = CKA_SENSITIVE;
1758         a[0].value = &b;
1759         a[0].value_len = sizeof(b);
1760
1761         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1762         if (rv == CKR_OK && b != 0)
1763                 pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE;
1764
1765         a[0].type = CKA_CERTIFICATE_CATEGORY;
1766         a[0].value = &category;
1767         a[0].value_len = sizeof(category);
1768
1769         rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1770         if (rv == CKR_OK && category == 2)
1771                 pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_CA;
1772
1773         /* now recover the object label/id */
1774         a[0].type = CKA_LABEL;
1775         a[0].value = label_tmp;
1776         a[0].value_len = sizeof(label_tmp);
1777         rv = pkcs11_get_attribute_value
1778             (sinfo->module, sinfo->pks, obj, a, 1);
1779         if (rv != CKR_OK) {
1780                 gnutls_assert();
1781                 label.data = NULL;
1782                 label.size = 0;
1783         } else {
1784                 label.data = a[0].value;
1785                 label.size = a[0].value_len;
1786         }
1787
1788         a[0].type = CKA_ID;
1789         a[0].value = id_tmp;
1790         a[0].value_len = sizeof(id_tmp);
1791         rv = pkcs11_get_attribute_value
1792             (sinfo->module, sinfo->pks, obj, a, 1);
1793         if (rv != CKR_OK) {
1794                 gnutls_assert();
1795                 id.data = NULL;
1796                 id.size = 0;
1797         } else {
1798                 id.data = a[0].value;
1799                 id.size = a[0].value_len;
1800         }
1801
1802         if (label.data == NULL && id.data == NULL)
1803                 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1804
1805         rv = pkcs11_get_attribute_avalue
1806             (sinfo->module, sinfo->pks, obj, CKA_VALUE, &data);
1807         if (rv != CKR_OK) {
1808                 gnutls_assert();
1809                 /* data will be null */
1810         }
1811
1812         if (class == CKO_PUBLIC_KEY) {
1813                 ret =
1814                     pkcs11_obj_import_pubkey(sinfo->module,
1815                                              sinfo->pks,
1816                                              obj,
1817                                              pobj,
1818                                              &data,
1819                                              &id, &label,
1820                                              &info->tinfo,
1821                                              lib_info);
1822         } else {
1823                 ret =
1824                     pkcs11_obj_import(class,
1825                                       pobj,
1826                                       &data, &id, &label,
1827                                       &info->tinfo,
1828                                       lib_info);
1829         }
1830         if (ret < 0) {
1831                 gnutls_assert();
1832                 goto cleanup;
1833         }
1834
1835         ret = 0;
1836  cleanup:
1837         gnutls_free(data.data);
1838         return ret;
1839 }
1840
1841 static int
1842 find_obj_url_cb(struct pkcs11_session_info *sinfo,
1843              struct token_info *info, struct ck_info *lib_info,
1844              void *input)
1845 {
1846         struct find_url_data_st *find_data = input;
1847         struct ck_attribute a[4];
1848         struct ck_attribute *attr;
1849         ck_object_class_t class = -1;
1850         ck_certificate_type_t type = (ck_certificate_type_t) - 1;
1851         ck_rv_t rv;
1852         ck_object_handle_t obj = CK_INVALID_HANDLE;
1853         unsigned long count, a_vals;
1854         int found = 0, ret;
1855
1856         if (info == NULL) {     /* we don't support multiple calls */
1857                 gnutls_assert();
1858                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1859         }
1860
1861         /* do not bother reading the token if basic fields do not match
1862          */
1863         if (!p11_kit_uri_match_token_info
1864             (find_data->obj->info, &info->tinfo)
1865             || !p11_kit_uri_match_module_info(find_data->obj->info,
1866                                               lib_info)) {
1867                 gnutls_assert();
1868                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1869         }
1870
1871         a_vals = 0;
1872         attr = p11_kit_uri_get_attribute(find_data->obj->info, CKA_ID);
1873         if (attr) {
1874                 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1875                 a_vals++;
1876         }
1877
1878         attr = p11_kit_uri_get_attribute(find_data->obj->info, CKA_LABEL);
1879         if (attr) {
1880                 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1881                 a_vals++;
1882         }
1883
1884         if (!a_vals) {
1885                 gnutls_assert();
1886                 return GNUTLS_E_INVALID_REQUEST;
1887         }
1888
1889         /* Find objects with given class and type */
1890         attr = p11_kit_uri_get_attribute(find_data->obj->info, CKA_CLASS);
1891         if (attr) {
1892                 if (attr->value
1893                     && attr->value_len == sizeof(ck_object_class_t))
1894                         class = *((ck_object_class_t *) attr->value);
1895                 if (class == CKO_CERTIFICATE)
1896                         type = CKC_X_509;
1897                 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1898                 a_vals++;
1899         }
1900
1901         if (type != (ck_certificate_type_t) - 1) {
1902                 a[a_vals].type = CKA_CERTIFICATE_TYPE;
1903                 a[a_vals].value = &type;
1904                 a[a_vals].value_len = sizeof type;
1905                 a_vals++;
1906         }
1907
1908
1909         rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
1910                                       a_vals);
1911         if (rv != CKR_OK) {
1912                 gnutls_assert();
1913                 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
1914                 ret = pkcs11_rv_to_err(rv);
1915                 goto cleanup;
1916         }
1917
1918         if (pkcs11_find_objects(sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK &&
1919             count == 1) {
1920                 ret = pkcs11_import_object(obj, class, sinfo, info, lib_info, find_data->obj);
1921                 if (ret >= 0) {
1922                         found = 1;
1923                 }
1924         } else {
1925                 _gnutls_debug_log
1926                     ("p11: Skipped object, missing attrs.\n");
1927         }
1928
1929         if (found == 0) {
1930                 gnutls_assert();
1931                 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1932         } else {
1933                 ret = 0;
1934         }
1935
1936       cleanup:
1937         pkcs11_find_objects_final(sinfo);
1938
1939         if (ret == 0 && find_data->overwrite_exts && find_data->obj->raw.size > 0 && obj != CK_INVALID_HANDLE) {
1940                 gnutls_datum_t spki;
1941                 rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, obj, CKA_PUBLIC_KEY_INFO, &spki);
1942                 if (rv == CKR_OK) {
1943                         ret = pkcs11_override_cert_exts(sinfo, &spki, &find_data->obj->raw);
1944                         gnutls_free(spki.data);
1945                         if (ret < 0) {
1946                                 gnutls_assert();
1947                                 return ret;
1948                         }
1949                 }
1950         }
1951
1952         return ret;
1953 }
1954
1955 unsigned int pkcs11_obj_flags_to_int(unsigned int flags)
1956 {
1957         unsigned int ret_flags = 0;
1958
1959         if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN)
1960                 ret_flags |= SESSION_LOGIN;
1961         if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO)
1962                 ret_flags |= SESSION_LOGIN | SESSION_SO;
1963         if (flags & GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE)
1964                 ret_flags |= SESSION_TRUSTED;
1965
1966         return ret_flags;
1967 }
1968
1969 /**
1970  * gnutls_pkcs11_obj_import_url:
1971  * @obj: The structure to store the object
1972  * @url: a PKCS 11 url identifying the key
1973  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
1974  *
1975  * This function will "import" a PKCS 11 URL identifying an object (e.g. certificate)
1976  * to the #gnutls_pkcs11_obj_t structure. This does not involve any
1977  * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is
1978  * format agnostic. Only data are transferred.
1979  *
1980  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1981  *   negative error value.
1982  *
1983  * Since: 2.12.0
1984  **/
1985 int
1986 gnutls_pkcs11_obj_import_url(gnutls_pkcs11_obj_t obj, const char *url,
1987                              unsigned int flags)
1988 {
1989         int ret;
1990         struct find_url_data_st find_data;
1991
1992         PKCS11_CHECK_INIT;
1993         memset(&find_data, 0, sizeof(find_data));
1994
1995         /* fill in the find data structure */
1996         find_data.obj = obj;
1997
1998         ret = pkcs11_url_to_info(url, &obj->info, flags);
1999         if (ret < 0) {
2000                 gnutls_assert();
2001                 return ret;
2002         }
2003
2004         if (flags & GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT) {
2005                 find_data.overwrite_exts = 1;
2006         }
2007
2008         ret =
2009             _pkcs11_traverse_tokens(find_obj_url_cb, &find_data, obj->info,
2010                                     &obj->pin,
2011                                     pkcs11_obj_flags_to_int(flags));
2012         if (ret < 0) {
2013                 gnutls_assert();
2014                 return ret;
2015         }
2016
2017         return 0;
2018 }
2019
2020 static int
2021 find_token_num_cb(struct pkcs11_session_info *sinfo,
2022                struct token_info *tinfo,
2023                struct ck_info *lib_info, void *input)
2024 {
2025         struct find_token_num *find_data = input;
2026
2027         if (tinfo == NULL) {    /* we don't support multiple calls */
2028                 gnutls_assert();
2029                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2030         }
2031
2032         if (find_data->current == find_data->seq) {
2033                 memcpy(p11_kit_uri_get_token_info(find_data->info),
2034                        &tinfo->tinfo, sizeof(struct ck_token_info));
2035                 memcpy(p11_kit_uri_get_module_info(find_data->info),
2036                        lib_info, sizeof(struct ck_info));
2037                 return 0;
2038         }
2039
2040         find_data->current++;
2041         /* search the token for the id */
2042
2043
2044         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;   /* non zero is enough */
2045 }
2046
2047 /**
2048  * gnutls_pkcs11_token_get_url:
2049  * @seq: sequence number starting from 0
2050  * @detailed: non zero if a detailed URL is required
2051  * @url: will contain an allocated url
2052  *
2053  * This function will return the URL for each token available
2054  * in system. The url has to be released using gnutls_free()
2055  *
2056  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
2057  * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if the sequence number
2058  * exceeds the available tokens, otherwise a negative error value.
2059  *
2060  * Since: 2.12.0
2061  **/
2062 int
2063 gnutls_pkcs11_token_get_url(unsigned int seq,
2064                             gnutls_pkcs11_url_type_t detailed, char **url)
2065 {
2066         int ret;
2067         struct find_token_num tn;
2068
2069         PKCS11_CHECK_INIT;
2070
2071         memset(&tn, 0, sizeof(tn));
2072         tn.seq = seq;
2073         tn.info = p11_kit_uri_new();
2074
2075         ret = _pkcs11_traverse_tokens(find_token_num_cb, &tn, NULL, NULL, 0);
2076         if (ret < 0) {
2077                 p11_kit_uri_free(tn.info);
2078                 gnutls_assert();
2079                 return ret;
2080         }
2081
2082         ret = pkcs11_info_to_url(tn.info, detailed, url);
2083         p11_kit_uri_free(tn.info);
2084
2085         if (ret < 0) {
2086                 gnutls_assert();
2087                 return ret;
2088         }
2089
2090         return 0;
2091
2092 }
2093
2094 /**
2095  * gnutls_pkcs11_token_get_info:
2096  * @url: should contain a PKCS 11 URL
2097  * @ttype: Denotes the type of information requested
2098  * @output: where output will be stored
2099  * @output_size: contains the maximum size of the output and will be overwritten with actual
2100  *
2101  * This function will return information about the PKCS 11 token such
2102  * as the label, id, etc.
2103  *
2104  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code
2105  * on error.
2106  *
2107  * Since: 2.12.0
2108  **/
2109 int
2110 gnutls_pkcs11_token_get_info(const char *url,
2111                              gnutls_pkcs11_token_info_t ttype,
2112                              void *output, size_t * output_size)
2113 {
2114         struct p11_kit_uri *info = NULL;
2115         const uint8_t *str;
2116         size_t str_max;
2117         size_t len;
2118         int ret;
2119
2120         PKCS11_CHECK_INIT;
2121
2122         ret = pkcs11_url_to_info(url, &info, 0);
2123         if (ret < 0) {
2124                 gnutls_assert();
2125                 return ret;
2126         }
2127
2128         switch (ttype) {
2129         case GNUTLS_PKCS11_TOKEN_LABEL:
2130                 str = p11_kit_uri_get_token_info(info)->label;
2131                 str_max = 32;
2132                 break;
2133         case GNUTLS_PKCS11_TOKEN_SERIAL:
2134                 str = p11_kit_uri_get_token_info(info)->serial_number;
2135                 str_max = 16;
2136                 break;
2137         case GNUTLS_PKCS11_TOKEN_MANUFACTURER:
2138                 str = p11_kit_uri_get_token_info(info)->manufacturer_id;
2139                 str_max = 32;
2140                 break;
2141         case GNUTLS_PKCS11_TOKEN_MODEL:
2142                 str = p11_kit_uri_get_token_info(info)->model;
2143                 str_max = 16;
2144                 break;
2145         default:
2146                 p11_kit_uri_free(info);
2147                 gnutls_assert();
2148                 return GNUTLS_E_INVALID_REQUEST;
2149         }
2150
2151         len = p11_kit_space_strlen(str, str_max);
2152
2153         if (len + 1 > *output_size) {
2154                 *output_size = len + 1;
2155                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
2156         }
2157
2158         memcpy(output, str, len);
2159         ((char *) output)[len] = '\0';
2160
2161         *output_size = len;
2162
2163         ret = 0;
2164
2165         p11_kit_uri_free(info);
2166         return ret;
2167 }
2168
2169 /**
2170  * gnutls_pkcs11_obj_export_url:
2171  * @obj: Holds the PKCS 11 certificate
2172  * @detailed: non zero if a detailed URL is required
2173  * @url: will contain an allocated url
2174  *
2175  * This function will export a URL identifying the given certificate.
2176  *
2177  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2178  *   negative error value.
2179  *
2180  * Since: 2.12.0
2181  **/
2182 int
2183 gnutls_pkcs11_obj_export_url(gnutls_pkcs11_obj_t obj,
2184                              gnutls_pkcs11_url_type_t detailed, char **url)
2185 {
2186         int ret;
2187
2188         ret = pkcs11_info_to_url(obj->info, detailed, url);
2189         if (ret < 0) {
2190                 gnutls_assert();
2191                 return ret;
2192         }
2193
2194         return 0;
2195 }
2196
2197 /**
2198  * gnutls_pkcs11_obj_get_type:
2199  * @obj: Holds the PKCS 11 object
2200  *
2201  * This function will return the type of the object being
2202  * stored in the structure.
2203  *
2204  * Returns: The type of the object
2205  *
2206  * Since: 2.12.0
2207  **/
2208 gnutls_pkcs11_obj_type_t
2209 gnutls_pkcs11_obj_get_type(gnutls_pkcs11_obj_t obj)
2210 {
2211         return obj->type;
2212 }
2213
2214 static int
2215 retrieve_pin_from_source(const char *pinfile,
2216                          struct ck_token_info *token_info, int attempts,
2217                          ck_user_type_t user_type,
2218                          struct p11_kit_pin **pin)
2219 {
2220         unsigned int flags = 0;
2221         struct p11_kit_uri *token_uri;
2222         struct p11_kit_pin *result;
2223         char *label;
2224
2225         label =
2226             p11_kit_space_strdup(token_info->label,
2227                                  sizeof(token_info->label));
2228         if (label == NULL) {
2229                 gnutls_assert();
2230                 return GNUTLS_E_MEMORY_ERROR;
2231         }
2232
2233         token_uri = p11_kit_uri_new();
2234         if (token_uri == NULL) {
2235                 free(label);
2236                 gnutls_assert();
2237                 return GNUTLS_E_MEMORY_ERROR;
2238         }
2239
2240         memcpy(p11_kit_uri_get_token_info(token_uri), token_info,
2241                sizeof(struct ck_token_info));
2242
2243         if (attempts)
2244                 flags |= P11_KIT_PIN_FLAGS_RETRY;
2245         if (user_type == CKU_USER) {
2246                 flags |= P11_KIT_PIN_FLAGS_USER_LOGIN;
2247                 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
2248                         flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
2249                 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
2250                         flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
2251         } else if (user_type == CKU_SO) {
2252                 flags |= P11_KIT_PIN_FLAGS_SO_LOGIN;
2253                 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
2254                         flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
2255                 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
2256                         flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
2257         } else if (user_type == CKU_CONTEXT_SPECIFIC) {
2258                 flags |= P11_KIT_PIN_FLAGS_CONTEXT_LOGIN;
2259         }
2260
2261         result = p11_kit_pin_request(pinfile, token_uri, label, flags);
2262         p11_kit_uri_free(token_uri);
2263         free(label);
2264
2265         if (result == NULL) {
2266                 gnutls_assert();
2267                 return GNUTLS_E_PKCS11_PIN_ERROR;
2268         }
2269
2270         *pin = result;
2271         return 0;
2272 }
2273
2274 static int
2275 retrieve_pin_from_callback(const struct pin_info_st *pin_info,
2276                            struct ck_token_info *token_info,
2277                            int attempts, ck_user_type_t user_type,
2278                            struct p11_kit_pin **pin)
2279 {
2280         char pin_value[GNUTLS_PKCS11_MAX_PIN_LEN];
2281         unsigned int flags = 0;
2282         char *token_str;
2283         char *label;
2284         struct p11_kit_uri *token_uri;
2285         int ret = 0;
2286
2287         label =
2288             p11_kit_space_strdup(token_info->label,
2289                                  sizeof(token_info->label));
2290         if (label == NULL) {
2291                 gnutls_assert();
2292                 return GNUTLS_E_MEMORY_ERROR;
2293         }
2294
2295         token_uri = p11_kit_uri_new();
2296         if (token_uri == NULL) {
2297                 free(label);
2298                 gnutls_assert();
2299                 return GNUTLS_E_MEMORY_ERROR;
2300         }
2301
2302         memcpy(p11_kit_uri_get_token_info(token_uri), token_info,
2303                sizeof(struct ck_token_info));
2304         ret = pkcs11_info_to_url(token_uri, 1, &token_str);
2305         p11_kit_uri_free(token_uri);
2306
2307         if (ret < 0) {
2308                 free(label);
2309                 gnutls_assert();
2310                 return GNUTLS_E_MEMORY_ERROR;
2311         }
2312
2313         if (user_type == CKU_USER || user_type == CKU_CONTEXT_SPECIFIC) {
2314                 flags |= GNUTLS_PIN_USER;
2315
2316                 if (user_type == CKU_CONTEXT_SPECIFIC)
2317                         flags |= GNUTLS_PIN_CONTEXT_SPECIFIC;
2318                 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
2319                         flags |= GNUTLS_PIN_COUNT_LOW;
2320                 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
2321                         flags |= GNUTLS_PIN_FINAL_TRY;
2322         } else if (user_type == CKU_SO) {
2323                 flags |= GNUTLS_PIN_SO;
2324                 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
2325                         flags |= GNUTLS_PIN_COUNT_LOW;
2326                 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
2327                         flags |= GNUTLS_PIN_FINAL_TRY;
2328         }
2329
2330         if (attempts > 0)
2331                 flags |= GNUTLS_PIN_WRONG;
2332
2333         if (pin_info && pin_info->cb)
2334                 ret =
2335                     pin_info->cb(pin_info->data, attempts,
2336                                  (char *) token_str, label, flags,
2337                                  pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2338         else if (_gnutls_pin_func)
2339                 ret =
2340                     _gnutls_pin_func(_gnutls_pin_data, attempts,
2341                                      (char *) token_str, label, flags,
2342                                      pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2343         else
2344                 ret = gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2345
2346         free(token_str);
2347         free(label);
2348
2349         if (ret < 0)
2350                 return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2351
2352         *pin = p11_kit_pin_new_for_string(pin_value);
2353
2354         if (*pin == NULL)
2355                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2356
2357         return 0;
2358 }
2359
2360 static int
2361 retrieve_pin(struct pin_info_st *pin_info, struct p11_kit_uri *info,
2362              struct ck_token_info *token_info, int attempts,
2363              ck_user_type_t user_type, struct p11_kit_pin **pin)
2364 {
2365         const char *pinfile;
2366         int ret = GNUTLS_E_PKCS11_PIN_ERROR;
2367
2368         *pin = NULL;
2369
2370 #ifdef P11_KIT_HAS_PIN_VALUE
2371         /* First check for pin-value field */
2372         pinfile = p11_kit_uri_get_pin_value(info);
2373         if (pinfile != NULL) {
2374                 _gnutls_debug_log("p11: Using pin-value to retrieve PIN\n");
2375                 *pin = p11_kit_pin_new_for_string(pinfile);
2376                 if (*pin != NULL)
2377                         ret = 0;
2378         } else { /* try pin-source */
2379                 /* Check if a pinfile is specified, and use that if possible */
2380                 pinfile = p11_kit_uri_get_pin_source(info);
2381                 if (pinfile != NULL) {
2382                         _gnutls_debug_log("p11: Using pin-source to retrieve PIN\n");
2383                         ret =
2384                             retrieve_pin_from_source(pinfile, token_info, attempts,
2385                                                      user_type, pin);
2386                 }
2387         }
2388 #else
2389         /* Check if a pinfile is specified, and use that if possible */
2390         pinfile = p11_kit_uri_get_pinfile(info);
2391         if (pinfile != NULL) {
2392                 _gnutls_debug_log("p11: Using pinfile to retrieve PIN\n");
2393                 ret =
2394                     retrieve_pin_from_source(pinfile, token_info, attempts,
2395                                              user_type, pin);
2396         }
2397 #endif
2398
2399         /* The global gnutls pin callback */
2400         if (ret < 0)
2401                 ret =
2402                     retrieve_pin_from_callback(pin_info, token_info,
2403                                                attempts, user_type, pin);
2404
2405         /* Otherwise, PIN entry is necessary for login, so fail if there's
2406          * no callback. */
2407
2408         if (ret < 0) {
2409                 gnutls_assert();
2410                 _gnutls_debug_log
2411                     ("p11: No suitable pin callback but login required.\n");
2412         }
2413
2414         return ret;
2415 }
2416
2417 int
2418 pkcs11_login(struct pkcs11_session_info *sinfo,
2419              struct pin_info_st *pin_info,
2420              struct p11_kit_uri *info,
2421              unsigned so,
2422              unsigned reauth)
2423 {
2424         struct ck_session_info session_info;
2425         int attempt = 0, ret;
2426         ck_user_type_t user_type;
2427         ck_rv_t rv;
2428
2429         if (so == 0) {
2430                 if (reauth == 0)
2431                         user_type = CKU_USER;
2432                 else
2433                         user_type = CKU_CONTEXT_SPECIFIC;
2434         } else
2435                 user_type = CKU_SO;
2436
2437         if (so == 0 && (sinfo->tinfo.flags & CKF_LOGIN_REQUIRED) == 0) {
2438                 gnutls_assert();
2439                 _gnutls_debug_log("p11: No login required.\n");
2440                 return 0;
2441         }
2442
2443         /* For a token with a "protected" (out-of-band) authentication
2444          * path, calling login with a NULL username is all that is
2445          * required. */
2446         if (sinfo->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
2447                 rv = (sinfo->module)->C_Login(sinfo->pks,
2448                                               user_type,
2449                                               NULL, 0);
2450                 if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) {
2451                         return 0;
2452                 } else {
2453                         gnutls_assert();
2454                         _gnutls_debug_log
2455                             ("p11: Protected login failed.\n");
2456                         ret = GNUTLS_E_PKCS11_ERROR;
2457                         goto cleanup;
2458                 }
2459         }
2460
2461         do {
2462                 struct p11_kit_pin *pin;
2463                 struct ck_token_info tinfo;
2464
2465                 memcpy(&tinfo, &sinfo->tinfo, sizeof(tinfo));
2466
2467                 /* Check whether the session is already logged in, and if so, just skip */
2468                 rv = (sinfo->module)->C_GetSessionInfo(sinfo->pks,
2469                                                        &session_info);
2470                 if (rv == CKR_OK && reauth == 0 &&
2471                     (session_info.state == CKS_RO_USER_FUNCTIONS
2472                         || session_info.state == CKS_RW_USER_FUNCTIONS)) {
2473                         ret = 0;
2474                         goto cleanup;
2475                 }
2476
2477                 /* If login has been attempted once already, check the token
2478                  * status again, the flags might change. */
2479                 if (attempt) {
2480                         if (pkcs11_get_token_info
2481                             (sinfo->module, sinfo->sid,
2482                              &tinfo) != CKR_OK) {
2483                                 gnutls_assert();
2484                                 _gnutls_debug_log
2485                                     ("p11: GetTokenInfo failed\n");
2486                                 ret = GNUTLS_E_PKCS11_ERROR;
2487                                 goto cleanup;
2488                         }
2489                 }
2490
2491                 ret =
2492                     retrieve_pin(pin_info, info, &tinfo, attempt++,
2493                                  user_type, &pin);
2494                 if (ret < 0) {
2495                         gnutls_assert();
2496                         goto cleanup;
2497                 }
2498
2499                 rv = (sinfo->module)->C_Login(sinfo->pks, user_type,
2500                                               (unsigned char *)
2501                                               p11_kit_pin_get_value(pin,
2502                                                                     NULL),
2503                                               p11_kit_pin_get_length(pin));
2504
2505                 p11_kit_pin_unref(pin);
2506         }
2507         while (rv == CKR_PIN_INCORRECT);
2508
2509         _gnutls_debug_log("p11: Login result = %lu\n", rv);
2510
2511
2512         ret = (rv == CKR_OK
2513                || rv ==
2514                CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err(rv);
2515
2516       cleanup:
2517         return ret;
2518 }
2519
2520 int pkcs11_call_token_func(struct p11_kit_uri *info, const unsigned retry)
2521 {
2522         struct ck_token_info *tinfo;
2523         char *label;
2524         int ret = 0;
2525
2526         tinfo = p11_kit_uri_get_token_info(info);
2527         label = p11_kit_space_strdup(tinfo->label, sizeof(tinfo->label));
2528         ret = (_gnutls_token_func) (_gnutls_token_data, label, retry);
2529         free(label);
2530
2531         return ret;
2532 }
2533
2534
2535 static int
2536 find_privkeys(struct pkcs11_session_info *sinfo,
2537               struct token_info *info, struct find_pkey_list_st *list)
2538 {
2539         struct ck_attribute a[3];
2540         ck_object_class_t class;
2541         ck_rv_t rv;
2542         ck_object_handle_t obj;
2543         unsigned long count, current;
2544         char certid_tmp[PKCS11_ID_SIZE];
2545
2546         class = CKO_PRIVATE_KEY;
2547
2548         /* Find an object with private key class and a certificate ID
2549          * which matches the certificate. */
2550         /* FIXME: also match the cert subject. */
2551         a[0].type = CKA_CLASS;
2552         a[0].value = &class;
2553         a[0].value_len = sizeof class;
2554
2555         rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 1);
2556         if (rv != CKR_OK) {
2557                 gnutls_assert();
2558                 return pkcs11_rv_to_err(rv);
2559         }
2560
2561         list->key_ids_size = 0;
2562         while (pkcs11_find_objects
2563                (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK
2564                && count == 1) {
2565                 list->key_ids_size++;
2566         }
2567
2568         pkcs11_find_objects_final(sinfo);
2569
2570         if (list->key_ids_size == 0) {
2571                 gnutls_assert();
2572                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2573         }
2574
2575         list->key_ids =
2576             gnutls_malloc(sizeof(gnutls_buffer_st) * list->key_ids_size);
2577         if (list->key_ids == NULL) {
2578                 gnutls_assert();
2579                 return GNUTLS_E_MEMORY_ERROR;
2580         }
2581
2582         /* actual search */
2583         a[0].type = CKA_CLASS;
2584         a[0].value = &class;
2585         a[0].value_len = sizeof class;
2586
2587         rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 1);
2588         if (rv != CKR_OK) {
2589                 gnutls_assert();
2590                 return pkcs11_rv_to_err(rv);
2591         }
2592
2593         current = 0;
2594         while (pkcs11_find_objects
2595                (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK
2596                && count == 1) {
2597
2598                 a[0].type = CKA_ID;
2599                 a[0].value = certid_tmp;
2600                 a[0].value_len = sizeof(certid_tmp);
2601
2602                 _gnutls_buffer_init(&list->key_ids[current]);
2603
2604                 if (pkcs11_get_attribute_value
2605                     (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK) {
2606                         _gnutls_buffer_append_data(&list->key_ids[current],
2607                                                    a[0].value,
2608                                                    a[0].value_len);
2609                         current++;
2610                 }
2611
2612                 if (current > list->key_ids_size)
2613                         break;
2614         }
2615
2616         pkcs11_find_objects_final(sinfo);
2617
2618         list->key_ids_size = current - 1;
2619
2620         return 0;
2621 }
2622
2623 /* Recover certificate list from tokens */
2624
2625 #define OBJECTS_A_TIME 8*1024
2626
2627 static int
2628 find_objs_cb(struct pkcs11_session_info *sinfo,
2629           struct token_info *info, struct ck_info *lib_info, void *input)
2630 {
2631         struct find_obj_data_st *find_data = input;
2632         struct ck_attribute a[16];
2633         struct ck_attribute *attr;
2634         ck_object_class_t class = (ck_object_class_t) -1;
2635         ck_certificate_type_t type = (ck_certificate_type_t) -1;
2636         ck_bool_t trusted;
2637         unsigned long category;
2638         ck_rv_t rv;
2639         ck_object_handle_t *objs = NULL;
2640         unsigned long count;
2641         char certid_tmp[PKCS11_ID_SIZE];
2642         int ret;
2643         struct find_pkey_list_st plist; /* private key holder */
2644         unsigned int i, tot_values = 0;
2645
2646         if (info == NULL) {
2647                 gnutls_assert();
2648                 return 0;
2649         }
2650
2651         /* do not bother reading the token if basic fields do not match
2652          */
2653         if (!p11_kit_uri_match_token_info(find_data->info, &info->tinfo) ||
2654             !p11_kit_uri_match_module_info(find_data->info, lib_info)) {
2655                 gnutls_assert();
2656                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2657         }
2658
2659         memset(&plist, 0, sizeof(plist));
2660
2661         if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) {
2662                 ret = find_privkeys(sinfo, info, &plist);
2663                 if (ret < 0) {
2664                         gnutls_assert();
2665                         return ret;
2666                 }
2667
2668                 if (plist.key_ids_size == 0) {
2669                         gnutls_assert();
2670                         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2671                 }
2672         }
2673
2674         /* Find objects with given class and type */
2675         attr = p11_kit_uri_get_attribute(find_data->info, CKA_CLASS);
2676         if (attr) {
2677                 if (attr->value
2678                     && attr->value_len == sizeof(ck_object_class_t))
2679                         class = *((ck_object_class_t *) attr->value);
2680                 if (class == CKO_CERTIFICATE)
2681                         type = CKC_X_509;
2682         }
2683
2684         /* Find objects with cert class and X.509 cert type. */
2685
2686         tot_values = 0;
2687
2688         if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL
2689             || find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2690         {
2691                 class = CKO_CERTIFICATE;
2692                 type = CKC_X_509;
2693                 trusted = 1;
2694
2695                 a[tot_values].type = CKA_CLASS;
2696                 a[tot_values].value = &class;
2697                 a[tot_values].value_len = sizeof class;
2698                 tot_values++;
2699
2700                 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2701                 a[tot_values].value = &type;
2702                 a[tot_values].value_len = sizeof type;
2703                 tot_values++;
2704
2705         } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_MATCH) {
2706                 if (class != (ck_object_class_t)-1) {
2707                         a[tot_values].type = CKA_CLASS;
2708                         a[tot_values].value = &class;
2709                         a[tot_values].value_len = sizeof class;
2710                         tot_values++;
2711                 }
2712
2713         } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED) {
2714                 class = CKO_CERTIFICATE;
2715                 type = CKC_X_509;
2716                 trusted = 1;
2717
2718                 a[tot_values].type = CKA_CLASS;
2719                 a[tot_values].value = &class;
2720                 a[tot_values].value_len = sizeof class;
2721                 tot_values++;
2722
2723                 a[tot_values].type = CKA_TRUSTED;
2724                 a[tot_values].value = &trusted;
2725                 a[tot_values].value_len = sizeof trusted;
2726                 tot_values++;
2727
2728         } else if (find_data->flags ==
2729                    GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED_CA) {
2730                 class = CKO_CERTIFICATE;
2731                 type = CKC_X_509;
2732                 trusted = 1;
2733
2734                 a[tot_values].type = CKA_CLASS;
2735                 a[tot_values].value = &class;
2736                 a[tot_values].value_len = sizeof class;
2737                 tot_values++;
2738
2739                 a[tot_values].type = CKA_TRUSTED;
2740                 a[tot_values].value = &trusted;
2741                 a[tot_values].value_len = sizeof trusted;
2742                 tot_values++;
2743
2744                 category = 2;
2745                 a[tot_values].type = CKA_CERTIFICATE_CATEGORY;
2746                 a[tot_values].value = &category;
2747                 a[tot_values].value_len = sizeof category;
2748                 tot_values++;
2749         } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY) {
2750                 class = CKO_PUBLIC_KEY;
2751
2752                 a[tot_values].type = CKA_CLASS;
2753                 a[tot_values].value = &class;
2754                 a[tot_values].value_len = sizeof class;
2755                 tot_values++;
2756         } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY) {
2757                 class = CKO_PRIVATE_KEY;
2758
2759                 a[tot_values].type = CKA_CLASS;
2760                 a[tot_values].value = &class;
2761                 a[tot_values].value_len = sizeof class;
2762                 tot_values++;
2763         } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL) {
2764                 if (class != (ck_object_class_t) - 1) {
2765                         a[tot_values].type = CKA_CLASS;
2766                         a[tot_values].value = &class;
2767                         a[tot_values].value_len = sizeof class;
2768                         tot_values++;
2769                 }
2770                 if (type != (ck_certificate_type_t) - 1) {
2771                         a[tot_values].type = CKA_CERTIFICATE_TYPE;
2772                         a[tot_values].value = &type;
2773                         a[tot_values].value_len = sizeof type;
2774                         tot_values++;
2775                 }
2776         } else {
2777                 gnutls_assert();
2778                 ret = GNUTLS_E_INVALID_REQUEST;
2779                 goto fail;
2780         }
2781
2782         attr = p11_kit_uri_get_attribute(find_data->info, CKA_ID);
2783         if (attr != NULL) {
2784                 a[tot_values].type = CKA_ID;
2785                 a[tot_values].value = attr->value;
2786                 a[tot_values].value_len = attr->value_len;
2787                 tot_values++;
2788         }
2789
2790         attr = p11_kit_uri_get_attribute(find_data->info, CKA_LABEL);
2791         if (attr) {
2792                 a[tot_values].type = CKA_LABEL;
2793                 a[tot_values].value = attr->value;
2794                 a[tot_values].value_len = attr->value_len;
2795                 tot_values++;
2796         }
2797
2798         rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
2799                                       tot_values);
2800         if (rv != CKR_OK) {
2801                 gnutls_assert();
2802                 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
2803                 return pkcs11_rv_to_err(rv);
2804         }
2805
2806         objs = gnutls_malloc(OBJECTS_A_TIME*sizeof(objs[0]));
2807         if (objs == NULL) {
2808                 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2809                 goto fail;
2810         }
2811
2812         while (pkcs11_find_objects
2813                (sinfo->module, sinfo->pks, objs, OBJECTS_A_TIME, &count) == CKR_OK
2814                && count > 0) {
2815                 unsigned j;
2816                 gnutls_datum_t id;
2817
2818                 find_data->p_list = gnutls_realloc_fast(find_data->p_list, (find_data->current+count)*sizeof(find_data->p_list[0]));
2819                 if (find_data->p_list == NULL) {
2820                         ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2821                         goto fail;
2822                 }
2823
2824                 for (j=0;j<count;j++) {
2825                         a[0].type = CKA_ID;
2826                         a[0].value = certid_tmp;
2827                         a[0].value_len = sizeof certid_tmp;
2828
2829                         if (pkcs11_get_attribute_value
2830                             (sinfo->module, sinfo->pks, objs[j], a, 1) == CKR_OK) {
2831                                 id.data = a[0].value;
2832                                 id.size = a[0].value_len;
2833                         } else {
2834                                 id.data = NULL;
2835                                 id.size = 0;
2836                         }
2837
2838                         if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL ||
2839                             find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_MATCH) {
2840                                 a[0].type = CKA_CLASS;
2841                                 a[0].value = &class;
2842                                 a[0].value_len = sizeof class;
2843
2844                                 rv = pkcs11_get_attribute_value(sinfo->module,
2845                                                            sinfo->pks, objs[j], a, 1);
2846                                 if (rv != CKR_OK) {
2847                                         class = -1;
2848                                 }
2849                         }
2850
2851                         if (find_data->flags ==
2852                             GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) {
2853                                 for (i = 0; i < plist.key_ids_size; i++) {
2854                                         if (plist.key_ids[i].length !=
2855                                             id.size
2856                                             || memcmp(plist.key_ids[i].data,
2857                                                       id.data,
2858                                                       id.size) != 0) {
2859                                                 /* not found */
2860                                                 continue;
2861                                         }
2862                                 }
2863                         }
2864
2865                         ret =
2866                             gnutls_pkcs11_obj_init(&find_data->p_list
2867                                                    [find_data->current]);
2868                         if (ret < 0) {
2869                                 gnutls_assert();
2870                                 goto fail;
2871                         }
2872
2873                         ret = pkcs11_import_object(objs[j], class, sinfo,
2874                                              info, lib_info,
2875                                              find_data->p_list[find_data->current]);
2876                         if (ret < 0) {
2877                                 gnutls_assert();
2878                                 /* skip the failed object */
2879                                 continue;
2880                         }
2881
2882                         find_data->current++;
2883                 }
2884         }
2885
2886         gnutls_free(objs);
2887         pkcs11_find_objects_final(sinfo);
2888
2889         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;   /* continue until all tokens have been checked */
2890
2891       fail:
2892         gnutls_free(objs);
2893         pkcs11_find_objects_final(sinfo);
2894         if (plist.key_ids != NULL) {
2895                 for (i = 0; i < plist.key_ids_size; i++) {
2896                         _gnutls_buffer_clear(&plist.key_ids[i]);
2897                 }
2898                 gnutls_free(plist.key_ids);
2899         }
2900         if (find_data->p_list != NULL) {
2901                 for (i = 0; i < find_data->current; i++) {
2902                         gnutls_pkcs11_obj_deinit(find_data->p_list[i]);
2903                 }
2904                 gnutls_free(find_data->p_list);
2905         }
2906         find_data->p_list = NULL;
2907         find_data->current = 0;
2908
2909         return ret;
2910 }
2911
2912 /**
2913  * gnutls_pkcs11_obj_list_import_url:
2914  * @p_list: An uninitialized object list (may be NULL)
2915  * @n_list: initially should hold the maximum size of the list. Will contain the actual size.
2916  * @url: A PKCS 11 url identifying a set of objects
2917  * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2918  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
2919  *
2920  * This function will initialize and set values to an object list
2921  * by using all objects identified by a PKCS 11 URL.
2922  *
2923  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2924  *   negative error value.
2925  *
2926  * Since: 2.12.0
2927  **/
2928 int
2929 gnutls_pkcs11_obj_list_import_url(gnutls_pkcs11_obj_t * p_list,
2930                                   unsigned int *n_list,
2931                                   const char *url,
2932                                   gnutls_pkcs11_obj_attr_t attrs,
2933                                   unsigned int flags)
2934 {
2935         int ret;
2936         struct find_obj_data_st priv;
2937         unsigned i;
2938
2939         PKCS11_CHECK_INIT;
2940
2941         memset(&priv, 0, sizeof(priv));
2942
2943         /* fill in the find data structure */
2944         priv.flags = attrs;
2945
2946         if (url == NULL || url[0] == 0) {
2947                 url = "pkcs11:";
2948         }
2949
2950         ret = pkcs11_url_to_info(url, &priv.info, flags);
2951         if (ret < 0) {
2952                 gnutls_assert();
2953                 return ret;
2954         }
2955
2956         ret =
2957             _pkcs11_traverse_tokens(find_objs_cb, &priv, priv.info,
2958                                     NULL, pkcs11_obj_flags_to_int(flags));
2959         p11_kit_uri_free(priv.info);
2960
2961         if (ret < 0) {
2962                 gnutls_assert();
2963                 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2964                         *n_list = 0;
2965                         ret = 0;
2966                 }
2967                 return ret;
2968         }
2969
2970         if (priv.current > *n_list) {
2971                 *n_list = priv.current;
2972                 for (i=0;i<priv.current;i++) {
2973                         gnutls_pkcs11_obj_deinit(priv.p_list[i]);
2974                 }
2975                 gnutls_free(priv.p_list);
2976                 return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
2977         }
2978
2979         *n_list = priv.current;
2980         if (p_list)
2981                 memcpy(p_list, priv.p_list, priv.current*sizeof(p_list[0]));
2982         gnutls_free(priv.p_list);
2983
2984         return 0;
2985 }
2986
2987 /**
2988  * gnutls_pkcs11_obj_list_import_url2:
2989  * @p_list: An uninitialized object list (may be NULL)
2990  * @n_list: It will contain the size of the list.
2991  * @url: A PKCS 11 url identifying a set of objects
2992  * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2993  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
2994  *
2995  * This function will initialize and set values to an object list
2996  * by using all objects identified by the PKCS 11 URL. The output
2997  * is stored in @p_list, which will be initialized.
2998  *
2999  * All returned objects must be deinitialized using gnutls_pkcs11_obj_deinit(),
3000  * and @p_list must be free'd using gnutls_free().
3001  *
3002  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3003  *   negative error value.
3004  *
3005  * Since: 3.1.0
3006  **/
3007 int
3008 gnutls_pkcs11_obj_list_import_url2(gnutls_pkcs11_obj_t ** p_list,
3009                                    unsigned int *n_list,
3010                                    const char *url,
3011                                    gnutls_pkcs11_obj_attr_t attrs,
3012                                    unsigned int flags)
3013 {
3014         int ret;
3015         struct find_obj_data_st priv;
3016
3017         PKCS11_CHECK_INIT;
3018
3019         memset(&priv, 0, sizeof(priv));
3020
3021         /* fill in the find data structure */
3022         priv.flags = attrs;
3023
3024         if (url == NULL || url[0] == 0) {
3025                 url = "pkcs11:";
3026         }
3027
3028         ret = pkcs11_url_to_info(url, &priv.info, flags);
3029         if (ret < 0) {
3030                 gnutls_assert();
3031                 return ret;
3032         }
3033
3034         ret =
3035             _pkcs11_traverse_tokens(find_objs_cb, &priv, priv.info,
3036                                     NULL, pkcs11_obj_flags_to_int(flags));
3037         p11_kit_uri_free(priv.info);
3038
3039         if (ret < 0) {
3040                 gnutls_assert();
3041                 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
3042                         *p_list = NULL;
3043                         *n_list = 0;
3044                         ret = 0;
3045                 }
3046                 return ret;
3047         }
3048
3049         *n_list = priv.current;
3050         *p_list = priv.p_list;
3051
3052         return 0;
3053 }
3054
3055 /**
3056  * gnutls_x509_crt_import_pkcs11_url:
3057  * @crt: A certificate of type #gnutls_x509_crt_t
3058  * @url: A PKCS 11 url
3059  * @flags: One of GNUTLS_PKCS11_OBJ_* flags
3060  *
3061  * This function will import a PKCS 11 certificate directly from a token
3062  * without involving the #gnutls_pkcs11_obj_t structure. This function will
3063  * fail if the certificate stored is not of X.509 type.
3064  *
3065  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3066  *   negative error value.
3067  *
3068  * Since: 2.12.0
3069  **/
3070 int
3071 gnutls_x509_crt_import_pkcs11_url(gnutls_x509_crt_t crt,
3072                                   const char *url, unsigned int flags)
3073 {
3074         gnutls_pkcs11_obj_t pcrt;
3075         int ret;
3076
3077         ret = gnutls_pkcs11_obj_init(&pcrt);
3078         if (ret < 0) {
3079                 gnutls_assert();
3080                 return ret;
3081         }
3082
3083         if (crt->pin.cb)
3084                 gnutls_pkcs11_obj_set_pin_function(pcrt, crt->pin.cb,
3085                                                    crt->pin.data);
3086
3087         ret = gnutls_pkcs11_obj_import_url(pcrt, url, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_CERT);
3088         if (ret < 0) {
3089                 gnutls_assert();
3090                 goto cleanup;
3091         }
3092
3093         ret = gnutls_x509_crt_import(crt, &pcrt->raw, GNUTLS_X509_FMT_DER);
3094         if (ret < 0) {
3095                 gnutls_assert();
3096                 goto cleanup;
3097         }
3098
3099         ret = 0;
3100       cleanup:
3101
3102         gnutls_pkcs11_obj_deinit(pcrt);
3103
3104         return ret;
3105 }
3106
3107 /**
3108  * gnutls_x509_crt_import_pkcs11:
3109  * @crt: A certificate of type #gnutls_x509_crt_t
3110  * @pkcs11_crt: A PKCS 11 object that contains a certificate
3111  *
3112  * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t
3113  * structure.
3114  *
3115  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3116  *   negative error value.
3117  *
3118  * Since: 2.12.0
3119  **/
3120 int
3121 gnutls_x509_crt_import_pkcs11(gnutls_x509_crt_t crt,
3122                               gnutls_pkcs11_obj_t pkcs11_crt)
3123 {
3124         return gnutls_x509_crt_import(crt, &pkcs11_crt->raw,
3125                                       GNUTLS_X509_FMT_DER);
3126 }
3127
3128 /**
3129  * gnutls_x509_crt_list_import_pkcs11:
3130  * @certs: A list of certificates of type #gnutls_x509_crt_t
3131  * @cert_max: The maximum size of the list
3132  * @objs: A list of PKCS 11 objects
3133  * @flags: 0 for now
3134  *
3135  * This function will import a PKCS 11 certificate list to a list of 
3136  * #gnutls_x509_crt_t structure. These must not be initialized.
3137  *
3138  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3139  *   negative error value.
3140  *
3141  * Since: 2.12.0
3142  **/
3143 int
3144 gnutls_x509_crt_list_import_pkcs11(gnutls_x509_crt_t * certs,
3145                                    unsigned int cert_max,
3146                                    gnutls_pkcs11_obj_t * const objs,
3147                                    unsigned int flags)
3148 {
3149         unsigned int i, j;
3150         int ret;
3151
3152         for (i = 0; i < cert_max; i++) {
3153                 ret = gnutls_x509_crt_init(&certs[i]);
3154                 if (ret < 0) {
3155                         gnutls_assert();
3156                         goto cleanup;
3157                 }
3158
3159                 ret = gnutls_x509_crt_import_pkcs11(certs[i], objs[i]);
3160                 if (ret < 0) {
3161                         gnutls_assert();
3162                         goto cleanup;
3163                 }
3164         }
3165
3166         return 0;
3167
3168       cleanup:
3169         for (j = 0; j < i; j++) {
3170                 gnutls_x509_crt_deinit(certs[j]);
3171         }
3172
3173         return ret;
3174 }
3175
3176 static int
3177 find_flags_cb(struct pkcs11_session_info *sinfo,
3178            struct token_info *info, struct ck_info *lib_info, void *input)
3179 {
3180         struct find_flags_data_st *find_data = input;
3181
3182         if (info == NULL) {     /* we don't support multiple calls */
3183                 gnutls_assert();
3184                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3185         }
3186
3187         /* do not bother reading the token if basic fields do not match
3188          */
3189         if (!p11_kit_uri_match_token_info(find_data->info, &info->tinfo) ||
3190             !p11_kit_uri_match_module_info(find_data->info, lib_info)) {
3191                 gnutls_assert();
3192                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3193         }
3194
3195         /* found token! */
3196         if (p11_kit_module_get_flags(sinfo->module) & P11_KIT_MODULE_TRUSTED)
3197                 find_data->trusted = 1;
3198         else
3199                 find_data->trusted = 0;
3200         find_data->slot_flags = info->sinfo.flags;
3201
3202         return 0;
3203 }
3204
3205 /**
3206  * gnutls_pkcs11_token_get_flags:
3207  * @url: should contain a PKCS 11 URL
3208  * @flags: The output flags (GNUTLS_PKCS11_TOKEN_*)
3209  *
3210  * This function will return information about the PKCS 11 token flags.
3211  *
3212  * The supported flags are: %GNUTLS_PKCS11_TOKEN_HW and %GNUTLS_PKCS11_TOKEN_TRUSTED.
3213  *
3214  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
3215  *
3216  * Since: 2.12.0
3217  **/
3218 int gnutls_pkcs11_token_get_flags(const char *url, unsigned int *flags)
3219 {
3220         struct find_flags_data_st find_data;
3221         int ret;
3222
3223         PKCS11_CHECK_INIT;
3224
3225         memset(&find_data, 0, sizeof(find_data));
3226         ret = pkcs11_url_to_info(url, &find_data.info, 0);
3227         if (ret < 0) {
3228                 gnutls_assert();
3229                 return ret;
3230         }
3231
3232         ret =
3233             _pkcs11_traverse_tokens(find_flags_cb, &find_data, find_data.info,
3234                                     NULL, 0);
3235         p11_kit_uri_free(find_data.info);
3236
3237         if (ret < 0) {
3238                 gnutls_assert();
3239                 return ret;
3240         }
3241
3242         *flags = 0;
3243         if (find_data.slot_flags & CKF_HW_SLOT)
3244                 *flags |= GNUTLS_PKCS11_TOKEN_HW;
3245
3246         if (find_data.trusted != 0)
3247                 *flags |= GNUTLS_PKCS11_TOKEN_TRUSTED;
3248
3249         return 0;
3250
3251 }
3252
3253 /**
3254  * gnutls_pkcs11_token_get_mechanism:
3255  * @url: should contain a PKCS 11 URL
3256  * @idx: The index of the mechanism
3257  * @mechanism: The PKCS #11 mechanism ID
3258  *
3259  * This function will return the names of the supported mechanisms
3260  * by the token. It should be called with an increasing index until
3261  * it return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
3262  *
3263  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
3264  *
3265  * Since: 2.12.0
3266  **/
3267 int
3268 gnutls_pkcs11_token_get_mechanism(const char *url, unsigned int idx,
3269                                   unsigned long *mechanism)
3270 {
3271         int ret;
3272         ck_rv_t rv;
3273         struct ck_function_list *module;
3274         ck_slot_id_t slot;
3275         struct token_info tinfo;
3276         struct p11_kit_uri *info = NULL;
3277         unsigned long count;
3278         ck_mechanism_type_t mlist[400];
3279
3280         PKCS11_CHECK_INIT;
3281
3282         ret = pkcs11_url_to_info(url, &info, 0);
3283         if (ret < 0) {
3284                 gnutls_assert();
3285                 return ret;
3286         }
3287
3288         ret = pkcs11_find_slot(&module, &slot, info, &tinfo);
3289         p11_kit_uri_free(info);
3290
3291         if (ret < 0) {
3292                 gnutls_assert();
3293                 return ret;
3294         }
3295
3296         count = sizeof(mlist) / sizeof(mlist[0]);
3297         rv = pkcs11_get_mechanism_list(module, slot, mlist, &count);
3298         if (rv != CKR_OK) {
3299                 gnutls_assert();
3300                 return pkcs11_rv_to_err(rv);
3301         }
3302
3303         if (idx >= count) {
3304                 gnutls_assert();
3305                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3306         }
3307
3308         *mechanism = mlist[idx];
3309
3310         return 0;
3311
3312 }
3313
3314 /**
3315  * gnutls_pkcs11_type_get_name:
3316  * @type: Holds the PKCS 11 object type, a #gnutls_pkcs11_obj_type_t.
3317  *
3318  * This function will return a human readable description of the
3319  * PKCS11 object type @obj.  It will return "Unknown" for unknown
3320  * types.
3321  *
3322  * Returns: human readable string labeling the PKCS11 object type
3323  * @type.
3324  *
3325  * Since: 2.12.0
3326  **/
3327 const char *gnutls_pkcs11_type_get_name(gnutls_pkcs11_obj_type_t type)
3328 {
3329         switch (type) {
3330         case GNUTLS_PKCS11_OBJ_X509_CRT:
3331                 return "X.509 Certificate";
3332         case GNUTLS_PKCS11_OBJ_PUBKEY:
3333                 return "Public key";
3334         case GNUTLS_PKCS11_OBJ_PRIVKEY:
3335                 return "Private key";
3336         case GNUTLS_PKCS11_OBJ_SECRET_KEY:
3337                 return "Secret key";
3338         case GNUTLS_PKCS11_OBJ_DATA:
3339                 return "Data";
3340         case GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION:
3341                 return "X.509 certificate extension";
3342         case GNUTLS_PKCS11_OBJ_UNKNOWN:
3343         default:
3344                 return "Unknown";
3345         }
3346 }
3347
3348 static
3349 int check_found_cert(struct find_cert_st *priv, gnutls_datum_t *data, time_t now)
3350 {
3351         gnutls_x509_crt_t tcrt = NULL;
3352         int ret;
3353
3354         ret = gnutls_x509_crt_init(&tcrt);
3355         if (ret < 0) {
3356                 gnutls_assert();
3357                 return ret;
3358         }
3359
3360         ret = gnutls_x509_crt_import(tcrt, data, GNUTLS_X509_FMT_DER);
3361         if (ret < 0) {
3362                 gnutls_assert();
3363                 goto cleanup;
3364         }
3365
3366         if (priv->key_id.size > 0 &&
3367             !_gnutls_check_valid_key_id(&priv->key_id, tcrt, now)) {
3368                 gnutls_assert();
3369                 ret = -1;
3370                 goto cleanup;
3371         }
3372
3373         if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE) {
3374                 if (priv->crt == NULL) {
3375                         gnutls_assert();
3376                         ret = -1;
3377                         goto cleanup;
3378                 }
3379
3380                 if (_gnutls_check_if_same_cert(priv->crt, tcrt) == 0) {
3381                         /* doesn't match */
3382                         ret = -1;
3383                         goto cleanup;
3384                 }
3385         }
3386
3387         if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY) {
3388                 if (priv->crt == NULL) {
3389                         gnutls_assert();
3390                         ret = -1;
3391                         goto cleanup;
3392                 }
3393
3394                 if (_gnutls_check_if_same_key(priv->crt, tcrt, 1) == 0) {
3395                         /* doesn't match */
3396                         ret = -1;
3397                         goto cleanup;
3398                 }
3399         }
3400
3401         ret = 0;
3402 cleanup:
3403         if (tcrt != NULL)
3404                 gnutls_x509_crt_deinit(tcrt);
3405         return ret;
3406 }
3407
3408 static int
3409 find_cert_cb(struct pkcs11_session_info *sinfo,
3410             struct token_info *info, struct ck_info *lib_info, void *input)
3411 {
3412         struct ck_attribute a[10];
3413         ck_object_class_t class = -1;
3414         ck_certificate_type_t type = (ck_certificate_type_t) - 1;
3415         ck_rv_t rv;
3416         ck_object_handle_t obj;
3417         unsigned long count, a_vals;
3418         int found = 0, ret;
3419         struct find_cert_st *priv = input;
3420         char label_tmp[PKCS11_LABEL_SIZE];
3421         char id_tmp[PKCS11_ID_SIZE];
3422         gnutls_datum_t data = {NULL, 0};
3423         unsigned tries, i, finalized;
3424         ck_bool_t trusted = 1;
3425         time_t now;
3426         gnutls_datum_t label = {NULL,0}, id = {NULL,0};
3427
3428         if (info == NULL) {
3429                 gnutls_assert();
3430                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3431         }
3432
3433         /* the DISTRUSTED flag is p11-kit module specific */
3434         if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) {
3435                 if (memcmp(lib_info->manufacturer_id, "PKCS#11 Kit", 11) != 0) {
3436                         gnutls_assert();
3437                         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3438                 }
3439         }
3440
3441         if (priv->dn.size == 0 && priv->key_id.size == 0 && priv->issuer_dn.size == 0 &&
3442                 priv->serial.size == 0)
3443                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
3444
3445         /* Find objects with given class and type */
3446
3447         if (priv->key_id.size > 0 && priv->dn.size > 0)
3448                 tries = 2;
3449         else
3450                 tries = 1;
3451
3452         now = gnutls_time(0);
3453         for (i = 0; i < tries; i++) {
3454
3455                 a_vals = 0;
3456                 class = CKO_CERTIFICATE;
3457                 a[a_vals].type = CKA_CLASS;
3458                 a[a_vals].value = &class;
3459                 a[a_vals].value_len = sizeof class;
3460                 a_vals++;
3461
3462                 if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED) {
3463                         a[a_vals].type = CKA_TRUSTED;
3464                         a[a_vals].value = &trusted;
3465                         a[a_vals].value_len = sizeof trusted;
3466                         a_vals++;
3467                 }
3468
3469                 if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) {
3470                         a[a_vals].type = CKA_X_DISTRUSTED;
3471                         a[a_vals].value = &trusted;
3472                         a[a_vals].value_len = sizeof trusted;
3473                         a_vals++;
3474                 }
3475
3476                 if (priv->need_import != 0) {
3477                         type = CKC_X_509;
3478                         a[a_vals].type = CKA_CERTIFICATE_TYPE;
3479                         a[a_vals].value = &type;
3480                         a[a_vals].value_len = sizeof type;
3481                         a_vals++;
3482                 }
3483
3484                 if (i == 0 && priv->key_id.size > 0) {
3485                         a[a_vals].type = CKA_ID;
3486                         a[a_vals].value = priv->key_id.data;
3487                         a[a_vals].value_len = priv->key_id.size;
3488                         a_vals++;
3489                 }
3490
3491                 if (priv->dn.size > 0) {
3492                         a[a_vals].type = CKA_SUBJECT;
3493                         a[a_vals].value = priv->dn.data;
3494                         a[a_vals].value_len = priv->dn.size;
3495                         a_vals++;
3496                 }
3497
3498                 if (priv->serial.size > 0) {
3499                         a[a_vals].type = CKA_SERIAL_NUMBER;
3500                         a[a_vals].value = priv->serial.data;
3501                         a[a_vals].value_len = priv->serial.size;
3502                         a_vals++;
3503                 }
3504
3505                 if (priv->issuer_dn.size > 0) {
3506                         a[a_vals].type = CKA_ISSUER;
3507                         a[a_vals].value = priv->issuer_dn.data;
3508                         a[a_vals].value_len = priv->issuer_dn.size;
3509                         a_vals++;
3510                 }
3511
3512                 finalized = 0;
3513                 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
3514                                               a_vals);
3515                 if (rv != CKR_OK) {
3516                         gnutls_assert();
3517                         _gnutls_debug_log
3518                             ("p11: FindObjectsInit failed.\n");
3519                         ret = pkcs11_rv_to_err(rv);
3520                         goto cleanup;
3521                 }
3522
3523                 while (pkcs11_find_objects
3524                        (sinfo->module, sinfo->pks, &obj, 1,
3525                         &count) == CKR_OK && count == 1) {
3526
3527                         if (priv->need_import == 0 && !(priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE)
3528                             && !(priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY)) {
3529                                 found = 1;
3530                                 break;
3531                         }
3532
3533                         /* data will contain the certificate */
3534                         rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, obj, CKA_VALUE, &data);
3535
3536                         if (rv == CKR_OK) {
3537                                 ret = check_found_cert(priv, &data, now);
3538                                 if (ret < 0) {
3539                                         _gnutls_free_datum(&data);
3540                                         continue;
3541                                 }
3542
3543                                 a[0].type = CKA_LABEL;
3544                                 a[0].value = label_tmp;
3545                                 a[0].value_len = sizeof(label_tmp);
3546
3547                                 a[1].type = CKA_ID;
3548                                 a[1].value = id_tmp;
3549                                 a[1].value_len = sizeof(id_tmp);
3550
3551                                 if (pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 2) == CKR_OK) {
3552                                         label.data = a[0].value;
3553                                         label.size = a[0].value_len;
3554                                         id.data = a[1].value;
3555                                         id.size = a[1].value_len;
3556
3557                                         found = 1;
3558                                         break;
3559                                 } else {
3560                                         _gnutls_free_datum(&data);
3561                                         _gnutls_debug_log
3562                                             ("p11: Skipped cert, missing attrs.\n");
3563                                 }
3564                         }
3565                 }
3566
3567                 pkcs11_find_objects_final(sinfo);
3568                 finalized = 1;
3569
3570                 if (found != 0) {
3571                         if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT && data.size > 0) {
3572                                 gnutls_datum_t spki;
3573                                 rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, obj, CKA_PUBLIC_KEY_INFO, &spki);
3574                                 if (rv == CKR_OK) {
3575                                         ret = pkcs11_override_cert_exts(sinfo, &spki, &data);
3576                                         gnutls_free(spki.data);
3577                                         if (ret < 0) {
3578                                                 gnutls_assert();
3579                                                 goto cleanup;
3580                                         }
3581                                 }
3582                         }
3583
3584                         if (priv->need_import != 0) {
3585                                 ret =
3586                                     pkcs11_obj_import(class, priv->obj,
3587                                                       &data, &id, &label,
3588                                                       &info->tinfo,
3589                                                       lib_info);
3590                                 if (ret < 0) {
3591                                         gnutls_assert();
3592                                         goto cleanup;
3593                                 }
3594                         }
3595                         break;
3596                 }
3597         }
3598
3599         if (found == 0) {
3600                 gnutls_assert();
3601                 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3602         } else {
3603                 ret = 0;
3604         }
3605
3606       cleanup:
3607         gnutls_free(data.data);
3608         if (finalized == 0)
3609                 pkcs11_find_objects_final(sinfo);
3610
3611         return ret;
3612 }
3613
3614 /**
3615  * gnutls_pkcs11_get_raw_issuer:
3616  * @url: A PKCS 11 url identifying a token
3617  * @cert: is the certificate to find issuer for
3618  * @issuer: Will hold the issuer if any in an allocated buffer.
3619  * @fmt: The format of the exported issuer.
3620  * @flags: Use zero or flags from %GNUTLS_PKCS11_OBJ_FLAG.
3621  *
3622  * This function will return the issuer of a given certificate, if it
3623  * is stored in the token. By default only marked as trusted issuers
3624  * are retuned. If any issuer should be returned specify
3625  * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY in @flags.
3626  *
3627  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3628  *   negative error value.
3629  *
3630  * Since: 3.2.7
3631  **/
3632 int gnutls_pkcs11_get_raw_issuer(const char *url, gnutls_x509_crt_t cert,
3633                                  gnutls_datum_t * issuer,
3634                                  gnutls_x509_crt_fmt_t fmt,
3635                                  unsigned int flags)
3636 {
3637         int ret;
3638         struct find_cert_st priv;
3639         uint8_t id[PKCS11_ID_SIZE];
3640         size_t id_size;
3641         struct p11_kit_uri *info = NULL;
3642
3643         PKCS11_CHECK_INIT;
3644
3645         memset(&priv, 0, sizeof(priv));
3646
3647         if (url == NULL || url[0] == 0) {
3648                 url = "pkcs11:";
3649         }
3650
3651         ret = pkcs11_url_to_info(url, &info, flags);
3652         if (ret < 0) {
3653                 gnutls_assert();
3654                 return ret;
3655         }
3656
3657         id_size = sizeof(id);
3658         ret =
3659             gnutls_x509_crt_get_authority_key_id(cert, id, &id_size, NULL);
3660         if (ret >= 0) {
3661                 priv.key_id.data = id;
3662                 priv.key_id.size = id_size;
3663         }
3664
3665         priv.dn.data = cert->raw_issuer_dn.data;
3666         priv.dn.size = cert->raw_issuer_dn.size;
3667
3668         if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY))
3669                 flags |= GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED;
3670
3671         priv.flags = flags;
3672
3673         ret = gnutls_pkcs11_obj_init(&priv.obj);
3674         if (ret < 0) {
3675                 gnutls_assert();
3676                 goto cleanup;
3677         }
3678         priv.need_import = 1;
3679
3680         ret =
3681             _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
3682                                     NULL, pkcs11_obj_flags_to_int(flags));
3683         if (ret < 0) {
3684                 gnutls_assert();
3685                 goto cleanup;
3686         }
3687
3688         ret = gnutls_pkcs11_obj_export3(priv.obj, fmt, issuer);
3689         if (ret < 0) {
3690                 gnutls_assert();
3691                 goto cleanup;
3692         }
3693
3694         ret = 0;
3695
3696       cleanup:
3697         if (priv.obj)
3698                 gnutls_pkcs11_obj_deinit(priv.obj);
3699         if (info)
3700                 p11_kit_uri_free(info);
3701
3702         return ret;
3703 }
3704
3705 /**
3706  * gnutls_pkcs11_crt_is_known:
3707  * @url: A PKCS 11 url identifying a token
3708  * @cert: is the certificate to find issuer for
3709  * @issuer: Will hold the issuer if any in an allocated buffer.
3710  * @fmt: The format of the exported issuer.
3711  * @flags: Use zero or flags from %GNUTLS_PKCS11_OBJ_FLAG.
3712  *
3713  * This function will check whether the provided certificate is stored
3714  * in the specified token. This is useful in combination with 
3715  * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED or
3716  * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED,
3717  * to check whether a CA is present or a certificate is blacklisted in
3718  * a trust PKCS #11 module.
3719  *
3720  * This function can be used with a @url of "pkcs11:", and in that case all modules
3721  * will be searched. To restrict the modules to the marked as trusted in p11-kit
3722  * use the %GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE flag.
3723  *
3724  * Note that the flag %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED is
3725  * specific to p11-kit trust modules.
3726  *
3727  * Returns: If the certificate exists non-zero is returned, otherwise zero.
3728  *
3729  * Since: 3.3.0
3730  **/
3731 int gnutls_pkcs11_crt_is_known(const char *url, gnutls_x509_crt_t cert,
3732                                  unsigned int flags)
3733 {
3734         int ret;
3735         struct find_cert_st priv;
3736         uint8_t serial[128];
3737         size_t serial_size;
3738         struct p11_kit_uri *info = NULL;
3739
3740         PKCS11_CHECK_INIT_RET(0);
3741
3742         memset(&priv, 0, sizeof(priv));
3743
3744         if (url == NULL || url[0] == 0) {
3745                 url = "pkcs11:";
3746         }
3747
3748         ret = pkcs11_url_to_info(url, &info, 0);
3749         if (ret < 0) {
3750                 gnutls_assert();
3751                 return 0;
3752         }
3753
3754         /* Attempt searching using the issuer DN + serial number */
3755         serial_size = sizeof(serial);
3756         ret =
3757             gnutls_x509_crt_get_serial(cert, serial, &serial_size);
3758         if (ret < 0) {
3759                 gnutls_assert();
3760                 ret = 0;
3761                 goto cleanup;
3762         }
3763
3764         ret = _gnutls_x509_ext_gen_number(serial, serial_size, &priv.serial);
3765         if (ret < 0) {
3766                 gnutls_assert();
3767                 ret = 0;
3768                 goto cleanup;
3769         }
3770
3771         priv.crt = cert;
3772
3773         priv.issuer_dn.data = cert->raw_issuer_dn.data;
3774         priv.issuer_dn.size = cert->raw_issuer_dn.size;
3775
3776         /* assume PKCS11_OBJ_FLAG_COMPARE everywhere but DISTRUST info */
3777         if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) && !(flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY)) {
3778                 flags |= GNUTLS_PKCS11_OBJ_FLAG_COMPARE;
3779         }
3780
3781         priv.flags = flags;
3782
3783         ret =
3784             _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
3785                                     NULL, pkcs11_obj_flags_to_int(flags));
3786         if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
3787                 _gnutls_debug_log("crt_is_known: did not find cert, using issuer DN + serial, using DN only\n");
3788                 /* attempt searching with the subject DN only */
3789                 gnutls_assert();
3790                 gnutls_free(priv.serial.data);
3791                 memset(&priv, 0, sizeof(priv));
3792                 priv.crt = cert;
3793                 priv.flags = flags;
3794
3795                 priv.dn.data = cert->raw_dn.data;
3796                 priv.dn.size = cert->raw_dn.size;
3797                 ret =
3798                     _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
3799                                     NULL, pkcs11_obj_flags_to_int(flags));
3800         }
3801         if (ret < 0) {
3802                 gnutls_assert();
3803                 _gnutls_debug_log("crt_is_known: did not find any cert\n");
3804                 ret = 0;
3805                 goto cleanup;
3806         }
3807
3808         ret = 1;
3809
3810       cleanup:
3811         if (info)
3812                 p11_kit_uri_free(info);
3813         gnutls_free(priv.serial.data);
3814
3815         return ret;
3816 }
3817
3818 /**
3819  * gnutls_pkcs11_obj_get_flags:
3820  * @obj: The structure that holds the object
3821  * @oflags: Will hold the output flags
3822  *
3823  * This function will return the flags of the object being
3824  * stored in the structure. The @oflags are the %GNUTLS_PKCS11_OBJ_FLAG_MARK
3825  * flags.
3826  *
3827  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3828  *   negative error value.
3829  *
3830  * Since: 3.3.7
3831  **/
3832 int
3833 gnutls_pkcs11_obj_get_flags(gnutls_pkcs11_obj_t obj, unsigned int *oflags)
3834 {
3835         *oflags = obj->flags;
3836
3837         return 0;
3838 }
3839
3840 /**
3841  * gnutls_pkcs11_obj_flags_get_str:
3842  * @flags: holds the flags
3843  *
3844  * This function given an or-sequence of %GNUTLS_PKCS11_OBJ_FLAG_MARK,
3845  * will return an allocated string with its description. The string
3846  * needs to be deallocated using gnutls_free().
3847  *
3848  * Returns: If flags is zero %NULL is returned, otherwise an allocated string.
3849  *
3850  * Since: 3.3.7
3851  **/
3852 char *gnutls_pkcs11_obj_flags_get_str(unsigned int flags)
3853 {
3854         gnutls_buffer_st str;
3855         gnutls_datum_t out;
3856         int ret;
3857
3858         if (flags == 0)
3859                 return NULL;
3860
3861         _gnutls_buffer_init(&str);
3862         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP)
3863                 _gnutls_buffer_append_str(&str, "CKA_WRAP/UNWRAP; ");
3864
3865         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA)
3866                 _gnutls_buffer_append_str(&str, "CKA_CERTIFICATE_CATEGORY=CA; ");
3867
3868         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE)
3869                 _gnutls_buffer_append_str(&str, "CKA_PRIVATE; ");
3870
3871         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED)
3872                 _gnutls_buffer_append_str(&str, "CKA_TRUSTED; ");
3873
3874         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
3875                 _gnutls_buffer_append_str(&str, "CKA_SENSITIVE; ");
3876
3877         ret = _gnutls_buffer_to_datum(&str, &out);
3878         if (ret < 0) {
3879                 gnutls_assert();
3880                 goto fail;
3881         }
3882
3883         return (char*)out.data;
3884 fail:
3885         return NULL;
3886
3887 }