Add `gnutls/dtls.h' to the distribution.
[gnutls.git] / lib / pkcs11.c
blob06242e2c0dcf50f668c2c93455a6bde97acff204
1 /*
2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010 Free Software Foundation
4 * Copyright (C) 2008, Joe Orton <joe@manyfish.co.uk>
5 *
6 * Author: Nikos Mavrogiannopoulos
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 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public
23 * License along with this library; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA
28 #include <gnutls_int.h>
29 #include <gnutls/pkcs11.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <gnutls_errors.h>
33 #include <gnutls_datum.h>
34 #include <pkcs11_int.h>
36 #define MAX_PROVIDERS 16
38 static void terminate_string (unsigned char *str, size_t len);
40 /* XXX: try to eliminate this */
41 #define MAX_CERT_SIZE 8*1024
43 struct gnutls_pkcs11_provider_s
45 pakchois_module_t *module;
46 unsigned long nslots;
47 ck_slot_id_t *slots;
48 struct ck_info info;
51 struct flags_find_data_st
53 struct pkcs11_url_info info;
54 unsigned int slot_flags;
57 struct url_find_data_st
59 gnutls_pkcs11_obj_t crt;
62 struct crt_find_data_st
64 gnutls_pkcs11_obj_t *p_list;
65 unsigned int *n_list;
66 unsigned int current;
67 gnutls_pkcs11_obj_attr_t flags;
68 struct pkcs11_url_info info;
72 static struct gnutls_pkcs11_provider_s providers[MAX_PROVIDERS];
73 static int active_providers = 0;
75 static gnutls_pkcs11_pin_callback_t pin_func;
76 static void *pin_data;
78 gnutls_pkcs11_token_callback_t token_func;
79 void *token_data;
81 int
82 pkcs11_rv_to_err (ck_rv_t rv)
84 switch (rv)
86 case CKR_OK:
87 return 0;
88 case CKR_HOST_MEMORY:
89 return GNUTLS_E_MEMORY_ERROR;
90 case CKR_SLOT_ID_INVALID:
91 return GNUTLS_E_PKCS11_SLOT_ERROR;
92 case CKR_ARGUMENTS_BAD:
93 case CKR_MECHANISM_PARAM_INVALID:
94 return GNUTLS_E_INVALID_REQUEST;
95 case CKR_NEED_TO_CREATE_THREADS:
96 case CKR_CANT_LOCK:
97 case CKR_FUNCTION_NOT_PARALLEL:
98 case CKR_MUTEX_BAD:
99 case CKR_MUTEX_NOT_LOCKED:
100 return GNUTLS_E_LOCKING_ERROR;
101 case CKR_ATTRIBUTE_READ_ONLY:
102 case CKR_ATTRIBUTE_SENSITIVE:
103 case CKR_ATTRIBUTE_TYPE_INVALID:
104 case CKR_ATTRIBUTE_VALUE_INVALID:
105 return GNUTLS_E_PKCS11_ATTRIBUTE_ERROR;
106 case CKR_DEVICE_ERROR:
107 case CKR_DEVICE_MEMORY:
108 case CKR_DEVICE_REMOVED:
109 return GNUTLS_E_PKCS11_DEVICE_ERROR;
110 case CKR_DATA_INVALID:
111 case CKR_DATA_LEN_RANGE:
112 case CKR_ENCRYPTED_DATA_INVALID:
113 case CKR_ENCRYPTED_DATA_LEN_RANGE:
114 case CKR_OBJECT_HANDLE_INVALID:
115 return GNUTLS_E_PKCS11_DATA_ERROR;
116 case CKR_FUNCTION_NOT_SUPPORTED:
117 case CKR_MECHANISM_INVALID:
118 return GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR;
119 case CKR_KEY_HANDLE_INVALID:
120 case CKR_KEY_SIZE_RANGE:
121 case CKR_KEY_TYPE_INCONSISTENT:
122 case CKR_KEY_NOT_NEEDED:
123 case CKR_KEY_CHANGED:
124 case CKR_KEY_NEEDED:
125 case CKR_KEY_INDIGESTIBLE:
126 case CKR_KEY_FUNCTION_NOT_PERMITTED:
127 case CKR_KEY_NOT_WRAPPABLE:
128 case CKR_KEY_UNEXTRACTABLE:
129 return GNUTLS_E_PKCS11_KEY_ERROR;
130 case CKR_PIN_INCORRECT:
131 case CKR_PIN_INVALID:
132 case CKR_PIN_LEN_RANGE:
133 return GNUTLS_E_PKCS11_PIN_ERROR;
134 case CKR_PIN_EXPIRED:
135 return GNUTLS_E_PKCS11_PIN_EXPIRED;
136 case CKR_PIN_LOCKED:
137 return GNUTLS_E_PKCS11_PIN_LOCKED;
138 case CKR_SESSION_CLOSED:
139 case CKR_SESSION_COUNT:
140 case CKR_SESSION_HANDLE_INVALID:
141 case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
142 case CKR_SESSION_READ_ONLY:
143 case CKR_SESSION_EXISTS:
144 case CKR_SESSION_READ_ONLY_EXISTS:
145 case CKR_SESSION_READ_WRITE_SO_EXISTS:
146 return GNUTLS_E_PKCS11_SESSION_ERROR;
147 case CKR_SIGNATURE_INVALID:
148 case CKR_SIGNATURE_LEN_RANGE:
149 return GNUTLS_E_PKCS11_SIGNATURE_ERROR;
150 case CKR_TOKEN_NOT_PRESENT:
151 case CKR_TOKEN_NOT_RECOGNIZED:
152 case CKR_TOKEN_WRITE_PROTECTED:
153 return GNUTLS_E_PKCS11_TOKEN_ERROR;
154 case CKR_USER_ALREADY_LOGGED_IN:
155 case CKR_USER_NOT_LOGGED_IN:
156 case CKR_USER_PIN_NOT_INITIALIZED:
157 case CKR_USER_TYPE_INVALID:
158 case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
159 case CKR_USER_TOO_MANY_TYPES:
160 return GNUTLS_E_PKCS11_USER_ERROR;
161 case CKR_BUFFER_TOO_SMALL:
162 return GNUTLS_E_SHORT_MEMORY_BUFFER;
163 default:
164 return GNUTLS_E_PKCS11_ERROR;
168 /* Fake scan */
169 void
170 pkcs11_rescan_slots (void)
172 unsigned long slots;
174 pakchois_get_slot_list (providers[active_providers - 1].module, 0,
175 NULL, &slots);
179 * gnutls_pkcs11_add_provider:
180 * @name: The filename of the module
181 * @params: should be NULL
183 * This function will load and add a PKCS 11 module to the module
184 * list used in gnutls. After this function is called the module will
185 * be used for PKCS 11 operations.
187 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
188 * negative error value.
191 gnutls_pkcs11_add_provider (const char *name, const char *params)
194 if (active_providers >= MAX_PROVIDERS)
196 gnutls_assert ();
197 return GNUTLS_E_CONSTRAINT_ERROR;
200 active_providers++;
201 if (pakchois_module_load_abs
202 (&providers[active_providers - 1].module, name) != CKR_OK)
204 gnutls_assert ();
205 _gnutls_debug_log ("p11: Cannot load provider %s\n", name);
206 active_providers--;
207 return GNUTLS_E_PKCS11_LOAD_ERROR;
210 /* cache the number of slots in this module */
211 if (pakchois_get_slot_list
212 (providers[active_providers - 1].module, 0, NULL,
213 &providers[active_providers - 1].nslots) != CKR_OK)
215 gnutls_assert ();
216 goto fail;
219 providers[active_providers - 1].slots =
220 gnutls_malloc (sizeof (*providers[active_providers - 1].slots) *
221 providers[active_providers - 1].nslots);
222 if (providers[active_providers - 1].slots == NULL)
224 gnutls_assert ();
225 goto fail;
228 if (pakchois_get_slot_list
229 (providers[active_providers - 1].module, 0,
230 providers[active_providers - 1].slots,
231 &providers[active_providers - 1].nslots) != CKR_OK)
233 gnutls_assert ();
234 gnutls_free (providers[active_providers - 1].slots);
235 goto fail;
238 memset (&providers[active_providers - 1].info, 0,
239 sizeof (providers[active_providers - 1].info));
240 pakchois_get_info (providers[active_providers - 1].module,
241 &providers[active_providers - 1].info);
243 terminate_string (providers[active_providers - 1].info.manufacturer_id,
244 sizeof (providers[active_providers - 1].
245 info.manufacturer_id));
246 terminate_string (providers[active_providers - 1].info.library_description,
247 sizeof (providers[active_providers - 1].
248 info.library_description));
250 _gnutls_debug_log ("p11: loaded provider '%s' with %d slots\n",
251 name, (int) providers[active_providers - 1].nslots);
253 return 0;
255 fail:
256 pakchois_module_destroy (providers[active_providers - 1].module);
257 active_providers--;
258 return GNUTLS_E_PKCS11_LOAD_ERROR;
264 * gnutls_pkcs11_obj_get_info:
265 * @crt: should contain a #gnutls_pkcs11_obj_t structure
266 * @itype: Denotes the type of information requested
267 * @output: where output will be stored
268 * @output_size: contains the maximum size of the output and will be overwritten with actual
270 * This function will return information about the PKCS 11 certificatesuch
271 * as the label, id as well as token information where the key is stored. When
272 * output is text it returns null terminated string although %output_size contains
273 * the size of the actual data only.
275 * Returns: zero on success or a negative value on error.
278 gnutls_pkcs11_obj_get_info (gnutls_pkcs11_obj_t crt,
279 gnutls_pkcs11_obj_info_t itype,
280 void *output, size_t * output_size)
282 return pkcs11_get_info (&crt->info, itype, output, output_size);
286 pkcs11_get_info (struct pkcs11_url_info *info,
287 gnutls_pkcs11_obj_info_t itype, void *output,
288 size_t * output_size)
290 const char *str = NULL;
291 size_t len;
293 switch (itype)
295 case GNUTLS_PKCS11_OBJ_ID:
296 if (*output_size < info->certid_raw_size)
298 *output_size = info->certid_raw_size;
299 return GNUTLS_E_SHORT_MEMORY_BUFFER;
301 if (output)
302 memcpy (output, info->certid_raw, info->certid_raw_size);
303 *output_size = info->certid_raw_size;
305 return 0;
306 case GNUTLS_PKCS11_OBJ_ID_HEX:
307 str = info->id;
308 break;
309 case GNUTLS_PKCS11_OBJ_LABEL:
310 str = info->label;
311 break;
312 case GNUTLS_PKCS11_OBJ_TOKEN_LABEL:
313 str = info->token;
314 break;
315 case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL:
316 str = info->serial;
317 break;
318 case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER:
319 str = info->manufacturer;
320 break;
321 case GNUTLS_PKCS11_OBJ_TOKEN_MODEL:
322 str = info->model;
323 break;
324 case GNUTLS_PKCS11_OBJ_LIBRARY_DESCRIPTION:
325 str = info->lib_desc;
326 break;
327 case GNUTLS_PKCS11_OBJ_LIBRARY_VERSION:
328 str = info->lib_version;
329 break;
330 case GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER:
331 str = info->lib_manufacturer;
332 break;
333 default:
334 gnutls_assert ();
335 return GNUTLS_E_INVALID_REQUEST;
338 len = strlen (str);
340 if (len + 1 > *output_size)
342 *output_size = len + 1;
343 return GNUTLS_E_SHORT_MEMORY_BUFFER;
346 strcpy (output, str);
348 *output_size = len;
350 return 0;
353 static int init = 0;
357 * gnutls_pkcs11_init:
358 * @flags: GNUTLS_PKCS11_FLAG_MANUAL or GNUTLS_PKCS11_FLAG_AUTO
359 * @configfile: either NULL or the location of a configuration file
361 * This function will initialize the PKCS 11 subsystem in gnutls. It will
362 * read a configuration file if %GNUTLS_PKCS11_FLAG_AUTO is used or allow
363 * you to independently load PKCS 11 modules using gnutls_pkcs11_add_provider()
364 * if %GNUTLS_PKCS11_FLAG_MANUAL is specified.
366 * Normally you don't need to call this function since it is being called
367 * by gnutls_global_init(). Otherwise you must call it before it.
369 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
370 * negative error value.
373 gnutls_pkcs11_init (unsigned int flags, const char *configfile)
375 int ret;
377 if (init != 0)
379 init++;
380 return 0;
382 init++;
384 if (flags == GNUTLS_PKCS11_FLAG_MANUAL)
385 return 0;
386 else
388 FILE *fp;
389 char line[512];
390 const char *library;
392 if (configfile == NULL)
393 configfile = "/etc/gnutls/pkcs11.conf";
395 fp = fopen (configfile, "r");
396 if (fp == NULL)
398 gnutls_assert ();
399 _gnutls_debug_log ("Cannot load %s\n", configfile);
400 return GNUTLS_E_FILE_ERROR;
403 while (fgets (line, sizeof (line), fp) != NULL)
405 if (strncmp (line, "load", sizeof ("load") - 1) == 0)
407 char *p;
408 p = strchr (line, '=');
409 if (p == NULL)
410 continue;
412 library = ++p;
414 p = strchr (line, '\n');
415 if (p != NULL)
417 *p = 0;
420 ret = gnutls_pkcs11_add_provider (library, NULL);
421 if (ret < 0)
423 gnutls_assert ();
424 _gnutls_debug_log ("Cannot load provider: %s\n", library);
425 continue;
431 return 0;
435 * gnutls_pkcs11_deinit:
437 * This function will deinitialize the PKCS 11 subsystem in gnutls.
440 void
441 gnutls_pkcs11_deinit (void)
443 int i;
445 init--;
446 if (init > 0)
447 return;
448 if (init < 0)
450 init = 0;
451 return;
454 for (i = 0; i < active_providers; i++)
456 pakchois_module_destroy (providers[i].module);
458 active_providers = 0;
462 * gnutls_pkcs11_set_pin_function:
463 * @fn: The PIN callback
464 * @userdata: data to be supplied to callback
466 * This function will set a callback function to be used when a PIN
467 * is required for PKCS 11 operations.
469 * Callback for PKCS#11 PIN entry. The callback provides the PIN code
470 * to unlock the token with label 'token_label', specified by the URL
471 * 'token_url'.
473 * The PIN code, as a NUL-terminated ASCII string, should be copied
474 * into the 'pin' buffer (of maximum size pin_max), and
475 * return 0 to indicate success. Alternatively, the callback may
476 * return a negative gnutls error code to indicate failure and cancel
477 * PIN entry (in which case, the contents of the 'pin' parameter are ignored).
479 * When a PIN is required, the callback will be invoked repeatedly
480 * (and indefinitely) until either the returned PIN code is correct,
481 * the callback returns failure, or the token refuses login (e.g. when
482 * the token is locked due to too many incorrect PINs!). For the
483 * first such invocation, the 'attempt' counter will have value zero;
484 * it will increase by one for each subsequent attempt.
486 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
487 * negative error value.
489 void
490 gnutls_pkcs11_set_pin_function (gnutls_pkcs11_pin_callback_t fn,
491 void *userdata)
493 pin_func = fn;
494 pin_data = userdata;
498 * gnutls_pkcs11_set_token_function:
499 * @fn: The PIN callback
500 * @userdata: data to be supplied to callback
502 * This function will set a callback function to be used when a token
503 * needs to be inserted to continue PKCS 11 operations.
505 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
506 * negative error value.
508 void
509 gnutls_pkcs11_set_token_function (gnutls_pkcs11_token_callback_t fn,
510 void *userdata)
512 token_func = fn;
513 token_data = userdata;
516 static int
517 unescape_string (char *output, const char *input, size_t * size,
518 char terminator)
520 gnutls_buffer_st str;
521 int ret = 0;
522 char *p;
523 int len;
525 _gnutls_buffer_init (&str);
527 /* find terminator */
528 p = strchr (input, terminator);
529 if (p != NULL)
530 len = p - input;
531 else
532 len = strlen (input);
534 ret = _gnutls_buffer_append_data (&str, input, len);
535 if (ret < 0)
537 gnutls_assert ();
538 return ret;
541 ret = _gnutls_buffer_unescape (&str);
542 if (ret < 0)
544 gnutls_assert ();
545 return ret;
548 ret = _gnutls_buffer_append_data (&str, "", 1);
549 if (ret < 0)
551 gnutls_assert ();
552 return ret;
555 _gnutls_buffer_pop_data (&str, output, size);
557 _gnutls_buffer_clear (&str);
559 return ret;
563 pkcs11_url_to_info (const char *url, struct pkcs11_url_info *info)
565 int ret;
566 char *p1, *p2;
567 size_t l;
569 memset (info, 0, sizeof (*info));
571 if (strstr (url, "pkcs11:") == NULL)
573 ret = GNUTLS_E_PARSING_ERROR;
574 goto cleanup;
577 if ((p1 = strstr (url, "library-manufacturer=")) != NULL)
579 p1 += sizeof ("library-manufacturer=") - 1;
580 l = sizeof (info->lib_manufacturer);
582 ret = unescape_string (info->lib_manufacturer, p1, &l, ';');
583 if (ret < 0)
585 goto cleanup;
589 if ((p1 = strstr (url, "library-description=")) != NULL)
591 p1 += sizeof ("library-description=") - 1;
592 l = sizeof (info->lib_desc);
594 ret = unescape_string (info->lib_desc, p1, &l, ';');
595 if (ret < 0)
597 goto cleanup;
601 if ((p1 = strstr (url, "library-version=")) != NULL)
603 p1 += sizeof ("library-version=") - 1;
604 l = sizeof (info->lib_version);
606 ret = unescape_string (info->lib_version, p1, &l, ';');
607 if (ret < 0)
609 goto cleanup;
613 if ((p1 = strstr (url, ";manufacturer=")) != NULL ||
614 (p1 = strstr (url, ":manufacturer=")) != NULL)
617 p1 += sizeof (";manufacturer=") - 1;
618 l = sizeof (info->manufacturer);
620 ret = unescape_string (info->manufacturer, p1, &l, ';');
621 if (ret < 0)
623 goto cleanup;
627 if ((p1 = strstr (url, "token=")) != NULL)
629 p1 += sizeof ("token=") - 1;
630 l = sizeof (info->token);
632 ret = unescape_string (info->token, p1, &l, ';');
633 if (ret < 0)
635 goto cleanup;
639 if ((p1 = strstr (url, "object=")) != NULL)
641 p1 += sizeof ("object=") - 1;
642 l = sizeof (info->label);
644 ret = unescape_string (info->label, p1, &l, ';');
645 if (ret < 0)
647 goto cleanup;
651 if ((p1 = strstr (url, "serial=")) != NULL)
653 p1 += sizeof ("serial=") - 1;
654 l = sizeof (info->serial);
656 ret = unescape_string (info->serial, p1, &l, ';');
657 if (ret < 0)
659 goto cleanup;
663 if ((p1 = strstr (url, "model=")) != NULL)
665 p1 += sizeof ("model=") - 1;
666 l = sizeof (info->model);
668 ret = unescape_string (info->model, p1, &l, ';');
669 if (ret < 0)
671 goto cleanup;
675 if ((p1 = strstr (url, "objecttype=")) != NULL)
677 p1 += sizeof ("objecttype=") - 1;
678 l = sizeof (info->model);
680 ret = unescape_string (info->type, p1, &l, ';');
681 if (ret < 0)
683 goto cleanup;
687 if (((p1 = strstr (url, ";id=")) != NULL)
688 || ((p1 = strstr (url, ":id=")) != NULL))
690 p1 += sizeof (";id=") - 1;
692 if ((p2 = strchr (p1, ';')) == NULL)
694 l = strlen (p1);
696 else
698 l = p2 - p1;
701 if (l > sizeof (info->id) - 1)
703 gnutls_assert ();
704 ret = GNUTLS_E_PARSING_ERROR;
707 memcpy (info->id, p1, l);
708 info->id[l] = 0;
710 /* convert to raw */
711 info->certid_raw_size = sizeof (info->certid_raw);
712 ret =
713 _gnutls_hex2bin (info->id, strlen (info->id),
714 info->certid_raw, &info->certid_raw_size);
715 if (ret < 0)
717 gnutls_assert ();
718 goto cleanup;
722 ret = 0;
724 cleanup:
726 return ret;
730 #define INVALID_CHARS "\\/\"'%&#@!?$* <>{}[]()`|:;,.+-"
732 static int
733 append (gnutls_buffer_st * dest, const char *tname,
734 const char *p11name, int init)
736 gnutls_buffer_st tmpstr;
737 int ret;
739 _gnutls_buffer_init (&tmpstr);
740 if ((ret = _gnutls_buffer_append_str (&tmpstr, tname)) < 0)
742 gnutls_assert ();
743 goto cleanup;
746 ret = _gnutls_buffer_escape (&tmpstr, INVALID_CHARS);
747 if (ret < 0)
749 gnutls_assert ();
750 goto cleanup;
753 if ((ret = _gnutls_buffer_append_data (&tmpstr, "", 1)) < 0)
755 gnutls_assert ();
756 goto cleanup;
759 if ((ret =
760 _gnutls_buffer_append_printf (dest, "%s%s=%s",
761 (init != 0) ? ";" : "", p11name,
762 tmpstr.data)) < 0)
764 gnutls_assert ();
765 goto cleanup;
768 ret = 0;
770 cleanup:
771 _gnutls_buffer_clear (&tmpstr);
773 return ret;
779 pkcs11_info_to_url (const struct pkcs11_url_info *info,
780 gnutls_pkcs11_url_type_t detailed, char **url)
782 gnutls_buffer_st str;
783 int init = 0;
784 int ret;
786 _gnutls_buffer_init (&str);
788 _gnutls_buffer_append_str (&str, "pkcs11:");
790 if (info->token[0])
792 ret = append (&str, info->token, "token", init);
793 if (ret < 0)
795 gnutls_assert ();
796 goto cleanup;
798 init = 1;
801 if (info->serial[0])
803 ret = append (&str, info->serial, "serial", init);
804 if (ret < 0)
806 gnutls_assert ();
807 goto cleanup;
809 init = 1;
812 if (info->model[0])
814 ret = append (&str, info->model, "model", init);
815 if (ret < 0)
817 gnutls_assert ();
818 goto cleanup;
820 init = 1;
824 if (info->manufacturer[0])
826 ret = append (&str, info->manufacturer, "manufacturer", init);
827 if (ret < 0)
829 gnutls_assert ();
830 goto cleanup;
832 init = 1;
835 if (info->label[0])
837 ret = append (&str, info->label, "object", init);
838 if (ret < 0)
840 gnutls_assert ();
841 goto cleanup;
843 init = 1;
846 if (info->type[0])
848 ret = append (&str, info->type, "objecttype", init);
849 if (ret < 0)
851 gnutls_assert ();
852 goto cleanup;
854 init = 1;
857 if (detailed > GNUTLS_PKCS11_URL_GENERIC)
859 if (info->lib_manufacturer[0])
861 ret =
862 append (&str, info->lib_manufacturer, "library-manufacturer",
863 init);
864 if (ret < 0)
866 gnutls_assert ();
867 goto cleanup;
869 init = 1;
872 if (info->lib_desc[0])
874 ret = append (&str, info->lib_desc, "library-description", init);
875 if (ret < 0)
877 gnutls_assert ();
878 goto cleanup;
880 init = 1;
884 if (detailed > GNUTLS_PKCS11_URL_LIB)
886 if (info->lib_version[0])
888 ret = append (&str, info->lib_version, "library-version", init);
889 if (ret < 0)
891 gnutls_assert ();
892 goto cleanup;
894 init = 1;
898 if (info->id[0] != 0)
900 ret = _gnutls_buffer_append_printf (&str, ";id=%s", info->id);
901 if (ret < 0)
903 gnutls_assert ();
904 return ret;
908 _gnutls_buffer_append_data (&str, "", 1);
910 *url = str.data;
912 return 0;
914 cleanup:
915 _gnutls_buffer_clear (&str);
916 return ret;
920 * gnutls_pkcs11_obj_init:
921 * @crt: The structure to be initialized
923 * This function will initialize a pkcs11 certificate structure.
925 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
926 * negative error value.
929 gnutls_pkcs11_obj_init (gnutls_pkcs11_obj_t * crt)
931 *crt = gnutls_calloc (1, sizeof (struct gnutls_pkcs11_obj_st));
932 if (*crt == NULL)
934 gnutls_assert ();
935 return GNUTLS_E_MEMORY_ERROR;
938 return 0;
942 * gnutls_pkcs11_obj_deinit:
943 * @key: The structure to be initialized
945 * This function will deinitialize a certificate structure.
947 void
948 gnutls_pkcs11_obj_deinit (gnutls_pkcs11_obj_t crt)
950 _gnutls_free_datum (&crt->raw);
951 free (crt);
955 * gnutls_pkcs11_obj_export:
956 * @key: Holds the object
957 * @output_data: will contain a certificate PEM or DER encoded
958 * @output_data_size: holds the size of output_data (and will be
959 * replaced by the actual size of parameters)
961 * This function will export the pkcs11 object data. It is normal
962 * for PKCS #11 data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
963 * will be returned.
965 * If the buffer provided is not long enough to hold the output, then
966 * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
967 * be returned.
969 * If the structure is PEM encoded, it will have a header
970 * of "BEGIN CERTIFICATE".
972 * Return value: In case of failure a negative value will be
973 * returned, and 0 on success.
976 gnutls_pkcs11_obj_export (gnutls_pkcs11_obj_t obj,
977 void *output_data, size_t * output_data_size)
979 if (obj == NULL || obj->raw.data == NULL)
981 gnutls_assert ();
982 return GNUTLS_E_INVALID_REQUEST;
985 if (output_data == NULL || *output_data_size < obj->raw.size)
987 *output_data_size = obj->raw.size;
988 gnutls_assert ();
989 return GNUTLS_E_SHORT_MEMORY_BUFFER;
991 *output_data_size = obj->raw.size;
993 memcpy (output_data, obj->raw.data, obj->raw.size);
994 return 0;
997 static void
998 terminate_string (unsigned char *str, size_t len)
1000 unsigned char *ptr = str + len - 1;
1002 while ((*ptr == ' ' || *ptr == '\t' || *ptr == '\0') && ptr >= str)
1003 ptr--;
1005 if (ptr == str - 1)
1006 str[0] = '\0';
1007 else if (ptr == str + len - 1)
1008 str[len - 1] = '\0';
1009 else
1010 ptr[1] = '\0';
1014 pkcs11_find_object (pakchois_session_t ** _pks,
1015 ck_object_handle_t * _obj,
1016 struct pkcs11_url_info *info, unsigned int flags)
1018 int ret;
1019 pakchois_session_t *pks;
1020 ck_object_handle_t obj;
1021 ck_object_class_t class;
1022 struct ck_attribute a[4];
1023 int a_vals = 0;
1024 unsigned long count;
1025 ck_rv_t rv;
1027 class = pkcs11_strtype_to_class (info->type);
1028 if (class == -1)
1030 gnutls_assert ();
1031 return GNUTLS_E_INVALID_REQUEST;
1034 ret = pkcs11_open_session (&pks, info, flags & SESSION_LOGIN);
1035 if (ret < 0)
1037 gnutls_assert ();
1038 return ret;
1041 a[a_vals].type = CKA_CLASS;
1042 a[a_vals].value = &class;
1043 a[a_vals].value_len = sizeof class;
1044 a_vals++;
1046 if (info->certid_raw_size > 0)
1048 a[a_vals].type = CKA_ID;
1049 a[a_vals].value = info->certid_raw;
1050 a[a_vals].value_len = info->certid_raw_size;
1051 a_vals++;
1054 rv = pakchois_find_objects_init (pks, a, a_vals);
1055 if (rv != CKR_OK)
1057 gnutls_assert ();
1058 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
1059 ret = pkcs11_rv_to_err (rv);
1060 goto fail;
1063 if (pakchois_find_objects (pks, &obj, 1, &count) == CKR_OK && count == 1)
1065 *_obj = obj;
1066 *_pks = pks;
1067 pakchois_find_objects_final (pks);
1068 return 0;
1072 pakchois_find_objects_final (pks);
1073 fail:
1074 pakchois_close_session (pks);
1076 return ret;
1079 static void
1080 fix_strings (struct token_info *info)
1082 terminate_string (info->tinfo.manufacturer_id,
1083 sizeof info->tinfo.manufacturer_id);
1084 terminate_string (info->tinfo.label, sizeof info->tinfo.label);
1085 terminate_string (info->tinfo.model, sizeof info->tinfo.model);
1086 terminate_string (info->tinfo.serial_number,
1087 sizeof info->tinfo.serial_number);
1088 terminate_string (info->sinfo.slot_description,
1089 sizeof info->sinfo.slot_description);
1093 pkcs11_find_slot (pakchois_module_t ** module, ck_slot_id_t * slot,
1094 struct pkcs11_url_info *info, struct token_info *_tinfo)
1096 int x, z;
1098 for (x = 0; x < active_providers; x++)
1100 for (z = 0; z < providers[x].nslots; z++)
1102 struct token_info tinfo;
1104 if (pakchois_get_token_info
1105 (providers[x].module, providers[x].slots[z],
1106 &tinfo.tinfo) != CKR_OK)
1108 continue;
1110 tinfo.sid = providers[x].slots[z];
1111 tinfo.prov = &providers[x];
1113 if (pakchois_get_slot_info
1114 (providers[x].module, providers[x].slots[z],
1115 &tinfo.sinfo) != CKR_OK)
1117 continue;
1120 /* XXX make wrapper for token_info? */
1121 fix_strings (&tinfo);
1123 if (pkcs11_token_matches_info (info, &tinfo.tinfo,
1124 &providers[x].info) < 0)
1126 continue;
1129 /* ok found */
1130 *module = providers[x].module;
1131 *slot = providers[x].slots[z];
1133 if (_tinfo != NULL)
1134 memcpy (_tinfo, &tinfo, sizeof (tinfo));
1136 return 0;
1140 gnutls_assert ();
1141 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1145 pkcs11_open_session (pakchois_session_t ** _pks,
1146 struct pkcs11_url_info *info, unsigned int flags)
1148 ck_rv_t rv;
1149 int ret;
1150 pakchois_session_t *pks = NULL;
1151 pakchois_module_t *module;
1152 ck_slot_id_t slot;
1153 struct token_info tinfo;
1155 ret = pkcs11_find_slot (&module, &slot, info, &tinfo);
1156 if (ret < 0)
1158 gnutls_assert ();
1159 return ret;
1162 rv = pakchois_open_session (module,
1163 slot,
1164 ((flags & SESSION_WRITE)
1165 ? CKF_RW_SESSION : 0) |
1166 CKF_SERIAL_SESSION, NULL, NULL, &pks);
1167 if (rv != CKR_OK)
1169 gnutls_assert ();
1170 return pkcs11_rv_to_err (rv);
1173 if (flags & SESSION_LOGIN)
1175 ret = pkcs11_login (pks, &tinfo, (flags & SESSION_SO) ? 1 : 0);
1176 if (ret < 0)
1178 gnutls_assert ();
1179 pakchois_close_session (pks);
1180 return ret;
1184 /* ok found */
1185 *_pks = pks;
1186 return 0;
1191 _pkcs11_traverse_tokens (find_func_t find_func, void *input,
1192 unsigned int flags)
1194 ck_rv_t rv;
1195 int found = 0, x, z, ret;
1196 pakchois_session_t *pks = NULL;
1198 for (x = 0; x < active_providers; x++)
1200 for (z = 0; z < providers[x].nslots; z++)
1202 struct token_info info;
1204 ret = GNUTLS_E_PKCS11_ERROR;
1206 if (pakchois_get_token_info
1207 (providers[x].module, providers[x].slots[z],
1208 &info.tinfo) != CKR_OK)
1210 continue;
1212 info.sid = providers[x].slots[z];
1213 info.prov = &providers[x];
1215 if (pakchois_get_slot_info
1216 (providers[x].module, providers[x].slots[z],
1217 &info.sinfo) != CKR_OK)
1219 continue;
1222 /* XXX make wrapper for token_info? */
1223 fix_strings (&info);
1225 rv = pakchois_open_session (providers[x].module,
1226 providers[x].slots[z],
1227 ((flags & SESSION_WRITE)
1228 ? CKF_RW_SESSION : 0) |
1229 CKF_SERIAL_SESSION, NULL, NULL, &pks);
1230 if (rv != CKR_OK)
1232 continue;
1235 if (flags & SESSION_LOGIN)
1237 ret = pkcs11_login (pks, &info, (flags & SESSION_SO) ? 1 : 0);
1238 if (ret < 0)
1240 gnutls_assert ();
1241 return ret;
1245 ret = find_func (pks, &info, &providers[x].info, input);
1247 if (ret == 0)
1249 found = 1;
1250 goto finish;
1252 else
1254 pakchois_close_session (pks);
1255 pks = NULL;
1260 finish:
1261 /* final call */
1263 if (found == 0)
1265 ret = find_func (pks, NULL, NULL, input);
1267 else
1269 ret = 0;
1272 if (pks != NULL)
1274 pakchois_close_session (pks);
1277 return ret;
1280 static const char *
1281 pkcs11_obj_type_to_str (gnutls_pkcs11_obj_type_t type)
1283 switch (type)
1285 case GNUTLS_PKCS11_OBJ_X509_CRT:
1286 return "cert";
1287 case GNUTLS_PKCS11_OBJ_PUBKEY:
1288 return "public";
1289 case GNUTLS_PKCS11_OBJ_PRIVKEY:
1290 return "private";
1291 case GNUTLS_PKCS11_OBJ_SECRET_KEY:
1292 return "secretkey";
1293 case GNUTLS_PKCS11_OBJ_DATA:
1294 return "data";
1295 case GNUTLS_PKCS11_OBJ_UNKNOWN:
1296 default:
1297 return "unknown";
1301 /* imports a raw certificate from a token to a pkcs11_obj_t structure.
1303 static int
1304 pkcs11_obj_import (unsigned int class, gnutls_pkcs11_obj_t obj,
1305 const gnutls_datum_t * data,
1306 const gnutls_datum_t * id,
1307 const gnutls_datum_t * label,
1308 struct ck_token_info *tinfo, struct ck_info *lib_info)
1310 char *s;
1311 int ret;
1313 switch (class)
1315 case CKO_CERTIFICATE:
1316 obj->type = GNUTLS_PKCS11_OBJ_X509_CRT;
1317 break;
1318 case CKO_PUBLIC_KEY:
1319 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1320 break;
1321 case CKO_PRIVATE_KEY:
1322 obj->type = GNUTLS_PKCS11_OBJ_PRIVKEY;
1323 break;
1324 case CKO_SECRET_KEY:
1325 obj->type = GNUTLS_PKCS11_OBJ_SECRET_KEY;
1326 break;
1327 case CKO_DATA:
1328 obj->type = GNUTLS_PKCS11_OBJ_DATA;
1329 break;
1330 default:
1331 obj->type = GNUTLS_PKCS11_OBJ_UNKNOWN;
1334 if (obj->type != GNUTLS_PKCS11_OBJ_UNKNOWN)
1335 strcpy (obj->info.type, pkcs11_obj_type_to_str (obj->type));
1337 if (data && data->data)
1339 ret = _gnutls_set_datum (&obj->raw, data->data, data->size);
1340 if (ret < 0)
1342 gnutls_assert ();
1343 return ret;
1347 terminate_string (tinfo->manufacturer_id, sizeof tinfo->manufacturer_id);
1348 terminate_string (tinfo->label, sizeof tinfo->label);
1349 terminate_string (tinfo->model, sizeof tinfo->model);
1350 terminate_string (tinfo->serial_number, sizeof tinfo->serial_number);
1352 /* write data */
1353 snprintf (obj->info.manufacturer, sizeof (obj->info.manufacturer),
1354 "%s", tinfo->manufacturer_id);
1355 snprintf (obj->info.token, sizeof (obj->info.token), "%s", tinfo->label);
1356 snprintf (obj->info.model, sizeof (obj->info.model), "%s", tinfo->model);
1357 snprintf (obj->info.serial, sizeof (obj->info.serial), "%s",
1358 tinfo->serial_number);
1360 snprintf (obj->info.lib_manufacturer, sizeof (obj->info.lib_manufacturer),
1361 "%s", lib_info->manufacturer_id);
1362 snprintf (obj->info.lib_desc, sizeof (obj->info.lib_desc), "%s",
1363 lib_info->library_description);
1364 snprintf (obj->info.lib_version, sizeof (obj->info.lib_version), "%u.%u",
1365 (unsigned int) lib_info->library_version.major,
1366 (unsigned int) lib_info->library_version.minor);
1370 if (label && label->data)
1372 memcpy (obj->info.label, label->data, label->size);
1373 obj->info.label[label->size] = 0;
1376 if (id && id->data)
1378 s = _gnutls_bin2hex (id->data, id->size, obj->info.id,
1379 sizeof (obj->info.id), ":");
1380 if (s == NULL)
1382 gnutls_assert ();
1383 return GNUTLS_E_PKCS11_ERROR;
1386 memmove (obj->info.certid_raw, id->data, id->size);
1387 obj->info.certid_raw_size = id->size;
1390 return 0;
1393 static int
1394 pkcs11_obj_import_pubkey (pakchois_session_t * pks,
1395 ck_object_handle_t obj,
1396 gnutls_pkcs11_obj_t crt,
1397 const gnutls_datum_t * id,
1398 const gnutls_datum_t * label,
1399 struct ck_token_info *tinfo,
1400 struct ck_info *lib_info)
1403 struct ck_attribute a[4];
1404 ck_key_type_t key_type;
1405 opaque tmp1[2048];
1406 opaque tmp2[2048];
1407 int ret;
1408 unsigned int tval;
1410 a[0].type = CKA_KEY_TYPE;
1411 a[0].value = &key_type;
1412 a[0].value_len = sizeof (key_type);
1414 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
1416 switch (key_type)
1418 case CKK_RSA:
1419 a[0].type = CKA_MODULUS;
1420 a[0].value = tmp1;
1421 a[0].value_len = sizeof (tmp1);
1422 a[1].type = CKA_PUBLIC_EXPONENT;
1423 a[1].value = tmp2;
1424 a[1].value_len = sizeof (tmp2);
1426 if (pakchois_get_attribute_value (pks, obj, a, 2) == CKR_OK)
1429 ret =
1430 _gnutls_set_datum (&crt->pubkey[0],
1431 a[0].value, a[0].value_len);
1433 if (ret >= 0)
1434 ret =
1435 _gnutls_set_datum (&crt->pubkey
1436 [1], a[1].value, a[1].value_len);
1438 if (ret < 0)
1440 gnutls_assert ();
1441 _gnutls_free_datum (&crt->pubkey[1]);
1442 _gnutls_free_datum (&crt->pubkey[0]);
1443 return GNUTLS_E_MEMORY_ERROR;
1446 else
1448 gnutls_assert ();
1449 return GNUTLS_E_PKCS11_ERROR;
1451 crt->pk_algorithm = GNUTLS_PK_RSA;
1452 break;
1453 case CKK_DSA:
1454 a[0].type = CKA_PRIME;
1455 a[0].value = tmp1;
1456 a[0].value_len = sizeof (tmp1);
1457 a[1].type = CKA_SUBPRIME;
1458 a[1].value = tmp2;
1459 a[1].value_len = sizeof (tmp2);
1461 if (pakchois_get_attribute_value (pks, obj, a, 2) == CKR_OK)
1463 ret =
1464 _gnutls_set_datum (&crt->pubkey[0],
1465 a[0].value, a[0].value_len);
1467 if (ret >= 0)
1468 ret =
1469 _gnutls_set_datum (&crt->pubkey
1470 [1], a[1].value, a[1].value_len);
1472 if (ret < 0)
1474 gnutls_assert ();
1475 _gnutls_free_datum (&crt->pubkey[1]);
1476 _gnutls_free_datum (&crt->pubkey[0]);
1477 return GNUTLS_E_MEMORY_ERROR;
1480 else
1482 gnutls_assert ();
1483 return GNUTLS_E_PKCS11_ERROR;
1486 a[0].type = CKA_BASE;
1487 a[0].value = tmp1;
1488 a[0].value_len = sizeof (tmp1);
1489 a[1].type = CKA_VALUE;
1490 a[1].value = tmp2;
1491 a[1].value_len = sizeof (tmp2);
1493 if (pakchois_get_attribute_value (pks, obj, a, 2) == CKR_OK)
1495 ret =
1496 _gnutls_set_datum (&crt->pubkey[2],
1497 a[0].value, a[0].value_len);
1499 if (ret >= 0)
1500 ret =
1501 _gnutls_set_datum (&crt->pubkey
1502 [3], a[1].value, a[1].value_len);
1504 if (ret < 0)
1506 gnutls_assert ();
1507 _gnutls_free_datum (&crt->pubkey[0]);
1508 _gnutls_free_datum (&crt->pubkey[1]);
1509 _gnutls_free_datum (&crt->pubkey[2]);
1510 _gnutls_free_datum (&crt->pubkey[3]);
1511 return GNUTLS_E_MEMORY_ERROR;
1514 else
1516 gnutls_assert ();
1517 return GNUTLS_E_PKCS11_ERROR;
1519 crt->pk_algorithm = GNUTLS_PK_RSA;
1520 break;
1521 default:
1522 gnutls_assert ();
1523 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
1527 /* read key usage flags */
1528 a[0].type = CKA_ENCRYPT;
1529 a[0].value = &tval;
1530 a[0].value_len = sizeof (tval);
1532 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
1534 if (tval != 0)
1536 crt->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
1540 a[0].type = CKA_VERIFY;
1541 a[0].value = &tval;
1542 a[0].value_len = sizeof (tval);
1544 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
1546 if (tval != 0)
1548 crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1549 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1550 | GNUTLS_KEY_NON_REPUDIATION;
1554 a[0].type = CKA_VERIFY_RECOVER;
1555 a[0].value = &tval;
1556 a[0].value_len = sizeof (tval);
1558 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
1560 if (tval != 0)
1562 crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1563 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1564 | GNUTLS_KEY_NON_REPUDIATION;
1568 a[0].type = CKA_DERIVE;
1569 a[0].value = &tval;
1570 a[0].value_len = sizeof (tval);
1572 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
1574 if (tval != 0)
1576 crt->key_usage |= GNUTLS_KEY_KEY_AGREEMENT;
1580 a[0].type = CKA_WRAP;
1581 a[0].value = &tval;
1582 a[0].value_len = sizeof (tval);
1584 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
1586 if (tval != 0)
1588 crt->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
1592 return pkcs11_obj_import (CKO_PUBLIC_KEY, crt, NULL, id, label,
1593 tinfo, lib_info);
1596 ck_object_class_t
1597 pkcs11_strtype_to_class (const char *type)
1599 ck_object_class_t class;
1601 if (strcmp (type, "cert") == 0)
1603 class = CKO_CERTIFICATE;
1605 else if (strcmp (type, "public") == 0)
1607 class = CKO_PUBLIC_KEY;
1609 else if (strcmp (type, "private") == 0)
1611 class = CKO_PRIVATE_KEY;
1613 else if (strcmp (type, "secretkey") == 0)
1615 class = CKO_SECRET_KEY;
1617 else if (strcmp (type, "data") == 0)
1619 class = CKO_DATA;
1621 else
1623 class = -1;
1626 return class;
1630 static int
1631 find_obj_url (pakchois_session_t * pks, struct token_info *info,
1632 struct ck_info *lib_info, void *input)
1634 struct url_find_data_st *find_data = input;
1635 struct ck_attribute a[4];
1636 ck_object_class_t class = -1;
1637 ck_certificate_type_t type = -1;
1638 ck_rv_t rv;
1639 ck_object_handle_t obj;
1640 unsigned long count, a_vals;
1641 int found = 0, ret;
1642 opaque *cert_data = NULL;
1643 char label_tmp[PKCS11_LABEL_SIZE];
1645 if (info == NULL)
1646 { /* we don't support multiple calls */
1647 gnutls_assert ();
1648 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1651 /* do not bother reading the token if basic fields do not match
1653 if (pkcs11_token_matches_info
1654 (&find_data->crt->info, &info->tinfo, lib_info) < 0)
1656 gnutls_assert ();
1657 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1660 if (find_data->crt->info.type[0] != 0)
1662 class = pkcs11_strtype_to_class (find_data->crt->info.type);
1663 if (class == CKO_CERTIFICATE)
1664 type = CKC_X_509;
1666 if (class == -1)
1668 gnutls_assert ();
1669 return GNUTLS_E_INVALID_REQUEST;
1673 /* search the token for the id */
1675 cert_data = gnutls_malloc (MAX_CERT_SIZE);
1676 if (cert_data == NULL)
1678 gnutls_assert ();
1679 return GNUTLS_E_MEMORY_ERROR;
1682 /* Find objects with given class and type */
1684 a[0].type = CKA_ID;
1685 a[0].value = find_data->crt->info.certid_raw;
1686 a[0].value_len = find_data->crt->info.certid_raw_size;
1688 a_vals = 1;
1690 if (class != -1)
1692 a[a_vals].type = CKA_CLASS;
1693 a[a_vals].value = &class;
1694 a[a_vals].value_len = sizeof class;
1695 a_vals++;
1698 if (type != -1)
1700 a[a_vals].type = CKA_CERTIFICATE_TYPE;
1701 a[a_vals].value = &type;
1702 a[a_vals].value_len = sizeof type;
1703 a_vals++;
1706 rv = pakchois_find_objects_init (pks, a, a_vals);
1707 if (rv != CKR_OK)
1709 gnutls_assert ();
1710 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
1711 ret = pkcs11_rv_to_err (rv);
1712 goto cleanup;
1715 while (pakchois_find_objects (pks, &obj, 1, &count) == CKR_OK && count == 1)
1718 a[0].type = CKA_VALUE;
1719 a[0].value = cert_data;
1720 a[0].value_len = MAX_CERT_SIZE;
1721 a[1].type = CKA_LABEL;
1722 a[1].value = label_tmp;
1723 a[1].value_len = sizeof (label_tmp);
1725 if (pakchois_get_attribute_value (pks, obj, a, 2) == CKR_OK)
1727 gnutls_datum_t id = { find_data->crt->info.certid_raw,
1728 find_data->crt->info.certid_raw_size
1730 gnutls_datum_t data = { a[0].value, a[0].value_len };
1731 gnutls_datum_t label = { a[1].value, a[1].value_len };
1733 if (class == CKO_PUBLIC_KEY)
1735 ret =
1736 pkcs11_obj_import_pubkey (pks, obj,
1737 find_data->crt,
1738 &id, &label,
1739 &info->tinfo, lib_info);
1741 else
1743 ret =
1744 pkcs11_obj_import (class,
1745 find_data->crt,
1746 &data, &id, &label,
1747 &info->tinfo, lib_info);
1749 if (ret < 0)
1751 gnutls_assert ();
1752 goto cleanup;
1755 found = 1;
1756 break;
1758 else
1760 _gnutls_debug_log ("pk11: Skipped cert, missing attrs.\n");
1764 if (found == 0)
1766 gnutls_assert ();
1767 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1769 else
1771 ret = 0;
1774 cleanup:
1775 gnutls_free (cert_data);
1776 pakchois_find_objects_final (pks);
1778 return ret;
1781 unsigned int
1782 pkcs11_obj_flags_to_int (unsigned int flags)
1784 unsigned int ret_flags = 0;
1786 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN)
1787 ret_flags |= SESSION_LOGIN;
1789 return ret_flags;
1793 * gnutls_pkcs11_privkey_import_url:
1794 * @cert: The structure to store the parsed certificate
1795 * @url: a PKCS 11 url identifying the key
1796 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1798 * This function will "import" a PKCS 11 URL identifying a certificate
1799 * key to the #gnutls_pkcs11_obj_t structure. This does not involve any
1800 * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is
1801 * format agnostic. Only data are transferred.
1803 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1804 * negative error value.
1807 gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t cert, const char *url,
1808 unsigned int flags)
1810 int ret;
1811 struct url_find_data_st find_data;
1813 /* fill in the find data structure */
1814 find_data.crt = cert;
1816 ret = pkcs11_url_to_info (url, &cert->info);
1817 if (ret < 0)
1819 gnutls_assert ();
1820 return ret;
1823 ret =
1824 _pkcs11_traverse_tokens (find_obj_url, &find_data,
1825 pkcs11_obj_flags_to_int (flags));
1827 if (ret < 0)
1829 gnutls_assert ();
1830 return ret;
1833 return 0;
1836 struct token_num
1838 struct pkcs11_url_info info;
1839 unsigned int seq; /* which one we are looking for */
1840 unsigned int current; /* which one are we now */
1843 static int
1844 find_token_num (pakchois_session_t * pks,
1845 struct token_info *tinfo,
1846 struct ck_info *lib_info, void *input)
1848 struct token_num *find_data = input;
1850 if (tinfo == NULL)
1851 { /* we don't support multiple calls */
1852 gnutls_assert ();
1853 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1856 if (find_data->current == find_data->seq)
1858 strcpy (find_data->info.manufacturer, tinfo->tinfo.manufacturer_id);
1859 strcpy (find_data->info.token, tinfo->tinfo.label);
1860 strcpy (find_data->info.model, tinfo->tinfo.model);
1861 strcpy (find_data->info.serial, tinfo->tinfo.serial_number);
1863 strcpy (find_data->info.lib_manufacturer, lib_info->manufacturer_id);
1864 strcpy (find_data->info.lib_desc, lib_info->library_description);
1865 snprintf (find_data->info.lib_version,
1866 sizeof (find_data->info.lib_version), "%u.%u",
1867 (unsigned int) lib_info->library_version.major,
1868 (unsigned int) lib_info->library_version.minor);
1870 return 0;
1873 find_data->current++;
1874 /* search the token for the id */
1877 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* non zero is enough */
1881 * gnutls_pkcs11_token_get_url:
1882 * @seq: sequence number starting from 0
1883 * @detailed: non zero if a detailed URL is required
1884 * @url: will contain an allocated url
1886 * This function will return the URL for each token available
1887 * in system. The url has to be released using gnutls_free()
1889 * Returns: On success, %GNUTLS_E_SUCCESS is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1890 * if the sequence number exceeds the available tokens, otherwise a negative error value.
1894 gnutls_pkcs11_token_get_url (unsigned int seq,
1895 gnutls_pkcs11_url_type_t detailed, char **url)
1897 int ret;
1898 struct token_num tn;
1900 memset (&tn, 0, sizeof (tn));
1901 tn.seq = seq;
1903 ret = _pkcs11_traverse_tokens (find_token_num, &tn, 0);
1904 if (ret < 0)
1906 gnutls_assert ();
1907 return ret;
1910 ret = pkcs11_info_to_url (&tn.info, detailed, url);
1911 if (ret < 0)
1913 gnutls_assert ();
1914 return ret;
1917 return 0;
1922 * gnutls_pkcs11_token_get_info:
1923 * @url: should contain a PKCS 11 URL
1924 * @itype: Denotes the type of information requested
1925 * @output: where output will be stored
1926 * @output_size: contains the maximum size of the output and will be overwritten with actual
1928 * This function will return information about the PKCS 11 token such
1929 * as the label, id as well as token information where the key is stored.
1931 * Returns: zero on success or a negative value on error.
1934 gnutls_pkcs11_token_get_info (const char *url,
1935 gnutls_pkcs11_token_info_t ttype,
1936 void *output, size_t * output_size)
1938 const char *str;
1939 size_t len;
1940 struct pkcs11_url_info info;
1941 int ret;
1943 ret = pkcs11_url_to_info (url, &info);
1944 if (ret < 0)
1946 gnutls_assert ();
1947 return ret;
1950 switch (ttype)
1952 case GNUTLS_PKCS11_TOKEN_LABEL:
1953 str = info.token;
1954 break;
1955 case GNUTLS_PKCS11_TOKEN_SERIAL:
1956 str = info.serial;
1957 break;
1958 case GNUTLS_PKCS11_TOKEN_MANUFACTURER:
1959 str = info.manufacturer;
1960 break;
1961 case GNUTLS_PKCS11_TOKEN_MODEL:
1962 str = info.model;
1963 break;
1964 default:
1965 gnutls_assert ();
1966 return GNUTLS_E_INVALID_REQUEST;
1969 len = strlen (str);
1971 if (len + 1 > *output_size)
1973 *output_size = len + 1;
1974 return GNUTLS_E_SHORT_MEMORY_BUFFER;
1977 strcpy (output, str);
1979 *output_size = len;
1981 return 0;
1985 * gnutls_pkcs11_obj_export_url:
1986 * @crt: Holds the PKCS 11 certificate
1987 * @detailed: non zero if a detailed URL is required
1988 * @url: will contain an allocated url
1990 * This function will export a URL identifying the given certificate.
1992 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1993 * negative error value.
1996 gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t cert,
1997 gnutls_pkcs11_url_type_t detailed, char **url)
1999 int ret;
2001 ret = pkcs11_info_to_url (&cert->info, detailed, url);
2002 if (ret < 0)
2004 gnutls_assert ();
2005 return ret;
2008 return 0;
2012 * gnutls_pkcs11_obj_get_type:
2013 * @certificate: Holds the PKCS 11 certificate
2015 * This function will return the type of the certificate being
2016 * stored in the structure.
2018 * Returns: The type of the certificate.
2020 gnutls_pkcs11_obj_type_t
2021 gnutls_pkcs11_obj_get_type (gnutls_pkcs11_obj_t obj)
2023 return obj->type;
2026 struct pkey_list
2028 gnutls_buffer_st *key_ids;
2029 size_t key_ids_size;
2033 pkcs11_login (pakchois_session_t * pks, const struct token_info *info, int so)
2035 int attempt = 0, ret;
2036 ck_rv_t rv;
2037 char *token_url;
2038 int pin_len;
2039 struct pkcs11_url_info uinfo;
2042 if (so == 0 && (info->tinfo.flags & CKF_LOGIN_REQUIRED) == 0)
2044 gnutls_assert ();
2045 _gnutls_debug_log ("pk11: No login required.\n");
2046 return 0;
2049 memset (&uinfo, 0, sizeof (uinfo));
2050 strcpy (uinfo.manufacturer, info->tinfo.manufacturer_id);
2051 strcpy (uinfo.token, info->tinfo.label);
2052 strcpy (uinfo.model, info->tinfo.model);
2053 strcpy (uinfo.serial, info->tinfo.serial_number);
2054 ret = pkcs11_info_to_url (&uinfo, 1, &token_url);
2055 if (ret < 0)
2057 gnutls_assert ();
2058 return ret;
2061 /* For a token with a "protected" (out-of-band) authentication
2062 * path, calling login with a NULL username is all that is
2063 * required. */
2064 if (info->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
2066 if (pakchois_login (pks, (so == 0) ? CKU_USER : CKU_SO, NULL, 0) ==
2067 CKR_OK)
2069 return 0;
2071 else
2073 gnutls_assert ();
2074 _gnutls_debug_log ("pk11: Protected login failed.\n");
2075 ret = GNUTLS_E_PKCS11_ERROR;
2076 goto cleanup;
2080 /* Otherwise, PIN entry is necessary for login, so fail if there's
2081 * no callback. */
2082 if (!pin_func)
2084 gnutls_assert ();
2085 _gnutls_debug_log ("pk11: No pin callback but login required.\n");
2086 ret = GNUTLS_E_PKCS11_ERROR;
2087 goto cleanup;
2092 struct ck_token_info tinfo;
2093 char pin[GNUTLS_PKCS11_MAX_PIN_LEN];
2094 unsigned int flags;
2096 /* If login has been attempted once already, check the token
2097 * status again, the flags might change. */
2098 if (attempt)
2100 if (pakchois_get_token_info
2101 (info->prov->module, info->sid, &tinfo) != CKR_OK)
2103 gnutls_assert ();
2104 _gnutls_debug_log ("pk11: GetTokenInfo failed\n");
2105 ret = GNUTLS_E_PKCS11_ERROR;
2106 goto cleanup;
2110 flags = 0;
2111 if (so == 0)
2113 flags |= GNUTLS_PKCS11_PIN_USER;
2114 if (tinfo.flags & CKF_USER_PIN_COUNT_LOW)
2115 flags |= GNUTLS_PKCS11_PIN_COUNT_LOW;
2116 if (tinfo.flags & CKF_USER_PIN_FINAL_TRY)
2117 flags |= GNUTLS_PKCS11_PIN_FINAL_TRY;
2119 else
2121 flags |= GNUTLS_PKCS11_PIN_SO;
2122 if (tinfo.flags & CKF_SO_PIN_COUNT_LOW)
2123 flags |= GNUTLS_PKCS11_PIN_COUNT_LOW;
2124 if (tinfo.flags & CKF_SO_PIN_FINAL_TRY)
2125 flags |= GNUTLS_PKCS11_PIN_FINAL_TRY;
2128 ret = pin_func (pin_data, attempt++,
2129 (char *) token_url,
2130 (char *) info->tinfo.label, flags, pin, sizeof (pin));
2131 if (ret < 0)
2133 gnutls_assert ();
2134 ret = GNUTLS_E_PKCS11_PIN_ERROR;
2135 goto cleanup;
2137 pin_len = strlen (pin);
2139 rv = pakchois_login (pks, (so == 0) ? CKU_USER : CKU_SO,
2140 (unsigned char *) pin, pin_len);
2142 /* Try to scrub the pin off the stack. Clever compilers will
2143 * probably optimize this away, oh well. */
2144 memset (pin, 0, sizeof pin);
2146 while (rv == CKR_PIN_INCORRECT);
2148 _gnutls_debug_log ("pk11: Login result = %lu\n", rv);
2151 ret = (rv == CKR_OK
2152 || rv == CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err (rv);
2154 cleanup:
2155 gnutls_free (token_url);
2156 return ret;
2159 static int
2160 find_privkeys (pakchois_session_t * pks, struct token_info *info,
2161 struct pkey_list *list)
2163 struct ck_attribute a[3];
2164 ck_object_class_t class;
2165 ck_rv_t rv;
2166 ck_object_handle_t obj;
2167 unsigned long count, current;
2168 char certid_tmp[PKCS11_ID_SIZE];
2170 class = CKO_PRIVATE_KEY;
2172 /* Find an object with private key class and a certificate ID
2173 * which matches the certificate. */
2174 /* FIXME: also match the cert subject. */
2175 a[0].type = CKA_CLASS;
2176 a[0].value = &class;
2177 a[0].value_len = sizeof class;
2179 rv = pakchois_find_objects_init (pks, a, 1);
2180 if (rv != CKR_OK)
2182 gnutls_assert ();
2183 return pkcs11_rv_to_err (rv);
2186 list->key_ids_size = 0;
2187 while (pakchois_find_objects (pks, &obj, 1, &count) == CKR_OK && count == 1)
2189 list->key_ids_size++;
2192 pakchois_find_objects_final (pks);
2194 if (list->key_ids_size == 0)
2196 gnutls_assert ();
2197 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2200 list->key_ids =
2201 gnutls_malloc (sizeof (gnutls_buffer_st) * list->key_ids_size);
2202 if (list->key_ids == NULL)
2204 gnutls_assert ();
2205 return GNUTLS_E_MEMORY_ERROR;
2208 /* actual search */
2209 a[0].type = CKA_CLASS;
2210 a[0].value = &class;
2211 a[0].value_len = sizeof class;
2213 rv = pakchois_find_objects_init (pks, a, 1);
2214 if (rv != CKR_OK)
2216 gnutls_assert ();
2217 return pkcs11_rv_to_err (rv);
2220 current = 0;
2221 while (pakchois_find_objects (pks, &obj, 1, &count) == CKR_OK && count == 1)
2224 a[0].type = CKA_ID;
2225 a[0].value = certid_tmp;
2226 a[0].value_len = sizeof (certid_tmp);
2228 _gnutls_buffer_init (&list->key_ids[current]);
2230 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
2232 _gnutls_buffer_append_data (&list->key_ids[current],
2233 a[0].value, a[0].value_len);
2234 current++;
2237 if (current > list->key_ids_size)
2238 break;
2241 pakchois_find_objects_final (pks);
2243 list->key_ids_size = current - 1;
2245 return 0;
2248 /* Recover certificate list from tokens */
2251 static int
2252 find_objs (pakchois_session_t * pks, struct token_info *info,
2253 struct ck_info *lib_info, void *input)
2255 struct crt_find_data_st *find_data = input;
2256 struct ck_attribute a[4];
2257 ck_object_class_t class = -1;
2258 ck_certificate_type_t type = -1;
2259 unsigned int trusted;
2260 ck_rv_t rv;
2261 ck_object_handle_t obj;
2262 unsigned long count;
2263 opaque *cert_data;
2264 char certid_tmp[PKCS11_ID_SIZE];
2265 char label_tmp[PKCS11_LABEL_SIZE];
2266 int ret, i;
2267 struct pkey_list plist; /* private key holder */
2268 int tot_values = 0;
2270 if (info == NULL)
2271 { /* final call */
2272 if (find_data->current <= *find_data->n_list)
2273 ret = 0;
2274 else
2275 ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
2277 *find_data->n_list = find_data->current;
2279 return ret;
2282 /* do not bother reading the token if basic fields do not match
2284 if (pkcs11_token_matches_info (&find_data->info, &info->tinfo, lib_info) <
2287 gnutls_assert ();
2288 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2291 if (find_data->info.type[0] != 0)
2293 class = pkcs11_strtype_to_class (find_data->info.type);
2294 if (class == CKO_CERTIFICATE)
2295 type = CKC_X_509;
2296 else
2297 type = -1;
2299 if (class == -1)
2301 gnutls_assert ();
2302 return GNUTLS_E_INVALID_REQUEST;
2307 memset (&plist, 0, sizeof (plist));
2309 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2311 ret = find_privkeys (pks, info, &plist);
2312 if (ret < 0)
2314 gnutls_assert ();
2315 return ret;
2318 if (plist.key_ids_size == 0)
2320 gnutls_assert ();
2321 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2325 cert_data = gnutls_malloc (MAX_CERT_SIZE);
2326 if (cert_data == NULL)
2328 gnutls_assert ();
2329 return GNUTLS_E_MEMORY_ERROR;
2332 /* Find objects with cert class and X.509 cert type. */
2334 tot_values = 0;
2336 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL
2337 || find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2339 class = CKO_CERTIFICATE;
2340 type = CKC_X_509;
2341 trusted = 1;
2343 a[tot_values].type = CKA_CLASS;
2344 a[tot_values].value = &class;
2345 a[tot_values].value_len = sizeof class;
2346 tot_values++;
2348 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2349 a[tot_values].value = &type;
2350 a[tot_values].value_len = sizeof type;
2351 tot_values++;
2354 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED)
2356 class = CKO_CERTIFICATE;
2357 type = CKC_X_509;
2358 trusted = 1;
2360 a[tot_values].type = CKA_CLASS;
2361 a[tot_values].value = &class;
2362 a[tot_values].value_len = sizeof class;
2363 tot_values++;
2365 a[tot_values].type = CKA_TRUSTED;
2366 a[tot_values].value = &trusted;
2367 a[tot_values].value_len = sizeof trusted;
2368 tot_values++;
2371 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY)
2373 class = CKO_PUBLIC_KEY;
2375 a[tot_values].type = CKA_CLASS;
2376 a[tot_values].value = &class;
2377 a[tot_values].value_len = sizeof class;
2378 tot_values++;
2380 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY)
2382 class = CKO_PRIVATE_KEY;
2384 a[tot_values].type = CKA_CLASS;
2385 a[tot_values].value = &class;
2386 a[tot_values].value_len = sizeof class;
2387 tot_values++;
2389 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL)
2391 if (class != -1)
2393 a[tot_values].type = CKA_CLASS;
2394 a[tot_values].value = &class;
2395 a[tot_values].value_len = sizeof class;
2396 tot_values++;
2398 if (type != -1)
2400 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2401 a[tot_values].value = &type;
2402 a[tot_values].value_len = sizeof type;
2403 tot_values++;
2406 else
2408 gnutls_assert ();
2409 ret = GNUTLS_E_INVALID_REQUEST;
2410 goto fail;
2413 if (find_data->info.certid_raw_size != 0)
2415 a[tot_values].type = CKA_ID;
2416 a[tot_values].value = find_data->info.certid_raw;
2417 a[tot_values].value_len = find_data->info.certid_raw_size;
2418 tot_values++;
2421 rv = pakchois_find_objects_init (pks, a, tot_values);
2422 if (rv != CKR_OK)
2424 gnutls_assert ();
2425 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
2426 return pkcs11_rv_to_err (rv);
2429 while (pakchois_find_objects (pks, &obj, 1, &count) == CKR_OK && count == 1)
2431 gnutls_datum_t label, id, value;
2433 a[0].type = CKA_LABEL;
2434 a[0].value = label_tmp;
2435 a[0].value_len = sizeof label_tmp;
2437 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
2439 label.data = a[0].value;
2440 label.size = a[0].value_len;
2442 else
2444 label.data = NULL;
2445 label.size = 0;
2448 a[0].type = CKA_ID;
2449 a[0].value = certid_tmp;
2450 a[0].value_len = sizeof certid_tmp;
2452 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
2454 id.data = a[0].value;
2455 id.size = a[0].value_len;
2457 else
2459 id.data = NULL;
2460 id.size = 0;
2463 a[0].type = CKA_VALUE;
2464 a[0].value = cert_data;
2465 a[0].value_len = MAX_CERT_SIZE;
2466 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
2468 value.data = a[0].value;
2469 value.size = a[0].value_len;
2471 else
2473 value.data = NULL;
2474 value.size = 0;
2477 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL)
2479 a[0].type = CKA_CLASS;
2480 a[0].value = &class;
2481 a[0].value_len = sizeof class;
2483 pakchois_get_attribute_value (pks, obj, a, 1);
2486 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2488 for (i = 0; i < plist.key_ids_size; i++)
2490 if (plist.key_ids[i].length !=
2491 a[1].value_len
2492 || memcmp (plist.key_ids[i].data,
2493 a[1].value, a[1].value_len) != 0)
2495 /* not found */
2496 continue;
2501 if (find_data->current < *find_data->n_list)
2503 ret =
2504 gnutls_pkcs11_obj_init (&find_data->p_list[find_data->current]);
2505 if (ret < 0)
2507 gnutls_assert ();
2508 goto fail;
2511 if (class == CKO_PUBLIC_KEY)
2513 ret =
2514 pkcs11_obj_import_pubkey (pks, obj,
2515 find_data->p_list
2516 [find_data->current],
2517 &id, &label,
2518 &info->tinfo, lib_info);
2520 else
2522 ret =
2523 pkcs11_obj_import (class,
2524 find_data->p_list
2525 [find_data->current],
2526 &value, &id, &label,
2527 &info->tinfo, lib_info);
2529 if (ret < 0)
2531 gnutls_assert ();
2532 goto fail;
2536 find_data->current++;
2540 gnutls_free (cert_data);
2541 pakchois_find_objects_final (pks);
2543 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* continue until all tokens have been checked */
2545 fail:
2546 gnutls_free (cert_data);
2547 pakchois_find_objects_final (pks);
2548 if (plist.key_ids != NULL)
2550 for (i = 0; i < plist.key_ids_size; i++)
2552 _gnutls_buffer_clear (&plist.key_ids[i]);
2554 gnutls_free (plist.key_ids);
2556 for (i = 0; i < find_data->current; i++)
2558 gnutls_pkcs11_obj_deinit (find_data->p_list[i]);
2560 find_data->current = 0;
2562 return ret;
2566 * gnutls_pkcs11_obj_list_import_url:
2567 * @p_list: An uninitialized object list (may be NULL)
2568 * @n_list: initially should hold the maximum size of the list. Will contain the actual size.
2569 * @url: A PKCS 11 url identifying a set of objects
2570 * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2571 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2573 * This function will initialize and set values to an object list
2574 * by using all objects identified by a PKCS 11 URL.
2576 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
2577 * negative error value.
2580 gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list,
2581 unsigned int *n_list,
2582 const char *url,
2583 gnutls_pkcs11_obj_attr_t attrs,
2584 unsigned int flags)
2586 int ret;
2587 struct crt_find_data_st find_data;
2589 /* fill in the find data structure */
2590 find_data.p_list = p_list;
2591 find_data.n_list = n_list;
2592 find_data.flags = attrs;
2593 find_data.current = 0;
2595 if (url == NULL || url[0] == 0)
2597 url = "pkcs11:";
2600 ret = pkcs11_url_to_info (url, &find_data.info);
2601 if (ret < 0)
2603 gnutls_assert ();
2604 return ret;
2607 ret =
2608 _pkcs11_traverse_tokens (find_objs, &find_data,
2609 pkcs11_obj_flags_to_int (flags));
2610 if (ret < 0)
2612 gnutls_assert ();
2613 return ret;
2616 return 0;
2620 * gnutls_x509_crt_import_pkcs11_url:
2621 * @crt: A certificate of type #gnutls_x509_crt_t
2622 * @url: A PKCS 11 url
2623 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2625 * This function will import a PKCS 11 certificate directly from a token
2626 * without involving the #gnutls_pkcs11_obj_t structure. This function will
2627 * fail if the certificate stored is not of X.509 type.
2629 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
2630 * negative error value.
2633 gnutls_x509_crt_import_pkcs11_url (gnutls_x509_crt_t crt,
2634 const char *url, unsigned int flags)
2636 gnutls_pkcs11_obj_t pcrt;
2637 int ret;
2639 ret = gnutls_pkcs11_obj_init (&pcrt);
2640 if (ret < 0)
2642 gnutls_assert ();
2643 return ret;
2646 ret = gnutls_pkcs11_obj_import_url (pcrt, url, flags);
2647 if (ret < 0)
2649 gnutls_assert ();
2650 goto cleanup;
2653 ret = gnutls_x509_crt_import (crt, &pcrt->raw, GNUTLS_X509_FMT_DER);
2654 if (ret < 0)
2656 gnutls_assert ();
2657 goto cleanup;
2660 ret = 0;
2661 cleanup:
2663 gnutls_pkcs11_obj_deinit (pcrt);
2665 return ret;
2670 * gnutls_x509_crt_import_pkcs11:
2671 * @crt: A certificate of type #gnutls_x509_crt_t
2672 * @pkcs11_obj: A PKCS 11 object that contains a certificate
2674 * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t
2675 * structure.
2677 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
2678 * negative error value.
2681 gnutls_x509_crt_import_pkcs11 (gnutls_x509_crt_t crt,
2682 gnutls_pkcs11_obj_t pkcs11_crt)
2684 return gnutls_x509_crt_import (crt, &pkcs11_crt->raw, GNUTLS_X509_FMT_DER);
2688 * gnutls_x509_crt_list_import_pkcs11:
2689 * @cert: A list of certificates of type #gnutls_x509_crt_t
2690 * @cert_max: The maximum size of the list
2691 * @objs: A list of PKCS 11 objects
2692 * @flags: 0 for now
2694 * This function will import a PKCS 11 certificate list to a list of
2695 * #gnutls_x509_crt_t structure. These must not be initialized.
2697 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
2698 * negative error value.
2701 gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs,
2702 unsigned int cert_max,
2703 gnutls_pkcs11_obj_t * const objs,
2704 unsigned int flags)
2706 int i, j;
2707 int ret;
2709 for (i = 0; i < cert_max; i++)
2711 ret = gnutls_x509_crt_init (&certs[i]);
2712 if (ret < 0)
2714 gnutls_assert ();
2715 goto cleanup;
2718 ret = gnutls_x509_crt_import_pkcs11 (certs[i], objs[i]);
2719 if (ret < 0)
2721 gnutls_assert ();
2722 goto cleanup;
2726 return 0;
2728 cleanup:
2729 for (j = 0; j < i; j++)
2731 gnutls_x509_crt_deinit (certs[j]);
2734 return ret;
2737 static int
2738 find_flags (pakchois_session_t * pks, struct token_info *info,
2739 struct ck_info *lib_info, void *input)
2741 struct flags_find_data_st *find_data = input;
2743 if (info == NULL)
2744 { /* we don't support multiple calls */
2745 gnutls_assert ();
2746 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2749 /* do not bother reading the token if basic fields do not match
2751 if (pkcs11_token_matches_info (&find_data->info, &info->tinfo, lib_info) <
2754 gnutls_assert ();
2755 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2758 /* found token! */
2760 find_data->slot_flags = info->sinfo.flags;
2762 return 0;
2766 * gnutls_pkcs11_token_get_flags:
2767 * @url: should contain a PKCS 11 URL
2768 * @flags: The output flags (GNUTLS_PKCS11_TOKEN_*)
2770 * This function will return information about the PKCS 11 token flags.
2772 * Returns: zero on success or a negative value on error.
2775 gnutls_pkcs11_token_get_flags (const char *url, unsigned int *flags)
2777 struct flags_find_data_st find_data;
2778 int ret;
2780 ret = pkcs11_url_to_info (url, &find_data.info);
2781 if (ret < 0)
2783 gnutls_assert ();
2784 return ret;
2787 ret = _pkcs11_traverse_tokens (find_flags, &find_data, 0);
2788 if (ret < 0)
2790 gnutls_assert ();
2791 return ret;
2794 *flags = 0;
2795 if (find_data.slot_flags & CKF_HW_SLOT)
2796 *flags |= GNUTLS_PKCS11_TOKEN_HW;
2798 return 0;
2804 * gnutls_pkcs11_token_get_mechanism:
2805 * @url: should contain a PKCS 11 URL
2806 * @idx: The index of the mechanism
2807 * @mechanism: The PKCS #11 mechanism ID
2809 * This function will return the names of the supported mechanisms
2810 * by the token. It should be called with an increasing index until
2811 * it return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
2813 * Returns: zero on success or a negative value on error.
2816 gnutls_pkcs11_token_get_mechanism (const char *url, int idx,
2817 unsigned long *mechanism)
2819 int ret;
2820 ck_rv_t rv;
2821 pakchois_module_t *module;
2822 ck_slot_id_t slot;
2823 struct token_info tinfo;
2824 struct pkcs11_url_info info;
2825 unsigned long count;
2826 ck_mechanism_type_t mlist[400];
2828 ret = pkcs11_url_to_info (url, &info);
2829 if (ret < 0)
2831 gnutls_assert ();
2832 return ret;
2836 ret = pkcs11_find_slot (&module, &slot, &info, &tinfo);
2837 if (ret < 0)
2839 gnutls_assert ();
2840 return ret;
2843 count = sizeof (mlist) / sizeof (mlist[0]);
2844 rv = pakchois_get_mechanism_list (module, slot, mlist, &count);
2845 if (rv != CKR_OK)
2847 gnutls_assert ();
2848 return pkcs11_rv_to_err (rv);
2851 if (idx >= count)
2853 gnutls_assert ();
2854 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2857 *mechanism = mlist[idx];
2859 return 0;
2864 const char *
2865 gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t type)
2867 switch (type)
2869 case GNUTLS_PKCS11_OBJ_X509_CRT:
2870 return "X.509 Certificate";
2871 case GNUTLS_PKCS11_OBJ_PUBKEY:
2872 return "Public key";
2873 case GNUTLS_PKCS11_OBJ_PRIVKEY:
2874 return "Private key";
2875 case GNUTLS_PKCS11_OBJ_SECRET_KEY:
2876 return "Secret key";
2877 case GNUTLS_PKCS11_OBJ_DATA:
2878 return "Data";
2879 case GNUTLS_PKCS11_OBJ_UNKNOWN:
2880 default:
2881 return "Unknown";
2886 pkcs11_token_matches_info (struct pkcs11_url_info *info,
2887 struct ck_token_info *tinfo,
2888 struct ck_info *lib_info)
2890 if (info->manufacturer[0] != 0)
2892 if (strcmp (info->manufacturer, tinfo->manufacturer_id) != 0)
2893 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2896 if (info->token[0] != 0)
2898 if (strcmp (info->token, tinfo->label) != 0)
2899 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2902 if (info->model[0] != 0)
2904 if (strcmp (info->model, tinfo->model) != 0)
2905 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2908 if (info->serial[0] != 0)
2910 if (strcmp (info->serial, tinfo->serial_number) != 0)
2911 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2914 if (info->lib_manufacturer[0] != 0)
2916 if (strcmp (info->lib_manufacturer, lib_info->manufacturer_id) != 0)
2917 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2920 if (info->lib_desc[0] != 0)
2922 if (strcmp (info->lib_desc, lib_info->library_description) != 0)
2923 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2926 if (info->lib_version[0] != 0)
2928 char version[16];
2930 snprintf (version, sizeof (version), "%u.%u",
2931 (unsigned int) lib_info->library_version.major,
2932 (unsigned int) lib_info->library_version.minor);
2933 if (strcmp (info->lib_version, version) != 0)
2934 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2937 return 0;