updated makefiles
[gnutls.git] / lib / pkcs11.c
blob056c68cf17b304546a95dd0f0964a90565583d06
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 static gnutls_pkcs11_pin_callback_t pin_func;
78 static void *pin_data;
80 gnutls_pkcs11_token_callback_t token_func;
81 void *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;
640 * gnutls_pkcs11_set_pin_function:
641 * @fn: The PIN callback, a gnutls_pkcs11_pin_callback_t() function.
642 * @userdata: data to be supplied to callback
644 * This function will set a callback function to be used when a PIN is
645 * required for PKCS 11 operations. See
646 * gnutls_pkcs11_pin_callback_t() on how the callback should behave.
648 * Since: 2.12.0
650 void
651 gnutls_pkcs11_set_pin_function (gnutls_pkcs11_pin_callback_t fn,
652 void *userdata)
654 pin_func = fn;
655 pin_data = userdata;
659 * gnutls_pkcs11_set_token_function:
660 * @fn: The token callback
661 * @userdata: data to be supplied to callback
663 * This function will set a callback function to be used when a token
664 * needs to be inserted to continue PKCS 11 operations.
666 * Since: 2.12.0
668 void
669 gnutls_pkcs11_set_token_function (gnutls_pkcs11_token_callback_t fn,
670 void *userdata)
672 token_func = fn;
673 token_data = userdata;
677 pkcs11_url_to_info (const char *url, struct p11_kit_uri **info)
679 int allocated = 0;
680 int ret;
682 if (*info == NULL)
684 *info = p11_kit_uri_new ();
685 if (*info == NULL)
687 gnutls_assert ();
688 return GNUTLS_E_MEMORY_ERROR;
690 allocated = 1;
693 ret = p11_kit_uri_parse (url, P11_KIT_URI_FOR_ANY, *info);
694 if (ret < 0)
696 if (allocated)
698 p11_kit_uri_free (*info);
699 *info = NULL;
701 gnutls_assert ();
702 return ret == P11_KIT_URI_NO_MEMORY ?
703 GNUTLS_E_MEMORY_ERROR : GNUTLS_E_PARSING_ERROR;
706 return 0;
710 pkcs11_info_to_url (struct p11_kit_uri *info,
711 gnutls_pkcs11_url_type_t detailed, char **url)
713 p11_kit_uri_type_t type = 0;
714 int ret;
716 switch (detailed)
718 case GNUTLS_PKCS11_URL_GENERIC:
719 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN;
720 break;
721 case GNUTLS_PKCS11_URL_LIB:
722 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE;
723 break;
724 case GNUTLS_PKCS11_URL_LIB_VERSION:
725 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE | P11_KIT_URI_FOR_MODULE_WITH_VERSION;
726 break;
729 ret = p11_kit_uri_format (info, type, url);
730 if (ret < 0)
732 gnutls_assert ();
733 return ret == P11_KIT_URI_NO_MEMORY ?
734 GNUTLS_E_MEMORY_ERROR : GNUTLS_E_INTERNAL_ERROR;
737 return 0;
741 * gnutls_pkcs11_obj_init:
742 * @obj: The structure to be initialized
744 * This function will initialize a pkcs11 certificate structure.
746 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
747 * negative error value.
749 * Since: 2.12.0
752 gnutls_pkcs11_obj_init (gnutls_pkcs11_obj_t * obj)
754 *obj = gnutls_calloc (1, sizeof (struct gnutls_pkcs11_obj_st));
755 if (*obj == NULL)
757 gnutls_assert ();
758 return GNUTLS_E_MEMORY_ERROR;
761 (*obj)->info = p11_kit_uri_new ();
762 if ((*obj)->info == NULL)
764 free (*obj);
765 gnutls_assert ();
766 return GNUTLS_E_MEMORY_ERROR;
769 return 0;
773 * gnutls_pkcs11_obj_deinit:
774 * @obj: The structure to be initialized
776 * This function will deinitialize a certificate structure.
778 * Since: 2.12.0
780 void
781 gnutls_pkcs11_obj_deinit (gnutls_pkcs11_obj_t obj)
783 _gnutls_free_datum (&obj->raw);
784 p11_kit_uri_free (obj->info);
785 free (obj);
789 * gnutls_pkcs11_obj_export:
790 * @obj: Holds the object
791 * @output_data: will contain a certificate PEM or DER encoded
792 * @output_data_size: holds the size of output_data (and will be
793 * replaced by the actual size of parameters)
795 * This function will export the PKCS11 object data. It is normal for
796 * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
797 * will be returned.
799 * If the buffer provided is not long enough to hold the output, then
800 * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
801 * be returned.
803 * If the structure is PEM encoded, it will have a header
804 * of "BEGIN CERTIFICATE".
806 * Returns: In case of failure a negative error code will be
807 * returned, and %GNUTLS_E_SUCCESS (0) on success.
809 * Since: 2.12.0
812 gnutls_pkcs11_obj_export (gnutls_pkcs11_obj_t obj,
813 void *output_data, size_t * output_data_size)
815 if (obj == NULL || obj->raw.data == NULL)
817 gnutls_assert ();
818 return GNUTLS_E_INVALID_REQUEST;
821 if (output_data == NULL || *output_data_size < obj->raw.size)
823 *output_data_size = obj->raw.size;
824 gnutls_assert ();
825 return GNUTLS_E_SHORT_MEMORY_BUFFER;
827 *output_data_size = obj->raw.size;
829 memcpy (output_data, obj->raw.data, obj->raw.size);
830 return 0;
834 pkcs11_find_object (struct ck_function_list ** _module,
835 ck_session_handle_t * _pks,
836 ck_object_handle_t * _obj,
837 struct p11_kit_uri *info, unsigned int flags)
839 int ret;
840 struct ck_function_list *module;
841 ck_session_handle_t pks;
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 (&module, &pks, 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 (module, 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 (module, pks, &obj, 1, &count) == CKR_OK && count == 1)
867 *_obj = obj;
868 *_pks = pks;
869 *_module = module;
870 pkcs11_find_objects_final (module, pks);
871 return 0;
874 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
875 pkcs11_find_objects_final (module, pks);
876 fail:
877 pkcs11_close_session (module, pks);
879 return ret;
883 pkcs11_find_slot (struct ck_function_list ** module, ck_slot_id_t * slot,
884 struct p11_kit_uri *info, struct token_info *_tinfo)
886 unsigned int x, z;
888 for (x = 0; x < active_providers; x++)
890 for (z = 0; z < providers[x].nslots; z++)
892 struct token_info tinfo;
894 if (pkcs11_get_token_info
895 (providers[x].module, providers[x].slots[z],
896 &tinfo.tinfo) != CKR_OK)
898 continue;
900 tinfo.sid = providers[x].slots[z];
901 tinfo.prov = &providers[x];
903 if (pkcs11_get_slot_info
904 (providers[x].module, providers[x].slots[z],
905 &tinfo.sinfo) != CKR_OK)
907 continue;
910 if (!p11_kit_uri_match_token_info (info, &tinfo.tinfo) ||
911 !p11_kit_uri_match_module_info (info, &providers[x].info))
913 continue;
916 /* ok found */
917 *module = providers[x].module;
918 *slot = providers[x].slots[z];
920 if (_tinfo != NULL)
921 memcpy (_tinfo, &tinfo, sizeof (tinfo));
923 return 0;
927 gnutls_assert ();
928 return GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE;
932 pkcs11_open_session (struct ck_function_list ** _module, ck_session_handle_t * _pks,
933 struct p11_kit_uri *info, 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 if (flags & SESSION_LOGIN)
961 ret = pkcs11_login (module, pks, &tinfo, info, (flags & SESSION_SO) ? 1 : 0);
962 if (ret < 0)
964 gnutls_assert ();
965 pkcs11_close_session (module, pks);
966 return ret;
970 /* ok found */
971 *_pks = pks;
972 *_module = module;
973 return 0;
978 _pkcs11_traverse_tokens (find_func_t find_func, void *input,
979 struct p11_kit_uri *info, unsigned int flags)
981 ck_rv_t rv;
982 unsigned int found = 0, x, z;
983 int ret;
984 ck_session_handle_t pks = 0;
985 struct ck_function_list *module = NULL;
987 for (x = 0; x < active_providers; x++)
989 module = providers[x].module;
990 for (z = 0; z < providers[x].nslots; z++)
992 struct token_info tinfo;
994 ret = GNUTLS_E_PKCS11_ERROR;
996 if (pkcs11_get_token_info (module, providers[x].slots[z],
997 &tinfo.tinfo) != CKR_OK)
999 continue;
1001 tinfo.sid = providers[x].slots[z];
1002 tinfo.prov = &providers[x];
1004 if (pkcs11_get_slot_info (module, providers[x].slots[z],
1005 &tinfo.sinfo) != CKR_OK)
1007 continue;
1010 rv = (module)->C_OpenSession (providers[x].slots[z],
1011 ((flags & SESSION_WRITE)
1012 ? CKF_RW_SESSION : 0) |
1013 CKF_SERIAL_SESSION, NULL, NULL, &pks);
1014 if (rv != CKR_OK)
1016 continue;
1019 if (flags & SESSION_LOGIN)
1021 ret = pkcs11_login (module, pks, &tinfo, info, (flags & SESSION_SO) ? 1 : 0);
1022 if (ret < 0)
1024 gnutls_assert ();
1025 return ret;
1029 ret = find_func (module, pks, &tinfo, &providers[x].info, input);
1031 if (ret == 0)
1033 found = 1;
1034 goto finish;
1036 else
1038 pkcs11_close_session (module, pks);
1039 pks = 0;
1044 finish:
1045 /* final call */
1047 if (found == 0)
1049 if (module)
1050 ret = find_func (module, pks, NULL, NULL, input);
1051 else
1052 ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1054 else
1056 ret = 0;
1059 if (pks != 0 && module != NULL)
1061 pkcs11_close_session (module, pks);
1064 return ret;
1067 /* imports a raw certificate from a token to a pkcs11_obj_t structure.
1069 static int
1070 pkcs11_obj_import (ck_object_class_t class, gnutls_pkcs11_obj_t obj,
1071 const gnutls_datum_t * data,
1072 const gnutls_datum_t * id,
1073 const gnutls_datum_t * label,
1074 struct ck_token_info *tinfo, struct ck_info *lib_info)
1076 struct ck_attribute attr;
1077 int ret;
1079 switch (class)
1081 case CKO_CERTIFICATE:
1082 obj->type = GNUTLS_PKCS11_OBJ_X509_CRT;
1083 break;
1084 case CKO_PUBLIC_KEY:
1085 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1086 break;
1087 case CKO_PRIVATE_KEY:
1088 obj->type = GNUTLS_PKCS11_OBJ_PRIVKEY;
1089 break;
1090 case CKO_SECRET_KEY:
1091 obj->type = GNUTLS_PKCS11_OBJ_SECRET_KEY;
1092 break;
1093 case CKO_DATA:
1094 obj->type = GNUTLS_PKCS11_OBJ_DATA;
1095 break;
1096 default:
1097 obj->type = GNUTLS_PKCS11_OBJ_UNKNOWN;
1100 attr.type = CKA_CLASS;
1101 attr.value = &class;
1102 attr.value_len = sizeof (class);
1103 ret = p11_kit_uri_set_attribute (obj->info, &attr);
1104 if (ret < 0)
1106 gnutls_assert ();
1107 return GNUTLS_E_MEMORY_ERROR;
1110 if (data && data->data)
1112 ret = _gnutls_set_datum (&obj->raw, data->data, data->size);
1113 if (ret < 0)
1115 gnutls_assert ();
1116 return ret;
1120 /* copy the token and library info into the uri */
1121 memcpy (p11_kit_uri_get_token_info (obj->info), tinfo, sizeof (struct ck_token_info));
1122 memcpy (p11_kit_uri_get_module_info (obj->info), lib_info, sizeof (struct ck_info));
1124 if (label && label->data)
1126 attr.type = CKA_LABEL;
1127 attr.value = label->data;
1128 attr.value_len = label->size;
1129 ret = p11_kit_uri_set_attribute (obj->info, &attr);
1130 if (ret < 0)
1132 gnutls_assert ();
1133 return GNUTLS_E_MEMORY_ERROR;
1137 if (id && id->data)
1139 attr.type = CKA_ID;
1140 attr.value = id->data;
1141 attr.value_len = id->size;
1142 ret = p11_kit_uri_set_attribute (obj->info, &attr);
1143 if (ret < 0)
1145 gnutls_assert ();
1146 return GNUTLS_E_MEMORY_ERROR;
1150 return 0;
1153 static int read_pkcs11_pubkey(struct ck_function_list *module,
1154 ck_session_handle_t pks, ck_object_handle_t obj,
1155 ck_key_type_t key_type, gnutls_datum_t * pubkey)
1157 struct ck_attribute a[4];
1158 uint8_t tmp1[2048];
1159 uint8_t tmp2[2048];
1160 int ret;
1162 switch (key_type)
1164 case CKK_RSA:
1165 a[0].type = CKA_MODULUS;
1166 a[0].value = tmp1;
1167 a[0].value_len = sizeof (tmp1);
1168 a[1].type = CKA_PUBLIC_EXPONENT;
1169 a[1].value = tmp2;
1170 a[1].value_len = sizeof (tmp2);
1172 if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
1175 ret =
1176 _gnutls_set_datum (&pubkey[0],
1177 a[0].value, a[0].value_len);
1179 if (ret >= 0)
1180 ret =
1181 _gnutls_set_datum (&pubkey
1182 [1], a[1].value, a[1].value_len);
1184 if (ret < 0)
1186 gnutls_assert ();
1187 _gnutls_free_datum (&pubkey[1]);
1188 _gnutls_free_datum (&pubkey[0]);
1189 return GNUTLS_E_MEMORY_ERROR;
1192 else
1194 gnutls_assert ();
1195 return GNUTLS_E_PKCS11_ERROR;
1197 break;
1198 case CKK_DSA:
1199 a[0].type = CKA_PRIME;
1200 a[0].value = tmp1;
1201 a[0].value_len = sizeof (tmp1);
1202 a[1].type = CKA_SUBPRIME;
1203 a[1].value = tmp2;
1204 a[1].value_len = sizeof (tmp2);
1206 if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
1208 ret =
1209 _gnutls_set_datum (&pubkey[0],
1210 a[0].value, a[0].value_len);
1212 if (ret >= 0)
1213 ret =
1214 _gnutls_set_datum (&pubkey
1215 [1], a[1].value, a[1].value_len);
1217 if (ret < 0)
1219 gnutls_assert ();
1220 _gnutls_free_datum (&pubkey[1]);
1221 _gnutls_free_datum (&pubkey[0]);
1222 return GNUTLS_E_MEMORY_ERROR;
1225 else
1227 gnutls_assert ();
1228 return GNUTLS_E_PKCS11_ERROR;
1231 a[0].type = CKA_BASE;
1232 a[0].value = tmp1;
1233 a[0].value_len = sizeof (tmp1);
1234 a[1].type = CKA_VALUE;
1235 a[1].value = tmp2;
1236 a[1].value_len = sizeof (tmp2);
1238 if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
1240 ret =
1241 _gnutls_set_datum (&pubkey[2],
1242 a[0].value, a[0].value_len);
1244 if (ret >= 0)
1245 ret =
1246 _gnutls_set_datum (&pubkey
1247 [3], a[1].value, a[1].value_len);
1249 if (ret < 0)
1251 gnutls_assert ();
1252 _gnutls_free_datum (&pubkey[0]);
1253 _gnutls_free_datum (&pubkey[1]);
1254 _gnutls_free_datum (&pubkey[2]);
1255 _gnutls_free_datum (&pubkey[3]);
1256 return GNUTLS_E_MEMORY_ERROR;
1259 else
1261 gnutls_assert ();
1262 return GNUTLS_E_PKCS11_ERROR;
1264 break;
1265 case CKK_ECDSA:
1266 a[0].type = CKA_EC_PARAMS;
1267 a[0].value = tmp1;
1268 a[0].value_len = sizeof (tmp1);
1269 a[1].type = CKA_EC_POINT;
1270 a[1].value = tmp2;
1271 a[1].value_len = sizeof (tmp2);
1273 if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
1275 ret =
1276 _gnutls_set_datum (&pubkey[0],
1277 a[0].value, a[0].value_len);
1279 if (ret >= 0)
1280 ret =
1281 _gnutls_set_datum (&pubkey
1282 [1], a[1].value, a[1].value_len);
1284 if (ret < 0)
1286 gnutls_assert ();
1287 _gnutls_free_datum (&pubkey[1]);
1288 _gnutls_free_datum (&pubkey[0]);
1289 return GNUTLS_E_MEMORY_ERROR;
1292 else
1294 gnutls_assert ();
1295 return GNUTLS_E_PKCS11_ERROR;
1298 break;
1299 default:
1300 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1303 return 0;
1306 static int
1307 pkcs11_obj_import_pubkey (struct ck_function_list *module,
1308 ck_session_handle_t pks,
1309 ck_object_handle_t obj,
1310 gnutls_pkcs11_obj_t crt,
1311 const gnutls_datum_t * id,
1312 const gnutls_datum_t * label,
1313 struct ck_token_info *tinfo,
1314 struct ck_info *lib_info)
1316 struct ck_attribute a[4];
1317 ck_key_type_t key_type;
1318 int ret;
1319 ck_bool_t tval;
1321 a[0].type = CKA_KEY_TYPE;
1322 a[0].value = &key_type;
1323 a[0].value_len = sizeof (key_type);
1325 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1327 crt->pk_algorithm = mech_to_pk(key_type);
1329 ret = read_pkcs11_pubkey(module, pks, obj, key_type, crt->pubkey);
1330 if (ret < 0)
1331 return gnutls_assert_val(ret);
1334 /* read key usage flags */
1335 a[0].type = CKA_ENCRYPT;
1336 a[0].value = &tval;
1337 a[0].value_len = sizeof (tval);
1339 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1341 if (tval != 0)
1343 crt->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
1347 a[0].type = CKA_VERIFY;
1348 a[0].value = &tval;
1349 a[0].value_len = sizeof (tval);
1351 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1353 if (tval != 0)
1355 crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1356 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1357 | GNUTLS_KEY_NON_REPUDIATION;
1361 a[0].type = CKA_VERIFY_RECOVER;
1362 a[0].value = &tval;
1363 a[0].value_len = sizeof (tval);
1365 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1367 if (tval != 0)
1369 crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1370 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1371 | GNUTLS_KEY_NON_REPUDIATION;
1375 a[0].type = CKA_DERIVE;
1376 a[0].value = &tval;
1377 a[0].value_len = sizeof (tval);
1379 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1381 if (tval != 0)
1383 crt->key_usage |= GNUTLS_KEY_KEY_AGREEMENT;
1387 a[0].type = CKA_WRAP;
1388 a[0].value = &tval;
1389 a[0].value_len = sizeof (tval);
1391 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
1393 if (tval != 0)
1395 crt->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
1399 return pkcs11_obj_import (CKO_PUBLIC_KEY, crt, NULL, id, label,
1400 tinfo, lib_info);
1403 static int
1404 find_obj_url (struct ck_function_list *module, ck_session_handle_t pks,
1405 struct token_info *info, struct ck_info *lib_info, void *input)
1407 struct url_find_data_st *find_data = input;
1408 struct ck_attribute a[4];
1409 struct ck_attribute *attr;
1410 ck_object_class_t class = -1;
1411 ck_certificate_type_t type = (ck_certificate_type_t)-1;
1412 ck_rv_t rv;
1413 ck_object_handle_t obj;
1414 unsigned long count, a_vals;
1415 int found = 0, ret;
1416 uint8_t *cert_data = NULL;
1417 char label_tmp[PKCS11_LABEL_SIZE];
1418 char id_tmp[PKCS11_ID_SIZE];
1420 if (info == NULL)
1421 { /* we don't support multiple calls */
1422 gnutls_assert ();
1423 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1426 /* do not bother reading the token if basic fields do not match
1428 if (!p11_kit_uri_match_token_info (find_data->crt->info, &info->tinfo) ||
1429 !p11_kit_uri_match_module_info (find_data->crt->info, lib_info))
1431 gnutls_assert ();
1432 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1435 a_vals = 0;
1436 attr = p11_kit_uri_get_attribute (find_data->crt->info, CKA_ID);
1437 if (attr)
1439 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
1440 a_vals++;
1443 attr = p11_kit_uri_get_attribute (find_data->crt->info, CKA_LABEL);
1444 if (attr)
1446 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
1447 a_vals++;
1450 if (!a_vals)
1452 gnutls_assert ();
1453 return GNUTLS_E_INVALID_REQUEST;
1456 /* search the token for the id */
1458 cert_data = gnutls_malloc (MAX_CERT_SIZE);
1459 if (cert_data == NULL)
1461 gnutls_assert ();
1462 return GNUTLS_E_MEMORY_ERROR;
1465 /* Find objects with given class and type */
1466 attr = p11_kit_uri_get_attribute (find_data->crt->info, CKA_CLASS);
1467 if (attr)
1469 if(attr->value && attr->value_len == sizeof (ck_object_class_t))
1470 class = *((ck_object_class_t*)attr->value);
1471 if (class == CKO_CERTIFICATE)
1472 type = CKC_X_509;
1473 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
1474 a_vals++;
1477 if (type != (ck_certificate_type_t)-1)
1479 a[a_vals].type = CKA_CERTIFICATE_TYPE;
1480 a[a_vals].value = &type;
1481 a[a_vals].value_len = sizeof type;
1482 a_vals++;
1485 rv = pkcs11_find_objects_init (module, pks, a, a_vals);
1486 if (rv != CKR_OK)
1488 gnutls_assert ();
1489 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
1490 ret = pkcs11_rv_to_err (rv);
1491 goto cleanup;
1494 while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1)
1497 a[0].type = CKA_VALUE;
1498 a[0].value = cert_data;
1499 a[0].value_len = MAX_CERT_SIZE;
1500 a[1].type = CKA_LABEL;
1501 a[1].value = label_tmp;
1502 a[1].value_len = sizeof (label_tmp);
1503 a[2].type = CKA_ID;
1504 a[2].value = id_tmp;
1505 a[2].value_len = sizeof(id_tmp);
1507 if (pkcs11_get_attribute_value (module, pks, obj, a, 3) == CKR_OK)
1509 gnutls_datum_t id = { a[2].value, a[2].value_len };
1510 gnutls_datum_t data = { a[0].value, a[0].value_len };
1511 gnutls_datum_t label = { a[1].value, a[1].value_len };
1513 if (class == CKO_PUBLIC_KEY)
1515 ret =
1516 pkcs11_obj_import_pubkey (module, pks, obj,
1517 find_data->crt,
1518 &id, &label,
1519 &info->tinfo, lib_info);
1521 else
1523 ret =
1524 pkcs11_obj_import (class,
1525 find_data->crt,
1526 &data, &id, &label,
1527 &info->tinfo, lib_info);
1529 if (ret < 0)
1531 gnutls_assert ();
1532 goto cleanup;
1535 found = 1;
1536 break;
1538 else
1540 _gnutls_debug_log ("pk11: Skipped cert, missing attrs.\n");
1544 if (found == 0)
1546 gnutls_assert ();
1547 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1549 else
1551 ret = 0;
1554 cleanup:
1555 gnutls_free (cert_data);
1556 pkcs11_find_objects_final (module, pks);
1558 return ret;
1561 unsigned int
1562 pkcs11_obj_flags_to_int (unsigned int flags)
1564 unsigned int ret_flags = 0;
1566 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN)
1567 ret_flags |= SESSION_LOGIN;
1568 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO)
1569 ret_flags |= SESSION_LOGIN|SESSION_SO;
1571 return ret_flags;
1575 * gnutls_pkcs11_obj_import_url:
1576 * @cert: The structure to store the parsed certificate
1577 * @url: a PKCS 11 url identifying the key
1578 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1580 * This function will "import" a PKCS 11 URL identifying a certificate
1581 * key to the #gnutls_pkcs11_obj_t structure. This does not involve any
1582 * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is
1583 * format agnostic. Only data are transferred.
1585 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1586 * negative error value.
1588 * Since: 2.12.0
1591 gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t cert, const char *url,
1592 unsigned int flags)
1594 int ret;
1595 struct url_find_data_st find_data;
1597 /* fill in the find data structure */
1598 find_data.crt = cert;
1600 ret = pkcs11_url_to_info (url, &cert->info);
1601 if (ret < 0)
1603 gnutls_assert ();
1604 return ret;
1607 ret =
1608 _pkcs11_traverse_tokens (find_obj_url, &find_data, cert->info,
1609 pkcs11_obj_flags_to_int (flags));
1611 if (ret < 0)
1613 gnutls_assert ();
1614 return ret;
1617 return 0;
1620 struct token_num
1622 struct p11_kit_uri *info;
1623 unsigned int seq; /* which one we are looking for */
1624 unsigned int current; /* which one are we now */
1627 static int
1628 find_token_num (struct ck_function_list *module,
1629 ck_session_handle_t pks,
1630 struct token_info *tinfo,
1631 struct ck_info *lib_info, void *input)
1633 struct token_num *find_data = input;
1635 if (tinfo == NULL)
1636 { /* we don't support multiple calls */
1637 gnutls_assert ();
1638 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1641 if (find_data->current == find_data->seq)
1643 memcpy (p11_kit_uri_get_token_info (find_data->info), &tinfo->tinfo, sizeof (struct ck_token_info));
1644 memcpy (p11_kit_uri_get_module_info (find_data->info), lib_info, sizeof (struct ck_info));
1645 return 0;
1648 find_data->current++;
1649 /* search the token for the id */
1652 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* non zero is enough */
1656 * gnutls_pkcs11_token_get_url:
1657 * @seq: sequence number starting from 0
1658 * @detailed: non zero if a detailed URL is required
1659 * @url: will contain an allocated url
1661 * This function will return the URL for each token available
1662 * in system. The url has to be released using gnutls_free()
1664 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
1665 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if the sequence number
1666 * exceeds the available tokens, otherwise a negative error value.
1668 * Since: 2.12.0
1671 gnutls_pkcs11_token_get_url (unsigned int seq,
1672 gnutls_pkcs11_url_type_t detailed, char **url)
1674 int ret;
1675 struct token_num tn;
1677 memset (&tn, 0, sizeof (tn));
1678 tn.seq = seq;
1679 tn.info = p11_kit_uri_new ();
1681 ret = _pkcs11_traverse_tokens (find_token_num, &tn, NULL, 0);
1682 if (ret < 0)
1684 p11_kit_uri_free (tn.info);
1685 gnutls_assert ();
1686 return ret;
1689 ret = pkcs11_info_to_url (tn.info, detailed, url);
1690 p11_kit_uri_free (tn.info);
1692 if (ret < 0)
1694 gnutls_assert ();
1695 return ret;
1698 return 0;
1703 * gnutls_pkcs11_token_get_info:
1704 * @url: should contain a PKCS 11 URL
1705 * @ttype: Denotes the type of information requested
1706 * @output: where output will be stored
1707 * @output_size: contains the maximum size of the output and will be overwritten with actual
1709 * This function will return information about the PKCS 11 token such
1710 * as the label, id, etc.
1712 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code
1713 * on error.
1715 * Since: 2.12.0
1718 gnutls_pkcs11_token_get_info (const char *url,
1719 gnutls_pkcs11_token_info_t ttype,
1720 void *output, size_t * output_size)
1722 struct p11_kit_uri *info = NULL;
1723 const uint8_t *str;
1724 size_t str_max;
1725 size_t len;
1726 int ret;
1728 ret = pkcs11_url_to_info (url, &info);
1729 if (ret < 0)
1731 gnutls_assert ();
1732 return ret;
1735 switch (ttype)
1737 case GNUTLS_PKCS11_TOKEN_LABEL:
1738 str = p11_kit_uri_get_token_info (info)->label;
1739 str_max = 32;
1740 break;
1741 case GNUTLS_PKCS11_TOKEN_SERIAL:
1742 str = p11_kit_uri_get_token_info (info)->serial_number;
1743 str_max = 16;
1744 break;
1745 case GNUTLS_PKCS11_TOKEN_MANUFACTURER:
1746 str = p11_kit_uri_get_token_info (info)->manufacturer_id;
1747 str_max = 32;
1748 break;
1749 case GNUTLS_PKCS11_TOKEN_MODEL:
1750 str = p11_kit_uri_get_token_info (info)->model;
1751 str_max = 16;
1752 break;
1753 default:
1754 p11_kit_uri_free (info);
1755 gnutls_assert ();
1756 return GNUTLS_E_INVALID_REQUEST;
1759 len = p11_kit_space_strlen (str, str_max);
1761 if (len + 1 > *output_size)
1763 *output_size = len + 1;
1764 return GNUTLS_E_SHORT_MEMORY_BUFFER;
1767 memcpy (output, str, len);
1768 ((char*)output)[len] = '\0';
1770 *output_size = len;
1772 p11_kit_uri_free (info);
1773 return 0;
1777 * gnutls_pkcs11_obj_export_url:
1778 * @obj: Holds the PKCS 11 certificate
1779 * @detailed: non zero if a detailed URL is required
1780 * @url: will contain an allocated url
1782 * This function will export a URL identifying the given certificate.
1784 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1785 * negative error value.
1787 * Since: 2.12.0
1790 gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t obj,
1791 gnutls_pkcs11_url_type_t detailed, char **url)
1793 int ret;
1795 ret = pkcs11_info_to_url (obj->info, detailed, url);
1796 if (ret < 0)
1798 gnutls_assert ();
1799 return ret;
1802 return 0;
1806 * gnutls_pkcs11_obj_get_type:
1807 * @obj: Holds the PKCS 11 object
1809 * This function will return the type of the certificate being
1810 * stored in the structure.
1812 * Returns: The type of the certificate.
1814 * Since: 2.12.0
1816 gnutls_pkcs11_obj_type_t
1817 gnutls_pkcs11_obj_get_type (gnutls_pkcs11_obj_t obj)
1819 return obj->type;
1822 struct pkey_list
1824 gnutls_buffer_st *key_ids;
1825 size_t key_ids_size;
1829 static int
1830 retrieve_pin_from_source (const char *pinfile, struct ck_token_info *token_info,
1831 int attempts, ck_user_type_t user_type, struct p11_kit_pin **pin)
1833 unsigned int flags = 0;
1834 struct p11_kit_uri *token_uri;
1835 struct p11_kit_pin *result;
1836 char *label;
1838 label = p11_kit_space_strdup (token_info->label, sizeof (token_info->label));
1839 if (label == NULL)
1841 gnutls_assert ();
1842 return GNUTLS_E_MEMORY_ERROR;
1845 token_uri = p11_kit_uri_new ();
1846 if (token_uri == NULL)
1848 free (label);
1849 gnutls_assert ();
1850 return GNUTLS_E_MEMORY_ERROR;
1853 memcpy (p11_kit_uri_get_token_info (token_uri), token_info,
1854 sizeof (struct ck_token_info));
1856 if (attempts)
1857 flags |= P11_KIT_PIN_FLAGS_RETRY;
1858 if (user_type == CKU_USER)
1860 flags |= P11_KIT_PIN_FLAGS_USER_LOGIN;
1861 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
1862 flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
1863 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
1864 flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
1866 else if (user_type == CKU_SO)
1868 flags |= P11_KIT_PIN_FLAGS_SO_LOGIN;
1869 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
1870 flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
1871 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
1872 flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
1874 else if (user_type == CKU_CONTEXT_SPECIFIC)
1876 flags |= P11_KIT_PIN_FLAGS_CONTEXT_LOGIN;
1879 result = p11_kit_pin_request (pinfile, token_uri, label, flags);
1880 p11_kit_uri_free (token_uri);
1881 free (label);
1883 if (result == NULL)
1885 gnutls_assert ();
1886 return GNUTLS_E_PKCS11_PIN_ERROR;
1889 *pin = result;
1890 return 0;
1893 static int
1894 retrieve_pin_for_callback (struct ck_token_info *token_info, int attempts,
1895 ck_user_type_t user_type, struct p11_kit_pin **pin)
1897 char pin_value[GNUTLS_PKCS11_MAX_PIN_LEN];
1898 unsigned int flags = 0;
1899 char *token_str;
1900 char *label;
1901 struct p11_kit_uri *token_uri;
1902 int ret = 0;
1904 label = p11_kit_space_strdup (token_info->label, sizeof (token_info->label));
1905 if (label == NULL)
1907 gnutls_assert ();
1908 return GNUTLS_E_MEMORY_ERROR;
1911 token_uri = p11_kit_uri_new ();
1912 if (token_uri == NULL)
1914 free (label);
1915 gnutls_assert ();
1916 return GNUTLS_E_MEMORY_ERROR;
1919 memcpy (p11_kit_uri_get_token_info (token_uri), token_info,
1920 sizeof (struct ck_token_info));
1921 ret = pkcs11_info_to_url (token_uri, 1, &token_str);
1922 p11_kit_uri_free (token_uri);
1924 if (ret < 0)
1926 free (label);
1927 gnutls_assert ();
1928 return GNUTLS_E_MEMORY_ERROR;
1931 if (user_type == CKU_USER)
1933 flags |= GNUTLS_PKCS11_PIN_USER;
1934 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
1935 flags |= GNUTLS_PKCS11_PIN_COUNT_LOW;
1936 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
1937 flags |= GNUTLS_PKCS11_PIN_FINAL_TRY;
1939 else if (user_type == CKU_SO)
1941 flags |= GNUTLS_PKCS11_PIN_SO;
1942 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
1943 flags |= GNUTLS_PKCS11_PIN_COUNT_LOW;
1944 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
1945 flags |= GNUTLS_PKCS11_PIN_FINAL_TRY;
1948 if (attempts > 0)
1949 flags |= GNUTLS_PKCS11_PIN_WRONG;
1951 ret = pin_func (pin_data, attempts, (char*)token_str, label,
1952 flags, pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
1953 free (token_str);
1954 free (label);
1956 if (ret < 0)
1957 return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
1959 *pin = p11_kit_pin_new_for_string (pin_value);
1961 if (*pin == NULL)
1962 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1964 return 0;
1967 static int
1968 retrieve_pin (struct p11_kit_uri *info, struct ck_token_info *token_info,
1969 int attempts, ck_user_type_t user_type, struct p11_kit_pin **pin)
1971 const char *pinfile;
1972 int ret = GNUTLS_E_PKCS11_PIN_ERROR;
1974 *pin = NULL;
1976 /* Check if a pinfile is specified, and use that if possible */
1977 pinfile = p11_kit_uri_get_pinfile (info);
1978 if (pinfile != NULL)
1980 _gnutls_debug_log("pk11: Using pinfile to retrieve PIN\n");
1981 ret = retrieve_pin_from_source (pinfile, token_info, attempts, user_type, pin);
1984 /* The global gnutls pin callback */
1985 if (pin_func && ret < 0)
1986 ret = retrieve_pin_for_callback (token_info, attempts, user_type, pin);
1988 /* Otherwise, PIN entry is necessary for login, so fail if there's
1989 * no callback. */
1991 if (ret < 0)
1993 gnutls_assert ();
1994 _gnutls_debug_log ("pk11: No suitable pin callback but login required.\n");
1997 return ret;
2001 pkcs11_login (struct ck_function_list * module, ck_session_handle_t pks,
2002 const struct token_info *tokinfo, struct p11_kit_uri *info, int so)
2004 struct ck_session_info session_info;
2005 int attempt = 0, ret;
2006 ck_user_type_t user_type;
2007 ck_rv_t rv;
2009 user_type = (so == 0) ? CKU_USER : CKU_SO;
2010 if (so == 0 && (tokinfo->tinfo.flags & CKF_LOGIN_REQUIRED) == 0)
2012 gnutls_assert ();
2013 _gnutls_debug_log ("pk11: No login required.\n");
2014 return 0;
2017 /* For a token with a "protected" (out-of-band) authentication
2018 * path, calling login with a NULL username is all that is
2019 * required. */
2020 if (tokinfo->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
2022 rv = (module)->C_Login (pks, (so == 0) ? CKU_USER : CKU_SO, NULL, 0);
2023 if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN)
2025 return 0;
2027 else
2029 gnutls_assert ();
2030 _gnutls_debug_log ("pk11: Protected login failed.\n");
2031 ret = GNUTLS_E_PKCS11_ERROR;
2032 goto cleanup;
2038 struct p11_kit_pin *pin;
2039 struct ck_token_info tinfo;
2041 memcpy (&tinfo, &tokinfo->tinfo, sizeof(tinfo));
2043 /* Check whether the session is already logged in, and if so, just skip */
2044 rv = (module)->C_GetSessionInfo (pks, &session_info);
2045 if (rv == CKR_OK && (session_info.state == CKS_RO_USER_FUNCTIONS ||
2046 session_info.state == CKS_RW_USER_FUNCTIONS))
2048 ret = 0;
2049 goto cleanup;
2052 /* If login has been attempted once already, check the token
2053 * status again, the flags might change. */
2054 if (attempt)
2056 if (pkcs11_get_token_info
2057 (tokinfo->prov->module, tokinfo->sid, &tinfo) != CKR_OK)
2059 gnutls_assert ();
2060 _gnutls_debug_log ("pk11: GetTokenInfo failed\n");
2061 ret = GNUTLS_E_PKCS11_ERROR;
2062 goto cleanup;
2066 ret = retrieve_pin (info, &tinfo, attempt++, user_type, &pin);
2067 if (ret < 0)
2069 gnutls_assert ();
2070 goto cleanup;
2073 rv = (module)->C_Login (pks, user_type,
2074 (unsigned char *)p11_kit_pin_get_value (pin, NULL),
2075 p11_kit_pin_get_length (pin));
2077 p11_kit_pin_unref (pin);
2079 while (rv == CKR_PIN_INCORRECT);
2081 _gnutls_debug_log ("pk11: Login result = %lu\n", rv);
2084 ret = (rv == CKR_OK
2085 || rv == CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err (rv);
2087 cleanup:
2088 return ret;
2092 pkcs11_call_token_func (struct p11_kit_uri *info, const unsigned retry)
2094 struct ck_token_info *tinfo;
2095 char *label;
2096 int ret = 0;
2098 tinfo = p11_kit_uri_get_token_info (info);
2099 label = p11_kit_space_strdup (tinfo->label, sizeof (tinfo->label));
2100 ret = (token_func) (token_data, label, retry);
2101 free (label);
2103 return ret;
2107 static int
2108 find_privkeys (struct ck_function_list *module, ck_session_handle_t pks,
2109 struct token_info *info, struct pkey_list *list)
2111 struct ck_attribute a[3];
2112 ck_object_class_t class;
2113 ck_rv_t rv;
2114 ck_object_handle_t obj;
2115 unsigned long count, current;
2116 char certid_tmp[PKCS11_ID_SIZE];
2118 class = CKO_PRIVATE_KEY;
2120 /* Find an object with private key class and a certificate ID
2121 * which matches the certificate. */
2122 /* FIXME: also match the cert subject. */
2123 a[0].type = CKA_CLASS;
2124 a[0].value = &class;
2125 a[0].value_len = sizeof class;
2127 rv = pkcs11_find_objects_init (module, pks, a, 1);
2128 if (rv != CKR_OK)
2130 gnutls_assert ();
2131 return pkcs11_rv_to_err (rv);
2134 list->key_ids_size = 0;
2135 while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1)
2137 list->key_ids_size++;
2140 pkcs11_find_objects_final (module, pks);
2142 if (list->key_ids_size == 0)
2144 gnutls_assert ();
2145 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2148 list->key_ids =
2149 gnutls_malloc (sizeof (gnutls_buffer_st) * list->key_ids_size);
2150 if (list->key_ids == NULL)
2152 gnutls_assert ();
2153 return GNUTLS_E_MEMORY_ERROR;
2156 /* actual search */
2157 a[0].type = CKA_CLASS;
2158 a[0].value = &class;
2159 a[0].value_len = sizeof class;
2161 rv = pkcs11_find_objects_init (module, pks, a, 1);
2162 if (rv != CKR_OK)
2164 gnutls_assert ();
2165 return pkcs11_rv_to_err (rv);
2168 current = 0;
2169 while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1)
2172 a[0].type = CKA_ID;
2173 a[0].value = certid_tmp;
2174 a[0].value_len = sizeof (certid_tmp);
2176 _gnutls_buffer_init (&list->key_ids[current]);
2178 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
2180 _gnutls_buffer_append_data (&list->key_ids[current],
2181 a[0].value, a[0].value_len);
2182 current++;
2185 if (current > list->key_ids_size)
2186 break;
2189 pkcs11_find_objects_final (module, pks);
2191 list->key_ids_size = current - 1;
2193 return 0;
2196 /* Recover certificate list from tokens */
2199 static int
2200 find_objs (struct ck_function_list * module, ck_session_handle_t pks,
2201 struct token_info *info, struct ck_info *lib_info, void *input)
2203 struct crt_find_data_st *find_data = input;
2204 struct ck_attribute a[4];
2205 struct ck_attribute *attr;
2206 ck_object_class_t class = (ck_object_class_t)-1;
2207 ck_certificate_type_t type = (ck_certificate_type_t)-1;
2208 unsigned int trusted;
2209 ck_rv_t rv;
2210 ck_object_handle_t obj;
2211 unsigned long count;
2212 uint8_t *cert_data;
2213 char certid_tmp[PKCS11_ID_SIZE];
2214 char label_tmp[PKCS11_LABEL_SIZE];
2215 int ret;
2216 struct pkey_list plist; /* private key holder */
2217 unsigned int i, tot_values = 0;
2219 if (info == NULL)
2220 { /* final call */
2221 if (find_data->current <= *find_data->n_list)
2222 ret = 0;
2223 else
2224 ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
2226 *find_data->n_list = find_data->current;
2228 return ret;
2231 /* do not bother reading the token if basic fields do not match
2233 if (!p11_kit_uri_match_token_info (find_data->info, &info->tinfo) ||
2234 !p11_kit_uri_match_module_info (find_data->info, lib_info))
2236 gnutls_assert ();
2237 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2240 memset (&plist, 0, sizeof (plist));
2242 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2244 ret = find_privkeys (module, pks, info, &plist);
2245 if (ret < 0)
2247 gnutls_assert ();
2248 return ret;
2251 if (plist.key_ids_size == 0)
2253 gnutls_assert ();
2254 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2258 cert_data = gnutls_malloc (MAX_CERT_SIZE);
2259 if (cert_data == NULL)
2261 gnutls_assert ();
2262 return GNUTLS_E_MEMORY_ERROR;
2265 /* Find objects with cert class and X.509 cert type. */
2267 tot_values = 0;
2269 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL
2270 || find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2272 class = CKO_CERTIFICATE;
2273 type = CKC_X_509;
2274 trusted = 1;
2276 a[tot_values].type = CKA_CLASS;
2277 a[tot_values].value = &class;
2278 a[tot_values].value_len = sizeof class;
2279 tot_values++;
2281 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2282 a[tot_values].value = &type;
2283 a[tot_values].value_len = sizeof type;
2284 tot_values++;
2287 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED)
2289 class = CKO_CERTIFICATE;
2290 type = CKC_X_509;
2291 trusted = 1;
2293 a[tot_values].type = CKA_CLASS;
2294 a[tot_values].value = &class;
2295 a[tot_values].value_len = sizeof class;
2296 tot_values++;
2298 a[tot_values].type = CKA_TRUSTED;
2299 a[tot_values].value = &trusted;
2300 a[tot_values].value_len = sizeof trusted;
2301 tot_values++;
2304 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY)
2306 class = CKO_PUBLIC_KEY;
2308 a[tot_values].type = CKA_CLASS;
2309 a[tot_values].value = &class;
2310 a[tot_values].value_len = sizeof class;
2311 tot_values++;
2313 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY)
2315 class = CKO_PRIVATE_KEY;
2317 a[tot_values].type = CKA_CLASS;
2318 a[tot_values].value = &class;
2319 a[tot_values].value_len = sizeof class;
2320 tot_values++;
2322 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL)
2324 if (class != (ck_object_class_t)-1)
2326 a[tot_values].type = CKA_CLASS;
2327 a[tot_values].value = &class;
2328 a[tot_values].value_len = sizeof class;
2329 tot_values++;
2331 if (type != (ck_certificate_type_t)-1)
2333 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2334 a[tot_values].value = &type;
2335 a[tot_values].value_len = sizeof type;
2336 tot_values++;
2339 else
2341 gnutls_assert ();
2342 ret = GNUTLS_E_INVALID_REQUEST;
2343 goto fail;
2346 attr = p11_kit_uri_get_attribute (find_data->info, CKA_ID);
2347 if (attr != NULL)
2349 memcpy (a + tot_values, attr, sizeof (struct ck_attribute));
2350 tot_values++;
2353 rv = pkcs11_find_objects_init (module, pks, a, tot_values);
2354 if (rv != CKR_OK)
2356 gnutls_assert ();
2357 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
2358 return pkcs11_rv_to_err (rv);
2361 while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1)
2363 gnutls_datum_t label, id, value;
2365 a[0].type = CKA_LABEL;
2366 a[0].value = label_tmp;
2367 a[0].value_len = sizeof label_tmp;
2369 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
2371 label.data = a[0].value;
2372 label.size = a[0].value_len;
2374 else
2376 label.data = NULL;
2377 label.size = 0;
2380 a[0].type = CKA_ID;
2381 a[0].value = certid_tmp;
2382 a[0].value_len = sizeof certid_tmp;
2384 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
2386 id.data = a[0].value;
2387 id.size = a[0].value_len;
2389 else
2391 id.data = NULL;
2392 id.size = 0;
2395 a[0].type = CKA_VALUE;
2396 a[0].value = cert_data;
2397 a[0].value_len = MAX_CERT_SIZE;
2398 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
2400 value.data = a[0].value;
2401 value.size = a[0].value_len;
2403 else
2405 value.data = NULL;
2406 value.size = 0;
2409 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL)
2411 a[0].type = CKA_CLASS;
2412 a[0].value = &class;
2413 a[0].value_len = sizeof class;
2415 pkcs11_get_attribute_value (module, pks, obj, a, 1);
2418 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2420 for (i = 0; i < plist.key_ids_size; i++)
2422 if (plist.key_ids[i].length !=
2423 a[1].value_len
2424 || memcmp (plist.key_ids[i].data,
2425 a[1].value, a[1].value_len) != 0)
2427 /* not found */
2428 continue;
2433 if (find_data->current < *find_data->n_list)
2435 ret =
2436 gnutls_pkcs11_obj_init (&find_data->p_list[find_data->current]);
2437 if (ret < 0)
2439 gnutls_assert ();
2440 goto fail;
2443 if (class == CKO_PUBLIC_KEY)
2445 ret =
2446 pkcs11_obj_import_pubkey (module, pks, obj,
2447 find_data->p_list
2448 [find_data->current],
2449 &id, &label,
2450 &info->tinfo, lib_info);
2452 else
2454 ret =
2455 pkcs11_obj_import (class,
2456 find_data->p_list
2457 [find_data->current],
2458 &value, &id, &label,
2459 &info->tinfo, lib_info);
2461 if (ret < 0)
2463 gnutls_assert ();
2464 goto fail;
2468 find_data->current++;
2472 gnutls_free (cert_data);
2473 pkcs11_find_objects_final (module, pks);
2475 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* continue until all tokens have been checked */
2477 fail:
2478 gnutls_free (cert_data);
2479 pkcs11_find_objects_final (module, pks);
2480 if (plist.key_ids != NULL)
2482 for (i = 0; i < plist.key_ids_size; i++)
2484 _gnutls_buffer_clear (&plist.key_ids[i]);
2486 gnutls_free (plist.key_ids);
2488 for (i = 0; i < find_data->current; i++)
2490 gnutls_pkcs11_obj_deinit (find_data->p_list[i]);
2492 find_data->current = 0;
2494 return ret;
2498 * gnutls_pkcs11_obj_list_import_url:
2499 * @p_list: An uninitialized object list (may be NULL)
2500 * @n_list: initially should hold the maximum size of the list. Will contain the actual size.
2501 * @url: A PKCS 11 url identifying a set of objects
2502 * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2503 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2505 * This function will initialize and set values to an object list
2506 * by using all objects identified by a PKCS 11 URL.
2508 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2509 * negative error value.
2511 * Since: 2.12.0
2514 gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list,
2515 unsigned int *n_list,
2516 const char *url,
2517 gnutls_pkcs11_obj_attr_t attrs,
2518 unsigned int flags)
2520 int ret;
2521 struct crt_find_data_st find_data;
2523 memset (&find_data, 0, sizeof (find_data));
2525 /* fill in the find data structure */
2526 find_data.p_list = p_list;
2527 find_data.n_list = n_list;
2528 find_data.flags = attrs;
2529 find_data.current = 0;
2531 if (url == NULL || url[0] == 0)
2533 url = "pkcs11:";
2536 ret = pkcs11_url_to_info (url, &find_data.info);
2537 if (ret < 0)
2539 gnutls_assert ();
2540 return ret;
2543 ret =
2544 _pkcs11_traverse_tokens (find_objs, &find_data, find_data.info,
2545 pkcs11_obj_flags_to_int (flags));
2546 p11_kit_uri_free (find_data.info);
2548 if (ret < 0)
2550 gnutls_assert ();
2551 return ret;
2554 return 0;
2558 * gnutls_x509_crt_import_pkcs11_url:
2559 * @crt: A certificate of type #gnutls_x509_crt_t
2560 * @url: A PKCS 11 url
2561 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2563 * This function will import a PKCS 11 certificate directly from a token
2564 * without involving the #gnutls_pkcs11_obj_t structure. This function will
2565 * fail if the certificate stored is not of X.509 type.
2567 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2568 * negative error value.
2570 * Since: 2.12.0
2573 gnutls_x509_crt_import_pkcs11_url (gnutls_x509_crt_t crt,
2574 const char *url, unsigned int flags)
2576 gnutls_pkcs11_obj_t pcrt;
2577 int ret;
2579 ret = gnutls_pkcs11_obj_init (&pcrt);
2580 if (ret < 0)
2582 gnutls_assert ();
2583 return ret;
2586 ret = gnutls_pkcs11_obj_import_url (pcrt, url, flags);
2587 if (ret < 0)
2589 gnutls_assert ();
2590 goto cleanup;
2593 ret = gnutls_x509_crt_import (crt, &pcrt->raw, GNUTLS_X509_FMT_DER);
2594 if (ret < 0)
2596 gnutls_assert ();
2597 goto cleanup;
2600 ret = 0;
2601 cleanup:
2603 gnutls_pkcs11_obj_deinit (pcrt);
2605 return ret;
2610 * gnutls_x509_crt_import_pkcs11:
2611 * @crt: A certificate of type #gnutls_x509_crt_t
2612 * @pkcs11_crt: A PKCS 11 object that contains a certificate
2614 * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t
2615 * structure.
2617 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2618 * negative error value.
2620 * Since: 2.12.0
2623 gnutls_x509_crt_import_pkcs11 (gnutls_x509_crt_t crt,
2624 gnutls_pkcs11_obj_t pkcs11_crt)
2626 return gnutls_x509_crt_import (crt, &pkcs11_crt->raw, GNUTLS_X509_FMT_DER);
2630 * gnutls_x509_crt_list_import_pkcs11:
2631 * @certs: A list of certificates of type #gnutls_x509_crt_t
2632 * @cert_max: The maximum size of the list
2633 * @objs: A list of PKCS 11 objects
2634 * @flags: 0 for now
2636 * This function will import a PKCS 11 certificate list to a list of
2637 * #gnutls_x509_crt_t structure. These must not be initialized.
2639 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2640 * negative error value.
2642 * Since: 2.12.0
2645 gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs,
2646 unsigned int cert_max,
2647 gnutls_pkcs11_obj_t * const objs,
2648 unsigned int flags)
2650 unsigned int i, j;
2651 int ret;
2653 for (i = 0; i < cert_max; i++)
2655 ret = gnutls_x509_crt_init (&certs[i]);
2656 if (ret < 0)
2658 gnutls_assert ();
2659 goto cleanup;
2662 ret = gnutls_x509_crt_import_pkcs11 (certs[i], objs[i]);
2663 if (ret < 0)
2665 gnutls_assert ();
2666 goto cleanup;
2670 return 0;
2672 cleanup:
2673 for (j = 0; j < i; j++)
2675 gnutls_x509_crt_deinit (certs[j]);
2678 return ret;
2681 static int
2682 find_flags (struct ck_function_list * module, ck_session_handle_t pks,
2683 struct token_info *info, struct ck_info *lib_info, void *input)
2685 struct flags_find_data_st *find_data = input;
2687 if (info == NULL)
2688 { /* we don't support multiple calls */
2689 gnutls_assert ();
2690 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2693 /* do not bother reading the token if basic fields do not match
2695 if (!p11_kit_uri_match_token_info (find_data->info, &info->tinfo) ||
2696 !p11_kit_uri_match_module_info (find_data->info, lib_info))
2698 gnutls_assert ();
2699 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2702 /* found token! */
2704 find_data->slot_flags = info->sinfo.flags;
2706 return 0;
2710 * gnutls_pkcs11_token_get_flags:
2711 * @url: should contain a PKCS 11 URL
2712 * @flags: The output flags (GNUTLS_PKCS11_TOKEN_*)
2714 * This function will return information about the PKCS 11 token flags.
2715 * The flags from the %gnutls_pkcs11_token_info_t enumeration.
2717 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
2719 * Since: 2.12.0
2722 gnutls_pkcs11_token_get_flags (const char *url, unsigned int *flags)
2724 struct flags_find_data_st find_data;
2725 int ret;
2727 memset (&find_data, 0, sizeof (find_data));
2728 ret = pkcs11_url_to_info (url, &find_data.info);
2729 if (ret < 0)
2731 gnutls_assert ();
2732 return ret;
2735 ret = _pkcs11_traverse_tokens (find_flags, &find_data, find_data.info, 0);
2736 p11_kit_uri_free (find_data.info);
2738 if (ret < 0)
2740 gnutls_assert ();
2741 return ret;
2744 *flags = 0;
2745 if (find_data.slot_flags & CKF_HW_SLOT)
2746 *flags |= GNUTLS_PKCS11_TOKEN_HW;
2748 return 0;
2753 * gnutls_pkcs11_token_get_mechanism:
2754 * @url: should contain a PKCS 11 URL
2755 * @idx: The index of the mechanism
2756 * @mechanism: The PKCS #11 mechanism ID
2758 * This function will return the names of the supported mechanisms
2759 * by the token. It should be called with an increasing index until
2760 * it return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
2762 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
2764 * Since: 2.12.0
2767 gnutls_pkcs11_token_get_mechanism (const char *url, unsigned int idx,
2768 unsigned long *mechanism)
2770 int ret;
2771 ck_rv_t rv;
2772 struct ck_function_list *module;
2773 ck_slot_id_t slot;
2774 struct token_info tinfo;
2775 struct p11_kit_uri *info = NULL;
2776 unsigned long count;
2777 ck_mechanism_type_t mlist[400];
2779 ret = pkcs11_url_to_info (url, &info);
2780 if (ret < 0)
2782 gnutls_assert ();
2783 return ret;
2787 ret = pkcs11_find_slot (&module, &slot, info, &tinfo);
2788 p11_kit_uri_free (info);
2790 if (ret < 0)
2792 gnutls_assert ();
2793 return ret;
2796 count = sizeof (mlist) / sizeof (mlist[0]);
2797 rv = pkcs11_get_mechanism_list (module, slot, mlist, &count);
2798 if (rv != CKR_OK)
2800 gnutls_assert ();
2801 return pkcs11_rv_to_err (rv);
2804 if (idx >= count)
2806 gnutls_assert ();
2807 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2810 *mechanism = mlist[idx];
2812 return 0;
2817 * gnutls_pkcs11_type_get_name:
2818 * @type: Holds the PKCS 11 object type, a #gnutls_pkcs11_obj_type_t.
2820 * This function will return a human readable description of the
2821 * PKCS11 object type @obj. It will return "Unknown" for unknown
2822 * types.
2824 * Returns: human readable string labeling the PKCS11 object type
2825 * @type.
2827 * Since: 2.12.0
2829 const char *
2830 gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t type)
2832 switch (type)
2834 case GNUTLS_PKCS11_OBJ_X509_CRT:
2835 return "X.509 Certificate";
2836 case GNUTLS_PKCS11_OBJ_PUBKEY:
2837 return "Public key";
2838 case GNUTLS_PKCS11_OBJ_PRIVKEY:
2839 return "Private key";
2840 case GNUTLS_PKCS11_OBJ_SECRET_KEY:
2841 return "Secret key";
2842 case GNUTLS_PKCS11_OBJ_DATA:
2843 return "Data";
2844 case GNUTLS_PKCS11_OBJ_UNKNOWN:
2845 default:
2846 return "Unknown";
2850 ck_rv_t
2851 pkcs11_get_slot_list (struct ck_function_list * module, unsigned char token_present,
2852 ck_slot_id_t *slot_list, unsigned long *count)
2854 return (module)->C_GetSlotList (token_present, slot_list, count);
2857 ck_rv_t
2858 pkcs11_get_module_info (struct ck_function_list * module,
2859 struct ck_info * info)
2861 return (module)->C_GetInfo (info);
2864 ck_rv_t
2865 pkcs11_get_slot_info(struct ck_function_list * module,
2866 ck_slot_id_t slot_id,
2867 struct ck_slot_info *info)
2869 return (module)->C_GetSlotInfo (slot_id, info);
2872 ck_rv_t
2873 pkcs11_get_token_info (struct ck_function_list * module,
2874 ck_slot_id_t slot_id,
2875 struct ck_token_info *info)
2877 return (module)->C_GetTokenInfo (slot_id, info);
2880 ck_rv_t
2881 pkcs11_find_objects_init (struct ck_function_list *module,
2882 ck_session_handle_t sess,
2883 struct ck_attribute *templ,
2884 unsigned long count)
2886 return (module)->C_FindObjectsInit (sess, templ, count);
2889 ck_rv_t
2890 pkcs11_find_objects (struct ck_function_list *module,
2891 ck_session_handle_t sess,
2892 ck_object_handle_t *objects,
2893 unsigned long max_object_count,
2894 unsigned long *object_count)
2896 return (module)->C_FindObjects (sess, objects, max_object_count, object_count);
2899 ck_rv_t
2900 pkcs11_find_objects_final (struct ck_function_list *module,
2901 ck_session_handle_t sess)
2903 return (module)->C_FindObjectsFinal (sess);
2906 ck_rv_t
2907 pkcs11_close_session (struct ck_function_list *module,
2908 ck_session_handle_t sess)
2910 return (module)->C_CloseSession (sess);
2913 ck_rv_t
2914 pkcs11_get_attribute_value(struct ck_function_list *module,
2915 ck_session_handle_t sess,
2916 ck_object_handle_t object,
2917 struct ck_attribute *templ,
2918 unsigned long count)
2920 return (module)->C_GetAttributeValue (sess, object, templ, count);
2923 ck_rv_t
2924 pkcs11_get_mechanism_list (struct ck_function_list *module,
2925 ck_slot_id_t slot_id,
2926 ck_mechanism_type_t *mechanism_list,
2927 unsigned long *count)
2929 return (module)->C_GetMechanismList (slot_id, mechanism_list, count);
2932 ck_rv_t
2933 pkcs11_sign_init (struct ck_function_list *module,
2934 ck_session_handle_t sess,
2935 struct ck_mechanism *mechanism,
2936 ck_object_handle_t key)
2938 return (module)->C_SignInit (sess, mechanism, key);
2941 ck_rv_t
2942 pkcs11_sign (struct ck_function_list *module,
2943 ck_session_handle_t sess,
2944 unsigned char *data,
2945 unsigned long data_len,
2946 unsigned char *signature,
2947 unsigned long *signature_len)
2949 return (module)->C_Sign (sess, data, data_len, signature, signature_len);
2952 ck_rv_t
2953 pkcs11_generate_key_pair (struct ck_function_list *module,
2954 ck_session_handle_t sess,
2955 struct ck_mechanism *mechanism,
2956 struct ck_attribute *pub_templ,
2957 unsigned long pub_templ_count,
2958 struct ck_attribute *priv_templ,
2959 unsigned long priv_templ_count,
2960 ck_object_handle_t *pub,
2961 ck_object_handle_t *priv)
2963 return (module)->C_GenerateKeyPair (sess, mechanism, pub_templ, pub_templ_count,
2964 priv_templ, priv_templ_count, pub, priv);
2967 ck_rv_t
2968 pkcs11_decrypt_init (struct ck_function_list *module,
2969 ck_session_handle_t sess,
2970 struct ck_mechanism *mechanism,
2971 ck_object_handle_t key)
2973 return (module)->C_DecryptInit (sess, mechanism, key);
2976 ck_rv_t
2977 pkcs11_decrypt (struct ck_function_list *module,
2978 ck_session_handle_t sess,
2979 unsigned char *encrypted_data,
2980 unsigned long encrypted_data_len,
2981 unsigned char *data, unsigned long *data_len)
2983 return (module)->C_Decrypt (sess, encrypted_data, encrypted_data_len,
2984 data, data_len);
2987 ck_rv_t
2988 pkcs11_create_object (struct ck_function_list *module,
2989 ck_session_handle_t sess,
2990 struct ck_attribute *templ,
2991 unsigned long count,
2992 ck_object_handle_t *object)
2994 return (module)->C_CreateObject (sess, templ, count, object);
2997 ck_rv_t
2998 pkcs11_destroy_object (struct ck_function_list *module,
2999 ck_session_handle_t sess,
3000 ck_object_handle_t object)
3002 return (module)->C_DestroyObject (sess, object);
3005 ck_rv_t
3006 pkcs11_init_token (struct ck_function_list *module,
3007 ck_slot_id_t slot_id, unsigned char *pin,
3008 unsigned long pin_len, unsigned char *label)
3010 return (module)->C_InitToken (slot_id, pin, pin_len, label);
3013 ck_rv_t
3014 pkcs11_init_pin (struct ck_function_list *module,
3015 ck_session_handle_t sess,
3016 unsigned char *pin,
3017 unsigned long pin_len)
3019 return (module)->C_InitPIN (sess, pin, pin_len);
3022 ck_rv_t
3023 pkcs11_set_pin (struct ck_function_list *module,
3024 ck_session_handle_t sess,
3025 const char *old_pin,
3026 unsigned long old_len,
3027 const char *new_pin,
3028 unsigned long new_len)
3030 return (module)->C_SetPIN (sess, (uint8_t*)old_pin, old_len, (uint8_t*)new_pin, new_len);
3033 const char *
3034 pkcs11_strerror (ck_rv_t rv)
3036 return p11_kit_strerror (rv);