benchmark time was increased.
[gnutls.git] / lib / pkcs11.c
blob48dcd035edcb60b9f61fc0564669278fef7afa54
1 /*
2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4 * Copyright (C) 2008, Joe Orton <joe@manyfish.co.uk>
5 *
6 * Authors: Nikos Mavrogiannopoulos, Stef Walter
8 * Inspired and some parts (pkcs11_login) based on neon PKCS #11 support
9 * by Joe Orton. More ideas came from the pkcs11-helper library by
10 * Alon Bar-Lev.
12 * The GnuTLS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 3 of
15 * the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>
26 #include <gnutls_int.h>
27 #include <gnutls/pkcs11.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <gnutls_errors.h>
31 #include <gnutls_datum.h>
33 #include <pin.h>
34 #include <pkcs11_int.h>
35 #include <p11-kit/p11-kit.h>
36 #include <p11-kit/pin.h>
38 #define MAX_PROVIDERS 16
40 /* XXX: try to eliminate this */
41 #define MAX_CERT_SIZE 8*1024
43 struct gnutls_pkcs11_provider_s
45 struct ck_function_list *module;
46 unsigned long nslots;
47 ck_slot_id_t *slots;
48 struct ck_info info;
49 unsigned int initialized;
52 struct flags_find_data_st
54 struct p11_kit_uri *info;
55 unsigned int slot_flags;
58 struct url_find_data_st
60 gnutls_pkcs11_obj_t crt;
63 struct crt_find_data_st
65 gnutls_pkcs11_obj_t *p_list;
66 unsigned int *n_list;
67 unsigned int current;
68 gnutls_pkcs11_obj_attr_t flags;
69 struct p11_kit_uri *info;
73 static struct gnutls_pkcs11_provider_s providers[MAX_PROVIDERS];
74 static unsigned int active_providers = 0;
75 static unsigned int initialized_registered = 0;
77 gnutls_pkcs11_token_callback_t _gnutls_token_func;
78 void *_gnutls_token_data;
80 int
81 pkcs11_rv_to_err (ck_rv_t rv)
83 switch (rv)
85 case CKR_OK:
86 return 0;
87 case CKR_HOST_MEMORY:
88 return GNUTLS_E_MEMORY_ERROR;
89 case CKR_SLOT_ID_INVALID:
90 return GNUTLS_E_PKCS11_SLOT_ERROR;
91 case CKR_ARGUMENTS_BAD:
92 case CKR_MECHANISM_PARAM_INVALID:
93 return GNUTLS_E_INVALID_REQUEST;
94 case CKR_NEED_TO_CREATE_THREADS:
95 case CKR_CANT_LOCK:
96 case CKR_FUNCTION_NOT_PARALLEL:
97 case CKR_MUTEX_BAD:
98 case CKR_MUTEX_NOT_LOCKED:
99 return GNUTLS_E_LOCKING_ERROR;
100 case CKR_ATTRIBUTE_READ_ONLY:
101 case CKR_ATTRIBUTE_SENSITIVE:
102 case CKR_ATTRIBUTE_TYPE_INVALID:
103 case CKR_ATTRIBUTE_VALUE_INVALID:
104 return GNUTLS_E_PKCS11_ATTRIBUTE_ERROR;
105 case CKR_DEVICE_ERROR:
106 case CKR_DEVICE_MEMORY:
107 case CKR_DEVICE_REMOVED:
108 return GNUTLS_E_PKCS11_DEVICE_ERROR;
109 case CKR_DATA_INVALID:
110 case CKR_DATA_LEN_RANGE:
111 case CKR_ENCRYPTED_DATA_INVALID:
112 case CKR_ENCRYPTED_DATA_LEN_RANGE:
113 case CKR_OBJECT_HANDLE_INVALID:
114 return GNUTLS_E_PKCS11_DATA_ERROR;
115 case CKR_FUNCTION_NOT_SUPPORTED:
116 case CKR_MECHANISM_INVALID:
117 return GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR;
118 case CKR_KEY_HANDLE_INVALID:
119 case CKR_KEY_SIZE_RANGE:
120 case CKR_KEY_TYPE_INCONSISTENT:
121 case CKR_KEY_NOT_NEEDED:
122 case CKR_KEY_CHANGED:
123 case CKR_KEY_NEEDED:
124 case CKR_KEY_INDIGESTIBLE:
125 case CKR_KEY_FUNCTION_NOT_PERMITTED:
126 case CKR_KEY_NOT_WRAPPABLE:
127 case CKR_KEY_UNEXTRACTABLE:
128 return GNUTLS_E_PKCS11_KEY_ERROR;
129 case CKR_PIN_INCORRECT:
130 case CKR_PIN_INVALID:
131 case CKR_PIN_LEN_RANGE:
132 return GNUTLS_E_PKCS11_PIN_ERROR;
133 case CKR_PIN_EXPIRED:
134 return GNUTLS_E_PKCS11_PIN_EXPIRED;
135 case CKR_PIN_LOCKED:
136 return GNUTLS_E_PKCS11_PIN_LOCKED;
137 case CKR_SESSION_CLOSED:
138 case CKR_SESSION_COUNT:
139 case CKR_SESSION_HANDLE_INVALID:
140 case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
141 case CKR_SESSION_READ_ONLY:
142 case CKR_SESSION_EXISTS:
143 case CKR_SESSION_READ_ONLY_EXISTS:
144 case CKR_SESSION_READ_WRITE_SO_EXISTS:
145 return GNUTLS_E_PKCS11_SESSION_ERROR;
146 case CKR_SIGNATURE_INVALID:
147 case CKR_SIGNATURE_LEN_RANGE:
148 return GNUTLS_E_PKCS11_SIGNATURE_ERROR;
149 case CKR_TOKEN_NOT_PRESENT:
150 case CKR_TOKEN_NOT_RECOGNIZED:
151 case CKR_TOKEN_WRITE_PROTECTED:
152 return GNUTLS_E_PKCS11_TOKEN_ERROR;
153 case CKR_USER_ALREADY_LOGGED_IN:
154 case CKR_USER_NOT_LOGGED_IN:
155 case CKR_USER_PIN_NOT_INITIALIZED:
156 case CKR_USER_TYPE_INVALID:
157 case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
158 case CKR_USER_TOO_MANY_TYPES:
159 return GNUTLS_E_PKCS11_USER_ERROR;
160 case CKR_BUFFER_TOO_SMALL:
161 return GNUTLS_E_SHORT_MEMORY_BUFFER;
162 default:
163 return GNUTLS_E_PKCS11_ERROR;
167 /* Fake scan */
168 void
169 pkcs11_rescan_slots (void)
171 unsigned long slots;
173 pkcs11_get_slot_list (providers[active_providers - 1].module, 0,
174 NULL, &slots);
177 static int
178 pkcs11_add_module (const char *name, struct ck_function_list *module)
180 struct ck_info info;
181 unsigned int i;
183 if (active_providers >= MAX_PROVIDERS)
185 gnutls_assert ();
186 return GNUTLS_E_CONSTRAINT_ERROR;
189 /* initially check if this module is a duplicate */
190 memset(&info, 0, sizeof(info));
191 pkcs11_get_module_info (module, &info);
192 for (i=0;i<active_providers;i++)
194 /* already loaded, skip the rest */
195 if (memcmp(&info, &providers[i].info, sizeof(info)) == 0)
197 _gnutls_debug_log("%s is already loaded.\n", name);
198 return GNUTLS_E_INT_RET_0;
202 active_providers++;
203 providers[active_providers - 1].module = module;
205 /* cache the number of slots in this module */
206 if (pkcs11_get_slot_list
207 (providers[active_providers - 1].module, 0, NULL,
208 &providers[active_providers - 1].nslots) != CKR_OK)
210 gnutls_assert ();
211 goto fail;
214 providers[active_providers - 1].slots =
215 gnutls_malloc (sizeof (*providers[active_providers - 1].slots) *
216 providers[active_providers - 1].nslots);
217 if (providers[active_providers - 1].slots == NULL)
219 gnutls_assert ();
220 goto fail;
223 if (pkcs11_get_slot_list
224 (providers[active_providers - 1].module, 0,
225 providers[active_providers - 1].slots,
226 &providers[active_providers - 1].nslots) != CKR_OK)
228 gnutls_assert ();
229 gnutls_free (providers[active_providers - 1].slots);
230 goto fail;
233 memcpy (&providers[active_providers - 1].info, &info, sizeof(info));
235 _gnutls_debug_log ("p11: loaded provider '%s' with %d slots\n",
236 name, (int) providers[active_providers - 1].nslots);
238 return 0;
240 fail:
241 active_providers--;
242 return GNUTLS_E_PKCS11_LOAD_ERROR;
247 * gnutls_pkcs11_add_provider:
248 * @name: The filename of the module
249 * @params: should be NULL
251 * This function will load and add a PKCS 11 module to the module
252 * list used in gnutls. After this function is called the module will
253 * be used for PKCS 11 operations.
255 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
256 * negative error value.
258 * Since: 2.12.0
261 gnutls_pkcs11_add_provider (const char *name, const char *params)
263 struct ck_function_list *module;
264 int ret;
266 active_providers++;
267 if (p11_kit_load_initialize_module (name, &module) != CKR_OK)
269 gnutls_assert ();
270 _gnutls_debug_log ("p11: Cannot load provider %s\n", name);
271 active_providers--;
272 return GNUTLS_E_PKCS11_LOAD_ERROR;
275 ret = pkcs11_add_module (name, module);
276 if (ret == 0)
278 /* Mark this one as having been separately initialized */
279 providers[active_providers - 1].initialized = 1;
281 else
283 if (ret == GNUTLS_E_INT_RET_0) ret = 0;
284 p11_kit_finalize_module (module);
285 gnutls_assert ();
288 return ret;
293 * gnutls_pkcs11_obj_get_info:
294 * @crt: should contain a #gnutls_pkcs11_obj_t structure
295 * @itype: Denotes the type of information requested
296 * @output: where output will be stored
297 * @output_size: contains the maximum size of the output and will be overwritten with actual
299 * This function will return information about the PKCS11 certificate
300 * such as the label, id as well as token information where the key is
301 * stored. When output is text it returns null terminated string
302 * although @output_size contains the size of the actual data only.
304 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
306 * Since: 2.12.0
309 gnutls_pkcs11_obj_get_info (gnutls_pkcs11_obj_t crt,
310 gnutls_pkcs11_obj_info_t itype,
311 void *output, size_t * output_size)
313 return pkcs11_get_info (crt->info, itype, output, output_size);
317 pkcs11_get_info (struct p11_kit_uri *info,
318 gnutls_pkcs11_obj_info_t itype, void *output,
319 size_t * output_size)
321 struct ck_attribute *attr = NULL;
322 struct ck_version *version = NULL;
323 const uint8_t *str = NULL;
324 size_t str_max = 0;
325 int terminate = 0;
326 int hexify = 0;
327 size_t length = 0;
328 const char *data = NULL;
329 char buf[32];
332 * Either attr, str or version is valid by the time switch
333 * finishes
336 switch (itype)
338 case GNUTLS_PKCS11_OBJ_ID:
339 attr = p11_kit_uri_get_attribute (info, CKA_ID);
340 break;
341 case GNUTLS_PKCS11_OBJ_ID_HEX:
342 attr = p11_kit_uri_get_attribute (info, CKA_ID);
343 hexify = 1;
344 terminate = 1;
345 break;
346 case GNUTLS_PKCS11_OBJ_LABEL:
347 attr = p11_kit_uri_get_attribute (info, CKA_LABEL);
348 terminate = 1;
349 break;
350 case GNUTLS_PKCS11_OBJ_TOKEN_LABEL:
351 str = p11_kit_uri_get_token_info (info)->label;
352 str_max = 32;
353 break;
354 case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL:
355 str = p11_kit_uri_get_token_info (info)->serial_number;
356 str_max = 16;
357 break;
358 case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER:
359 str = p11_kit_uri_get_token_info (info)->manufacturer_id;
360 str_max = 32;
361 break;
362 case GNUTLS_PKCS11_OBJ_TOKEN_MODEL:
363 str = p11_kit_uri_get_token_info (info)->model;
364 str_max = 16;
365 break;
366 case GNUTLS_PKCS11_OBJ_LIBRARY_DESCRIPTION:
367 str = p11_kit_uri_get_module_info (info)->library_description;
368 str_max = 32;
369 break;
370 case GNUTLS_PKCS11_OBJ_LIBRARY_VERSION:
371 version = &p11_kit_uri_get_module_info (info)->library_version;
372 break;
373 case GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER:
374 str = p11_kit_uri_get_module_info (info)->manufacturer_id;
375 str_max = 32;
376 break;
377 default:
378 gnutls_assert ();
379 return GNUTLS_E_INVALID_REQUEST;
382 if (attr != NULL)
384 data = attr->value;
385 length = attr->value_len;
387 else if (str != NULL)
389 data = (void*)str;
390 length = p11_kit_space_strlen (str, str_max);
391 terminate = 1;
393 else if (version != NULL)
395 data = buf;
396 length = snprintf (buf, sizeof (buf), "%d.%d", (int)version->major,
397 (int)version->minor);
398 terminate = 1;
400 else
402 *output_size = 0;
403 if (output) ((uint8_t*)output)[0] = 0;
404 return 0;
407 if (hexify)
409 /* terminate is assumed with hexify */
410 if (*output_size < length * 3)
412 *output_size = length * 3;
413 return GNUTLS_E_SHORT_MEMORY_BUFFER;
415 if (output)
416 _gnutls_bin2hex (data, length, output, *output_size, ":");
417 *output_size = length * 3;
418 return 0;
420 else
422 if (*output_size < length + terminate)
424 *output_size = length + terminate;
425 return GNUTLS_E_SHORT_MEMORY_BUFFER;
427 if (output)
429 memcpy (output, data, length);
430 if (terminate)
431 ((unsigned char*)output)[length] = '\0';
433 *output_size = length + terminate;
436 return 0;
439 static int init = 0;
441 /* tries to load modules from /etc/gnutls/pkcs11.conf if it exists
443 static void _pkcs11_compat_init(const char* configfile)
445 FILE *fp;
446 int ret;
447 char line[512];
448 const char *library;
450 if (configfile == NULL)
451 configfile = "/etc/gnutls/pkcs11.conf";
453 fp = fopen (configfile, "r");
454 if (fp == NULL)
456 gnutls_assert ();
457 return;
460 _gnutls_debug_log ("Loading PKCS #11 libraries from %s\n", configfile);
461 while (fgets (line, sizeof (line), fp) != NULL)
463 if (strncmp (line, "load", sizeof ("load") - 1) == 0)
465 char *p;
466 p = strchr (line, '=');
467 if (p == NULL)
468 continue;
470 library = ++p;
471 p = strchr (line, '\n');
472 if (p != NULL)
473 *p = 0;
475 ret = gnutls_pkcs11_add_provider (library, NULL);
476 if (ret < 0)
478 gnutls_assert ();
479 _gnutls_debug_log ("Cannot load provider: %s\n", library);
480 continue;
484 fclose(fp);
486 return;
489 static int
490 initialize_automatic_p11_kit (void)
492 struct ck_function_list **modules;
493 char *name;
494 ck_rv_t rv;
495 int i, ret;
497 rv = p11_kit_initialize_registered ();
498 if (rv != CKR_OK)
500 gnutls_assert ();
501 _gnutls_debug_log ("Cannot initialize registered module: %s\n",
502 p11_kit_strerror (rv));
503 return GNUTLS_E_INTERNAL_ERROR;
506 initialized_registered = 1;
508 modules = p11_kit_registered_modules ();
509 for (i = 0; modules[i] != NULL; i++)
511 name = p11_kit_registered_module_to_name (modules[i]);
512 ret = pkcs11_add_module (name, modules[i]);
513 if (ret != 0 && ret != GNUTLS_E_INT_RET_0)
515 gnutls_assert ();
516 _gnutls_debug_log ("Cannot add registered module: %s\n", name);
518 free(name);
521 free (modules);
522 return 0;
526 * gnutls_pkcs11_init:
527 * @flags: %GNUTLS_PKCS11_FLAG_MANUAL or %GNUTLS_PKCS11_FLAG_AUTO
528 * @deprecated_config_file: either NULL or the location of a deprecated
529 * configuration file
531 * This function will initialize the PKCS 11 subsystem in gnutls. It will
532 * read configuration files if %GNUTLS_PKCS11_FLAG_AUTO is used or allow
533 * you to independently load PKCS 11 modules using gnutls_pkcs11_add_provider()
534 * if %GNUTLS_PKCS11_FLAG_MANUAL is specified.
536 * Normally you don't need to call this function since it is being called
537 * by gnutls_global_init() using the %GNUTLS_PKCS11_FLAG_AUTO. If other option
538 * is required then it must be called before it.
540 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
541 * negative error value.
543 * Since: 2.12.0
546 gnutls_pkcs11_init (unsigned int flags, const char *deprecated_config_file)
548 int ret = 0;
550 if (init != 0)
552 init++;
553 return 0;
555 init++;
557 p11_kit_pin_register_callback (P11_KIT_PIN_FALLBACK, p11_kit_pin_file_callback,
558 NULL, NULL);
560 if (flags == GNUTLS_PKCS11_FLAG_MANUAL)
561 return 0;
562 else if (flags == GNUTLS_PKCS11_FLAG_AUTO)
564 if (deprecated_config_file == NULL)
565 ret = initialize_automatic_p11_kit ();
567 _pkcs11_compat_init(deprecated_config_file);
569 return ret;
572 return 0;
576 * gnutls_pkcs11_reinit:
578 * This function will reinitialize the PKCS 11 subsystem in gnutls.
579 * This is required by PKCS 11 when an application uses fork(). The
580 * reinitialization function must be called on the child.
582 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
583 * negative error value.
585 * Since: 3.0
587 int gnutls_pkcs11_reinit (void)
589 int rv;
591 rv = p11_kit_initialize_registered ();
592 if (rv != CKR_OK)
594 gnutls_assert ();
595 _gnutls_debug_log ("Cannot initialize registered module: %s\n",
596 p11_kit_strerror (rv));
597 return GNUTLS_E_INTERNAL_ERROR;
600 return 0;
604 * gnutls_pkcs11_deinit:
606 * This function will deinitialize the PKCS 11 subsystem in gnutls.
608 * Since: 2.12.0
610 void
611 gnutls_pkcs11_deinit (void)
613 unsigned int i;
615 init--;
616 if (init > 0)
617 return;
618 if (init < 0)
620 init = 0;
621 return;
624 for (i = 0; i < active_providers; i++)
626 if (providers[i].initialized)
627 p11_kit_finalize_module (providers[i].module);
629 active_providers = 0;
631 if (initialized_registered != 0)
632 p11_kit_finalize_registered ();
633 initialized_registered = 0;
635 gnutls_pkcs11_set_pin_function (NULL, NULL);
636 gnutls_pkcs11_set_token_function (NULL, NULL);
640 * gnutls_pkcs11_set_token_function:
641 * @fn: The token callback
642 * @userdata: data to be supplied to callback
644 * This function will set a callback function to be used when a token
645 * needs to be inserted to continue PKCS 11 operations.
647 * Since: 2.12.0
649 void
650 gnutls_pkcs11_set_token_function (gnutls_pkcs11_token_callback_t fn,
651 void *userdata)
653 _gnutls_token_func = fn;
654 _gnutls_token_data = userdata;
658 pkcs11_url_to_info (const char *url, struct p11_kit_uri **info)
660 int allocated = 0;
661 int ret;
663 if (*info == NULL)
665 *info = p11_kit_uri_new ();
666 if (*info == NULL)
668 gnutls_assert ();
669 return GNUTLS_E_MEMORY_ERROR;
671 allocated = 1;
674 ret = p11_kit_uri_parse (url, P11_KIT_URI_FOR_ANY, *info);
675 if (ret < 0)
677 if (allocated)
679 p11_kit_uri_free (*info);
680 *info = NULL;
682 gnutls_assert ();
683 return ret == P11_KIT_URI_NO_MEMORY ?
684 GNUTLS_E_MEMORY_ERROR : GNUTLS_E_PARSING_ERROR;
687 return 0;
691 pkcs11_info_to_url (struct p11_kit_uri *info,
692 gnutls_pkcs11_url_type_t detailed, char **url)
694 p11_kit_uri_type_t type = 0;
695 int ret;
697 switch (detailed)
699 case GNUTLS_PKCS11_URL_GENERIC:
700 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN;
701 break;
702 case GNUTLS_PKCS11_URL_LIB:
703 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE;
704 break;
705 case GNUTLS_PKCS11_URL_LIB_VERSION:
706 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE | P11_KIT_URI_FOR_MODULE_WITH_VERSION;
707 break;
710 ret = p11_kit_uri_format (info, type, url);
711 if (ret < 0)
713 gnutls_assert ();
714 return ret == P11_KIT_URI_NO_MEMORY ?
715 GNUTLS_E_MEMORY_ERROR : GNUTLS_E_INTERNAL_ERROR;
718 return 0;
722 * gnutls_pkcs11_obj_init:
723 * @obj: The structure to be initialized
725 * This function will initialize a pkcs11 certificate structure.
727 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
728 * negative error value.
730 * Since: 2.12.0
733 gnutls_pkcs11_obj_init (gnutls_pkcs11_obj_t * obj)
735 *obj = gnutls_calloc (1, sizeof (struct gnutls_pkcs11_obj_st));
736 if (*obj == NULL)
738 gnutls_assert ();
739 return GNUTLS_E_MEMORY_ERROR;
742 (*obj)->info = p11_kit_uri_new ();
743 if ((*obj)->info == NULL)
745 free (*obj);
746 gnutls_assert ();
747 return GNUTLS_E_MEMORY_ERROR;
750 return 0;
754 * gnutls_pkcs11_obj_set_pin_function:
755 * @obj: The object structure
756 * @fn: the callback
757 * @userdata: data associated with the callback
759 * This function will set a callback function to be used when
760 * required to access the object. This function overrides the global
761 * set using gnutls_pkcs11_set_pin_function().
763 * Since: 3.1.0
765 void
766 gnutls_pkcs11_obj_set_pin_function (gnutls_pkcs11_obj_t obj,
767 gnutls_pin_callback_t fn,
768 void *userdata)
770 obj->pin.cb = fn;
771 obj->pin.data = userdata;
775 * gnutls_pkcs11_obj_deinit:
776 * @obj: The structure to be initialized
778 * This function will deinitialize a certificate structure.
780 * Since: 2.12.0
782 void
783 gnutls_pkcs11_obj_deinit (gnutls_pkcs11_obj_t obj)
785 _gnutls_free_datum (&obj->raw);
786 p11_kit_uri_free (obj->info);
787 free (obj);
791 * gnutls_pkcs11_obj_export:
792 * @obj: Holds the object
793 * @output_data: will contain a certificate PEM or DER encoded
794 * @output_data_size: holds the size of output_data (and will be
795 * replaced by the actual size of parameters)
797 * This function will export the PKCS11 object data. It is normal for
798 * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
799 * will be returned.
801 * If the buffer provided is not long enough to hold the output, then
802 * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
803 * be returned.
805 * If the structure is PEM encoded, it will have a header
806 * of "BEGIN CERTIFICATE".
808 * Returns: In case of failure a negative error code will be
809 * returned, and %GNUTLS_E_SUCCESS (0) on success.
811 * Since: 2.12.0
814 gnutls_pkcs11_obj_export (gnutls_pkcs11_obj_t obj,
815 void *output_data, size_t * output_data_size)
817 if (obj == NULL || obj->raw.data == NULL)
819 gnutls_assert ();
820 return GNUTLS_E_INVALID_REQUEST;
823 if (output_data == NULL || *output_data_size < obj->raw.size)
825 *output_data_size = obj->raw.size;
826 gnutls_assert ();
827 return GNUTLS_E_SHORT_MEMORY_BUFFER;
829 *output_data_size = obj->raw.size;
831 memcpy (output_data, obj->raw.data, obj->raw.size);
832 return 0;
836 pkcs11_find_object (struct pkcs11_session_info* sinfo,
837 struct pin_info_st * pin_info,
838 ck_object_handle_t * _obj,
839 struct p11_kit_uri *info, unsigned int flags)
841 int ret;
842 ck_object_handle_t obj;
843 struct ck_attribute *attrs;
844 unsigned long attr_count;
845 unsigned long count;
846 ck_rv_t rv;
848 ret = pkcs11_open_session (sinfo, pin_info, info, flags & SESSION_LOGIN);
849 if (ret < 0)
851 gnutls_assert ();
852 return ret;
855 attrs = p11_kit_uri_get_attributes (info, &attr_count);
856 rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, attrs, attr_count);
857 if (rv != CKR_OK)
859 gnutls_assert ();
860 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
861 ret = pkcs11_rv_to_err (rv);
862 goto fail;
865 if (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1)
867 *_obj = obj;
868 pkcs11_find_objects_final (sinfo);
869 return 0;
872 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
873 pkcs11_find_objects_final (sinfo);
874 fail:
875 pkcs11_close_session (sinfo);
877 return ret;
881 pkcs11_find_slot (struct ck_function_list ** module, ck_slot_id_t * slot,
882 struct p11_kit_uri *info, struct token_info *_tinfo)
884 unsigned int x, z;
886 for (x = 0; x < active_providers; x++)
888 for (z = 0; z < providers[x].nslots; z++)
890 struct token_info tinfo;
892 if (pkcs11_get_token_info
893 (providers[x].module, providers[x].slots[z],
894 &tinfo.tinfo) != CKR_OK)
896 continue;
898 tinfo.sid = providers[x].slots[z];
899 tinfo.prov = &providers[x];
901 if (pkcs11_get_slot_info
902 (providers[x].module, providers[x].slots[z],
903 &tinfo.sinfo) != CKR_OK)
905 continue;
908 if (!p11_kit_uri_match_token_info (info, &tinfo.tinfo) ||
909 !p11_kit_uri_match_module_info (info, &providers[x].info))
911 continue;
914 /* ok found */
915 *module = providers[x].module;
916 *slot = providers[x].slots[z];
918 if (_tinfo != NULL)
919 memcpy (_tinfo, &tinfo, sizeof (tinfo));
921 return 0;
925 gnutls_assert ();
926 return GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE;
930 pkcs11_open_session (struct pkcs11_session_info *sinfo,
931 struct pin_info_st *pin_info,
932 struct p11_kit_uri *info,
933 unsigned int flags)
935 ck_rv_t rv;
936 int ret;
937 ck_session_handle_t pks = 0;
938 struct ck_function_list *module;
939 ck_slot_id_t slot;
940 struct token_info tinfo;
942 ret = pkcs11_find_slot (&module, &slot, info, &tinfo);
943 if (ret < 0)
945 gnutls_assert ();
946 return ret;
949 rv = (module)->C_OpenSession (slot,
950 ((flags & SESSION_WRITE)
951 ? CKF_RW_SESSION : 0) |
952 CKF_SERIAL_SESSION, NULL, NULL, &pks);
953 if (rv != CKR_OK)
955 gnutls_assert ();
956 return pkcs11_rv_to_err (rv);
959 /* ok found */
960 sinfo->pks = pks;
961 sinfo->module = module;
962 sinfo->init = 1;
963 memcpy(&sinfo->tinfo, &tinfo.tinfo, sizeof(sinfo->tinfo));
965 if (flags & SESSION_LOGIN)
967 ret = pkcs11_login (sinfo, pin_info, &tinfo, info, (flags & SESSION_SO) ? 1 : 0);
968 if (ret < 0)
970 gnutls_assert ();
971 pkcs11_close_session (sinfo);
972 return ret;
976 return 0;
981 _pkcs11_traverse_tokens (find_func_t find_func, void *input,
982 struct p11_kit_uri *info,
983 struct pin_info_st *pin_info,
984 unsigned int flags)
986 ck_rv_t rv;
987 unsigned int found = 0, x, z;
988 int ret;
989 ck_session_handle_t pks = 0;
990 struct pkcs11_session_info sinfo;
991 struct ck_function_list *module = NULL;
993 for (x = 0; x < active_providers; x++)
995 module = providers[x].module;
996 for (z = 0; z < providers[x].nslots; z++)
998 struct token_info tinfo;
1000 if (pkcs11_get_token_info (module, providers[x].slots[z],
1001 &tinfo.tinfo) != CKR_OK)
1003 continue;
1005 tinfo.sid = providers[x].slots[z];
1006 tinfo.prov = &providers[x];
1008 if (pkcs11_get_slot_info (module, providers[x].slots[z],
1009 &tinfo.sinfo) != CKR_OK)
1011 continue;
1014 rv = (module)->C_OpenSession (providers[x].slots[z],
1015 ((flags & SESSION_WRITE)
1016 ? CKF_RW_SESSION : 0) |
1017 CKF_SERIAL_SESSION, NULL, NULL, &pks);
1018 if (rv != CKR_OK)
1020 continue;
1023 sinfo.module = module;
1024 sinfo.pks = pks;
1026 if (flags & SESSION_LOGIN)
1028 ret = pkcs11_login (&sinfo, pin_info, &tinfo, info, (flags & SESSION_SO) ? 1 : 0);
1029 if (ret < 0)
1031 gnutls_assert ();
1032 return ret;
1036 ret = find_func (&sinfo, &tinfo, &providers[x].info, input);
1038 if (ret == 0)
1040 found = 1;
1041 goto finish;
1043 else
1045 pkcs11_close_session (&sinfo);
1046 pks = 0;
1051 finish:
1052 /* final call */
1054 if (found == 0)
1056 if (module)
1058 sinfo.module = module;
1059 sinfo.pks = pks;
1060 ret = find_func (&sinfo, NULL, NULL, input);
1062 else
1063 ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1065 else
1067 ret = 0;
1070 if (pks != 0 && module != NULL)
1072 pkcs11_close_session (&sinfo);
1075 return ret;
1078 /* imports a raw certificate from a token to a pkcs11_obj_t structure.
1080 static int
1081 pkcs11_obj_import (ck_object_class_t class, gnutls_pkcs11_obj_t obj,
1082 const gnutls_datum_t * data,
1083 const gnutls_datum_t * id,
1084 const gnutls_datum_t * label,
1085 struct ck_token_info *tinfo, struct ck_info *lib_info)
1087 struct ck_attribute attr;
1088 int ret;
1090 switch (class)
1092 case CKO_CERTIFICATE:
1093 obj->type = GNUTLS_PKCS11_OBJ_X509_CRT;
1094 break;
1095 case CKO_PUBLIC_KEY:
1096 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1097 break;
1098 case CKO_PRIVATE_KEY:
1099 obj->type = GNUTLS_PKCS11_OBJ_PRIVKEY;
1100 break;
1101 case CKO_SECRET_KEY:
1102 obj->type = GNUTLS_PKCS11_OBJ_SECRET_KEY;
1103 break;
1104 case CKO_DATA:
1105 obj->type = GNUTLS_PKCS11_OBJ_DATA;
1106 break;
1107 default:
1108 obj->type = GNUTLS_PKCS11_OBJ_UNKNOWN;
1111 attr.type = CKA_CLASS;
1112 attr.value = &class;
1113 attr.value_len = sizeof (class);
1114 ret = p11_kit_uri_set_attribute (obj->info, &attr);
1115 if (ret < 0)
1117 gnutls_assert ();
1118 return GNUTLS_E_MEMORY_ERROR;
1121 if (data && data->data)
1123 ret = _gnutls_set_datum (&obj->raw, data->data, data->size);
1124 if (ret < 0)
1126 gnutls_assert ();
1127 return ret;
1131 /* copy the token and library info into the uri */
1132 memcpy (p11_kit_uri_get_token_info (obj->info), tinfo, sizeof (struct ck_token_info));
1133 memcpy (p11_kit_uri_get_module_info (obj->info), lib_info, sizeof (struct ck_info));
1135 if (label && label->data)
1137 attr.type = CKA_LABEL;
1138 attr.value = label->data;
1139 attr.value_len = label->size;
1140 ret = p11_kit_uri_set_attribute (obj->info, &attr);
1141 if (ret < 0)
1143 gnutls_assert ();
1144 return GNUTLS_E_MEMORY_ERROR;
1148 if (id && id->data)
1150 attr.type = CKA_ID;
1151 attr.value = id->data;
1152 attr.value_len = id->size;
1153 ret = p11_kit_uri_set_attribute (obj->info, &attr);
1154 if (ret < 0)
1156 gnutls_assert ();
1157 return GNUTLS_E_MEMORY_ERROR;
1161 return 0;
1164 static int read_pkcs11_pubkey(struct ck_function_list *module,
1165 ck_session_handle_t pks, ck_object_handle_t obj,
1166 ck_key_type_t key_type, gnutls_datum_t * pubkey)
1168 struct ck_attribute a[4];
1169 uint8_t tmp1[2048];
1170 uint8_t tmp2[2048];
1171 int ret;
1173 switch (key_type)
1175 case CKK_RSA:
1176 a[0].type = CKA_MODULUS;
1177 a[0].value = tmp1;
1178 a[0].value_len = sizeof (tmp1);
1179 a[1].type = CKA_PUBLIC_EXPONENT;
1180 a[1].value = tmp2;
1181 a[1].value_len = sizeof (tmp2);
1183 if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
1186 ret =
1187 _gnutls_set_datum (&pubkey[0],
1188 a[0].value, a[0].value_len);
1190 if (ret >= 0)
1191 ret =
1192 _gnutls_set_datum (&pubkey
1193 [1], a[1].value, a[1].value_len);
1195 if (ret < 0)
1197 gnutls_assert ();
1198 _gnutls_free_datum (&pubkey[1]);
1199 _gnutls_free_datum (&pubkey[0]);
1200 return GNUTLS_E_MEMORY_ERROR;
1203 else
1205 gnutls_assert ();
1206 return GNUTLS_E_PKCS11_ERROR;
1208 break;
1209 case CKK_DSA:
1210 a[0].type = CKA_PRIME;
1211 a[0].value = tmp1;
1212 a[0].value_len = sizeof (tmp1);
1213 a[1].type = CKA_SUBPRIME;
1214 a[1].value = tmp2;
1215 a[1].value_len = sizeof (tmp2);
1217 if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
1219 ret =
1220 _gnutls_set_datum (&pubkey[0],
1221 a[0].value, a[0].value_len);
1223 if (ret >= 0)
1224 ret =
1225 _gnutls_set_datum (&pubkey
1226 [1], a[1].value, a[1].value_len);
1228 if (ret < 0)
1230 gnutls_assert ();
1231 _gnutls_free_datum (&pubkey[1]);
1232 _gnutls_free_datum (&pubkey[0]);
1233 return GNUTLS_E_MEMORY_ERROR;
1236 else
1238 gnutls_assert ();
1239 return GNUTLS_E_PKCS11_ERROR;
1242 a[0].type = CKA_BASE;
1243 a[0].value = tmp1;
1244 a[0].value_len = sizeof (tmp1);
1245 a[1].type = CKA_VALUE;
1246 a[1].value = tmp2;
1247 a[1].value_len = sizeof (tmp2);
1249 if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
1251 ret =
1252 _gnutls_set_datum (&pubkey[2],
1253 a[0].value, a[0].value_len);
1255 if (ret >= 0)
1256 ret =
1257 _gnutls_set_datum (&pubkey
1258 [3], a[1].value, a[1].value_len);
1260 if (ret < 0)
1262 gnutls_assert ();
1263 _gnutls_free_datum (&pubkey[0]);
1264 _gnutls_free_datum (&pubkey[1]);
1265 _gnutls_free_datum (&pubkey[2]);
1266 _gnutls_free_datum (&pubkey[3]);
1267 return GNUTLS_E_MEMORY_ERROR;
1270 else
1272 gnutls_assert ();
1273 return GNUTLS_E_PKCS11_ERROR;
1275 break;
1276 case CKK_ECDSA:
1277 a[0].type = CKA_EC_PARAMS;
1278 a[0].value = tmp1;
1279 a[0].value_len = sizeof (tmp1);
1280 a[1].type = CKA_EC_POINT;
1281 a[1].value = tmp2;
1282 a[1].value_len = sizeof (tmp2);
1284 if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
1286 ret =
1287 _gnutls_set_datum (&pubkey[0],
1288 a[0].value, a[0].value_len);
1290 if (ret >= 0)
1291 ret =
1292 _gnutls_set_datum (&pubkey
1293 [1], a[1].value, a[1].value_len);
1295 if (ret < 0)
1297 gnutls_assert ();
1298 _gnutls_free_datum (&pubkey[1]);
1299 _gnutls_free_datum (&pubkey[0]);
1300 return GNUTLS_E_MEMORY_ERROR;
1303 else
1305 gnutls_assert ();
1306 return GNUTLS_E_PKCS11_ERROR;
1309 break;
1310 default:
1311 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1314 return 0;
1317 static int
1318 pkcs11_obj_import_pubkey (struct ck_function_list *module,
1319 ck_session_handle_t pks,
1320 ck_object_handle_t obj,
1321 gnutls_pkcs11_obj_t crt,
1322 const gnutls_datum_t * id,
1323 const gnutls_datum_t * label,
1324 struct ck_token_info *tinfo,
1325 struct ck_info *lib_info)
1327 struct ck_attribute a[4];
1328 ck_key_type_t key_type;
1329 int ret;
1330 ck_bool_t tval;
1332 a[0].type = CKA_KEY_TYPE;
1333 a[0].value = &key_type;
1334 a[0].value_len = sizeof (key_type);
1336 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1338 crt->pk_algorithm = mech_to_pk(key_type);
1340 ret = read_pkcs11_pubkey(module, pks, obj, key_type, crt->pubkey);
1341 if (ret < 0)
1342 return gnutls_assert_val(ret);
1345 /* read key usage flags */
1346 a[0].type = CKA_ENCRYPT;
1347 a[0].value = &tval;
1348 a[0].value_len = sizeof (tval);
1350 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1352 if (tval != 0)
1354 crt->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
1358 a[0].type = CKA_VERIFY;
1359 a[0].value = &tval;
1360 a[0].value_len = sizeof (tval);
1362 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1364 if (tval != 0)
1366 crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1367 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1368 | GNUTLS_KEY_NON_REPUDIATION;
1372 a[0].type = CKA_VERIFY_RECOVER;
1373 a[0].value = &tval;
1374 a[0].value_len = sizeof (tval);
1376 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1378 if (tval != 0)
1380 crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1381 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1382 | GNUTLS_KEY_NON_REPUDIATION;
1386 a[0].type = CKA_DERIVE;
1387 a[0].value = &tval;
1388 a[0].value_len = sizeof (tval);
1390 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1392 if (tval != 0)
1394 crt->key_usage |= GNUTLS_KEY_KEY_AGREEMENT;
1398 a[0].type = CKA_WRAP;
1399 a[0].value = &tval;
1400 a[0].value_len = sizeof (tval);
1402 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1404 if (tval != 0)
1406 crt->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
1410 return pkcs11_obj_import (CKO_PUBLIC_KEY, crt, NULL, id, label,
1411 tinfo, lib_info);
1414 static int
1415 find_obj_url (struct pkcs11_session_info *sinfo,
1416 struct token_info *info, struct ck_info *lib_info, void *input)
1418 struct url_find_data_st *find_data = input;
1419 struct ck_attribute a[4];
1420 struct ck_attribute *attr;
1421 ck_object_class_t class = -1;
1422 ck_certificate_type_t type = (ck_certificate_type_t)-1;
1423 ck_rv_t rv;
1424 ck_object_handle_t obj;
1425 unsigned long count, a_vals;
1426 int found = 0, ret;
1427 uint8_t *cert_data = NULL;
1428 char label_tmp[PKCS11_LABEL_SIZE];
1429 char id_tmp[PKCS11_ID_SIZE];
1431 if (info == NULL)
1432 { /* we don't support multiple calls */
1433 gnutls_assert ();
1434 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1437 /* do not bother reading the token if basic fields do not match
1439 if (!p11_kit_uri_match_token_info (find_data->crt->info, &info->tinfo) ||
1440 !p11_kit_uri_match_module_info (find_data->crt->info, lib_info))
1442 gnutls_assert ();
1443 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1446 a_vals = 0;
1447 attr = p11_kit_uri_get_attribute (find_data->crt->info, CKA_ID);
1448 if (attr)
1450 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
1451 a_vals++;
1454 attr = p11_kit_uri_get_attribute (find_data->crt->info, CKA_LABEL);
1455 if (attr)
1457 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
1458 a_vals++;
1461 if (!a_vals)
1463 gnutls_assert ();
1464 return GNUTLS_E_INVALID_REQUEST;
1467 /* search the token for the id */
1469 cert_data = gnutls_malloc (MAX_CERT_SIZE);
1470 if (cert_data == NULL)
1472 gnutls_assert ();
1473 return GNUTLS_E_MEMORY_ERROR;
1476 /* Find objects with given class and type */
1477 attr = p11_kit_uri_get_attribute (find_data->crt->info, CKA_CLASS);
1478 if (attr)
1480 if(attr->value && attr->value_len == sizeof (ck_object_class_t))
1481 class = *((ck_object_class_t*)attr->value);
1482 if (class == CKO_CERTIFICATE)
1483 type = CKC_X_509;
1484 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
1485 a_vals++;
1488 if (type != (ck_certificate_type_t)-1)
1490 a[a_vals].type = CKA_CERTIFICATE_TYPE;
1491 a[a_vals].value = &type;
1492 a[a_vals].value_len = sizeof type;
1493 a_vals++;
1496 rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, a_vals);
1497 if (rv != CKR_OK)
1499 gnutls_assert ();
1500 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
1501 ret = pkcs11_rv_to_err (rv);
1502 goto cleanup;
1505 while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1)
1508 a[0].type = CKA_VALUE;
1509 a[0].value = cert_data;
1510 a[0].value_len = MAX_CERT_SIZE;
1511 a[1].type = CKA_LABEL;
1512 a[1].value = label_tmp;
1513 a[1].value_len = sizeof (label_tmp);
1514 a[2].type = CKA_ID;
1515 a[2].value = id_tmp;
1516 a[2].value_len = sizeof(id_tmp);
1518 if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 3) == CKR_OK)
1520 gnutls_datum_t id = { a[2].value, a[2].value_len };
1521 gnutls_datum_t data = { a[0].value, a[0].value_len };
1522 gnutls_datum_t label = { a[1].value, a[1].value_len };
1524 if (class == CKO_PUBLIC_KEY)
1526 ret =
1527 pkcs11_obj_import_pubkey (sinfo->module, sinfo->pks, obj,
1528 find_data->crt,
1529 &id, &label,
1530 &info->tinfo, lib_info);
1532 else
1534 ret =
1535 pkcs11_obj_import (class,
1536 find_data->crt,
1537 &data, &id, &label,
1538 &info->tinfo, lib_info);
1540 if (ret < 0)
1542 gnutls_assert ();
1543 goto cleanup;
1546 found = 1;
1547 break;
1549 else
1551 _gnutls_debug_log ("pk11: Skipped cert, missing attrs.\n");
1555 if (found == 0)
1557 gnutls_assert ();
1558 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1560 else
1562 ret = 0;
1565 cleanup:
1566 gnutls_free (cert_data);
1567 pkcs11_find_objects_final (sinfo);
1569 return ret;
1572 unsigned int
1573 pkcs11_obj_flags_to_int (unsigned int flags)
1575 unsigned int ret_flags = 0;
1577 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN)
1578 ret_flags |= SESSION_LOGIN;
1579 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO)
1580 ret_flags |= SESSION_LOGIN|SESSION_SO;
1582 return ret_flags;
1586 * gnutls_pkcs11_obj_import_url:
1587 * @obj: The structure to store the object
1588 * @url: a PKCS 11 url identifying the key
1589 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1591 * This function will "import" a PKCS 11 URL identifying an object (e.g. certificate)
1592 * to the #gnutls_pkcs11_obj_t structure. This does not involve any
1593 * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is
1594 * format agnostic. Only data are transferred.
1596 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1597 * negative error value.
1599 * Since: 2.12.0
1602 gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t obj, const char *url,
1603 unsigned int flags)
1605 int ret;
1606 struct url_find_data_st find_data;
1608 /* fill in the find data structure */
1609 find_data.crt = obj;
1611 ret = pkcs11_url_to_info (url, &obj->info);
1612 if (ret < 0)
1614 gnutls_assert ();
1615 return ret;
1618 ret =
1619 _pkcs11_traverse_tokens (find_obj_url, &find_data, obj->info,
1620 &obj->pin, pkcs11_obj_flags_to_int (flags));
1622 if (ret < 0)
1624 gnutls_assert ();
1625 return ret;
1628 return 0;
1631 struct token_num
1633 struct p11_kit_uri *info;
1634 unsigned int seq; /* which one we are looking for */
1635 unsigned int current; /* which one are we now */
1638 static int
1639 find_token_num (struct pkcs11_session_info* sinfo,
1640 struct token_info *tinfo,
1641 struct ck_info *lib_info, void *input)
1643 struct token_num *find_data = input;
1645 if (tinfo == NULL)
1646 { /* we don't support multiple calls */
1647 gnutls_assert ();
1648 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1651 if (find_data->current == find_data->seq)
1653 memcpy (p11_kit_uri_get_token_info (find_data->info), &tinfo->tinfo, sizeof (struct ck_token_info));
1654 memcpy (p11_kit_uri_get_module_info (find_data->info), lib_info, sizeof (struct ck_info));
1655 return 0;
1658 find_data->current++;
1659 /* search the token for the id */
1662 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* non zero is enough */
1666 * gnutls_pkcs11_token_get_url:
1667 * @seq: sequence number starting from 0
1668 * @detailed: non zero if a detailed URL is required
1669 * @url: will contain an allocated url
1671 * This function will return the URL for each token available
1672 * in system. The url has to be released using gnutls_free()
1674 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
1675 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if the sequence number
1676 * exceeds the available tokens, otherwise a negative error value.
1678 * Since: 2.12.0
1681 gnutls_pkcs11_token_get_url (unsigned int seq,
1682 gnutls_pkcs11_url_type_t detailed, char **url)
1684 int ret;
1685 struct token_num tn;
1687 memset (&tn, 0, sizeof (tn));
1688 tn.seq = seq;
1689 tn.info = p11_kit_uri_new ();
1691 ret = _pkcs11_traverse_tokens (find_token_num, &tn, NULL, NULL, 0);
1692 if (ret < 0)
1694 p11_kit_uri_free (tn.info);
1695 gnutls_assert ();
1696 return ret;
1699 ret = pkcs11_info_to_url (tn.info, detailed, url);
1700 p11_kit_uri_free (tn.info);
1702 if (ret < 0)
1704 gnutls_assert ();
1705 return ret;
1708 return 0;
1713 * gnutls_pkcs11_token_get_info:
1714 * @url: should contain a PKCS 11 URL
1715 * @ttype: Denotes the type of information requested
1716 * @output: where output will be stored
1717 * @output_size: contains the maximum size of the output and will be overwritten with actual
1719 * This function will return information about the PKCS 11 token such
1720 * as the label, id, etc.
1722 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code
1723 * on error.
1725 * Since: 2.12.0
1728 gnutls_pkcs11_token_get_info (const char *url,
1729 gnutls_pkcs11_token_info_t ttype,
1730 void *output, size_t * output_size)
1732 struct p11_kit_uri *info = NULL;
1733 const uint8_t *str;
1734 size_t str_max;
1735 size_t len;
1736 int ret;
1738 ret = pkcs11_url_to_info (url, &info);
1739 if (ret < 0)
1741 gnutls_assert ();
1742 return ret;
1745 switch (ttype)
1747 case GNUTLS_PKCS11_TOKEN_LABEL:
1748 str = p11_kit_uri_get_token_info (info)->label;
1749 str_max = 32;
1750 break;
1751 case GNUTLS_PKCS11_TOKEN_SERIAL:
1752 str = p11_kit_uri_get_token_info (info)->serial_number;
1753 str_max = 16;
1754 break;
1755 case GNUTLS_PKCS11_TOKEN_MANUFACTURER:
1756 str = p11_kit_uri_get_token_info (info)->manufacturer_id;
1757 str_max = 32;
1758 break;
1759 case GNUTLS_PKCS11_TOKEN_MODEL:
1760 str = p11_kit_uri_get_token_info (info)->model;
1761 str_max = 16;
1762 break;
1763 default:
1764 p11_kit_uri_free (info);
1765 gnutls_assert ();
1766 return GNUTLS_E_INVALID_REQUEST;
1769 len = p11_kit_space_strlen (str, str_max);
1771 if (len + 1 > *output_size)
1773 *output_size = len + 1;
1774 return GNUTLS_E_SHORT_MEMORY_BUFFER;
1777 memcpy (output, str, len);
1778 ((char*)output)[len] = '\0';
1780 *output_size = len;
1782 p11_kit_uri_free (info);
1783 return 0;
1787 * gnutls_pkcs11_obj_export_url:
1788 * @obj: Holds the PKCS 11 certificate
1789 * @detailed: non zero if a detailed URL is required
1790 * @url: will contain an allocated url
1792 * This function will export a URL identifying the given certificate.
1794 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1795 * negative error value.
1797 * Since: 2.12.0
1800 gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t obj,
1801 gnutls_pkcs11_url_type_t detailed, char **url)
1803 int ret;
1805 ret = pkcs11_info_to_url (obj->info, detailed, url);
1806 if (ret < 0)
1808 gnutls_assert ();
1809 return ret;
1812 return 0;
1816 * gnutls_pkcs11_obj_get_type:
1817 * @obj: Holds the PKCS 11 object
1819 * This function will return the type of the certificate being
1820 * stored in the structure.
1822 * Returns: The type of the certificate.
1824 * Since: 2.12.0
1826 gnutls_pkcs11_obj_type_t
1827 gnutls_pkcs11_obj_get_type (gnutls_pkcs11_obj_t obj)
1829 return obj->type;
1832 struct pkey_list
1834 gnutls_buffer_st *key_ids;
1835 size_t key_ids_size;
1839 static int
1840 retrieve_pin_from_source (const char *pinfile, struct ck_token_info *token_info,
1841 int attempts, ck_user_type_t user_type, struct p11_kit_pin **pin)
1843 unsigned int flags = 0;
1844 struct p11_kit_uri *token_uri;
1845 struct p11_kit_pin *result;
1846 char *label;
1848 label = p11_kit_space_strdup (token_info->label, sizeof (token_info->label));
1849 if (label == NULL)
1851 gnutls_assert ();
1852 return GNUTLS_E_MEMORY_ERROR;
1855 token_uri = p11_kit_uri_new ();
1856 if (token_uri == NULL)
1858 free (label);
1859 gnutls_assert ();
1860 return GNUTLS_E_MEMORY_ERROR;
1863 memcpy (p11_kit_uri_get_token_info (token_uri), token_info,
1864 sizeof (struct ck_token_info));
1866 if (attempts)
1867 flags |= P11_KIT_PIN_FLAGS_RETRY;
1868 if (user_type == CKU_USER)
1870 flags |= P11_KIT_PIN_FLAGS_USER_LOGIN;
1871 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
1872 flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
1873 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
1874 flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
1876 else if (user_type == CKU_SO)
1878 flags |= P11_KIT_PIN_FLAGS_SO_LOGIN;
1879 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
1880 flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
1881 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
1882 flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
1884 else if (user_type == CKU_CONTEXT_SPECIFIC)
1886 flags |= P11_KIT_PIN_FLAGS_CONTEXT_LOGIN;
1889 result = p11_kit_pin_request (pinfile, token_uri, label, flags);
1890 p11_kit_uri_free (token_uri);
1891 free (label);
1893 if (result == NULL)
1895 gnutls_assert ();
1896 return GNUTLS_E_PKCS11_PIN_ERROR;
1899 *pin = result;
1900 return 0;
1903 static int
1904 retrieve_pin_from_callback (const struct pin_info_st *pin_info,
1905 struct ck_token_info *token_info,
1906 int attempts, ck_user_type_t user_type,
1907 struct p11_kit_pin **pin)
1909 char pin_value[GNUTLS_PKCS11_MAX_PIN_LEN];
1910 unsigned int flags = 0;
1911 char *token_str;
1912 char *label;
1913 struct p11_kit_uri *token_uri;
1914 int ret = 0;
1916 label = p11_kit_space_strdup (token_info->label, sizeof (token_info->label));
1917 if (label == NULL)
1919 gnutls_assert ();
1920 return GNUTLS_E_MEMORY_ERROR;
1923 token_uri = p11_kit_uri_new ();
1924 if (token_uri == NULL)
1926 free (label);
1927 gnutls_assert ();
1928 return GNUTLS_E_MEMORY_ERROR;
1931 memcpy (p11_kit_uri_get_token_info (token_uri), token_info,
1932 sizeof (struct ck_token_info));
1933 ret = pkcs11_info_to_url (token_uri, 1, &token_str);
1934 p11_kit_uri_free (token_uri);
1936 if (ret < 0)
1938 free (label);
1939 gnutls_assert ();
1940 return GNUTLS_E_MEMORY_ERROR;
1943 if (user_type == CKU_USER)
1945 flags |= GNUTLS_PIN_USER;
1946 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
1947 flags |= GNUTLS_PIN_COUNT_LOW;
1948 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
1949 flags |= GNUTLS_PIN_FINAL_TRY;
1951 else if (user_type == CKU_SO)
1953 flags |= GNUTLS_PIN_SO;
1954 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
1955 flags |= GNUTLS_PIN_COUNT_LOW;
1956 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
1957 flags |= GNUTLS_PIN_FINAL_TRY;
1960 if (attempts > 0)
1961 flags |= GNUTLS_PIN_WRONG;
1963 if (pin_info && pin_info->cb)
1964 ret = pin_info->cb (pin_info->data, attempts, (char*)token_str, label,
1965 flags, pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
1966 else if (_gnutls_pin_func)
1967 ret = _gnutls_pin_func (_gnutls_pin_data, attempts, (char*)token_str, label,
1968 flags, pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
1969 else
1970 ret = gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
1972 free (token_str);
1973 free (label);
1975 if (ret < 0)
1976 return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
1978 *pin = p11_kit_pin_new_for_string (pin_value);
1980 if (*pin == NULL)
1981 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1983 return 0;
1986 static int
1987 retrieve_pin (struct pin_info_st* pin_info, struct p11_kit_uri *info,
1988 struct ck_token_info *token_info, int attempts,
1989 ck_user_type_t user_type, struct p11_kit_pin **pin)
1991 const char *pinfile;
1992 int ret = GNUTLS_E_PKCS11_PIN_ERROR;
1994 *pin = NULL;
1996 /* Check if a pinfile is specified, and use that if possible */
1997 pinfile = p11_kit_uri_get_pinfile (info);
1998 if (pinfile != NULL)
2000 _gnutls_debug_log("pk11: Using pinfile to retrieve PIN\n");
2001 ret = retrieve_pin_from_source (pinfile, token_info, attempts, user_type, pin);
2004 /* The global gnutls pin callback */
2005 if (ret < 0)
2006 ret = retrieve_pin_from_callback (pin_info, token_info, attempts, user_type, pin);
2008 /* Otherwise, PIN entry is necessary for login, so fail if there's
2009 * no callback. */
2011 if (ret < 0)
2013 gnutls_assert ();
2014 _gnutls_debug_log ("pk11: No suitable pin callback but login required.\n");
2017 return ret;
2021 pkcs11_login (struct pkcs11_session_info * sinfo, struct pin_info_st * pin_info,
2022 const struct token_info *tokinfo, struct p11_kit_uri *info, int so)
2024 struct ck_session_info session_info;
2025 int attempt = 0, ret;
2026 ck_user_type_t user_type;
2027 ck_rv_t rv;
2029 user_type = (so == 0) ? CKU_USER : CKU_SO;
2030 if (so == 0 && (tokinfo->tinfo.flags & CKF_LOGIN_REQUIRED) == 0)
2032 gnutls_assert ();
2033 _gnutls_debug_log ("pk11: No login required.\n");
2034 return 0;
2037 /* For a token with a "protected" (out-of-band) authentication
2038 * path, calling login with a NULL username is all that is
2039 * required. */
2040 if (tokinfo->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
2042 rv = (sinfo->module)->C_Login (sinfo->pks, (so == 0) ? CKU_USER : CKU_SO, NULL, 0);
2043 if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN)
2045 return 0;
2047 else
2049 gnutls_assert ();
2050 _gnutls_debug_log ("pk11: Protected login failed.\n");
2051 ret = GNUTLS_E_PKCS11_ERROR;
2052 goto cleanup;
2058 struct p11_kit_pin *pin;
2059 struct ck_token_info tinfo;
2061 memcpy (&tinfo, &tokinfo->tinfo, sizeof(tinfo));
2063 /* Check whether the session is already logged in, and if so, just skip */
2064 rv = (sinfo->module)->C_GetSessionInfo (sinfo->pks, &session_info);
2065 if (rv == CKR_OK && (session_info.state == CKS_RO_USER_FUNCTIONS ||
2066 session_info.state == CKS_RW_USER_FUNCTIONS))
2068 ret = 0;
2069 goto cleanup;
2072 /* If login has been attempted once already, check the token
2073 * status again, the flags might change. */
2074 if (attempt)
2076 if (pkcs11_get_token_info
2077 (tokinfo->prov->module, tokinfo->sid, &tinfo) != CKR_OK)
2079 gnutls_assert ();
2080 _gnutls_debug_log ("pk11: GetTokenInfo failed\n");
2081 ret = GNUTLS_E_PKCS11_ERROR;
2082 goto cleanup;
2086 ret = retrieve_pin (pin_info, info, &tinfo, attempt++, user_type, &pin);
2087 if (ret < 0)
2089 gnutls_assert ();
2090 goto cleanup;
2093 rv = (sinfo->module)->C_Login (sinfo->pks, user_type,
2094 (unsigned char *)p11_kit_pin_get_value (pin, NULL),
2095 p11_kit_pin_get_length (pin));
2097 p11_kit_pin_unref (pin);
2099 while (rv == CKR_PIN_INCORRECT);
2101 _gnutls_debug_log ("pk11: Login result = %lu\n", rv);
2104 ret = (rv == CKR_OK
2105 || rv == CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err (rv);
2107 cleanup:
2108 return ret;
2112 pkcs11_call_token_func (struct p11_kit_uri *info, const unsigned retry)
2114 struct ck_token_info *tinfo;
2115 char *label;
2116 int ret = 0;
2118 tinfo = p11_kit_uri_get_token_info (info);
2119 label = p11_kit_space_strdup (tinfo->label, sizeof (tinfo->label));
2120 ret = (_gnutls_token_func) (_gnutls_token_data, label, retry);
2121 free (label);
2123 return ret;
2127 static int
2128 find_privkeys (struct pkcs11_session_info* sinfo,
2129 struct token_info *info, struct pkey_list *list)
2131 struct ck_attribute a[3];
2132 ck_object_class_t class;
2133 ck_rv_t rv;
2134 ck_object_handle_t obj;
2135 unsigned long count, current;
2136 char certid_tmp[PKCS11_ID_SIZE];
2138 class = CKO_PRIVATE_KEY;
2140 /* Find an object with private key class and a certificate ID
2141 * which matches the certificate. */
2142 /* FIXME: also match the cert subject. */
2143 a[0].type = CKA_CLASS;
2144 a[0].value = &class;
2145 a[0].value_len = sizeof class;
2147 rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, 1);
2148 if (rv != CKR_OK)
2150 gnutls_assert ();
2151 return pkcs11_rv_to_err (rv);
2154 list->key_ids_size = 0;
2155 while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1)
2157 list->key_ids_size++;
2160 pkcs11_find_objects_final (sinfo);
2162 if (list->key_ids_size == 0)
2164 gnutls_assert ();
2165 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2168 list->key_ids =
2169 gnutls_malloc (sizeof (gnutls_buffer_st) * list->key_ids_size);
2170 if (list->key_ids == NULL)
2172 gnutls_assert ();
2173 return GNUTLS_E_MEMORY_ERROR;
2176 /* actual search */
2177 a[0].type = CKA_CLASS;
2178 a[0].value = &class;
2179 a[0].value_len = sizeof class;
2181 rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, 1);
2182 if (rv != CKR_OK)
2184 gnutls_assert ();
2185 return pkcs11_rv_to_err (rv);
2188 current = 0;
2189 while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1)
2192 a[0].type = CKA_ID;
2193 a[0].value = certid_tmp;
2194 a[0].value_len = sizeof (certid_tmp);
2196 _gnutls_buffer_init (&list->key_ids[current]);
2198 if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK)
2200 _gnutls_buffer_append_data (&list->key_ids[current],
2201 a[0].value, a[0].value_len);
2202 current++;
2205 if (current > list->key_ids_size)
2206 break;
2209 pkcs11_find_objects_final (sinfo);
2211 list->key_ids_size = current - 1;
2213 return 0;
2216 /* Recover certificate list from tokens */
2219 static int
2220 find_objs (struct pkcs11_session_info* sinfo,
2221 struct token_info *info, struct ck_info *lib_info, void *input)
2223 struct crt_find_data_st *find_data = input;
2224 struct ck_attribute a[4];
2225 struct ck_attribute *attr;
2226 ck_object_class_t class = (ck_object_class_t)-1;
2227 ck_certificate_type_t type = (ck_certificate_type_t)-1;
2228 unsigned int trusted;
2229 ck_rv_t rv;
2230 ck_object_handle_t obj;
2231 unsigned long count;
2232 uint8_t *cert_data;
2233 char certid_tmp[PKCS11_ID_SIZE];
2234 char label_tmp[PKCS11_LABEL_SIZE];
2235 int ret;
2236 struct pkey_list plist; /* private key holder */
2237 unsigned int i, tot_values = 0;
2239 if (info == NULL)
2240 { /* final call */
2241 if (find_data->current <= *find_data->n_list)
2242 ret = 0;
2243 else
2244 ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
2246 *find_data->n_list = find_data->current;
2248 return ret;
2251 /* do not bother reading the token if basic fields do not match
2253 if (!p11_kit_uri_match_token_info (find_data->info, &info->tinfo) ||
2254 !p11_kit_uri_match_module_info (find_data->info, lib_info))
2256 gnutls_assert ();
2257 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2260 memset (&plist, 0, sizeof (plist));
2262 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2264 ret = find_privkeys (sinfo, info, &plist);
2265 if (ret < 0)
2267 gnutls_assert ();
2268 return ret;
2271 if (plist.key_ids_size == 0)
2273 gnutls_assert ();
2274 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2278 cert_data = gnutls_malloc (MAX_CERT_SIZE);
2279 if (cert_data == NULL)
2281 gnutls_assert ();
2282 return GNUTLS_E_MEMORY_ERROR;
2285 /* Find objects with cert class and X.509 cert type. */
2287 tot_values = 0;
2289 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL
2290 || find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2292 class = CKO_CERTIFICATE;
2293 type = CKC_X_509;
2294 trusted = 1;
2296 a[tot_values].type = CKA_CLASS;
2297 a[tot_values].value = &class;
2298 a[tot_values].value_len = sizeof class;
2299 tot_values++;
2301 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2302 a[tot_values].value = &type;
2303 a[tot_values].value_len = sizeof type;
2304 tot_values++;
2307 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED)
2309 class = CKO_CERTIFICATE;
2310 type = CKC_X_509;
2311 trusted = 1;
2313 a[tot_values].type = CKA_CLASS;
2314 a[tot_values].value = &class;
2315 a[tot_values].value_len = sizeof class;
2316 tot_values++;
2318 a[tot_values].type = CKA_TRUSTED;
2319 a[tot_values].value = &trusted;
2320 a[tot_values].value_len = sizeof trusted;
2321 tot_values++;
2324 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY)
2326 class = CKO_PUBLIC_KEY;
2328 a[tot_values].type = CKA_CLASS;
2329 a[tot_values].value = &class;
2330 a[tot_values].value_len = sizeof class;
2331 tot_values++;
2333 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY)
2335 class = CKO_PRIVATE_KEY;
2337 a[tot_values].type = CKA_CLASS;
2338 a[tot_values].value = &class;
2339 a[tot_values].value_len = sizeof class;
2340 tot_values++;
2342 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL)
2344 if (class != (ck_object_class_t)-1)
2346 a[tot_values].type = CKA_CLASS;
2347 a[tot_values].value = &class;
2348 a[tot_values].value_len = sizeof class;
2349 tot_values++;
2351 if (type != (ck_certificate_type_t)-1)
2353 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2354 a[tot_values].value = &type;
2355 a[tot_values].value_len = sizeof type;
2356 tot_values++;
2359 else
2361 gnutls_assert ();
2362 ret = GNUTLS_E_INVALID_REQUEST;
2363 goto fail;
2366 attr = p11_kit_uri_get_attribute (find_data->info, CKA_ID);
2367 if (attr != NULL)
2369 memcpy (a + tot_values, attr, sizeof (struct ck_attribute));
2370 tot_values++;
2373 rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, tot_values);
2374 if (rv != CKR_OK)
2376 gnutls_assert ();
2377 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
2378 return pkcs11_rv_to_err (rv);
2381 while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1)
2383 gnutls_datum_t label, id, value;
2385 a[0].type = CKA_LABEL;
2386 a[0].value = label_tmp;
2387 a[0].value_len = sizeof label_tmp;
2389 if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK)
2391 label.data = a[0].value;
2392 label.size = a[0].value_len;
2394 else
2396 label.data = NULL;
2397 label.size = 0;
2400 a[0].type = CKA_ID;
2401 a[0].value = certid_tmp;
2402 a[0].value_len = sizeof certid_tmp;
2404 if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK)
2406 id.data = a[0].value;
2407 id.size = a[0].value_len;
2409 else
2411 id.data = NULL;
2412 id.size = 0;
2415 a[0].type = CKA_VALUE;
2416 a[0].value = cert_data;
2417 a[0].value_len = MAX_CERT_SIZE;
2418 if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK)
2420 value.data = a[0].value;
2421 value.size = a[0].value_len;
2423 else
2425 value.data = NULL;
2426 value.size = 0;
2429 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL)
2431 a[0].type = CKA_CLASS;
2432 a[0].value = &class;
2433 a[0].value_len = sizeof class;
2435 pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1);
2438 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2440 for (i = 0; i < plist.key_ids_size; i++)
2442 if (plist.key_ids[i].length !=
2443 a[1].value_len
2444 || memcmp (plist.key_ids[i].data,
2445 a[1].value, a[1].value_len) != 0)
2447 /* not found */
2448 continue;
2453 if (find_data->current < *find_data->n_list)
2455 ret =
2456 gnutls_pkcs11_obj_init (&find_data->p_list[find_data->current]);
2457 if (ret < 0)
2459 gnutls_assert ();
2460 goto fail;
2463 if (class == CKO_PUBLIC_KEY)
2465 ret =
2466 pkcs11_obj_import_pubkey (sinfo->module, sinfo->pks, obj,
2467 find_data->p_list
2468 [find_data->current],
2469 &id, &label,
2470 &info->tinfo, lib_info);
2472 else
2474 ret =
2475 pkcs11_obj_import (class,
2476 find_data->p_list
2477 [find_data->current],
2478 &value, &id, &label,
2479 &info->tinfo, lib_info);
2481 if (ret < 0)
2483 gnutls_assert ();
2484 goto fail;
2488 find_data->current++;
2492 gnutls_free (cert_data);
2493 pkcs11_find_objects_final (sinfo);
2495 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* continue until all tokens have been checked */
2497 fail:
2498 gnutls_free (cert_data);
2499 pkcs11_find_objects_final (sinfo);
2500 if (plist.key_ids != NULL)
2502 for (i = 0; i < plist.key_ids_size; i++)
2504 _gnutls_buffer_clear (&plist.key_ids[i]);
2506 gnutls_free (plist.key_ids);
2508 for (i = 0; i < find_data->current; i++)
2510 gnutls_pkcs11_obj_deinit (find_data->p_list[i]);
2512 find_data->current = 0;
2514 return ret;
2518 * gnutls_pkcs11_obj_list_import_url:
2519 * @p_list: An uninitialized object list (may be NULL)
2520 * @n_list: initially should hold the maximum size of the list. Will contain the actual size.
2521 * @url: A PKCS 11 url identifying a set of objects
2522 * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2523 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2525 * This function will initialize and set values to an object list
2526 * by using all objects identified by a PKCS 11 URL.
2528 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2529 * negative error value.
2531 * Since: 2.12.0
2534 gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list,
2535 unsigned int *n_list,
2536 const char *url,
2537 gnutls_pkcs11_obj_attr_t attrs,
2538 unsigned int flags)
2540 int ret;
2541 struct crt_find_data_st find_data;
2543 memset (&find_data, 0, sizeof (find_data));
2545 /* fill in the find data structure */
2546 find_data.p_list = p_list;
2547 find_data.n_list = n_list;
2548 find_data.flags = attrs;
2549 find_data.current = 0;
2551 if (url == NULL || url[0] == 0)
2553 url = "pkcs11:";
2556 ret = pkcs11_url_to_info (url, &find_data.info);
2557 if (ret < 0)
2559 gnutls_assert ();
2560 return ret;
2563 ret =
2564 _pkcs11_traverse_tokens (find_objs, &find_data, find_data.info,
2565 NULL,
2566 pkcs11_obj_flags_to_int (flags));
2567 p11_kit_uri_free (find_data.info);
2569 if (ret < 0)
2571 gnutls_assert ();
2572 return ret;
2575 return 0;
2579 * gnutls_pkcs11_obj_list_import_url2:
2580 * @p_list: An uninitialized object list (may be NULL)
2581 * @n_list: It will contain the size of the list.
2582 * @url: A PKCS 11 url identifying a set of objects
2583 * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2584 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2586 * This function will initialize and set values to an object list
2587 * by using all objects identified by the PKCS 11 URL. The output
2588 * is stored in @p_list, which will be initialized.
2590 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2591 * negative error value.
2593 * Since: 3.1.0
2596 gnutls_pkcs11_obj_list_import_url2 (gnutls_pkcs11_obj_t ** p_list,
2597 unsigned int *n_list,
2598 const char *url,
2599 gnutls_pkcs11_obj_attr_t attrs,
2600 unsigned int flags)
2602 unsigned int init = 1024;
2603 int ret;
2605 *p_list = gnutls_malloc(sizeof(gnutls_pkcs11_obj_t)*init);
2606 if (*p_list == NULL)
2608 gnutls_assert();
2609 return GNUTLS_E_MEMORY_ERROR;
2612 ret = gnutls_pkcs11_obj_list_import_url( *p_list, &init, url, attrs, flags);
2613 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
2615 *p_list = gnutls_realloc_fast(*p_list, sizeof(gnutls_pkcs11_obj_t)*init);
2616 if (*p_list == NULL)
2617 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2619 ret = gnutls_pkcs11_obj_list_import_url( *p_list, &init, url, attrs, flags);
2622 if (ret < 0)
2624 gnutls_assert();
2625 gnutls_free(*p_list);
2626 *p_list = NULL;
2627 return ret;
2630 *n_list = init;
2631 return 0;
2636 * gnutls_x509_crt_import_pkcs11_url:
2637 * @crt: A certificate of type #gnutls_x509_crt_t
2638 * @url: A PKCS 11 url
2639 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2641 * This function will import a PKCS 11 certificate directly from a token
2642 * without involving the #gnutls_pkcs11_obj_t structure. This function will
2643 * fail if the certificate stored is not of X.509 type.
2645 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2646 * negative error value.
2648 * Since: 2.12.0
2651 gnutls_x509_crt_import_pkcs11_url (gnutls_x509_crt_t crt,
2652 const char *url, unsigned int flags)
2654 gnutls_pkcs11_obj_t pcrt;
2655 int ret;
2657 ret = gnutls_pkcs11_obj_init (&pcrt);
2658 if (ret < 0)
2660 gnutls_assert ();
2661 return ret;
2664 if (crt->pin.cb)
2665 gnutls_pkcs11_obj_set_pin_function (pcrt, crt->pin.cb, crt->pin.data);
2667 ret = gnutls_pkcs11_obj_import_url (pcrt, url, flags);
2668 if (ret < 0)
2670 gnutls_assert ();
2671 goto cleanup;
2674 ret = gnutls_x509_crt_import (crt, &pcrt->raw, GNUTLS_X509_FMT_DER);
2675 if (ret < 0)
2677 gnutls_assert ();
2678 goto cleanup;
2681 ret = 0;
2682 cleanup:
2684 gnutls_pkcs11_obj_deinit (pcrt);
2686 return ret;
2690 * gnutls_x509_crt_import_pkcs11:
2691 * @crt: A certificate of type #gnutls_x509_crt_t
2692 * @pkcs11_crt: A PKCS 11 object that contains a certificate
2694 * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t
2695 * structure.
2697 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2698 * negative error value.
2700 * Since: 2.12.0
2703 gnutls_x509_crt_import_pkcs11 (gnutls_x509_crt_t crt,
2704 gnutls_pkcs11_obj_t pkcs11_crt)
2706 return gnutls_x509_crt_import (crt, &pkcs11_crt->raw, GNUTLS_X509_FMT_DER);
2710 * gnutls_x509_crt_list_import_pkcs11:
2711 * @certs: A list of certificates of type #gnutls_x509_crt_t
2712 * @cert_max: The maximum size of the list
2713 * @objs: A list of PKCS 11 objects
2714 * @flags: 0 for now
2716 * This function will import a PKCS 11 certificate list to a list of
2717 * #gnutls_x509_crt_t structure. These must not be initialized.
2719 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2720 * negative error value.
2722 * Since: 2.12.0
2725 gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs,
2726 unsigned int cert_max,
2727 gnutls_pkcs11_obj_t * const objs,
2728 unsigned int flags)
2730 unsigned int i, j;
2731 int ret;
2733 for (i = 0; i < cert_max; i++)
2735 ret = gnutls_x509_crt_init (&certs[i]);
2736 if (ret < 0)
2738 gnutls_assert ();
2739 goto cleanup;
2742 ret = gnutls_x509_crt_import_pkcs11 (certs[i], objs[i]);
2743 if (ret < 0)
2745 gnutls_assert ();
2746 goto cleanup;
2750 return 0;
2752 cleanup:
2753 for (j = 0; j < i; j++)
2755 gnutls_x509_crt_deinit (certs[j]);
2758 return ret;
2761 static int
2762 find_flags (struct pkcs11_session_info* sinfo,
2763 struct token_info *info, struct ck_info *lib_info, void *input)
2765 struct flags_find_data_st *find_data = input;
2767 if (info == NULL)
2768 { /* we don't support multiple calls */
2769 gnutls_assert ();
2770 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2773 /* do not bother reading the token if basic fields do not match
2775 if (!p11_kit_uri_match_token_info (find_data->info, &info->tinfo) ||
2776 !p11_kit_uri_match_module_info (find_data->info, lib_info))
2778 gnutls_assert ();
2779 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2782 /* found token! */
2784 find_data->slot_flags = info->sinfo.flags;
2786 return 0;
2790 * gnutls_pkcs11_token_get_flags:
2791 * @url: should contain a PKCS 11 URL
2792 * @flags: The output flags (GNUTLS_PKCS11_TOKEN_*)
2794 * This function will return information about the PKCS 11 token flags.
2795 * The flags from the %gnutls_pkcs11_token_info_t enumeration.
2797 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
2799 * Since: 2.12.0
2802 gnutls_pkcs11_token_get_flags (const char *url, unsigned int *flags)
2804 struct flags_find_data_st find_data;
2805 int ret;
2807 memset (&find_data, 0, sizeof (find_data));
2808 ret = pkcs11_url_to_info (url, &find_data.info);
2809 if (ret < 0)
2811 gnutls_assert ();
2812 return ret;
2815 ret = _pkcs11_traverse_tokens (find_flags, &find_data, find_data.info, NULL, 0);
2816 p11_kit_uri_free (find_data.info);
2818 if (ret < 0)
2820 gnutls_assert ();
2821 return ret;
2824 *flags = 0;
2825 if (find_data.slot_flags & CKF_HW_SLOT)
2826 *flags |= GNUTLS_PKCS11_TOKEN_HW;
2828 return 0;
2833 * gnutls_pkcs11_token_get_mechanism:
2834 * @url: should contain a PKCS 11 URL
2835 * @idx: The index of the mechanism
2836 * @mechanism: The PKCS #11 mechanism ID
2838 * This function will return the names of the supported mechanisms
2839 * by the token. It should be called with an increasing index until
2840 * it return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
2842 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
2844 * Since: 2.12.0
2847 gnutls_pkcs11_token_get_mechanism (const char *url, unsigned int idx,
2848 unsigned long *mechanism)
2850 int ret;
2851 ck_rv_t rv;
2852 struct ck_function_list *module;
2853 ck_slot_id_t slot;
2854 struct token_info tinfo;
2855 struct p11_kit_uri *info = NULL;
2856 unsigned long count;
2857 ck_mechanism_type_t mlist[400];
2859 ret = pkcs11_url_to_info (url, &info);
2860 if (ret < 0)
2862 gnutls_assert ();
2863 return ret;
2867 ret = pkcs11_find_slot (&module, &slot, info, &tinfo);
2868 p11_kit_uri_free (info);
2870 if (ret < 0)
2872 gnutls_assert ();
2873 return ret;
2876 count = sizeof (mlist) / sizeof (mlist[0]);
2877 rv = pkcs11_get_mechanism_list (module, slot, mlist, &count);
2878 if (rv != CKR_OK)
2880 gnutls_assert ();
2881 return pkcs11_rv_to_err (rv);
2884 if (idx >= count)
2886 gnutls_assert ();
2887 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2890 *mechanism = mlist[idx];
2892 return 0;
2897 * gnutls_pkcs11_type_get_name:
2898 * @type: Holds the PKCS 11 object type, a #gnutls_pkcs11_obj_type_t.
2900 * This function will return a human readable description of the
2901 * PKCS11 object type @obj. It will return "Unknown" for unknown
2902 * types.
2904 * Returns: human readable string labeling the PKCS11 object type
2905 * @type.
2907 * Since: 2.12.0
2909 const char *
2910 gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t type)
2912 switch (type)
2914 case GNUTLS_PKCS11_OBJ_X509_CRT:
2915 return "X.509 Certificate";
2916 case GNUTLS_PKCS11_OBJ_PUBKEY:
2917 return "Public key";
2918 case GNUTLS_PKCS11_OBJ_PRIVKEY:
2919 return "Private key";
2920 case GNUTLS_PKCS11_OBJ_SECRET_KEY:
2921 return "Secret key";
2922 case GNUTLS_PKCS11_OBJ_DATA:
2923 return "Data";
2924 case GNUTLS_PKCS11_OBJ_UNKNOWN:
2925 default:
2926 return "Unknown";
2930 ck_rv_t
2931 pkcs11_get_slot_list (struct ck_function_list * module, unsigned char token_present,
2932 ck_slot_id_t *slot_list, unsigned long *count)
2934 return (module)->C_GetSlotList (token_present, slot_list, count);
2937 ck_rv_t
2938 pkcs11_get_module_info (struct ck_function_list * module,
2939 struct ck_info * info)
2941 return (module)->C_GetInfo (info);
2944 ck_rv_t
2945 pkcs11_get_slot_info(struct ck_function_list * module,
2946 ck_slot_id_t slot_id,
2947 struct ck_slot_info *info)
2949 return (module)->C_GetSlotInfo (slot_id, info);
2952 ck_rv_t
2953 pkcs11_get_token_info (struct ck_function_list * module,
2954 ck_slot_id_t slot_id,
2955 struct ck_token_info *info)
2957 return (module)->C_GetTokenInfo (slot_id, info);
2960 ck_rv_t
2961 pkcs11_find_objects_init (struct ck_function_list *module,
2962 ck_session_handle_t sess,
2963 struct ck_attribute *templ,
2964 unsigned long count)
2966 return (module)->C_FindObjectsInit (sess, templ, count);
2969 ck_rv_t
2970 pkcs11_find_objects (struct ck_function_list *module,
2971 ck_session_handle_t sess,
2972 ck_object_handle_t *objects,
2973 unsigned long max_object_count,
2974 unsigned long *object_count)
2976 return (module)->C_FindObjects (sess, objects, max_object_count, object_count);
2979 ck_rv_t
2980 pkcs11_find_objects_final (struct pkcs11_session_info* sinfo)
2982 return (sinfo->module)->C_FindObjectsFinal (sinfo->pks);
2985 ck_rv_t
2986 pkcs11_close_session (struct pkcs11_session_info * sinfo)
2988 sinfo->init = 0;
2989 return (sinfo->module)->C_CloseSession (sinfo->pks);
2992 ck_rv_t
2993 pkcs11_get_attribute_value(struct ck_function_list *module,
2994 ck_session_handle_t sess,
2995 ck_object_handle_t object,
2996 struct ck_attribute *templ,
2997 unsigned long count)
2999 return (module)->C_GetAttributeValue (sess, object, templ, count);
3002 ck_rv_t
3003 pkcs11_get_mechanism_list (struct ck_function_list *module,
3004 ck_slot_id_t slot_id,
3005 ck_mechanism_type_t *mechanism_list,
3006 unsigned long *count)
3008 return (module)->C_GetMechanismList (slot_id, mechanism_list, count);
3011 ck_rv_t
3012 pkcs11_sign_init (struct ck_function_list *module,
3013 ck_session_handle_t sess,
3014 struct ck_mechanism *mechanism,
3015 ck_object_handle_t key)
3017 return (module)->C_SignInit (sess, mechanism, key);
3020 ck_rv_t
3021 pkcs11_sign (struct ck_function_list *module,
3022 ck_session_handle_t sess,
3023 unsigned char *data,
3024 unsigned long data_len,
3025 unsigned char *signature,
3026 unsigned long *signature_len)
3028 return (module)->C_Sign (sess, data, data_len, signature, signature_len);
3031 ck_rv_t
3032 pkcs11_generate_key_pair (struct ck_function_list *module,
3033 ck_session_handle_t sess,
3034 struct ck_mechanism *mechanism,
3035 struct ck_attribute *pub_templ,
3036 unsigned long pub_templ_count,
3037 struct ck_attribute *priv_templ,
3038 unsigned long priv_templ_count,
3039 ck_object_handle_t *pub,
3040 ck_object_handle_t *priv)
3042 return (module)->C_GenerateKeyPair (sess, mechanism, pub_templ, pub_templ_count,
3043 priv_templ, priv_templ_count, pub, priv);
3046 ck_rv_t
3047 pkcs11_decrypt_init (struct ck_function_list *module,
3048 ck_session_handle_t sess,
3049 struct ck_mechanism *mechanism,
3050 ck_object_handle_t key)
3052 return (module)->C_DecryptInit (sess, mechanism, key);
3055 ck_rv_t
3056 pkcs11_decrypt (struct ck_function_list *module,
3057 ck_session_handle_t sess,
3058 unsigned char *encrypted_data,
3059 unsigned long encrypted_data_len,
3060 unsigned char *data, unsigned long *data_len)
3062 return (module)->C_Decrypt (sess, encrypted_data, encrypted_data_len,
3063 data, data_len);
3066 ck_rv_t
3067 pkcs11_create_object (struct ck_function_list *module,
3068 ck_session_handle_t sess,
3069 struct ck_attribute *templ,
3070 unsigned long count,
3071 ck_object_handle_t *object)
3073 return (module)->C_CreateObject (sess, templ, count, object);
3076 ck_rv_t
3077 pkcs11_destroy_object (struct ck_function_list *module,
3078 ck_session_handle_t sess,
3079 ck_object_handle_t object)
3081 return (module)->C_DestroyObject (sess, object);
3084 ck_rv_t
3085 pkcs11_init_token (struct ck_function_list *module,
3086 ck_slot_id_t slot_id, unsigned char *pin,
3087 unsigned long pin_len, unsigned char *label)
3089 return (module)->C_InitToken (slot_id, pin, pin_len, label);
3092 ck_rv_t
3093 pkcs11_init_pin (struct ck_function_list *module,
3094 ck_session_handle_t sess,
3095 unsigned char *pin,
3096 unsigned long pin_len)
3098 return (module)->C_InitPIN (sess, pin, pin_len);
3101 ck_rv_t
3102 pkcs11_set_pin (struct ck_function_list *module,
3103 ck_session_handle_t sess,
3104 const char *old_pin,
3105 unsigned long old_len,
3106 const char *new_pin,
3107 unsigned long new_len)
3109 return (module)->C_SetPIN (sess, (uint8_t*)old_pin, old_len, (uint8_t*)new_pin, new_len);
3112 const char *
3113 pkcs11_strerror (ck_rv_t rv)
3115 return p11_kit_strerror (rv);