Added gnutls_pkcs11_advset_pin_function and gnutls_pkcs11_advset_token_function
[gnutls.git] / lib / pkcs11.c
blob907cfbdc374742b3973d6394ecf627d0e72771d0
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>
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_pin_callback_t _gnutls_pin_func;
78 void *_gnutls_pin_data;
80 gnutls_pkcs11_token_callback_t _gnutls_token_func;
81 void *_gnutls_token_data;
83 int
84 pkcs11_rv_to_err (ck_rv_t rv)
86 switch (rv)
88 case CKR_OK:
89 return 0;
90 case CKR_HOST_MEMORY:
91 return GNUTLS_E_MEMORY_ERROR;
92 case CKR_SLOT_ID_INVALID:
93 return GNUTLS_E_PKCS11_SLOT_ERROR;
94 case CKR_ARGUMENTS_BAD:
95 case CKR_MECHANISM_PARAM_INVALID:
96 return GNUTLS_E_INVALID_REQUEST;
97 case CKR_NEED_TO_CREATE_THREADS:
98 case CKR_CANT_LOCK:
99 case CKR_FUNCTION_NOT_PARALLEL:
100 case CKR_MUTEX_BAD:
101 case CKR_MUTEX_NOT_LOCKED:
102 return GNUTLS_E_LOCKING_ERROR;
103 case CKR_ATTRIBUTE_READ_ONLY:
104 case CKR_ATTRIBUTE_SENSITIVE:
105 case CKR_ATTRIBUTE_TYPE_INVALID:
106 case CKR_ATTRIBUTE_VALUE_INVALID:
107 return GNUTLS_E_PKCS11_ATTRIBUTE_ERROR;
108 case CKR_DEVICE_ERROR:
109 case CKR_DEVICE_MEMORY:
110 case CKR_DEVICE_REMOVED:
111 return GNUTLS_E_PKCS11_DEVICE_ERROR;
112 case CKR_DATA_INVALID:
113 case CKR_DATA_LEN_RANGE:
114 case CKR_ENCRYPTED_DATA_INVALID:
115 case CKR_ENCRYPTED_DATA_LEN_RANGE:
116 case CKR_OBJECT_HANDLE_INVALID:
117 return GNUTLS_E_PKCS11_DATA_ERROR;
118 case CKR_FUNCTION_NOT_SUPPORTED:
119 case CKR_MECHANISM_INVALID:
120 return GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR;
121 case CKR_KEY_HANDLE_INVALID:
122 case CKR_KEY_SIZE_RANGE:
123 case CKR_KEY_TYPE_INCONSISTENT:
124 case CKR_KEY_NOT_NEEDED:
125 case CKR_KEY_CHANGED:
126 case CKR_KEY_NEEDED:
127 case CKR_KEY_INDIGESTIBLE:
128 case CKR_KEY_FUNCTION_NOT_PERMITTED:
129 case CKR_KEY_NOT_WRAPPABLE:
130 case CKR_KEY_UNEXTRACTABLE:
131 return GNUTLS_E_PKCS11_KEY_ERROR;
132 case CKR_PIN_INCORRECT:
133 case CKR_PIN_INVALID:
134 case CKR_PIN_LEN_RANGE:
135 return GNUTLS_E_PKCS11_PIN_ERROR;
136 case CKR_PIN_EXPIRED:
137 return GNUTLS_E_PKCS11_PIN_EXPIRED;
138 case CKR_PIN_LOCKED:
139 return GNUTLS_E_PKCS11_PIN_LOCKED;
140 case CKR_SESSION_CLOSED:
141 case CKR_SESSION_COUNT:
142 case CKR_SESSION_HANDLE_INVALID:
143 case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
144 case CKR_SESSION_READ_ONLY:
145 case CKR_SESSION_EXISTS:
146 case CKR_SESSION_READ_ONLY_EXISTS:
147 case CKR_SESSION_READ_WRITE_SO_EXISTS:
148 return GNUTLS_E_PKCS11_SESSION_ERROR;
149 case CKR_SIGNATURE_INVALID:
150 case CKR_SIGNATURE_LEN_RANGE:
151 return GNUTLS_E_PKCS11_SIGNATURE_ERROR;
152 case CKR_TOKEN_NOT_PRESENT:
153 case CKR_TOKEN_NOT_RECOGNIZED:
154 case CKR_TOKEN_WRITE_PROTECTED:
155 return GNUTLS_E_PKCS11_TOKEN_ERROR;
156 case CKR_USER_ALREADY_LOGGED_IN:
157 case CKR_USER_NOT_LOGGED_IN:
158 case CKR_USER_PIN_NOT_INITIALIZED:
159 case CKR_USER_TYPE_INVALID:
160 case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
161 case CKR_USER_TOO_MANY_TYPES:
162 return GNUTLS_E_PKCS11_USER_ERROR;
163 case CKR_BUFFER_TOO_SMALL:
164 return GNUTLS_E_SHORT_MEMORY_BUFFER;
165 default:
166 return GNUTLS_E_PKCS11_ERROR;
170 /* Fake scan */
171 void
172 pkcs11_rescan_slots (void)
174 unsigned long slots;
176 pkcs11_get_slot_list (providers[active_providers - 1].module, 0,
177 NULL, &slots);
180 static int
181 pkcs11_add_module (const char *name, struct ck_function_list *module)
183 struct ck_info info;
184 unsigned int i;
186 if (active_providers >= MAX_PROVIDERS)
188 gnutls_assert ();
189 return GNUTLS_E_CONSTRAINT_ERROR;
192 /* initially check if this module is a duplicate */
193 memset(&info, 0, sizeof(info));
194 pkcs11_get_module_info (module, &info);
195 for (i=0;i<active_providers;i++)
197 /* already loaded, skip the rest */
198 if (memcmp(&info, &providers[i].info, sizeof(info)) == 0)
200 _gnutls_debug_log("%s is already loaded.\n", name);
201 return GNUTLS_E_INT_RET_0;
205 active_providers++;
206 providers[active_providers - 1].module = module;
208 /* cache the number of slots in this module */
209 if (pkcs11_get_slot_list
210 (providers[active_providers - 1].module, 0, NULL,
211 &providers[active_providers - 1].nslots) != CKR_OK)
213 gnutls_assert ();
214 goto fail;
217 providers[active_providers - 1].slots =
218 gnutls_malloc (sizeof (*providers[active_providers - 1].slots) *
219 providers[active_providers - 1].nslots);
220 if (providers[active_providers - 1].slots == NULL)
222 gnutls_assert ();
223 goto fail;
226 if (pkcs11_get_slot_list
227 (providers[active_providers - 1].module, 0,
228 providers[active_providers - 1].slots,
229 &providers[active_providers - 1].nslots) != CKR_OK)
231 gnutls_assert ();
232 gnutls_free (providers[active_providers - 1].slots);
233 goto fail;
236 memcpy (&providers[active_providers - 1].info, &info, sizeof(info));
238 _gnutls_debug_log ("p11: loaded provider '%s' with %d slots\n",
239 name, (int) providers[active_providers - 1].nslots);
241 return 0;
243 fail:
244 active_providers--;
245 return GNUTLS_E_PKCS11_LOAD_ERROR;
250 * gnutls_pkcs11_add_provider:
251 * @name: The filename of the module
252 * @params: should be NULL
254 * This function will load and add a PKCS 11 module to the module
255 * list used in gnutls. After this function is called the module will
256 * be used for PKCS 11 operations.
258 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
259 * negative error value.
261 * Since: 2.12.0
264 gnutls_pkcs11_add_provider (const char *name, const char *params)
266 struct ck_function_list *module;
267 int ret;
269 active_providers++;
270 if (p11_kit_load_initialize_module (name, &module) != CKR_OK)
272 gnutls_assert ();
273 _gnutls_debug_log ("p11: Cannot load provider %s\n", name);
274 active_providers--;
275 return GNUTLS_E_PKCS11_LOAD_ERROR;
278 ret = pkcs11_add_module (name, module);
279 if (ret == 0)
281 /* Mark this one as having been separately initialized */
282 providers[active_providers - 1].initialized = 1;
284 else
286 if (ret == GNUTLS_E_INT_RET_0) ret = 0;
287 p11_kit_finalize_module (module);
288 gnutls_assert ();
291 return ret;
296 * gnutls_pkcs11_obj_get_info:
297 * @crt: should contain a #gnutls_pkcs11_obj_t structure
298 * @itype: Denotes the type of information requested
299 * @output: where output will be stored
300 * @output_size: contains the maximum size of the output and will be overwritten with actual
302 * This function will return information about the PKCS11 certificate
303 * such as the label, id as well as token information where the key is
304 * stored. When output is text it returns null terminated string
305 * although @output_size contains the size of the actual data only.
307 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
309 * Since: 2.12.0
312 gnutls_pkcs11_obj_get_info (gnutls_pkcs11_obj_t crt,
313 gnutls_pkcs11_obj_info_t itype,
314 void *output, size_t * output_size)
316 return pkcs11_get_info (crt->info, itype, output, output_size);
320 pkcs11_get_info (struct p11_kit_uri *info,
321 gnutls_pkcs11_obj_info_t itype, void *output,
322 size_t * output_size)
324 struct ck_attribute *attr = NULL;
325 struct ck_version *version = NULL;
326 const uint8_t *str = NULL;
327 size_t str_max = 0;
328 int terminate = 0;
329 int hexify = 0;
330 size_t length = 0;
331 const char *data = NULL;
332 char buf[32];
335 * Either attr, str or version is valid by the time switch
336 * finishes
339 switch (itype)
341 case GNUTLS_PKCS11_OBJ_ID:
342 attr = p11_kit_uri_get_attribute (info, CKA_ID);
343 break;
344 case GNUTLS_PKCS11_OBJ_ID_HEX:
345 attr = p11_kit_uri_get_attribute (info, CKA_ID);
346 hexify = 1;
347 terminate = 1;
348 break;
349 case GNUTLS_PKCS11_OBJ_LABEL:
350 attr = p11_kit_uri_get_attribute (info, CKA_LABEL);
351 terminate = 1;
352 break;
353 case GNUTLS_PKCS11_OBJ_TOKEN_LABEL:
354 str = p11_kit_uri_get_token_info (info)->label;
355 str_max = 32;
356 break;
357 case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL:
358 str = p11_kit_uri_get_token_info (info)->serial_number;
359 str_max = 16;
360 break;
361 case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER:
362 str = p11_kit_uri_get_token_info (info)->manufacturer_id;
363 str_max = 32;
364 break;
365 case GNUTLS_PKCS11_OBJ_TOKEN_MODEL:
366 str = p11_kit_uri_get_token_info (info)->model;
367 str_max = 16;
368 break;
369 case GNUTLS_PKCS11_OBJ_LIBRARY_DESCRIPTION:
370 str = p11_kit_uri_get_module_info (info)->library_description;
371 str_max = 32;
372 break;
373 case GNUTLS_PKCS11_OBJ_LIBRARY_VERSION:
374 version = &p11_kit_uri_get_module_info (info)->library_version;
375 break;
376 case GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER:
377 str = p11_kit_uri_get_module_info (info)->manufacturer_id;
378 str_max = 32;
379 break;
380 default:
381 gnutls_assert ();
382 return GNUTLS_E_INVALID_REQUEST;
385 if (attr != NULL)
387 data = attr->value;
388 length = attr->value_len;
390 else if (str != NULL)
392 data = (void*)str;
393 length = p11_kit_space_strlen (str, str_max);
394 terminate = 1;
396 else if (version != NULL)
398 data = buf;
399 length = snprintf (buf, sizeof (buf), "%d.%d", (int)version->major,
400 (int)version->minor);
401 terminate = 1;
403 else
405 *output_size = 0;
406 if (output) ((uint8_t*)output)[0] = 0;
407 return 0;
410 if (hexify)
412 /* terminate is assumed with hexify */
413 if (*output_size < length * 3)
415 *output_size = length * 3;
416 return GNUTLS_E_SHORT_MEMORY_BUFFER;
418 if (output)
419 _gnutls_bin2hex (data, length, output, *output_size, ":");
420 *output_size = length * 3;
421 return 0;
423 else
425 if (*output_size < length + terminate)
427 *output_size = length + terminate;
428 return GNUTLS_E_SHORT_MEMORY_BUFFER;
430 if (output)
432 memcpy (output, data, length);
433 if (terminate)
434 ((unsigned char*)output)[length] = '\0';
436 *output_size = length + terminate;
439 return 0;
442 static int init = 0;
444 /* tries to load modules from /etc/gnutls/pkcs11.conf if it exists
446 static void _pkcs11_compat_init(const char* configfile)
448 FILE *fp;
449 int ret;
450 char line[512];
451 const char *library;
453 if (configfile == NULL)
454 configfile = "/etc/gnutls/pkcs11.conf";
456 fp = fopen (configfile, "r");
457 if (fp == NULL)
459 gnutls_assert ();
460 return;
463 _gnutls_debug_log ("Loading PKCS #11 libraries from %s\n", configfile);
464 while (fgets (line, sizeof (line), fp) != NULL)
466 if (strncmp (line, "load", sizeof ("load") - 1) == 0)
468 char *p;
469 p = strchr (line, '=');
470 if (p == NULL)
471 continue;
473 library = ++p;
474 p = strchr (line, '\n');
475 if (p != NULL)
476 *p = 0;
478 ret = gnutls_pkcs11_add_provider (library, NULL);
479 if (ret < 0)
481 gnutls_assert ();
482 _gnutls_debug_log ("Cannot load provider: %s\n", library);
483 continue;
487 fclose(fp);
489 return;
492 static int
493 initialize_automatic_p11_kit (void)
495 struct ck_function_list **modules;
496 char *name;
497 ck_rv_t rv;
498 int i, ret;
500 rv = p11_kit_initialize_registered ();
501 if (rv != CKR_OK)
503 gnutls_assert ();
504 _gnutls_debug_log ("Cannot initialize registered module: %s\n",
505 p11_kit_strerror (rv));
506 return GNUTLS_E_INTERNAL_ERROR;
509 initialized_registered = 1;
511 modules = p11_kit_registered_modules ();
512 for (i = 0; modules[i] != NULL; i++)
514 name = p11_kit_registered_module_to_name (modules[i]);
515 ret = pkcs11_add_module (name, modules[i]);
516 if (ret != 0 && ret != GNUTLS_E_INT_RET_0)
518 gnutls_assert ();
519 _gnutls_debug_log ("Cannot add registered module: %s\n", name);
521 free(name);
524 free (modules);
525 return 0;
529 * gnutls_pkcs11_init:
530 * @flags: %GNUTLS_PKCS11_FLAG_MANUAL or %GNUTLS_PKCS11_FLAG_AUTO
531 * @deprecated_config_file: either NULL or the location of a deprecated
532 * configuration file
534 * This function will initialize the PKCS 11 subsystem in gnutls. It will
535 * read configuration files if %GNUTLS_PKCS11_FLAG_AUTO is used or allow
536 * you to independently load PKCS 11 modules using gnutls_pkcs11_add_provider()
537 * if %GNUTLS_PKCS11_FLAG_MANUAL is specified.
539 * Normally you don't need to call this function since it is being called
540 * by gnutls_global_init() using the %GNUTLS_PKCS11_FLAG_AUTO. If other option
541 * is required then it must be called before it.
543 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
544 * negative error value.
546 * Since: 2.12.0
549 gnutls_pkcs11_init (unsigned int flags, const char *deprecated_config_file)
551 int ret = 0;
553 if (init != 0)
555 init++;
556 return 0;
558 init++;
560 p11_kit_pin_register_callback (P11_KIT_PIN_FALLBACK, p11_kit_pin_file_callback,
561 NULL, NULL);
563 if (flags == GNUTLS_PKCS11_FLAG_MANUAL)
564 return 0;
565 else if (flags == GNUTLS_PKCS11_FLAG_AUTO)
567 if (deprecated_config_file == NULL)
568 ret = initialize_automatic_p11_kit ();
570 _pkcs11_compat_init(deprecated_config_file);
572 return ret;
575 return 0;
579 * gnutls_pkcs11_reinit:
581 * This function will reinitialize the PKCS 11 subsystem in gnutls.
582 * This is required by PKCS 11 when an application uses fork(). The
583 * reinitialization function must be called on the child.
585 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
586 * negative error value.
588 * Since: 3.0
590 int gnutls_pkcs11_reinit (void)
592 int rv;
594 rv = p11_kit_initialize_registered ();
595 if (rv != CKR_OK)
597 gnutls_assert ();
598 _gnutls_debug_log ("Cannot initialize registered module: %s\n",
599 p11_kit_strerror (rv));
600 return GNUTLS_E_INTERNAL_ERROR;
603 return 0;
607 * gnutls_pkcs11_deinit:
609 * This function will deinitialize the PKCS 11 subsystem in gnutls.
611 * Since: 2.12.0
613 void
614 gnutls_pkcs11_deinit (void)
616 unsigned int i;
618 init--;
619 if (init > 0)
620 return;
621 if (init < 0)
623 init = 0;
624 return;
627 for (i = 0; i < active_providers; i++)
629 if (providers[i].initialized)
630 p11_kit_finalize_module (providers[i].module);
632 active_providers = 0;
634 if (initialized_registered != 0)
635 p11_kit_finalize_registered ();
636 initialized_registered = 0;
638 gnutls_pkcs11_set_pin_function (NULL, NULL);
639 gnutls_pkcs11_set_token_function (NULL, NULL);
643 * gnutls_pkcs11_set_pin_function:
644 * @fn: The PIN callback, a gnutls_pkcs11_pin_callback_t() function.
645 * @userdata: data to be supplied to callback
647 * This function will set a callback function to be used when a PIN is
648 * required for PKCS 11 operations. See
649 * gnutls_pkcs11_pin_callback_t() on how the callback should behave.
651 * Since: 2.12.0
653 void
654 gnutls_pkcs11_set_pin_function (gnutls_pkcs11_pin_callback_t fn,
655 void *userdata)
657 _gnutls_pin_func = fn;
658 _gnutls_pin_data = userdata;
662 * gnutls_pkcs11_advset_pin_function:
663 * @fn: The PIN callback, a gnutls_pkcs11_pin_callback_t() function.
664 * @userdata: data to be supplied to callback
666 * This function will set a callback function to be used when a PIN is
667 * required for PKCS 11 operations. See
668 * gnutls_pkcs11_pin_callback_t() on how the callback should behave.
670 * This function unlike gnutls_pkcs11_set_pin_function() will only
671 * set the provided function if it has not previously been set.
673 * Since: 3.1.0
675 void
676 gnutls_pkcs11_advset_pin_function (gnutls_pkcs11_pin_callback_t fn,
677 void *userdata)
679 if (_gnutls_pin_func == NULL)
681 _gnutls_pin_func = fn;
682 _gnutls_pin_data = userdata;
687 * gnutls_pkcs11_set_token_function:
688 * @fn: The token callback
689 * @userdata: data to be supplied to callback
691 * This function will set a callback function to be used when a token
692 * needs to be inserted to continue PKCS 11 operations.
694 * Since: 2.12.0
696 void
697 gnutls_pkcs11_set_token_function (gnutls_pkcs11_token_callback_t fn,
698 void *userdata)
700 _gnutls_token_func = fn;
701 _gnutls_token_data = userdata;
705 * gnutls_pkcs11_advset_token_function:
706 * @fn: The token callback
707 * @userdata: data to be supplied to callback
709 * This function will set a callback function to be used when a token
710 * needs to be inserted to continue PKCS 11 operations.
712 * This function unlike gnutls_pkcs11_set_token_function() will only
713 * set the provided function if it has not previously been set.
715 * Since: 3.1.0
717 void
718 gnutls_pkcs11_advset_token_function (gnutls_pkcs11_token_callback_t fn,
719 void *userdata)
721 if (_gnutls_token_func==NULL)
723 _gnutls_token_func = fn;
724 _gnutls_token_data = userdata;
729 pkcs11_url_to_info (const char *url, struct p11_kit_uri **info)
731 int allocated = 0;
732 int ret;
734 if (*info == NULL)
736 *info = p11_kit_uri_new ();
737 if (*info == NULL)
739 gnutls_assert ();
740 return GNUTLS_E_MEMORY_ERROR;
742 allocated = 1;
745 ret = p11_kit_uri_parse (url, P11_KIT_URI_FOR_ANY, *info);
746 if (ret < 0)
748 if (allocated)
750 p11_kit_uri_free (*info);
751 *info = NULL;
753 gnutls_assert ();
754 return ret == P11_KIT_URI_NO_MEMORY ?
755 GNUTLS_E_MEMORY_ERROR : GNUTLS_E_PARSING_ERROR;
758 return 0;
762 pkcs11_info_to_url (struct p11_kit_uri *info,
763 gnutls_pkcs11_url_type_t detailed, char **url)
765 p11_kit_uri_type_t type = 0;
766 int ret;
768 switch (detailed)
770 case GNUTLS_PKCS11_URL_GENERIC:
771 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN;
772 break;
773 case GNUTLS_PKCS11_URL_LIB:
774 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE;
775 break;
776 case GNUTLS_PKCS11_URL_LIB_VERSION:
777 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE | P11_KIT_URI_FOR_MODULE_WITH_VERSION;
778 break;
781 ret = p11_kit_uri_format (info, type, url);
782 if (ret < 0)
784 gnutls_assert ();
785 return ret == P11_KIT_URI_NO_MEMORY ?
786 GNUTLS_E_MEMORY_ERROR : GNUTLS_E_INTERNAL_ERROR;
789 return 0;
793 * gnutls_pkcs11_obj_init:
794 * @obj: The structure to be initialized
796 * This function will initialize a pkcs11 certificate structure.
798 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
799 * negative error value.
801 * Since: 2.12.0
804 gnutls_pkcs11_obj_init (gnutls_pkcs11_obj_t * obj)
806 *obj = gnutls_calloc (1, sizeof (struct gnutls_pkcs11_obj_st));
807 if (*obj == NULL)
809 gnutls_assert ();
810 return GNUTLS_E_MEMORY_ERROR;
813 (*obj)->info = p11_kit_uri_new ();
814 if ((*obj)->info == NULL)
816 free (*obj);
817 gnutls_assert ();
818 return GNUTLS_E_MEMORY_ERROR;
821 return 0;
825 * gnutls_pkcs11_obj_deinit:
826 * @obj: The structure to be initialized
828 * This function will deinitialize a certificate structure.
830 * Since: 2.12.0
832 void
833 gnutls_pkcs11_obj_deinit (gnutls_pkcs11_obj_t obj)
835 _gnutls_free_datum (&obj->raw);
836 p11_kit_uri_free (obj->info);
837 free (obj);
841 * gnutls_pkcs11_obj_export:
842 * @obj: Holds the object
843 * @output_data: will contain a certificate PEM or DER encoded
844 * @output_data_size: holds the size of output_data (and will be
845 * replaced by the actual size of parameters)
847 * This function will export the PKCS11 object data. It is normal for
848 * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
849 * will be returned.
851 * If the buffer provided is not long enough to hold the output, then
852 * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
853 * be returned.
855 * If the structure is PEM encoded, it will have a header
856 * of "BEGIN CERTIFICATE".
858 * Returns: In case of failure a negative error code will be
859 * returned, and %GNUTLS_E_SUCCESS (0) on success.
861 * Since: 2.12.0
864 gnutls_pkcs11_obj_export (gnutls_pkcs11_obj_t obj,
865 void *output_data, size_t * output_data_size)
867 if (obj == NULL || obj->raw.data == NULL)
869 gnutls_assert ();
870 return GNUTLS_E_INVALID_REQUEST;
873 if (output_data == NULL || *output_data_size < obj->raw.size)
875 *output_data_size = obj->raw.size;
876 gnutls_assert ();
877 return GNUTLS_E_SHORT_MEMORY_BUFFER;
879 *output_data_size = obj->raw.size;
881 memcpy (output_data, obj->raw.data, obj->raw.size);
882 return 0;
886 pkcs11_find_object (struct pkcs11_session_info* sinfo,
887 ck_object_handle_t * _obj,
888 struct p11_kit_uri *info, unsigned int flags)
890 int ret;
891 ck_object_handle_t obj;
892 struct ck_attribute *attrs;
893 unsigned long attr_count;
894 unsigned long count;
895 ck_rv_t rv;
897 ret = pkcs11_open_session (sinfo, info, flags & SESSION_LOGIN);
898 if (ret < 0)
900 gnutls_assert ();
901 return ret;
904 attrs = p11_kit_uri_get_attributes (info, &attr_count);
905 rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, attrs, attr_count);
906 if (rv != CKR_OK)
908 gnutls_assert ();
909 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
910 ret = pkcs11_rv_to_err (rv);
911 goto fail;
914 if (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1)
916 *_obj = obj;
917 pkcs11_find_objects_final (sinfo);
918 return 0;
921 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
922 pkcs11_find_objects_final (sinfo);
923 fail:
924 pkcs11_close_session (sinfo);
926 return ret;
930 pkcs11_find_slot (struct ck_function_list ** module, ck_slot_id_t * slot,
931 struct p11_kit_uri *info, struct token_info *_tinfo)
933 unsigned int x, z;
935 for (x = 0; x < active_providers; x++)
937 for (z = 0; z < providers[x].nslots; z++)
939 struct token_info tinfo;
941 if (pkcs11_get_token_info
942 (providers[x].module, providers[x].slots[z],
943 &tinfo.tinfo) != CKR_OK)
945 continue;
947 tinfo.sid = providers[x].slots[z];
948 tinfo.prov = &providers[x];
950 if (pkcs11_get_slot_info
951 (providers[x].module, providers[x].slots[z],
952 &tinfo.sinfo) != CKR_OK)
954 continue;
957 if (!p11_kit_uri_match_token_info (info, &tinfo.tinfo) ||
958 !p11_kit_uri_match_module_info (info, &providers[x].info))
960 continue;
963 /* ok found */
964 *module = providers[x].module;
965 *slot = providers[x].slots[z];
967 if (_tinfo != NULL)
968 memcpy (_tinfo, &tinfo, sizeof (tinfo));
970 return 0;
974 gnutls_assert ();
975 return GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE;
979 pkcs11_open_session (struct pkcs11_session_info *sinfo, struct p11_kit_uri *info,
980 unsigned int flags)
982 ck_rv_t rv;
983 int ret;
984 ck_session_handle_t pks = 0;
985 struct ck_function_list *module;
986 ck_slot_id_t slot;
987 struct token_info tinfo;
989 ret = pkcs11_find_slot (&module, &slot, info, &tinfo);
990 if (ret < 0)
992 gnutls_assert ();
993 return ret;
996 rv = (module)->C_OpenSession (slot,
997 ((flags & SESSION_WRITE)
998 ? CKF_RW_SESSION : 0) |
999 CKF_SERIAL_SESSION, NULL, NULL, &pks);
1000 if (rv != CKR_OK)
1002 gnutls_assert ();
1003 return pkcs11_rv_to_err (rv);
1006 /* ok found */
1007 sinfo->pks = pks;
1008 sinfo->module = module;
1009 sinfo->init = 1;
1010 memcpy(&sinfo->tinfo, &tinfo.tinfo, sizeof(sinfo->tinfo));
1012 if (flags & SESSION_LOGIN)
1014 ret = pkcs11_login (sinfo, &tinfo, info, (flags & SESSION_SO) ? 1 : 0);
1015 if (ret < 0)
1017 gnutls_assert ();
1018 pkcs11_close_session (sinfo);
1019 return ret;
1023 return 0;
1028 _pkcs11_traverse_tokens (find_func_t find_func, void *input,
1029 struct p11_kit_uri *info, unsigned int flags)
1031 ck_rv_t rv;
1032 unsigned int found = 0, x, z;
1033 int ret;
1034 ck_session_handle_t pks = 0;
1035 struct pkcs11_session_info sinfo;
1036 struct ck_function_list *module = NULL;
1038 for (x = 0; x < active_providers; x++)
1040 module = providers[x].module;
1041 for (z = 0; z < providers[x].nslots; z++)
1043 struct token_info tinfo;
1045 ret = GNUTLS_E_PKCS11_ERROR;
1047 if (pkcs11_get_token_info (module, providers[x].slots[z],
1048 &tinfo.tinfo) != CKR_OK)
1050 continue;
1052 tinfo.sid = providers[x].slots[z];
1053 tinfo.prov = &providers[x];
1055 if (pkcs11_get_slot_info (module, providers[x].slots[z],
1056 &tinfo.sinfo) != CKR_OK)
1058 continue;
1061 rv = (module)->C_OpenSession (providers[x].slots[z],
1062 ((flags & SESSION_WRITE)
1063 ? CKF_RW_SESSION : 0) |
1064 CKF_SERIAL_SESSION, NULL, NULL, &pks);
1065 if (rv != CKR_OK)
1067 continue;
1070 sinfo.module = module;
1071 sinfo.pks = pks;
1073 if (flags & SESSION_LOGIN)
1075 ret = pkcs11_login (&sinfo, &tinfo, info, (flags & SESSION_SO) ? 1 : 0);
1076 if (ret < 0)
1078 gnutls_assert ();
1079 return ret;
1083 ret = find_func (&sinfo, &tinfo, &providers[x].info, input);
1085 if (ret == 0)
1087 found = 1;
1088 goto finish;
1090 else
1092 pkcs11_close_session (&sinfo);
1093 pks = 0;
1098 finish:
1099 /* final call */
1101 if (found == 0)
1103 if (module)
1105 sinfo.module = module;
1106 sinfo.pks = pks;
1107 ret = find_func (&sinfo, NULL, NULL, input);
1109 else
1110 ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1112 else
1114 ret = 0;
1117 if (pks != 0 && module != NULL)
1119 pkcs11_close_session (&sinfo);
1122 return ret;
1125 /* imports a raw certificate from a token to a pkcs11_obj_t structure.
1127 static int
1128 pkcs11_obj_import (ck_object_class_t class, gnutls_pkcs11_obj_t obj,
1129 const gnutls_datum_t * data,
1130 const gnutls_datum_t * id,
1131 const gnutls_datum_t * label,
1132 struct ck_token_info *tinfo, struct ck_info *lib_info)
1134 struct ck_attribute attr;
1135 int ret;
1137 switch (class)
1139 case CKO_CERTIFICATE:
1140 obj->type = GNUTLS_PKCS11_OBJ_X509_CRT;
1141 break;
1142 case CKO_PUBLIC_KEY:
1143 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1144 break;
1145 case CKO_PRIVATE_KEY:
1146 obj->type = GNUTLS_PKCS11_OBJ_PRIVKEY;
1147 break;
1148 case CKO_SECRET_KEY:
1149 obj->type = GNUTLS_PKCS11_OBJ_SECRET_KEY;
1150 break;
1151 case CKO_DATA:
1152 obj->type = GNUTLS_PKCS11_OBJ_DATA;
1153 break;
1154 default:
1155 obj->type = GNUTLS_PKCS11_OBJ_UNKNOWN;
1158 attr.type = CKA_CLASS;
1159 attr.value = &class;
1160 attr.value_len = sizeof (class);
1161 ret = p11_kit_uri_set_attribute (obj->info, &attr);
1162 if (ret < 0)
1164 gnutls_assert ();
1165 return GNUTLS_E_MEMORY_ERROR;
1168 if (data && data->data)
1170 ret = _gnutls_set_datum (&obj->raw, data->data, data->size);
1171 if (ret < 0)
1173 gnutls_assert ();
1174 return ret;
1178 /* copy the token and library info into the uri */
1179 memcpy (p11_kit_uri_get_token_info (obj->info), tinfo, sizeof (struct ck_token_info));
1180 memcpy (p11_kit_uri_get_module_info (obj->info), lib_info, sizeof (struct ck_info));
1182 if (label && label->data)
1184 attr.type = CKA_LABEL;
1185 attr.value = label->data;
1186 attr.value_len = label->size;
1187 ret = p11_kit_uri_set_attribute (obj->info, &attr);
1188 if (ret < 0)
1190 gnutls_assert ();
1191 return GNUTLS_E_MEMORY_ERROR;
1195 if (id && id->data)
1197 attr.type = CKA_ID;
1198 attr.value = id->data;
1199 attr.value_len = id->size;
1200 ret = p11_kit_uri_set_attribute (obj->info, &attr);
1201 if (ret < 0)
1203 gnutls_assert ();
1204 return GNUTLS_E_MEMORY_ERROR;
1208 return 0;
1211 static int read_pkcs11_pubkey(struct ck_function_list *module,
1212 ck_session_handle_t pks, ck_object_handle_t obj,
1213 ck_key_type_t key_type, gnutls_datum_t * pubkey)
1215 struct ck_attribute a[4];
1216 uint8_t tmp1[2048];
1217 uint8_t tmp2[2048];
1218 int ret;
1220 switch (key_type)
1222 case CKK_RSA:
1223 a[0].type = CKA_MODULUS;
1224 a[0].value = tmp1;
1225 a[0].value_len = sizeof (tmp1);
1226 a[1].type = CKA_PUBLIC_EXPONENT;
1227 a[1].value = tmp2;
1228 a[1].value_len = sizeof (tmp2);
1230 if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
1233 ret =
1234 _gnutls_set_datum (&pubkey[0],
1235 a[0].value, a[0].value_len);
1237 if (ret >= 0)
1238 ret =
1239 _gnutls_set_datum (&pubkey
1240 [1], a[1].value, a[1].value_len);
1242 if (ret < 0)
1244 gnutls_assert ();
1245 _gnutls_free_datum (&pubkey[1]);
1246 _gnutls_free_datum (&pubkey[0]);
1247 return GNUTLS_E_MEMORY_ERROR;
1250 else
1252 gnutls_assert ();
1253 return GNUTLS_E_PKCS11_ERROR;
1255 break;
1256 case CKK_DSA:
1257 a[0].type = CKA_PRIME;
1258 a[0].value = tmp1;
1259 a[0].value_len = sizeof (tmp1);
1260 a[1].type = CKA_SUBPRIME;
1261 a[1].value = tmp2;
1262 a[1].value_len = sizeof (tmp2);
1264 if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
1266 ret =
1267 _gnutls_set_datum (&pubkey[0],
1268 a[0].value, a[0].value_len);
1270 if (ret >= 0)
1271 ret =
1272 _gnutls_set_datum (&pubkey
1273 [1], a[1].value, a[1].value_len);
1275 if (ret < 0)
1277 gnutls_assert ();
1278 _gnutls_free_datum (&pubkey[1]);
1279 _gnutls_free_datum (&pubkey[0]);
1280 return GNUTLS_E_MEMORY_ERROR;
1283 else
1285 gnutls_assert ();
1286 return GNUTLS_E_PKCS11_ERROR;
1289 a[0].type = CKA_BASE;
1290 a[0].value = tmp1;
1291 a[0].value_len = sizeof (tmp1);
1292 a[1].type = CKA_VALUE;
1293 a[1].value = tmp2;
1294 a[1].value_len = sizeof (tmp2);
1296 if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
1298 ret =
1299 _gnutls_set_datum (&pubkey[2],
1300 a[0].value, a[0].value_len);
1302 if (ret >= 0)
1303 ret =
1304 _gnutls_set_datum (&pubkey
1305 [3], a[1].value, a[1].value_len);
1307 if (ret < 0)
1309 gnutls_assert ();
1310 _gnutls_free_datum (&pubkey[0]);
1311 _gnutls_free_datum (&pubkey[1]);
1312 _gnutls_free_datum (&pubkey[2]);
1313 _gnutls_free_datum (&pubkey[3]);
1314 return GNUTLS_E_MEMORY_ERROR;
1317 else
1319 gnutls_assert ();
1320 return GNUTLS_E_PKCS11_ERROR;
1322 break;
1323 case CKK_ECDSA:
1324 a[0].type = CKA_EC_PARAMS;
1325 a[0].value = tmp1;
1326 a[0].value_len = sizeof (tmp1);
1327 a[1].type = CKA_EC_POINT;
1328 a[1].value = tmp2;
1329 a[1].value_len = sizeof (tmp2);
1331 if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
1333 ret =
1334 _gnutls_set_datum (&pubkey[0],
1335 a[0].value, a[0].value_len);
1337 if (ret >= 0)
1338 ret =
1339 _gnutls_set_datum (&pubkey
1340 [1], a[1].value, a[1].value_len);
1342 if (ret < 0)
1344 gnutls_assert ();
1345 _gnutls_free_datum (&pubkey[1]);
1346 _gnutls_free_datum (&pubkey[0]);
1347 return GNUTLS_E_MEMORY_ERROR;
1350 else
1352 gnutls_assert ();
1353 return GNUTLS_E_PKCS11_ERROR;
1356 break;
1357 default:
1358 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1361 return 0;
1364 static int
1365 pkcs11_obj_import_pubkey (struct ck_function_list *module,
1366 ck_session_handle_t pks,
1367 ck_object_handle_t obj,
1368 gnutls_pkcs11_obj_t crt,
1369 const gnutls_datum_t * id,
1370 const gnutls_datum_t * label,
1371 struct ck_token_info *tinfo,
1372 struct ck_info *lib_info)
1374 struct ck_attribute a[4];
1375 ck_key_type_t key_type;
1376 int ret;
1377 ck_bool_t tval;
1379 a[0].type = CKA_KEY_TYPE;
1380 a[0].value = &key_type;
1381 a[0].value_len = sizeof (key_type);
1383 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1385 crt->pk_algorithm = mech_to_pk(key_type);
1387 ret = read_pkcs11_pubkey(module, pks, obj, key_type, crt->pubkey);
1388 if (ret < 0)
1389 return gnutls_assert_val(ret);
1392 /* read key usage flags */
1393 a[0].type = CKA_ENCRYPT;
1394 a[0].value = &tval;
1395 a[0].value_len = sizeof (tval);
1397 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1399 if (tval != 0)
1401 crt->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
1405 a[0].type = CKA_VERIFY;
1406 a[0].value = &tval;
1407 a[0].value_len = sizeof (tval);
1409 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1411 if (tval != 0)
1413 crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1414 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1415 | GNUTLS_KEY_NON_REPUDIATION;
1419 a[0].type = CKA_VERIFY_RECOVER;
1420 a[0].value = &tval;
1421 a[0].value_len = sizeof (tval);
1423 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1425 if (tval != 0)
1427 crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1428 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1429 | GNUTLS_KEY_NON_REPUDIATION;
1433 a[0].type = CKA_DERIVE;
1434 a[0].value = &tval;
1435 a[0].value_len = sizeof (tval);
1437 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1439 if (tval != 0)
1441 crt->key_usage |= GNUTLS_KEY_KEY_AGREEMENT;
1445 a[0].type = CKA_WRAP;
1446 a[0].value = &tval;
1447 a[0].value_len = sizeof (tval);
1449 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1451 if (tval != 0)
1453 crt->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
1457 return pkcs11_obj_import (CKO_PUBLIC_KEY, crt, NULL, id, label,
1458 tinfo, lib_info);
1461 static int
1462 find_obj_url (struct pkcs11_session_info *sinfo,
1463 struct token_info *info, struct ck_info *lib_info, void *input)
1465 struct url_find_data_st *find_data = input;
1466 struct ck_attribute a[4];
1467 struct ck_attribute *attr;
1468 ck_object_class_t class = -1;
1469 ck_certificate_type_t type = (ck_certificate_type_t)-1;
1470 ck_rv_t rv;
1471 ck_object_handle_t obj;
1472 unsigned long count, a_vals;
1473 int found = 0, ret;
1474 uint8_t *cert_data = NULL;
1475 char label_tmp[PKCS11_LABEL_SIZE];
1476 char id_tmp[PKCS11_ID_SIZE];
1478 if (info == NULL)
1479 { /* we don't support multiple calls */
1480 gnutls_assert ();
1481 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1484 /* do not bother reading the token if basic fields do not match
1486 if (!p11_kit_uri_match_token_info (find_data->crt->info, &info->tinfo) ||
1487 !p11_kit_uri_match_module_info (find_data->crt->info, lib_info))
1489 gnutls_assert ();
1490 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1493 a_vals = 0;
1494 attr = p11_kit_uri_get_attribute (find_data->crt->info, CKA_ID);
1495 if (attr)
1497 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
1498 a_vals++;
1501 attr = p11_kit_uri_get_attribute (find_data->crt->info, CKA_LABEL);
1502 if (attr)
1504 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
1505 a_vals++;
1508 if (!a_vals)
1510 gnutls_assert ();
1511 return GNUTLS_E_INVALID_REQUEST;
1514 /* search the token for the id */
1516 cert_data = gnutls_malloc (MAX_CERT_SIZE);
1517 if (cert_data == NULL)
1519 gnutls_assert ();
1520 return GNUTLS_E_MEMORY_ERROR;
1523 /* Find objects with given class and type */
1524 attr = p11_kit_uri_get_attribute (find_data->crt->info, CKA_CLASS);
1525 if (attr)
1527 if(attr->value && attr->value_len == sizeof (ck_object_class_t))
1528 class = *((ck_object_class_t*)attr->value);
1529 if (class == CKO_CERTIFICATE)
1530 type = CKC_X_509;
1531 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
1532 a_vals++;
1535 if (type != (ck_certificate_type_t)-1)
1537 a[a_vals].type = CKA_CERTIFICATE_TYPE;
1538 a[a_vals].value = &type;
1539 a[a_vals].value_len = sizeof type;
1540 a_vals++;
1543 rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, a_vals);
1544 if (rv != CKR_OK)
1546 gnutls_assert ();
1547 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
1548 ret = pkcs11_rv_to_err (rv);
1549 goto cleanup;
1552 while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1)
1555 a[0].type = CKA_VALUE;
1556 a[0].value = cert_data;
1557 a[0].value_len = MAX_CERT_SIZE;
1558 a[1].type = CKA_LABEL;
1559 a[1].value = label_tmp;
1560 a[1].value_len = sizeof (label_tmp);
1561 a[2].type = CKA_ID;
1562 a[2].value = id_tmp;
1563 a[2].value_len = sizeof(id_tmp);
1565 if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 3) == CKR_OK)
1567 gnutls_datum_t id = { a[2].value, a[2].value_len };
1568 gnutls_datum_t data = { a[0].value, a[0].value_len };
1569 gnutls_datum_t label = { a[1].value, a[1].value_len };
1571 if (class == CKO_PUBLIC_KEY)
1573 ret =
1574 pkcs11_obj_import_pubkey (sinfo->module, sinfo->pks, obj,
1575 find_data->crt,
1576 &id, &label,
1577 &info->tinfo, lib_info);
1579 else
1581 ret =
1582 pkcs11_obj_import (class,
1583 find_data->crt,
1584 &data, &id, &label,
1585 &info->tinfo, lib_info);
1587 if (ret < 0)
1589 gnutls_assert ();
1590 goto cleanup;
1593 found = 1;
1594 break;
1596 else
1598 _gnutls_debug_log ("pk11: Skipped cert, missing attrs.\n");
1602 if (found == 0)
1604 gnutls_assert ();
1605 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1607 else
1609 ret = 0;
1612 cleanup:
1613 gnutls_free (cert_data);
1614 pkcs11_find_objects_final (sinfo);
1616 return ret;
1619 unsigned int
1620 pkcs11_obj_flags_to_int (unsigned int flags)
1622 unsigned int ret_flags = 0;
1624 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN)
1625 ret_flags |= SESSION_LOGIN;
1626 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO)
1627 ret_flags |= SESSION_LOGIN|SESSION_SO;
1629 return ret_flags;
1633 * gnutls_pkcs11_obj_import_url:
1634 * @cert: The structure to store the parsed certificate
1635 * @url: a PKCS 11 url identifying the key
1636 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1638 * This function will "import" a PKCS 11 URL identifying a certificate
1639 * key to the #gnutls_pkcs11_obj_t structure. This does not involve any
1640 * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is
1641 * format agnostic. Only data are transferred.
1643 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1644 * negative error value.
1646 * Since: 2.12.0
1649 gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t cert, const char *url,
1650 unsigned int flags)
1652 int ret;
1653 struct url_find_data_st find_data;
1655 /* fill in the find data structure */
1656 find_data.crt = cert;
1658 ret = pkcs11_url_to_info (url, &cert->info);
1659 if (ret < 0)
1661 gnutls_assert ();
1662 return ret;
1665 ret =
1666 _pkcs11_traverse_tokens (find_obj_url, &find_data, cert->info,
1667 pkcs11_obj_flags_to_int (flags));
1669 if (ret < 0)
1671 gnutls_assert ();
1672 return ret;
1675 return 0;
1678 struct token_num
1680 struct p11_kit_uri *info;
1681 unsigned int seq; /* which one we are looking for */
1682 unsigned int current; /* which one are we now */
1685 static int
1686 find_token_num (struct pkcs11_session_info* sinfo,
1687 struct token_info *tinfo,
1688 struct ck_info *lib_info, void *input)
1690 struct token_num *find_data = input;
1692 if (tinfo == NULL)
1693 { /* we don't support multiple calls */
1694 gnutls_assert ();
1695 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1698 if (find_data->current == find_data->seq)
1700 memcpy (p11_kit_uri_get_token_info (find_data->info), &tinfo->tinfo, sizeof (struct ck_token_info));
1701 memcpy (p11_kit_uri_get_module_info (find_data->info), lib_info, sizeof (struct ck_info));
1702 return 0;
1705 find_data->current++;
1706 /* search the token for the id */
1709 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* non zero is enough */
1713 * gnutls_pkcs11_token_get_url:
1714 * @seq: sequence number starting from 0
1715 * @detailed: non zero if a detailed URL is required
1716 * @url: will contain an allocated url
1718 * This function will return the URL for each token available
1719 * in system. The url has to be released using gnutls_free()
1721 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
1722 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if the sequence number
1723 * exceeds the available tokens, otherwise a negative error value.
1725 * Since: 2.12.0
1728 gnutls_pkcs11_token_get_url (unsigned int seq,
1729 gnutls_pkcs11_url_type_t detailed, char **url)
1731 int ret;
1732 struct token_num tn;
1734 memset (&tn, 0, sizeof (tn));
1735 tn.seq = seq;
1736 tn.info = p11_kit_uri_new ();
1738 ret = _pkcs11_traverse_tokens (find_token_num, &tn, NULL, 0);
1739 if (ret < 0)
1741 p11_kit_uri_free (tn.info);
1742 gnutls_assert ();
1743 return ret;
1746 ret = pkcs11_info_to_url (tn.info, detailed, url);
1747 p11_kit_uri_free (tn.info);
1749 if (ret < 0)
1751 gnutls_assert ();
1752 return ret;
1755 return 0;
1760 * gnutls_pkcs11_token_get_info:
1761 * @url: should contain a PKCS 11 URL
1762 * @ttype: Denotes the type of information requested
1763 * @output: where output will be stored
1764 * @output_size: contains the maximum size of the output and will be overwritten with actual
1766 * This function will return information about the PKCS 11 token such
1767 * as the label, id, etc.
1769 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code
1770 * on error.
1772 * Since: 2.12.0
1775 gnutls_pkcs11_token_get_info (const char *url,
1776 gnutls_pkcs11_token_info_t ttype,
1777 void *output, size_t * output_size)
1779 struct p11_kit_uri *info = NULL;
1780 const uint8_t *str;
1781 size_t str_max;
1782 size_t len;
1783 int ret;
1785 ret = pkcs11_url_to_info (url, &info);
1786 if (ret < 0)
1788 gnutls_assert ();
1789 return ret;
1792 switch (ttype)
1794 case GNUTLS_PKCS11_TOKEN_LABEL:
1795 str = p11_kit_uri_get_token_info (info)->label;
1796 str_max = 32;
1797 break;
1798 case GNUTLS_PKCS11_TOKEN_SERIAL:
1799 str = p11_kit_uri_get_token_info (info)->serial_number;
1800 str_max = 16;
1801 break;
1802 case GNUTLS_PKCS11_TOKEN_MANUFACTURER:
1803 str = p11_kit_uri_get_token_info (info)->manufacturer_id;
1804 str_max = 32;
1805 break;
1806 case GNUTLS_PKCS11_TOKEN_MODEL:
1807 str = p11_kit_uri_get_token_info (info)->model;
1808 str_max = 16;
1809 break;
1810 default:
1811 p11_kit_uri_free (info);
1812 gnutls_assert ();
1813 return GNUTLS_E_INVALID_REQUEST;
1816 len = p11_kit_space_strlen (str, str_max);
1818 if (len + 1 > *output_size)
1820 *output_size = len + 1;
1821 return GNUTLS_E_SHORT_MEMORY_BUFFER;
1824 memcpy (output, str, len);
1825 ((char*)output)[len] = '\0';
1827 *output_size = len;
1829 p11_kit_uri_free (info);
1830 return 0;
1834 * gnutls_pkcs11_obj_export_url:
1835 * @obj: Holds the PKCS 11 certificate
1836 * @detailed: non zero if a detailed URL is required
1837 * @url: will contain an allocated url
1839 * This function will export a URL identifying the given certificate.
1841 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1842 * negative error value.
1844 * Since: 2.12.0
1847 gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t obj,
1848 gnutls_pkcs11_url_type_t detailed, char **url)
1850 int ret;
1852 ret = pkcs11_info_to_url (obj->info, detailed, url);
1853 if (ret < 0)
1855 gnutls_assert ();
1856 return ret;
1859 return 0;
1863 * gnutls_pkcs11_obj_get_type:
1864 * @obj: Holds the PKCS 11 object
1866 * This function will return the type of the certificate being
1867 * stored in the structure.
1869 * Returns: The type of the certificate.
1871 * Since: 2.12.0
1873 gnutls_pkcs11_obj_type_t
1874 gnutls_pkcs11_obj_get_type (gnutls_pkcs11_obj_t obj)
1876 return obj->type;
1879 struct pkey_list
1881 gnutls_buffer_st *key_ids;
1882 size_t key_ids_size;
1886 static int
1887 retrieve_pin_from_source (const char *pinfile, struct ck_token_info *token_info,
1888 int attempts, ck_user_type_t user_type, struct p11_kit_pin **pin)
1890 unsigned int flags = 0;
1891 struct p11_kit_uri *token_uri;
1892 struct p11_kit_pin *result;
1893 char *label;
1895 label = p11_kit_space_strdup (token_info->label, sizeof (token_info->label));
1896 if (label == NULL)
1898 gnutls_assert ();
1899 return GNUTLS_E_MEMORY_ERROR;
1902 token_uri = p11_kit_uri_new ();
1903 if (token_uri == NULL)
1905 free (label);
1906 gnutls_assert ();
1907 return GNUTLS_E_MEMORY_ERROR;
1910 memcpy (p11_kit_uri_get_token_info (token_uri), token_info,
1911 sizeof (struct ck_token_info));
1913 if (attempts)
1914 flags |= P11_KIT_PIN_FLAGS_RETRY;
1915 if (user_type == CKU_USER)
1917 flags |= P11_KIT_PIN_FLAGS_USER_LOGIN;
1918 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
1919 flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
1920 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
1921 flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
1923 else if (user_type == CKU_SO)
1925 flags |= P11_KIT_PIN_FLAGS_SO_LOGIN;
1926 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
1927 flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
1928 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
1929 flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
1931 else if (user_type == CKU_CONTEXT_SPECIFIC)
1933 flags |= P11_KIT_PIN_FLAGS_CONTEXT_LOGIN;
1936 result = p11_kit_pin_request (pinfile, token_uri, label, flags);
1937 p11_kit_uri_free (token_uri);
1938 free (label);
1940 if (result == NULL)
1942 gnutls_assert ();
1943 return GNUTLS_E_PKCS11_PIN_ERROR;
1946 *pin = result;
1947 return 0;
1950 static int
1951 retrieve_pin_for_callback (struct ck_token_info *token_info, int attempts,
1952 ck_user_type_t user_type, struct p11_kit_pin **pin)
1954 char pin_value[GNUTLS_PKCS11_MAX_PIN_LEN];
1955 unsigned int flags = 0;
1956 char *token_str;
1957 char *label;
1958 struct p11_kit_uri *token_uri;
1959 int ret = 0;
1961 label = p11_kit_space_strdup (token_info->label, sizeof (token_info->label));
1962 if (label == NULL)
1964 gnutls_assert ();
1965 return GNUTLS_E_MEMORY_ERROR;
1968 token_uri = p11_kit_uri_new ();
1969 if (token_uri == NULL)
1971 free (label);
1972 gnutls_assert ();
1973 return GNUTLS_E_MEMORY_ERROR;
1976 memcpy (p11_kit_uri_get_token_info (token_uri), token_info,
1977 sizeof (struct ck_token_info));
1978 ret = pkcs11_info_to_url (token_uri, 1, &token_str);
1979 p11_kit_uri_free (token_uri);
1981 if (ret < 0)
1983 free (label);
1984 gnutls_assert ();
1985 return GNUTLS_E_MEMORY_ERROR;
1988 if (user_type == CKU_USER)
1990 flags |= GNUTLS_PKCS11_PIN_USER;
1991 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
1992 flags |= GNUTLS_PKCS11_PIN_COUNT_LOW;
1993 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
1994 flags |= GNUTLS_PKCS11_PIN_FINAL_TRY;
1996 else if (user_type == CKU_SO)
1998 flags |= GNUTLS_PKCS11_PIN_SO;
1999 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
2000 flags |= GNUTLS_PKCS11_PIN_COUNT_LOW;
2001 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
2002 flags |= GNUTLS_PKCS11_PIN_FINAL_TRY;
2005 if (attempts > 0)
2006 flags |= GNUTLS_PKCS11_PIN_WRONG;
2008 ret = _gnutls_pin_func (_gnutls_pin_data, attempts, (char*)token_str, label,
2009 flags, pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2010 free (token_str);
2011 free (label);
2013 if (ret < 0)
2014 return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2016 *pin = p11_kit_pin_new_for_string (pin_value);
2018 if (*pin == NULL)
2019 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2021 return 0;
2024 static int
2025 retrieve_pin (struct p11_kit_uri *info, struct ck_token_info *token_info,
2026 int attempts, ck_user_type_t user_type, struct p11_kit_pin **pin)
2028 const char *pinfile;
2029 int ret = GNUTLS_E_PKCS11_PIN_ERROR;
2031 *pin = NULL;
2033 /* Check if a pinfile is specified, and use that if possible */
2034 pinfile = p11_kit_uri_get_pinfile (info);
2035 if (pinfile != NULL)
2037 _gnutls_debug_log("pk11: Using pinfile to retrieve PIN\n");
2038 ret = retrieve_pin_from_source (pinfile, token_info, attempts, user_type, pin);
2041 /* The global gnutls pin callback */
2042 if (_gnutls_pin_func && ret < 0)
2043 ret = retrieve_pin_for_callback (token_info, attempts, user_type, pin);
2045 /* Otherwise, PIN entry is necessary for login, so fail if there's
2046 * no callback. */
2048 if (ret < 0)
2050 gnutls_assert ();
2051 _gnutls_debug_log ("pk11: No suitable pin callback but login required.\n");
2054 return ret;
2058 pkcs11_login (struct pkcs11_session_info * sinfo,
2059 const struct token_info *tokinfo, struct p11_kit_uri *info, int so)
2061 struct ck_session_info session_info;
2062 int attempt = 0, ret;
2063 ck_user_type_t user_type;
2064 ck_rv_t rv;
2066 user_type = (so == 0) ? CKU_USER : CKU_SO;
2067 if (so == 0 && (tokinfo->tinfo.flags & CKF_LOGIN_REQUIRED) == 0)
2069 gnutls_assert ();
2070 _gnutls_debug_log ("pk11: No login required.\n");
2071 return 0;
2074 /* For a token with a "protected" (out-of-band) authentication
2075 * path, calling login with a NULL username is all that is
2076 * required. */
2077 if (tokinfo->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
2079 rv = (sinfo->module)->C_Login (sinfo->pks, (so == 0) ? CKU_USER : CKU_SO, NULL, 0);
2080 if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN)
2082 return 0;
2084 else
2086 gnutls_assert ();
2087 _gnutls_debug_log ("pk11: Protected login failed.\n");
2088 ret = GNUTLS_E_PKCS11_ERROR;
2089 goto cleanup;
2095 struct p11_kit_pin *pin;
2096 struct ck_token_info tinfo;
2098 memcpy (&tinfo, &tokinfo->tinfo, sizeof(tinfo));
2100 /* Check whether the session is already logged in, and if so, just skip */
2101 rv = (sinfo->module)->C_GetSessionInfo (sinfo->pks, &session_info);
2102 if (rv == CKR_OK && (session_info.state == CKS_RO_USER_FUNCTIONS ||
2103 session_info.state == CKS_RW_USER_FUNCTIONS))
2105 ret = 0;
2106 goto cleanup;
2109 /* If login has been attempted once already, check the token
2110 * status again, the flags might change. */
2111 if (attempt)
2113 if (pkcs11_get_token_info
2114 (tokinfo->prov->module, tokinfo->sid, &tinfo) != CKR_OK)
2116 gnutls_assert ();
2117 _gnutls_debug_log ("pk11: GetTokenInfo failed\n");
2118 ret = GNUTLS_E_PKCS11_ERROR;
2119 goto cleanup;
2123 ret = retrieve_pin (info, &tinfo, attempt++, user_type, &pin);
2124 if (ret < 0)
2126 gnutls_assert ();
2127 goto cleanup;
2130 rv = (sinfo->module)->C_Login (sinfo->pks, user_type,
2131 (unsigned char *)p11_kit_pin_get_value (pin, NULL),
2132 p11_kit_pin_get_length (pin));
2134 p11_kit_pin_unref (pin);
2136 while (rv == CKR_PIN_INCORRECT);
2138 _gnutls_debug_log ("pk11: Login result = %lu\n", rv);
2141 ret = (rv == CKR_OK
2142 || rv == CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err (rv);
2144 cleanup:
2145 return ret;
2149 pkcs11_call_token_func (struct p11_kit_uri *info, const unsigned retry)
2151 struct ck_token_info *tinfo;
2152 char *label;
2153 int ret = 0;
2155 tinfo = p11_kit_uri_get_token_info (info);
2156 label = p11_kit_space_strdup (tinfo->label, sizeof (tinfo->label));
2157 ret = (_gnutls_token_func) (_gnutls_token_data, label, retry);
2158 free (label);
2160 return ret;
2164 static int
2165 find_privkeys (struct pkcs11_session_info* sinfo,
2166 struct token_info *info, struct pkey_list *list)
2168 struct ck_attribute a[3];
2169 ck_object_class_t class;
2170 ck_rv_t rv;
2171 ck_object_handle_t obj;
2172 unsigned long count, current;
2173 char certid_tmp[PKCS11_ID_SIZE];
2175 class = CKO_PRIVATE_KEY;
2177 /* Find an object with private key class and a certificate ID
2178 * which matches the certificate. */
2179 /* FIXME: also match the cert subject. */
2180 a[0].type = CKA_CLASS;
2181 a[0].value = &class;
2182 a[0].value_len = sizeof class;
2184 rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, 1);
2185 if (rv != CKR_OK)
2187 gnutls_assert ();
2188 return pkcs11_rv_to_err (rv);
2191 list->key_ids_size = 0;
2192 while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1)
2194 list->key_ids_size++;
2197 pkcs11_find_objects_final (sinfo);
2199 if (list->key_ids_size == 0)
2201 gnutls_assert ();
2202 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2205 list->key_ids =
2206 gnutls_malloc (sizeof (gnutls_buffer_st) * list->key_ids_size);
2207 if (list->key_ids == NULL)
2209 gnutls_assert ();
2210 return GNUTLS_E_MEMORY_ERROR;
2213 /* actual search */
2214 a[0].type = CKA_CLASS;
2215 a[0].value = &class;
2216 a[0].value_len = sizeof class;
2218 rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, 1);
2219 if (rv != CKR_OK)
2221 gnutls_assert ();
2222 return pkcs11_rv_to_err (rv);
2225 current = 0;
2226 while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1)
2229 a[0].type = CKA_ID;
2230 a[0].value = certid_tmp;
2231 a[0].value_len = sizeof (certid_tmp);
2233 _gnutls_buffer_init (&list->key_ids[current]);
2235 if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK)
2237 _gnutls_buffer_append_data (&list->key_ids[current],
2238 a[0].value, a[0].value_len);
2239 current++;
2242 if (current > list->key_ids_size)
2243 break;
2246 pkcs11_find_objects_final (sinfo);
2248 list->key_ids_size = current - 1;
2250 return 0;
2253 /* Recover certificate list from tokens */
2256 static int
2257 find_objs (struct pkcs11_session_info* sinfo,
2258 struct token_info *info, struct ck_info *lib_info, void *input)
2260 struct crt_find_data_st *find_data = input;
2261 struct ck_attribute a[4];
2262 struct ck_attribute *attr;
2263 ck_object_class_t class = (ck_object_class_t)-1;
2264 ck_certificate_type_t type = (ck_certificate_type_t)-1;
2265 unsigned int trusted;
2266 ck_rv_t rv;
2267 ck_object_handle_t obj;
2268 unsigned long count;
2269 uint8_t *cert_data;
2270 char certid_tmp[PKCS11_ID_SIZE];
2271 char label_tmp[PKCS11_LABEL_SIZE];
2272 int ret;
2273 struct pkey_list plist; /* private key holder */
2274 unsigned int i, tot_values = 0;
2276 if (info == NULL)
2277 { /* final call */
2278 if (find_data->current <= *find_data->n_list)
2279 ret = 0;
2280 else
2281 ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
2283 *find_data->n_list = find_data->current;
2285 return ret;
2288 /* do not bother reading the token if basic fields do not match
2290 if (!p11_kit_uri_match_token_info (find_data->info, &info->tinfo) ||
2291 !p11_kit_uri_match_module_info (find_data->info, lib_info))
2293 gnutls_assert ();
2294 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2297 memset (&plist, 0, sizeof (plist));
2299 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2301 ret = find_privkeys (sinfo, info, &plist);
2302 if (ret < 0)
2304 gnutls_assert ();
2305 return ret;
2308 if (plist.key_ids_size == 0)
2310 gnutls_assert ();
2311 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2315 cert_data = gnutls_malloc (MAX_CERT_SIZE);
2316 if (cert_data == NULL)
2318 gnutls_assert ();
2319 return GNUTLS_E_MEMORY_ERROR;
2322 /* Find objects with cert class and X.509 cert type. */
2324 tot_values = 0;
2326 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL
2327 || find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2329 class = CKO_CERTIFICATE;
2330 type = CKC_X_509;
2331 trusted = 1;
2333 a[tot_values].type = CKA_CLASS;
2334 a[tot_values].value = &class;
2335 a[tot_values].value_len = sizeof class;
2336 tot_values++;
2338 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2339 a[tot_values].value = &type;
2340 a[tot_values].value_len = sizeof type;
2341 tot_values++;
2344 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED)
2346 class = CKO_CERTIFICATE;
2347 type = CKC_X_509;
2348 trusted = 1;
2350 a[tot_values].type = CKA_CLASS;
2351 a[tot_values].value = &class;
2352 a[tot_values].value_len = sizeof class;
2353 tot_values++;
2355 a[tot_values].type = CKA_TRUSTED;
2356 a[tot_values].value = &trusted;
2357 a[tot_values].value_len = sizeof trusted;
2358 tot_values++;
2361 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY)
2363 class = CKO_PUBLIC_KEY;
2365 a[tot_values].type = CKA_CLASS;
2366 a[tot_values].value = &class;
2367 a[tot_values].value_len = sizeof class;
2368 tot_values++;
2370 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY)
2372 class = CKO_PRIVATE_KEY;
2374 a[tot_values].type = CKA_CLASS;
2375 a[tot_values].value = &class;
2376 a[tot_values].value_len = sizeof class;
2377 tot_values++;
2379 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL)
2381 if (class != (ck_object_class_t)-1)
2383 a[tot_values].type = CKA_CLASS;
2384 a[tot_values].value = &class;
2385 a[tot_values].value_len = sizeof class;
2386 tot_values++;
2388 if (type != (ck_certificate_type_t)-1)
2390 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2391 a[tot_values].value = &type;
2392 a[tot_values].value_len = sizeof type;
2393 tot_values++;
2396 else
2398 gnutls_assert ();
2399 ret = GNUTLS_E_INVALID_REQUEST;
2400 goto fail;
2403 attr = p11_kit_uri_get_attribute (find_data->info, CKA_ID);
2404 if (attr != NULL)
2406 memcpy (a + tot_values, attr, sizeof (struct ck_attribute));
2407 tot_values++;
2410 rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, a, tot_values);
2411 if (rv != CKR_OK)
2413 gnutls_assert ();
2414 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
2415 return pkcs11_rv_to_err (rv);
2418 while (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1)
2420 gnutls_datum_t label, id, value;
2422 a[0].type = CKA_LABEL;
2423 a[0].value = label_tmp;
2424 a[0].value_len = sizeof label_tmp;
2426 if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK)
2428 label.data = a[0].value;
2429 label.size = a[0].value_len;
2431 else
2433 label.data = NULL;
2434 label.size = 0;
2437 a[0].type = CKA_ID;
2438 a[0].value = certid_tmp;
2439 a[0].value_len = sizeof certid_tmp;
2441 if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK)
2443 id.data = a[0].value;
2444 id.size = a[0].value_len;
2446 else
2448 id.data = NULL;
2449 id.size = 0;
2452 a[0].type = CKA_VALUE;
2453 a[0].value = cert_data;
2454 a[0].value_len = MAX_CERT_SIZE;
2455 if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK)
2457 value.data = a[0].value;
2458 value.size = a[0].value_len;
2460 else
2462 value.data = NULL;
2463 value.size = 0;
2466 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL)
2468 a[0].type = CKA_CLASS;
2469 a[0].value = &class;
2470 a[0].value_len = sizeof class;
2472 pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, a, 1);
2475 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2477 for (i = 0; i < plist.key_ids_size; i++)
2479 if (plist.key_ids[i].length !=
2480 a[1].value_len
2481 || memcmp (plist.key_ids[i].data,
2482 a[1].value, a[1].value_len) != 0)
2484 /* not found */
2485 continue;
2490 if (find_data->current < *find_data->n_list)
2492 ret =
2493 gnutls_pkcs11_obj_init (&find_data->p_list[find_data->current]);
2494 if (ret < 0)
2496 gnutls_assert ();
2497 goto fail;
2500 if (class == CKO_PUBLIC_KEY)
2502 ret =
2503 pkcs11_obj_import_pubkey (sinfo->module, sinfo->pks, obj,
2504 find_data->p_list
2505 [find_data->current],
2506 &id, &label,
2507 &info->tinfo, lib_info);
2509 else
2511 ret =
2512 pkcs11_obj_import (class,
2513 find_data->p_list
2514 [find_data->current],
2515 &value, &id, &label,
2516 &info->tinfo, lib_info);
2518 if (ret < 0)
2520 gnutls_assert ();
2521 goto fail;
2525 find_data->current++;
2529 gnutls_free (cert_data);
2530 pkcs11_find_objects_final (sinfo);
2532 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* continue until all tokens have been checked */
2534 fail:
2535 gnutls_free (cert_data);
2536 pkcs11_find_objects_final (sinfo);
2537 if (plist.key_ids != NULL)
2539 for (i = 0; i < plist.key_ids_size; i++)
2541 _gnutls_buffer_clear (&plist.key_ids[i]);
2543 gnutls_free (plist.key_ids);
2545 for (i = 0; i < find_data->current; i++)
2547 gnutls_pkcs11_obj_deinit (find_data->p_list[i]);
2549 find_data->current = 0;
2551 return ret;
2555 * gnutls_pkcs11_obj_list_import_url:
2556 * @p_list: An uninitialized object list (may be NULL)
2557 * @n_list: initially should hold the maximum size of the list. Will contain the actual size.
2558 * @url: A PKCS 11 url identifying a set of objects
2559 * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2560 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2562 * This function will initialize and set values to an object list
2563 * by using all objects identified by a PKCS 11 URL.
2565 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2566 * negative error value.
2568 * Since: 2.12.0
2571 gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list,
2572 unsigned int *n_list,
2573 const char *url,
2574 gnutls_pkcs11_obj_attr_t attrs,
2575 unsigned int flags)
2577 int ret;
2578 struct crt_find_data_st find_data;
2580 memset (&find_data, 0, sizeof (find_data));
2582 /* fill in the find data structure */
2583 find_data.p_list = p_list;
2584 find_data.n_list = n_list;
2585 find_data.flags = attrs;
2586 find_data.current = 0;
2588 if (url == NULL || url[0] == 0)
2590 url = "pkcs11:";
2593 ret = pkcs11_url_to_info (url, &find_data.info);
2594 if (ret < 0)
2596 gnutls_assert ();
2597 return ret;
2600 ret =
2601 _pkcs11_traverse_tokens (find_objs, &find_data, find_data.info,
2602 pkcs11_obj_flags_to_int (flags));
2603 p11_kit_uri_free (find_data.info);
2605 if (ret < 0)
2607 gnutls_assert ();
2608 return ret;
2611 return 0;
2615 * gnutls_pkcs11_obj_list_import_url2:
2616 * @p_list: An uninitialized object list (may be NULL)
2617 * @n_list: It will contain the size of the list.
2618 * @url: A PKCS 11 url identifying a set of objects
2619 * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2620 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2622 * This function will initialize and set values to an object list
2623 * by using all objects identified by the PKCS 11 URL. The output
2624 * is stored in @p_list, which will be initialized.
2626 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2627 * negative error value.
2629 * Since: 3.1.0
2632 gnutls_pkcs11_obj_list_import_url2 (gnutls_pkcs11_obj_t ** p_list,
2633 unsigned int *n_list,
2634 const char *url,
2635 gnutls_pkcs11_obj_attr_t attrs,
2636 unsigned int flags)
2638 unsigned int init = 1024;
2639 int ret;
2641 *p_list = gnutls_malloc(sizeof(gnutls_pkcs11_obj_t)*init);
2642 if (*p_list == NULL)
2644 gnutls_assert();
2645 return GNUTLS_E_MEMORY_ERROR;
2648 ret = gnutls_pkcs11_obj_list_import_url( *p_list, &init, url, attrs, flags);
2649 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
2651 *p_list = gnutls_realloc_fast(*p_list, sizeof(gnutls_pkcs11_obj_t)*init);
2652 if (*p_list == NULL)
2653 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2655 ret = gnutls_pkcs11_obj_list_import_url( *p_list, &init, url, attrs, flags);
2658 if (ret < 0)
2660 gnutls_assert();
2661 gnutls_free(*p_list);
2662 *p_list = NULL;
2663 return ret;
2666 *n_list = init;
2667 return 0;
2672 * gnutls_x509_crt_import_pkcs11_url:
2673 * @crt: A certificate of type #gnutls_x509_crt_t
2674 * @url: A PKCS 11 url
2675 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2677 * This function will import a PKCS 11 certificate directly from a token
2678 * without involving the #gnutls_pkcs11_obj_t structure. This function will
2679 * fail if the certificate stored is not of X.509 type.
2681 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2682 * negative error value.
2684 * Since: 2.12.0
2687 gnutls_x509_crt_import_pkcs11_url (gnutls_x509_crt_t crt,
2688 const char *url, unsigned int flags)
2690 gnutls_pkcs11_obj_t pcrt;
2691 int ret;
2693 ret = gnutls_pkcs11_obj_init (&pcrt);
2694 if (ret < 0)
2696 gnutls_assert ();
2697 return ret;
2700 ret = gnutls_pkcs11_obj_import_url (pcrt, url, flags);
2701 if (ret < 0)
2703 gnutls_assert ();
2704 goto cleanup;
2707 ret = gnutls_x509_crt_import (crt, &pcrt->raw, GNUTLS_X509_FMT_DER);
2708 if (ret < 0)
2710 gnutls_assert ();
2711 goto cleanup;
2714 ret = 0;
2715 cleanup:
2717 gnutls_pkcs11_obj_deinit (pcrt);
2719 return ret;
2724 * gnutls_x509_crt_import_pkcs11:
2725 * @crt: A certificate of type #gnutls_x509_crt_t
2726 * @pkcs11_crt: A PKCS 11 object that contains a certificate
2728 * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t
2729 * structure.
2731 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2732 * negative error value.
2734 * Since: 2.12.0
2737 gnutls_x509_crt_import_pkcs11 (gnutls_x509_crt_t crt,
2738 gnutls_pkcs11_obj_t pkcs11_crt)
2740 return gnutls_x509_crt_import (crt, &pkcs11_crt->raw, GNUTLS_X509_FMT_DER);
2744 * gnutls_x509_crt_list_import_pkcs11:
2745 * @certs: A list of certificates of type #gnutls_x509_crt_t
2746 * @cert_max: The maximum size of the list
2747 * @objs: A list of PKCS 11 objects
2748 * @flags: 0 for now
2750 * This function will import a PKCS 11 certificate list to a list of
2751 * #gnutls_x509_crt_t structure. These must not be initialized.
2753 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2754 * negative error value.
2756 * Since: 2.12.0
2759 gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs,
2760 unsigned int cert_max,
2761 gnutls_pkcs11_obj_t * const objs,
2762 unsigned int flags)
2764 unsigned int i, j;
2765 int ret;
2767 for (i = 0; i < cert_max; i++)
2769 ret = gnutls_x509_crt_init (&certs[i]);
2770 if (ret < 0)
2772 gnutls_assert ();
2773 goto cleanup;
2776 ret = gnutls_x509_crt_import_pkcs11 (certs[i], objs[i]);
2777 if (ret < 0)
2779 gnutls_assert ();
2780 goto cleanup;
2784 return 0;
2786 cleanup:
2787 for (j = 0; j < i; j++)
2789 gnutls_x509_crt_deinit (certs[j]);
2792 return ret;
2795 static int
2796 find_flags (struct pkcs11_session_info* sinfo,
2797 struct token_info *info, struct ck_info *lib_info, void *input)
2799 struct flags_find_data_st *find_data = input;
2801 if (info == NULL)
2802 { /* we don't support multiple calls */
2803 gnutls_assert ();
2804 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2807 /* do not bother reading the token if basic fields do not match
2809 if (!p11_kit_uri_match_token_info (find_data->info, &info->tinfo) ||
2810 !p11_kit_uri_match_module_info (find_data->info, lib_info))
2812 gnutls_assert ();
2813 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2816 /* found token! */
2818 find_data->slot_flags = info->sinfo.flags;
2820 return 0;
2824 * gnutls_pkcs11_token_get_flags:
2825 * @url: should contain a PKCS 11 URL
2826 * @flags: The output flags (GNUTLS_PKCS11_TOKEN_*)
2828 * This function will return information about the PKCS 11 token flags.
2829 * The flags from the %gnutls_pkcs11_token_info_t enumeration.
2831 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
2833 * Since: 2.12.0
2836 gnutls_pkcs11_token_get_flags (const char *url, unsigned int *flags)
2838 struct flags_find_data_st find_data;
2839 int ret;
2841 memset (&find_data, 0, sizeof (find_data));
2842 ret = pkcs11_url_to_info (url, &find_data.info);
2843 if (ret < 0)
2845 gnutls_assert ();
2846 return ret;
2849 ret = _pkcs11_traverse_tokens (find_flags, &find_data, find_data.info, 0);
2850 p11_kit_uri_free (find_data.info);
2852 if (ret < 0)
2854 gnutls_assert ();
2855 return ret;
2858 *flags = 0;
2859 if (find_data.slot_flags & CKF_HW_SLOT)
2860 *flags |= GNUTLS_PKCS11_TOKEN_HW;
2862 return 0;
2867 * gnutls_pkcs11_token_get_mechanism:
2868 * @url: should contain a PKCS 11 URL
2869 * @idx: The index of the mechanism
2870 * @mechanism: The PKCS #11 mechanism ID
2872 * This function will return the names of the supported mechanisms
2873 * by the token. It should be called with an increasing index until
2874 * it return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
2876 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
2878 * Since: 2.12.0
2881 gnutls_pkcs11_token_get_mechanism (const char *url, unsigned int idx,
2882 unsigned long *mechanism)
2884 int ret;
2885 ck_rv_t rv;
2886 struct ck_function_list *module;
2887 ck_slot_id_t slot;
2888 struct token_info tinfo;
2889 struct p11_kit_uri *info = NULL;
2890 unsigned long count;
2891 ck_mechanism_type_t mlist[400];
2893 ret = pkcs11_url_to_info (url, &info);
2894 if (ret < 0)
2896 gnutls_assert ();
2897 return ret;
2901 ret = pkcs11_find_slot (&module, &slot, info, &tinfo);
2902 p11_kit_uri_free (info);
2904 if (ret < 0)
2906 gnutls_assert ();
2907 return ret;
2910 count = sizeof (mlist) / sizeof (mlist[0]);
2911 rv = pkcs11_get_mechanism_list (module, slot, mlist, &count);
2912 if (rv != CKR_OK)
2914 gnutls_assert ();
2915 return pkcs11_rv_to_err (rv);
2918 if (idx >= count)
2920 gnutls_assert ();
2921 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2924 *mechanism = mlist[idx];
2926 return 0;
2931 * gnutls_pkcs11_type_get_name:
2932 * @type: Holds the PKCS 11 object type, a #gnutls_pkcs11_obj_type_t.
2934 * This function will return a human readable description of the
2935 * PKCS11 object type @obj. It will return "Unknown" for unknown
2936 * types.
2938 * Returns: human readable string labeling the PKCS11 object type
2939 * @type.
2941 * Since: 2.12.0
2943 const char *
2944 gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t type)
2946 switch (type)
2948 case GNUTLS_PKCS11_OBJ_X509_CRT:
2949 return "X.509 Certificate";
2950 case GNUTLS_PKCS11_OBJ_PUBKEY:
2951 return "Public key";
2952 case GNUTLS_PKCS11_OBJ_PRIVKEY:
2953 return "Private key";
2954 case GNUTLS_PKCS11_OBJ_SECRET_KEY:
2955 return "Secret key";
2956 case GNUTLS_PKCS11_OBJ_DATA:
2957 return "Data";
2958 case GNUTLS_PKCS11_OBJ_UNKNOWN:
2959 default:
2960 return "Unknown";
2964 ck_rv_t
2965 pkcs11_get_slot_list (struct ck_function_list * module, unsigned char token_present,
2966 ck_slot_id_t *slot_list, unsigned long *count)
2968 return (module)->C_GetSlotList (token_present, slot_list, count);
2971 ck_rv_t
2972 pkcs11_get_module_info (struct ck_function_list * module,
2973 struct ck_info * info)
2975 return (module)->C_GetInfo (info);
2978 ck_rv_t
2979 pkcs11_get_slot_info(struct ck_function_list * module,
2980 ck_slot_id_t slot_id,
2981 struct ck_slot_info *info)
2983 return (module)->C_GetSlotInfo (slot_id, info);
2986 ck_rv_t
2987 pkcs11_get_token_info (struct ck_function_list * module,
2988 ck_slot_id_t slot_id,
2989 struct ck_token_info *info)
2991 return (module)->C_GetTokenInfo (slot_id, info);
2994 ck_rv_t
2995 pkcs11_find_objects_init (struct ck_function_list *module,
2996 ck_session_handle_t sess,
2997 struct ck_attribute *templ,
2998 unsigned long count)
3000 return (module)->C_FindObjectsInit (sess, templ, count);
3003 ck_rv_t
3004 pkcs11_find_objects (struct ck_function_list *module,
3005 ck_session_handle_t sess,
3006 ck_object_handle_t *objects,
3007 unsigned long max_object_count,
3008 unsigned long *object_count)
3010 return (module)->C_FindObjects (sess, objects, max_object_count, object_count);
3013 ck_rv_t
3014 pkcs11_find_objects_final (struct pkcs11_session_info* sinfo)
3016 return (sinfo->module)->C_FindObjectsFinal (sinfo->pks);
3019 ck_rv_t
3020 pkcs11_close_session (struct pkcs11_session_info * sinfo)
3022 sinfo->init = 0;
3023 return (sinfo->module)->C_CloseSession (sinfo->pks);
3026 ck_rv_t
3027 pkcs11_get_attribute_value(struct ck_function_list *module,
3028 ck_session_handle_t sess,
3029 ck_object_handle_t object,
3030 struct ck_attribute *templ,
3031 unsigned long count)
3033 return (module)->C_GetAttributeValue (sess, object, templ, count);
3036 ck_rv_t
3037 pkcs11_get_mechanism_list (struct ck_function_list *module,
3038 ck_slot_id_t slot_id,
3039 ck_mechanism_type_t *mechanism_list,
3040 unsigned long *count)
3042 return (module)->C_GetMechanismList (slot_id, mechanism_list, count);
3045 ck_rv_t
3046 pkcs11_sign_init (struct ck_function_list *module,
3047 ck_session_handle_t sess,
3048 struct ck_mechanism *mechanism,
3049 ck_object_handle_t key)
3051 return (module)->C_SignInit (sess, mechanism, key);
3054 ck_rv_t
3055 pkcs11_sign (struct ck_function_list *module,
3056 ck_session_handle_t sess,
3057 unsigned char *data,
3058 unsigned long data_len,
3059 unsigned char *signature,
3060 unsigned long *signature_len)
3062 return (module)->C_Sign (sess, data, data_len, signature, signature_len);
3065 ck_rv_t
3066 pkcs11_generate_key_pair (struct ck_function_list *module,
3067 ck_session_handle_t sess,
3068 struct ck_mechanism *mechanism,
3069 struct ck_attribute *pub_templ,
3070 unsigned long pub_templ_count,
3071 struct ck_attribute *priv_templ,
3072 unsigned long priv_templ_count,
3073 ck_object_handle_t *pub,
3074 ck_object_handle_t *priv)
3076 return (module)->C_GenerateKeyPair (sess, mechanism, pub_templ, pub_templ_count,
3077 priv_templ, priv_templ_count, pub, priv);
3080 ck_rv_t
3081 pkcs11_decrypt_init (struct ck_function_list *module,
3082 ck_session_handle_t sess,
3083 struct ck_mechanism *mechanism,
3084 ck_object_handle_t key)
3086 return (module)->C_DecryptInit (sess, mechanism, key);
3089 ck_rv_t
3090 pkcs11_decrypt (struct ck_function_list *module,
3091 ck_session_handle_t sess,
3092 unsigned char *encrypted_data,
3093 unsigned long encrypted_data_len,
3094 unsigned char *data, unsigned long *data_len)
3096 return (module)->C_Decrypt (sess, encrypted_data, encrypted_data_len,
3097 data, data_len);
3100 ck_rv_t
3101 pkcs11_create_object (struct ck_function_list *module,
3102 ck_session_handle_t sess,
3103 struct ck_attribute *templ,
3104 unsigned long count,
3105 ck_object_handle_t *object)
3107 return (module)->C_CreateObject (sess, templ, count, object);
3110 ck_rv_t
3111 pkcs11_destroy_object (struct ck_function_list *module,
3112 ck_session_handle_t sess,
3113 ck_object_handle_t object)
3115 return (module)->C_DestroyObject (sess, object);
3118 ck_rv_t
3119 pkcs11_init_token (struct ck_function_list *module,
3120 ck_slot_id_t slot_id, unsigned char *pin,
3121 unsigned long pin_len, unsigned char *label)
3123 return (module)->C_InitToken (slot_id, pin, pin_len, label);
3126 ck_rv_t
3127 pkcs11_init_pin (struct ck_function_list *module,
3128 ck_session_handle_t sess,
3129 unsigned char *pin,
3130 unsigned long pin_len)
3132 return (module)->C_InitPIN (sess, pin, pin_len);
3135 ck_rv_t
3136 pkcs11_set_pin (struct ck_function_list *module,
3137 ck_session_handle_t sess,
3138 const char *old_pin,
3139 unsigned long old_len,
3140 const char *new_pin,
3141 unsigned long new_len)
3143 return (module)->C_SetPIN (sess, (uint8_t*)old_pin, old_len, (uint8_t*)new_pin, new_len);
3146 const char *
3147 pkcs11_strerror (ck_rv_t rv)
3149 return p11_kit_strerror (rv);