Honor uninitialized private key in destructor
[gnutls.git] / lib / pkcs11.c
blobada3c5c522be66c39ceb9f69a252a9a7606cc5ae
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() using the %GNUTLS_PKCS11_FLAG_AUTO. If other option
368 * is required then it must be called before it.
370 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
371 * negative error value.
374 gnutls_pkcs11_init (unsigned int flags, const char *configfile)
376 int ret;
378 if (init != 0)
380 init++;
381 return 0;
383 init++;
385 if (flags == GNUTLS_PKCS11_FLAG_MANUAL)
386 return 0;
387 else
389 FILE *fp;
390 char line[512];
391 const char *library;
393 if (configfile == NULL)
394 configfile = "/etc/gnutls/pkcs11.conf";
396 fp = fopen (configfile, "r");
397 if (fp == NULL)
399 gnutls_assert ();
400 _gnutls_debug_log ("Cannot load %s\n", configfile);
401 return GNUTLS_E_FILE_ERROR;
404 while (fgets (line, sizeof (line), fp) != NULL)
406 if (strncmp (line, "load", sizeof ("load") - 1) == 0)
408 char *p;
409 p = strchr (line, '=');
410 if (p == NULL)
411 continue;
413 library = ++p;
415 p = strchr (line, '\n');
416 if (p != NULL)
418 *p = 0;
421 ret = gnutls_pkcs11_add_provider (library, NULL);
422 if (ret < 0)
424 gnutls_assert ();
425 _gnutls_debug_log ("Cannot load provider: %s\n", library);
426 continue;
430 fclose(fp);
433 return 0;
437 * gnutls_pkcs11_deinit:
439 * This function will deinitialize the PKCS 11 subsystem in gnutls.
442 void
443 gnutls_pkcs11_deinit (void)
445 int i;
447 init--;
448 if (init > 0)
449 return;
450 if (init < 0)
452 init = 0;
453 return;
456 for (i = 0; i < active_providers; i++)
458 pakchois_module_destroy (providers[i].module);
460 active_providers = 0;
461 pakchois_destructor();
465 * gnutls_pkcs11_set_pin_function:
466 * @fn: The PIN callback
467 * @userdata: data to be supplied to callback
469 * This function will set a callback function to be used when a PIN
470 * is required for PKCS 11 operations.
472 * Callback for PKCS#11 PIN entry. The callback provides the PIN code
473 * to unlock the token with label 'token_label', specified by the URL
474 * 'token_url'.
476 * The PIN code, as a NUL-terminated ASCII string, should be copied
477 * into the 'pin' buffer (of maximum size pin_max), and
478 * return 0 to indicate success. Alternatively, the callback may
479 * return a negative gnutls error code to indicate failure and cancel
480 * PIN entry (in which case, the contents of the 'pin' parameter are ignored).
482 * When a PIN is required, the callback will be invoked repeatedly
483 * (and indefinitely) until either the returned PIN code is correct,
484 * the callback returns failure, or the token refuses login (e.g. when
485 * the token is locked due to too many incorrect PINs!). For the
486 * first such invocation, the 'attempt' counter will have value zero;
487 * it will increase by one for each subsequent attempt.
489 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
490 * negative error value.
492 void
493 gnutls_pkcs11_set_pin_function (gnutls_pkcs11_pin_callback_t fn,
494 void *userdata)
496 pin_func = fn;
497 pin_data = userdata;
501 * gnutls_pkcs11_set_token_function:
502 * @fn: The token callback
503 * @userdata: data to be supplied to callback
505 * This function will set a callback function to be used when a token
506 * needs to be inserted to continue PKCS 11 operations.
508 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
509 * negative error value.
511 void
512 gnutls_pkcs11_set_token_function (gnutls_pkcs11_token_callback_t fn,
513 void *userdata)
515 token_func = fn;
516 token_data = userdata;
519 static int
520 unescape_string (char *output, const char *input, size_t * size,
521 char terminator)
523 gnutls_buffer_st str;
524 int ret = 0;
525 char *p;
526 int len;
528 _gnutls_buffer_init (&str);
530 /* find terminator */
531 p = strchr (input, terminator);
532 if (p != NULL)
533 len = p - input;
534 else
535 len = strlen (input);
537 ret = _gnutls_buffer_append_data (&str, input, len);
538 if (ret < 0)
540 gnutls_assert ();
541 return ret;
544 ret = _gnutls_buffer_unescape (&str);
545 if (ret < 0)
547 gnutls_assert ();
548 return ret;
551 ret = _gnutls_buffer_append_data (&str, "", 1);
552 if (ret < 0)
554 gnutls_assert ();
555 return ret;
558 _gnutls_buffer_pop_data (&str, output, size);
560 _gnutls_buffer_clear (&str);
562 return ret;
566 pkcs11_url_to_info (const char *url, struct pkcs11_url_info *info)
568 int ret;
569 char *p1, *p2;
570 size_t l;
572 memset (info, 0, sizeof (*info));
574 if (strstr (url, "pkcs11:") == NULL)
576 ret = GNUTLS_E_PARSING_ERROR;
577 goto cleanup;
580 if ((p1 = strstr (url, "library-manufacturer=")) != NULL)
582 p1 += sizeof ("library-manufacturer=") - 1;
583 l = sizeof (info->lib_manufacturer);
585 ret = unescape_string (info->lib_manufacturer, p1, &l, ';');
586 if (ret < 0)
588 goto cleanup;
592 if ((p1 = strstr (url, "library-description=")) != NULL)
594 p1 += sizeof ("library-description=") - 1;
595 l = sizeof (info->lib_desc);
597 ret = unescape_string (info->lib_desc, p1, &l, ';');
598 if (ret < 0)
600 goto cleanup;
604 if ((p1 = strstr (url, "library-version=")) != NULL)
606 p1 += sizeof ("library-version=") - 1;
607 l = sizeof (info->lib_version);
609 ret = unescape_string (info->lib_version, p1, &l, ';');
610 if (ret < 0)
612 goto cleanup;
616 if ((p1 = strstr (url, ";manufacturer=")) != NULL ||
617 (p1 = strstr (url, ":manufacturer=")) != NULL)
620 p1 += sizeof (";manufacturer=") - 1;
621 l = sizeof (info->manufacturer);
623 ret = unescape_string (info->manufacturer, p1, &l, ';');
624 if (ret < 0)
626 goto cleanup;
630 if ((p1 = strstr (url, "token=")) != NULL)
632 p1 += sizeof ("token=") - 1;
633 l = sizeof (info->token);
635 ret = unescape_string (info->token, p1, &l, ';');
636 if (ret < 0)
638 goto cleanup;
642 if ((p1 = strstr (url, "object=")) != NULL)
644 p1 += sizeof ("object=") - 1;
645 l = sizeof (info->label);
647 ret = unescape_string (info->label, p1, &l, ';');
648 if (ret < 0)
650 goto cleanup;
654 if ((p1 = strstr (url, "serial=")) != NULL)
656 p1 += sizeof ("serial=") - 1;
657 l = sizeof (info->serial);
659 ret = unescape_string (info->serial, p1, &l, ';');
660 if (ret < 0)
662 goto cleanup;
666 if ((p1 = strstr (url, "model=")) != NULL)
668 p1 += sizeof ("model=") - 1;
669 l = sizeof (info->model);
671 ret = unescape_string (info->model, p1, &l, ';');
672 if (ret < 0)
674 goto cleanup;
678 if ((p1 = strstr (url, "objecttype=")) != NULL)
680 p1 += sizeof ("objecttype=") - 1;
681 l = sizeof (info->type);
683 ret = unescape_string (info->type, p1, &l, ';');
684 if (ret < 0)
686 goto cleanup;
690 if (((p1 = strstr (url, ";id=")) != NULL)
691 || ((p1 = strstr (url, ":id=")) != NULL))
693 p1 += sizeof (";id=") - 1;
694 l = sizeof (info->certid_raw);
696 ret = unescape_string (info->certid_raw, p1, &l, ';');
697 if (ret < 0)
699 goto cleanup;
701 /* not null terminated */
702 info->certid_raw_size = l-1;
704 p2 = _gnutls_bin2hex(info->certid_raw, info->certid_raw_size,
705 info->id, sizeof(info->id), ":");
706 if (p2 == NULL)
708 ret = GNUTLS_E_PARSING_ERROR;
709 goto cleanup;
713 ret = 0;
715 cleanup:
717 return ret;
721 #define INVALID_CHARS "\\/\"'%&#@!?$* <>{}[]()`|:;,.+-"
723 /* Appends @tname to @dest under the name @p11name.
724 * init indicates whether it is the initial addition to buffer.
726 static int
727 append (gnutls_buffer_st * dest, const void *tname, int tname_size,
728 const char *p11name, int all, int init)
730 gnutls_buffer_st tmpstr;
731 int ret;
733 _gnutls_buffer_init (&tmpstr);
734 if ((ret = _gnutls_buffer_append_data (&tmpstr, tname, tname_size)) < 0)
736 gnutls_assert ();
737 goto cleanup;
740 ret = _gnutls_buffer_escape (&tmpstr, all, INVALID_CHARS);
741 if (ret < 0)
743 gnutls_assert ();
744 goto cleanup;
747 if ((ret = _gnutls_buffer_append_data (&tmpstr, "", 1)) < 0)
749 gnutls_assert ();
750 goto cleanup;
753 if ((ret =
754 _gnutls_buffer_append_printf (dest, "%s%s=%s",
755 (init != 0) ? ";" : "", p11name,
756 tmpstr.data)) < 0)
758 gnutls_assert ();
759 goto cleanup;
762 ret = 0;
764 cleanup:
765 _gnutls_buffer_clear (&tmpstr);
767 return ret;
773 pkcs11_info_to_url (const struct pkcs11_url_info *info,
774 gnutls_pkcs11_url_type_t detailed, char **url)
776 gnutls_buffer_st str;
777 int init = 0;
778 int ret;
780 _gnutls_buffer_init (&str);
782 _gnutls_buffer_append_str (&str, "pkcs11:");
784 if (info->token[0])
786 ret = append (&str, info->token, strlen(info->token), "token", 0, init);
787 if (ret < 0)
789 gnutls_assert ();
790 goto cleanup;
792 init = 1;
795 if (info->serial[0])
797 ret = append (&str, info->serial, strlen(info->serial), "serial", 0, init);
798 if (ret < 0)
800 gnutls_assert ();
801 goto cleanup;
803 init = 1;
806 if (info->model[0])
808 ret = append (&str, info->model, strlen(info->model), "model", 0, init);
809 if (ret < 0)
811 gnutls_assert ();
812 goto cleanup;
814 init = 1;
818 if (info->manufacturer[0])
820 ret = append (&str, info->manufacturer, strlen(info->manufacturer), "manufacturer", 0, init);
821 if (ret < 0)
823 gnutls_assert ();
824 goto cleanup;
826 init = 1;
829 if (info->label[0])
831 ret = append (&str, info->label, strlen(info->label), "object", 0, init);
832 if (ret < 0)
834 gnutls_assert ();
835 goto cleanup;
837 init = 1;
840 if (info->type[0])
842 ret = append (&str, info->type, strlen(info->type), "objecttype", 0, init);
843 if (ret < 0)
845 gnutls_assert ();
846 goto cleanup;
848 init = 1;
851 if (detailed > GNUTLS_PKCS11_URL_GENERIC)
853 if (info->lib_manufacturer[0])
855 ret =
856 append (&str, info->lib_manufacturer, strlen(info->lib_manufacturer), "library-manufacturer",
857 0, init);
858 if (ret < 0)
860 gnutls_assert ();
861 goto cleanup;
863 init = 1;
866 if (info->lib_desc[0])
868 ret = append (&str, info->lib_desc, strlen(info->lib_desc), "library-description", 0, init);
869 if (ret < 0)
871 gnutls_assert ();
872 goto cleanup;
874 init = 1;
878 if (detailed > GNUTLS_PKCS11_URL_LIB)
880 if (info->lib_version[0])
882 ret = append (&str, info->lib_version, strlen(info->lib_version), "library-version", 0, init);
883 if (ret < 0)
885 gnutls_assert ();
886 goto cleanup;
888 init = 1;
892 if (info->certid_raw_size > 0)
894 ret = append (&str, info->certid_raw, info->certid_raw_size, "id", 1, init);
895 if (ret < 0)
897 gnutls_assert ();
898 return ret;
902 _gnutls_buffer_append_data (&str, "", 1);
904 *url = str.data;
906 return 0;
908 cleanup:
909 _gnutls_buffer_clear (&str);
910 return ret;
914 * gnutls_pkcs11_obj_init:
915 * @obj: The structure to be initialized
917 * This function will initialize a pkcs11 certificate structure.
919 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
920 * negative error value.
923 gnutls_pkcs11_obj_init (gnutls_pkcs11_obj_t * obj)
925 *obj = gnutls_calloc (1, sizeof (struct gnutls_pkcs11_obj_st));
926 if (*obj == NULL)
928 gnutls_assert ();
929 return GNUTLS_E_MEMORY_ERROR;
932 return 0;
936 * gnutls_pkcs11_obj_deinit:
937 * @obj: The structure to be initialized
939 * This function will deinitialize a certificate structure.
941 void
942 gnutls_pkcs11_obj_deinit (gnutls_pkcs11_obj_t obj)
944 _gnutls_free_datum (&obj->raw);
945 free (obj);
949 * gnutls_pkcs11_obj_export:
950 * @obj: Holds the object
951 * @output_data: will contain a certificate PEM or DER encoded
952 * @output_data_size: holds the size of output_data (and will be
953 * replaced by the actual size of parameters)
955 * This function will export the pkcs11 object data. It is normal
956 * for PKCS #11 data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
957 * will be returned.
959 * If the buffer provided is not long enough to hold the output, then
960 * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
961 * be returned.
963 * If the structure is PEM encoded, it will have a header
964 * of "BEGIN CERTIFICATE".
966 * Return value: In case of failure a negative value will be
967 * returned, and 0 on success.
970 gnutls_pkcs11_obj_export (gnutls_pkcs11_obj_t obj,
971 void *output_data, size_t * output_data_size)
973 if (obj == NULL || obj->raw.data == NULL)
975 gnutls_assert ();
976 return GNUTLS_E_INVALID_REQUEST;
979 if (output_data == NULL || *output_data_size < obj->raw.size)
981 *output_data_size = obj->raw.size;
982 gnutls_assert ();
983 return GNUTLS_E_SHORT_MEMORY_BUFFER;
985 *output_data_size = obj->raw.size;
987 memcpy (output_data, obj->raw.data, obj->raw.size);
988 return 0;
991 static void
992 terminate_string (unsigned char *str, size_t len)
994 unsigned char *ptr = str + len - 1;
996 while ((*ptr == ' ' || *ptr == '\t' || *ptr == '\0') && ptr >= str)
997 ptr--;
999 if (ptr == str - 1)
1000 str[0] = '\0';
1001 else if (ptr == str + len - 1)
1002 str[len - 1] = '\0';
1003 else
1004 ptr[1] = '\0';
1008 pkcs11_find_object (pakchois_session_t ** _pks,
1009 ck_object_handle_t * _obj,
1010 struct pkcs11_url_info *info, unsigned int flags)
1012 int ret;
1013 pakchois_session_t *pks;
1014 ck_object_handle_t obj;
1015 ck_object_class_t class;
1016 struct ck_attribute a[4];
1017 int a_vals = 0;
1018 unsigned long count;
1019 ck_rv_t rv;
1021 class = pkcs11_strtype_to_class (info->type);
1022 if (class == -1)
1024 gnutls_assert ();
1025 return GNUTLS_E_INVALID_REQUEST;
1028 ret = pkcs11_open_session (&pks, info, flags & SESSION_LOGIN);
1029 if (ret < 0)
1031 gnutls_assert ();
1032 return ret;
1035 a[a_vals].type = CKA_CLASS;
1036 a[a_vals].value = &class;
1037 a[a_vals].value_len = sizeof class;
1038 a_vals++;
1040 if (info->certid_raw_size > 0)
1042 a[a_vals].type = CKA_ID;
1043 a[a_vals].value = info->certid_raw;
1044 a[a_vals].value_len = info->certid_raw_size;
1045 a_vals++;
1048 rv = pakchois_find_objects_init (pks, a, a_vals);
1049 if (rv != CKR_OK)
1051 gnutls_assert ();
1052 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
1053 ret = pkcs11_rv_to_err (rv);
1054 goto fail;
1057 if (pakchois_find_objects (pks, &obj, 1, &count) == CKR_OK && count == 1)
1059 *_obj = obj;
1060 *_pks = pks;
1061 pakchois_find_objects_final (pks);
1062 return 0;
1065 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1066 pakchois_find_objects_final (pks);
1067 fail:
1068 pakchois_close_session (pks);
1070 return ret;
1073 static void
1074 fix_strings (struct token_info *info)
1076 terminate_string (info->tinfo.manufacturer_id,
1077 sizeof info->tinfo.manufacturer_id);
1078 terminate_string (info->tinfo.label, sizeof info->tinfo.label);
1079 terminate_string (info->tinfo.model, sizeof info->tinfo.model);
1080 terminate_string (info->tinfo.serial_number,
1081 sizeof info->tinfo.serial_number);
1082 terminate_string (info->sinfo.slot_description,
1083 sizeof info->sinfo.slot_description);
1087 pkcs11_find_slot (pakchois_module_t ** module, ck_slot_id_t * slot,
1088 struct pkcs11_url_info *info, struct token_info *_tinfo)
1090 int x, z;
1092 for (x = 0; x < active_providers; x++)
1094 for (z = 0; z < providers[x].nslots; z++)
1096 struct token_info tinfo;
1098 if (pakchois_get_token_info
1099 (providers[x].module, providers[x].slots[z],
1100 &tinfo.tinfo) != CKR_OK)
1102 continue;
1104 tinfo.sid = providers[x].slots[z];
1105 tinfo.prov = &providers[x];
1107 if (pakchois_get_slot_info
1108 (providers[x].module, providers[x].slots[z],
1109 &tinfo.sinfo) != CKR_OK)
1111 continue;
1114 /* XXX make wrapper for token_info? */
1115 fix_strings (&tinfo);
1117 if (pkcs11_token_matches_info (info, &tinfo.tinfo,
1118 &providers[x].info) < 0)
1120 continue;
1123 /* ok found */
1124 *module = providers[x].module;
1125 *slot = providers[x].slots[z];
1127 if (_tinfo != NULL)
1128 memcpy (_tinfo, &tinfo, sizeof (tinfo));
1130 return 0;
1134 gnutls_assert ();
1135 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1139 pkcs11_open_session (pakchois_session_t ** _pks,
1140 struct pkcs11_url_info *info, unsigned int flags)
1142 ck_rv_t rv;
1143 int ret;
1144 pakchois_session_t *pks = NULL;
1145 pakchois_module_t *module;
1146 ck_slot_id_t slot;
1147 struct token_info tinfo;
1149 ret = pkcs11_find_slot (&module, &slot, info, &tinfo);
1150 if (ret < 0)
1152 gnutls_assert ();
1153 return ret;
1156 rv = pakchois_open_session (module,
1157 slot,
1158 ((flags & SESSION_WRITE)
1159 ? CKF_RW_SESSION : 0) |
1160 CKF_SERIAL_SESSION, NULL, NULL, &pks);
1161 if (rv != CKR_OK)
1163 gnutls_assert ();
1164 return pkcs11_rv_to_err (rv);
1167 if (flags & SESSION_LOGIN)
1169 ret = pkcs11_login (pks, &tinfo, (flags & SESSION_SO) ? 1 : 0);
1170 if (ret < 0)
1172 gnutls_assert ();
1173 pakchois_close_session (pks);
1174 return ret;
1178 /* ok found */
1179 *_pks = pks;
1180 return 0;
1185 _pkcs11_traverse_tokens (find_func_t find_func, void *input,
1186 unsigned int flags)
1188 ck_rv_t rv;
1189 int found = 0, x, z, ret;
1190 pakchois_session_t *pks = NULL;
1192 for (x = 0; x < active_providers; x++)
1194 for (z = 0; z < providers[x].nslots; z++)
1196 struct token_info info;
1198 ret = GNUTLS_E_PKCS11_ERROR;
1200 if (pakchois_get_token_info
1201 (providers[x].module, providers[x].slots[z],
1202 &info.tinfo) != CKR_OK)
1204 continue;
1206 info.sid = providers[x].slots[z];
1207 info.prov = &providers[x];
1209 if (pakchois_get_slot_info
1210 (providers[x].module, providers[x].slots[z],
1211 &info.sinfo) != CKR_OK)
1213 continue;
1216 /* XXX make wrapper for token_info? */
1217 fix_strings (&info);
1219 rv = pakchois_open_session (providers[x].module,
1220 providers[x].slots[z],
1221 ((flags & SESSION_WRITE)
1222 ? CKF_RW_SESSION : 0) |
1223 CKF_SERIAL_SESSION, NULL, NULL, &pks);
1224 if (rv != CKR_OK)
1226 continue;
1229 if (flags & SESSION_LOGIN)
1231 ret = pkcs11_login (pks, &info, (flags & SESSION_SO) ? 1 : 0);
1232 if (ret < 0)
1234 gnutls_assert ();
1235 return ret;
1239 ret = find_func (pks, &info, &providers[x].info, input);
1241 if (ret == 0)
1243 found = 1;
1244 goto finish;
1246 else
1248 pakchois_close_session (pks);
1249 pks = NULL;
1254 finish:
1255 /* final call */
1257 if (found == 0)
1259 ret = find_func (pks, NULL, NULL, input);
1261 else
1263 ret = 0;
1266 if (pks != NULL)
1268 pakchois_close_session (pks);
1271 return ret;
1274 static const char *
1275 pkcs11_obj_type_to_str (gnutls_pkcs11_obj_type_t type)
1277 switch (type)
1279 case GNUTLS_PKCS11_OBJ_X509_CRT:
1280 return "cert";
1281 case GNUTLS_PKCS11_OBJ_PUBKEY:
1282 return "public";
1283 case GNUTLS_PKCS11_OBJ_PRIVKEY:
1284 return "private";
1285 case GNUTLS_PKCS11_OBJ_SECRET_KEY:
1286 return "secretkey";
1287 case GNUTLS_PKCS11_OBJ_DATA:
1288 return "data";
1289 case GNUTLS_PKCS11_OBJ_UNKNOWN:
1290 default:
1291 return "unknown";
1295 /* imports a raw certificate from a token to a pkcs11_obj_t structure.
1297 static int
1298 pkcs11_obj_import (unsigned int class, gnutls_pkcs11_obj_t obj,
1299 const gnutls_datum_t * data,
1300 const gnutls_datum_t * id,
1301 const gnutls_datum_t * label,
1302 struct ck_token_info *tinfo, struct ck_info *lib_info)
1304 char *s;
1305 int ret;
1307 switch (class)
1309 case CKO_CERTIFICATE:
1310 obj->type = GNUTLS_PKCS11_OBJ_X509_CRT;
1311 break;
1312 case CKO_PUBLIC_KEY:
1313 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1314 break;
1315 case CKO_PRIVATE_KEY:
1316 obj->type = GNUTLS_PKCS11_OBJ_PRIVKEY;
1317 break;
1318 case CKO_SECRET_KEY:
1319 obj->type = GNUTLS_PKCS11_OBJ_SECRET_KEY;
1320 break;
1321 case CKO_DATA:
1322 obj->type = GNUTLS_PKCS11_OBJ_DATA;
1323 break;
1324 default:
1325 obj->type = GNUTLS_PKCS11_OBJ_UNKNOWN;
1328 if (obj->type != GNUTLS_PKCS11_OBJ_UNKNOWN)
1329 strcpy (obj->info.type, pkcs11_obj_type_to_str (obj->type));
1331 if (data && data->data)
1333 ret = _gnutls_set_datum (&obj->raw, data->data, data->size);
1334 if (ret < 0)
1336 gnutls_assert ();
1337 return ret;
1341 terminate_string (tinfo->manufacturer_id, sizeof tinfo->manufacturer_id);
1342 terminate_string (tinfo->label, sizeof tinfo->label);
1343 terminate_string (tinfo->model, sizeof tinfo->model);
1344 terminate_string (tinfo->serial_number, sizeof tinfo->serial_number);
1346 /* write data */
1347 snprintf (obj->info.manufacturer, sizeof (obj->info.manufacturer),
1348 "%s", tinfo->manufacturer_id);
1349 snprintf (obj->info.token, sizeof (obj->info.token), "%s", tinfo->label);
1350 snprintf (obj->info.model, sizeof (obj->info.model), "%s", tinfo->model);
1351 snprintf (obj->info.serial, sizeof (obj->info.serial), "%s",
1352 tinfo->serial_number);
1354 snprintf (obj->info.lib_manufacturer, sizeof (obj->info.lib_manufacturer),
1355 "%s", lib_info->manufacturer_id);
1356 snprintf (obj->info.lib_desc, sizeof (obj->info.lib_desc), "%s",
1357 lib_info->library_description);
1358 snprintf (obj->info.lib_version, sizeof (obj->info.lib_version), "%u.%u",
1359 (unsigned int) lib_info->library_version.major,
1360 (unsigned int) lib_info->library_version.minor);
1364 if (label && label->data)
1366 memcpy (obj->info.label, label->data, label->size);
1367 obj->info.label[label->size] = 0;
1370 if (id && id->data)
1372 s = _gnutls_bin2hex (id->data, id->size, obj->info.id,
1373 sizeof (obj->info.id), ":");
1374 if (s == NULL)
1376 gnutls_assert ();
1377 return GNUTLS_E_PKCS11_ERROR;
1380 memmove (obj->info.certid_raw, id->data, id->size);
1381 obj->info.certid_raw_size = id->size;
1384 return 0;
1387 static int
1388 pkcs11_obj_import_pubkey (pakchois_session_t * pks,
1389 ck_object_handle_t obj,
1390 gnutls_pkcs11_obj_t crt,
1391 const gnutls_datum_t * id,
1392 const gnutls_datum_t * label,
1393 struct ck_token_info *tinfo,
1394 struct ck_info *lib_info)
1397 struct ck_attribute a[4];
1398 ck_key_type_t key_type;
1399 opaque tmp1[2048];
1400 opaque tmp2[2048];
1401 int ret;
1402 ck_bool_t tval;
1404 a[0].type = CKA_KEY_TYPE;
1405 a[0].value = &key_type;
1406 a[0].value_len = sizeof (key_type);
1408 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
1410 switch (key_type)
1412 case CKK_RSA:
1413 a[0].type = CKA_MODULUS;
1414 a[0].value = tmp1;
1415 a[0].value_len = sizeof (tmp1);
1416 a[1].type = CKA_PUBLIC_EXPONENT;
1417 a[1].value = tmp2;
1418 a[1].value_len = sizeof (tmp2);
1420 if (pakchois_get_attribute_value (pks, obj, a, 2) == CKR_OK)
1423 ret =
1424 _gnutls_set_datum (&crt->pubkey[0],
1425 a[0].value, a[0].value_len);
1427 if (ret >= 0)
1428 ret =
1429 _gnutls_set_datum (&crt->pubkey
1430 [1], a[1].value, a[1].value_len);
1432 if (ret < 0)
1434 gnutls_assert ();
1435 _gnutls_free_datum (&crt->pubkey[1]);
1436 _gnutls_free_datum (&crt->pubkey[0]);
1437 return GNUTLS_E_MEMORY_ERROR;
1440 else
1442 gnutls_assert ();
1443 return GNUTLS_E_PKCS11_ERROR;
1445 crt->pk_algorithm = GNUTLS_PK_RSA;
1446 break;
1447 case CKK_DSA:
1448 a[0].type = CKA_PRIME;
1449 a[0].value = tmp1;
1450 a[0].value_len = sizeof (tmp1);
1451 a[1].type = CKA_SUBPRIME;
1452 a[1].value = tmp2;
1453 a[1].value_len = sizeof (tmp2);
1455 if (pakchois_get_attribute_value (pks, obj, a, 2) == CKR_OK)
1457 ret =
1458 _gnutls_set_datum (&crt->pubkey[0],
1459 a[0].value, a[0].value_len);
1461 if (ret >= 0)
1462 ret =
1463 _gnutls_set_datum (&crt->pubkey
1464 [1], a[1].value, a[1].value_len);
1466 if (ret < 0)
1468 gnutls_assert ();
1469 _gnutls_free_datum (&crt->pubkey[1]);
1470 _gnutls_free_datum (&crt->pubkey[0]);
1471 return GNUTLS_E_MEMORY_ERROR;
1474 else
1476 gnutls_assert ();
1477 return GNUTLS_E_PKCS11_ERROR;
1480 a[0].type = CKA_BASE;
1481 a[0].value = tmp1;
1482 a[0].value_len = sizeof (tmp1);
1483 a[1].type = CKA_VALUE;
1484 a[1].value = tmp2;
1485 a[1].value_len = sizeof (tmp2);
1487 if (pakchois_get_attribute_value (pks, obj, a, 2) == CKR_OK)
1489 ret =
1490 _gnutls_set_datum (&crt->pubkey[2],
1491 a[0].value, a[0].value_len);
1493 if (ret >= 0)
1494 ret =
1495 _gnutls_set_datum (&crt->pubkey
1496 [3], a[1].value, a[1].value_len);
1498 if (ret < 0)
1500 gnutls_assert ();
1501 _gnutls_free_datum (&crt->pubkey[0]);
1502 _gnutls_free_datum (&crt->pubkey[1]);
1503 _gnutls_free_datum (&crt->pubkey[2]);
1504 _gnutls_free_datum (&crt->pubkey[3]);
1505 return GNUTLS_E_MEMORY_ERROR;
1508 else
1510 gnutls_assert ();
1511 return GNUTLS_E_PKCS11_ERROR;
1513 crt->pk_algorithm = GNUTLS_PK_RSA;
1514 break;
1515 default:
1516 gnutls_assert ();
1517 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
1521 /* read key usage flags */
1522 a[0].type = CKA_ENCRYPT;
1523 a[0].value = &tval;
1524 a[0].value_len = sizeof (tval);
1526 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
1528 if (tval != 0)
1530 crt->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
1534 a[0].type = CKA_VERIFY;
1535 a[0].value = &tval;
1536 a[0].value_len = sizeof (tval);
1538 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
1540 if (tval != 0)
1542 crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1543 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1544 | GNUTLS_KEY_NON_REPUDIATION;
1548 a[0].type = CKA_VERIFY_RECOVER;
1549 a[0].value = &tval;
1550 a[0].value_len = sizeof (tval);
1552 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
1554 if (tval != 0)
1556 crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1557 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1558 | GNUTLS_KEY_NON_REPUDIATION;
1562 a[0].type = CKA_DERIVE;
1563 a[0].value = &tval;
1564 a[0].value_len = sizeof (tval);
1566 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
1568 if (tval != 0)
1570 crt->key_usage |= GNUTLS_KEY_KEY_AGREEMENT;
1574 a[0].type = CKA_WRAP;
1575 a[0].value = &tval;
1576 a[0].value_len = sizeof (tval);
1578 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
1580 if (tval != 0)
1582 crt->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
1586 return pkcs11_obj_import (CKO_PUBLIC_KEY, crt, NULL, id, label,
1587 tinfo, lib_info);
1590 ck_object_class_t
1591 pkcs11_strtype_to_class (const char *type)
1593 ck_object_class_t class;
1595 if (strcmp (type, "cert") == 0)
1597 class = CKO_CERTIFICATE;
1599 else if (strcmp (type, "public") == 0)
1601 class = CKO_PUBLIC_KEY;
1603 else if (strcmp (type, "private") == 0)
1605 class = CKO_PRIVATE_KEY;
1607 else if (strcmp (type, "secretkey") == 0)
1609 class = CKO_SECRET_KEY;
1611 else if (strcmp (type, "data") == 0)
1613 class = CKO_DATA;
1615 else
1617 class = -1;
1620 return class;
1624 static int
1625 find_obj_url (pakchois_session_t * pks, struct token_info *info,
1626 struct ck_info *lib_info, void *input)
1628 struct url_find_data_st *find_data = input;
1629 struct ck_attribute a[4];
1630 ck_object_class_t class = -1;
1631 ck_certificate_type_t type = -1;
1632 ck_rv_t rv;
1633 ck_object_handle_t obj;
1634 unsigned long count, a_vals;
1635 int found = 0, ret;
1636 opaque *cert_data = NULL;
1637 char label_tmp[PKCS11_LABEL_SIZE];
1639 if (info == NULL)
1640 { /* we don't support multiple calls */
1641 gnutls_assert ();
1642 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1645 /* do not bother reading the token if basic fields do not match
1647 if (pkcs11_token_matches_info
1648 (&find_data->crt->info, &info->tinfo, lib_info) < 0)
1650 gnutls_assert ();
1651 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1654 if (find_data->crt->info.type[0] != 0)
1656 class = pkcs11_strtype_to_class (find_data->crt->info.type);
1657 if (class == CKO_CERTIFICATE)
1658 type = CKC_X_509;
1660 if (class == -1)
1662 gnutls_assert ();
1663 return GNUTLS_E_INVALID_REQUEST;
1667 /* search the token for the id */
1669 cert_data = gnutls_malloc (MAX_CERT_SIZE);
1670 if (cert_data == NULL)
1672 gnutls_assert ();
1673 return GNUTLS_E_MEMORY_ERROR;
1676 /* Find objects with given class and type */
1678 a[0].type = CKA_ID;
1679 a[0].value = find_data->crt->info.certid_raw;
1680 a[0].value_len = find_data->crt->info.certid_raw_size;
1682 a_vals = 1;
1684 if (class != -1)
1686 a[a_vals].type = CKA_CLASS;
1687 a[a_vals].value = &class;
1688 a[a_vals].value_len = sizeof class;
1689 a_vals++;
1692 if (type != -1)
1694 a[a_vals].type = CKA_CERTIFICATE_TYPE;
1695 a[a_vals].value = &type;
1696 a[a_vals].value_len = sizeof type;
1697 a_vals++;
1700 rv = pakchois_find_objects_init (pks, a, a_vals);
1701 if (rv != CKR_OK)
1703 gnutls_assert ();
1704 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
1705 ret = pkcs11_rv_to_err (rv);
1706 goto cleanup;
1709 while (pakchois_find_objects (pks, &obj, 1, &count) == CKR_OK && count == 1)
1712 a[0].type = CKA_VALUE;
1713 a[0].value = cert_data;
1714 a[0].value_len = MAX_CERT_SIZE;
1715 a[1].type = CKA_LABEL;
1716 a[1].value = label_tmp;
1717 a[1].value_len = sizeof (label_tmp);
1719 if (pakchois_get_attribute_value (pks, obj, a, 2) == CKR_OK)
1721 gnutls_datum_t id = { find_data->crt->info.certid_raw,
1722 find_data->crt->info.certid_raw_size
1724 gnutls_datum_t data = { a[0].value, a[0].value_len };
1725 gnutls_datum_t label = { a[1].value, a[1].value_len };
1727 if (class == CKO_PUBLIC_KEY)
1729 ret =
1730 pkcs11_obj_import_pubkey (pks, obj,
1731 find_data->crt,
1732 &id, &label,
1733 &info->tinfo, lib_info);
1735 else
1737 ret =
1738 pkcs11_obj_import (class,
1739 find_data->crt,
1740 &data, &id, &label,
1741 &info->tinfo, lib_info);
1743 if (ret < 0)
1745 gnutls_assert ();
1746 goto cleanup;
1749 found = 1;
1750 break;
1752 else
1754 _gnutls_debug_log ("pk11: Skipped cert, missing attrs.\n");
1758 if (found == 0)
1760 gnutls_assert ();
1761 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1763 else
1765 ret = 0;
1768 cleanup:
1769 gnutls_free (cert_data);
1770 pakchois_find_objects_final (pks);
1772 return ret;
1775 unsigned int
1776 pkcs11_obj_flags_to_int (unsigned int flags)
1778 unsigned int ret_flags = 0;
1780 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN)
1781 ret_flags |= SESSION_LOGIN;
1782 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO)
1783 ret_flags |= SESSION_LOGIN|SESSION_SO;
1785 return ret_flags;
1789 * gnutls_pkcs11_privkey_import_url:
1790 * @cert: The structure to store the parsed certificate
1791 * @url: a PKCS 11 url identifying the key
1792 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1794 * This function will "import" a PKCS 11 URL identifying a certificate
1795 * key to the #gnutls_pkcs11_obj_t structure. This does not involve any
1796 * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is
1797 * format agnostic. Only data are transferred.
1799 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1800 * negative error value.
1803 gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t cert, const char *url,
1804 unsigned int flags)
1806 int ret;
1807 struct url_find_data_st find_data;
1809 /* fill in the find data structure */
1810 find_data.crt = cert;
1812 ret = pkcs11_url_to_info (url, &cert->info);
1813 if (ret < 0)
1815 gnutls_assert ();
1816 return ret;
1819 ret =
1820 _pkcs11_traverse_tokens (find_obj_url, &find_data,
1821 pkcs11_obj_flags_to_int (flags));
1823 if (ret < 0)
1825 gnutls_assert ();
1826 return ret;
1829 return 0;
1832 struct token_num
1834 struct pkcs11_url_info info;
1835 unsigned int seq; /* which one we are looking for */
1836 unsigned int current; /* which one are we now */
1839 static int
1840 find_token_num (pakchois_session_t * pks,
1841 struct token_info *tinfo,
1842 struct ck_info *lib_info, void *input)
1844 struct token_num *find_data = input;
1846 if (tinfo == NULL)
1847 { /* we don't support multiple calls */
1848 gnutls_assert ();
1849 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1852 if (find_data->current == find_data->seq)
1854 strcpy (find_data->info.manufacturer, tinfo->tinfo.manufacturer_id);
1855 strcpy (find_data->info.token, tinfo->tinfo.label);
1856 strcpy (find_data->info.model, tinfo->tinfo.model);
1857 strcpy (find_data->info.serial, tinfo->tinfo.serial_number);
1859 strcpy (find_data->info.lib_manufacturer, lib_info->manufacturer_id);
1860 strcpy (find_data->info.lib_desc, lib_info->library_description);
1861 snprintf (find_data->info.lib_version,
1862 sizeof (find_data->info.lib_version), "%u.%u",
1863 (unsigned int) lib_info->library_version.major,
1864 (unsigned int) lib_info->library_version.minor);
1866 return 0;
1869 find_data->current++;
1870 /* search the token for the id */
1873 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* non zero is enough */
1877 * gnutls_pkcs11_token_get_url:
1878 * @seq: sequence number starting from 0
1879 * @detailed: non zero if a detailed URL is required
1880 * @url: will contain an allocated url
1882 * This function will return the URL for each token available
1883 * in system. The url has to be released using gnutls_free()
1885 * Returns: On success, %GNUTLS_E_SUCCESS is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1886 * if the sequence number exceeds the available tokens, otherwise a negative error value.
1890 gnutls_pkcs11_token_get_url (unsigned int seq,
1891 gnutls_pkcs11_url_type_t detailed, char **url)
1893 int ret;
1894 struct token_num tn;
1896 memset (&tn, 0, sizeof (tn));
1897 tn.seq = seq;
1899 ret = _pkcs11_traverse_tokens (find_token_num, &tn, 0);
1900 if (ret < 0)
1902 gnutls_assert ();
1903 return ret;
1906 ret = pkcs11_info_to_url (&tn.info, detailed, url);
1907 if (ret < 0)
1909 gnutls_assert ();
1910 return ret;
1913 return 0;
1918 * gnutls_pkcs11_token_get_info:
1919 * @url: should contain a PKCS 11 URL
1920 * @ttype: Denotes the type of information requested
1921 * @output: where output will be stored
1922 * @output_size: contains the maximum size of the output and will be overwritten with actual
1924 * This function will return information about the PKCS 11 token such
1925 * as the label, id as well as token information where the key is stored.
1927 * Returns: zero on success or a negative value on error.
1930 gnutls_pkcs11_token_get_info (const char *url,
1931 gnutls_pkcs11_token_info_t ttype,
1932 void *output, size_t * output_size)
1934 const char *str;
1935 size_t len;
1936 struct pkcs11_url_info info;
1937 int ret;
1939 ret = pkcs11_url_to_info (url, &info);
1940 if (ret < 0)
1942 gnutls_assert ();
1943 return ret;
1946 switch (ttype)
1948 case GNUTLS_PKCS11_TOKEN_LABEL:
1949 str = info.token;
1950 break;
1951 case GNUTLS_PKCS11_TOKEN_SERIAL:
1952 str = info.serial;
1953 break;
1954 case GNUTLS_PKCS11_TOKEN_MANUFACTURER:
1955 str = info.manufacturer;
1956 break;
1957 case GNUTLS_PKCS11_TOKEN_MODEL:
1958 str = info.model;
1959 break;
1960 default:
1961 gnutls_assert ();
1962 return GNUTLS_E_INVALID_REQUEST;
1965 len = strlen (str);
1967 if (len + 1 > *output_size)
1969 *output_size = len + 1;
1970 return GNUTLS_E_SHORT_MEMORY_BUFFER;
1973 strcpy (output, str);
1975 *output_size = len;
1977 return 0;
1981 * gnutls_pkcs11_obj_export_url:
1982 * @obj: Holds the PKCS 11 certificate
1983 * @detailed: non zero if a detailed URL is required
1984 * @url: will contain an allocated url
1986 * This function will export a URL identifying the given certificate.
1988 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1989 * negative error value.
1992 gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t obj,
1993 gnutls_pkcs11_url_type_t detailed, char **url)
1995 int ret;
1997 ret = pkcs11_info_to_url (&obj->info, detailed, url);
1998 if (ret < 0)
2000 gnutls_assert ();
2001 return ret;
2004 return 0;
2008 * gnutls_pkcs11_obj_get_type:
2009 * @certificate: Holds the PKCS 11 certificate
2011 * This function will return the type of the certificate being
2012 * stored in the structure.
2014 * Returns: The type of the certificate.
2016 gnutls_pkcs11_obj_type_t
2017 gnutls_pkcs11_obj_get_type (gnutls_pkcs11_obj_t obj)
2019 return obj->type;
2022 struct pkey_list
2024 gnutls_buffer_st *key_ids;
2025 size_t key_ids_size;
2029 pkcs11_login (pakchois_session_t * pks, const struct token_info *info, int so)
2031 int attempt = 0, ret;
2032 ck_rv_t rv;
2033 char *token_url;
2034 int pin_len;
2035 struct pkcs11_url_info uinfo;
2038 if (so == 0 && (info->tinfo.flags & CKF_LOGIN_REQUIRED) == 0)
2040 gnutls_assert ();
2041 _gnutls_debug_log ("pk11: No login required.\n");
2042 return 0;
2045 memset (&uinfo, 0, sizeof (uinfo));
2046 strcpy (uinfo.manufacturer, info->tinfo.manufacturer_id);
2047 strcpy (uinfo.token, info->tinfo.label);
2048 strcpy (uinfo.model, info->tinfo.model);
2049 strcpy (uinfo.serial, info->tinfo.serial_number);
2050 ret = pkcs11_info_to_url (&uinfo, 1, &token_url);
2051 if (ret < 0)
2053 gnutls_assert ();
2054 return ret;
2057 /* For a token with a "protected" (out-of-band) authentication
2058 * path, calling login with a NULL username is all that is
2059 * required. */
2060 if (info->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
2062 rv = pakchois_login (pks, (so == 0) ? CKU_USER : CKU_SO, NULL, 0);
2063 if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN)
2065 return 0;
2067 else
2069 gnutls_assert ();
2070 _gnutls_debug_log ("pk11: Protected login failed.\n");
2071 ret = GNUTLS_E_PKCS11_ERROR;
2072 goto cleanup;
2076 /* Otherwise, PIN entry is necessary for login, so fail if there's
2077 * no callback. */
2078 if (!pin_func)
2080 gnutls_assert ();
2081 _gnutls_debug_log ("pk11: No pin callback but login required.\n");
2082 ret = GNUTLS_E_PKCS11_ERROR;
2083 goto cleanup;
2088 struct ck_token_info tinfo;
2089 char pin[GNUTLS_PKCS11_MAX_PIN_LEN];
2090 unsigned int flags;
2092 memcpy(&tinfo, &info->tinfo, sizeof(tinfo));
2094 /* If login has been attempted once already, check the token
2095 * status again, the flags might change. */
2096 if (attempt)
2098 if (pakchois_get_token_info
2099 (info->prov->module, info->sid, &tinfo) != CKR_OK)
2101 gnutls_assert ();
2102 _gnutls_debug_log ("pk11: GetTokenInfo failed\n");
2103 ret = GNUTLS_E_PKCS11_ERROR;
2104 goto cleanup;
2108 flags = 0;
2109 if (so == 0)
2111 flags |= GNUTLS_PKCS11_PIN_USER;
2112 if (tinfo.flags & CKF_USER_PIN_COUNT_LOW)
2113 flags |= GNUTLS_PKCS11_PIN_COUNT_LOW;
2114 if (tinfo.flags & CKF_USER_PIN_FINAL_TRY)
2115 flags |= GNUTLS_PKCS11_PIN_FINAL_TRY;
2117 else
2119 flags |= GNUTLS_PKCS11_PIN_SO;
2120 if (tinfo.flags & CKF_SO_PIN_COUNT_LOW)
2121 flags |= GNUTLS_PKCS11_PIN_COUNT_LOW;
2122 if (tinfo.flags & CKF_SO_PIN_FINAL_TRY)
2123 flags |= GNUTLS_PKCS11_PIN_FINAL_TRY;
2126 ret = pin_func (pin_data, attempt++,
2127 (char *) token_url,
2128 (char *) info->tinfo.label, flags, pin, sizeof (pin));
2129 if (ret < 0)
2131 gnutls_assert ();
2132 ret = GNUTLS_E_PKCS11_PIN_ERROR;
2133 goto cleanup;
2135 pin_len = strlen (pin);
2137 rv = pakchois_login (pks, (so == 0) ? CKU_USER : CKU_SO,
2138 (unsigned char *) pin, pin_len);
2140 /* Try to scrub the pin off the stack. Clever compilers will
2141 * probably optimize this away, oh well. */
2142 memset (pin, 0, sizeof pin);
2144 while (rv == CKR_PIN_INCORRECT);
2146 _gnutls_debug_log ("pk11: Login result = %lu\n", rv);
2149 ret = (rv == CKR_OK
2150 || rv == CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err (rv);
2152 cleanup:
2153 gnutls_free (token_url);
2154 return ret;
2157 static int
2158 find_privkeys (pakchois_session_t * pks, struct token_info *info,
2159 struct pkey_list *list)
2161 struct ck_attribute a[3];
2162 ck_object_class_t class;
2163 ck_rv_t rv;
2164 ck_object_handle_t obj;
2165 unsigned long count, current;
2166 char certid_tmp[PKCS11_ID_SIZE];
2168 class = CKO_PRIVATE_KEY;
2170 /* Find an object with private key class and a certificate ID
2171 * which matches the certificate. */
2172 /* FIXME: also match the cert subject. */
2173 a[0].type = CKA_CLASS;
2174 a[0].value = &class;
2175 a[0].value_len = sizeof class;
2177 rv = pakchois_find_objects_init (pks, a, 1);
2178 if (rv != CKR_OK)
2180 gnutls_assert ();
2181 return pkcs11_rv_to_err (rv);
2184 list->key_ids_size = 0;
2185 while (pakchois_find_objects (pks, &obj, 1, &count) == CKR_OK && count == 1)
2187 list->key_ids_size++;
2190 pakchois_find_objects_final (pks);
2192 if (list->key_ids_size == 0)
2194 gnutls_assert ();
2195 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2198 list->key_ids =
2199 gnutls_malloc (sizeof (gnutls_buffer_st) * list->key_ids_size);
2200 if (list->key_ids == NULL)
2202 gnutls_assert ();
2203 return GNUTLS_E_MEMORY_ERROR;
2206 /* actual search */
2207 a[0].type = CKA_CLASS;
2208 a[0].value = &class;
2209 a[0].value_len = sizeof class;
2211 rv = pakchois_find_objects_init (pks, a, 1);
2212 if (rv != CKR_OK)
2214 gnutls_assert ();
2215 return pkcs11_rv_to_err (rv);
2218 current = 0;
2219 while (pakchois_find_objects (pks, &obj, 1, &count) == CKR_OK && count == 1)
2222 a[0].type = CKA_ID;
2223 a[0].value = certid_tmp;
2224 a[0].value_len = sizeof (certid_tmp);
2226 _gnutls_buffer_init (&list->key_ids[current]);
2228 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
2230 _gnutls_buffer_append_data (&list->key_ids[current],
2231 a[0].value, a[0].value_len);
2232 current++;
2235 if (current > list->key_ids_size)
2236 break;
2239 pakchois_find_objects_final (pks);
2241 list->key_ids_size = current - 1;
2243 return 0;
2246 /* Recover certificate list from tokens */
2249 static int
2250 find_objs (pakchois_session_t * pks, struct token_info *info,
2251 struct ck_info *lib_info, void *input)
2253 struct crt_find_data_st *find_data = input;
2254 struct ck_attribute a[4];
2255 ck_object_class_t class = -1;
2256 ck_certificate_type_t type = -1;
2257 unsigned int trusted;
2258 ck_rv_t rv;
2259 ck_object_handle_t obj;
2260 unsigned long count;
2261 opaque *cert_data;
2262 char certid_tmp[PKCS11_ID_SIZE];
2263 char label_tmp[PKCS11_LABEL_SIZE];
2264 int ret, i;
2265 struct pkey_list plist; /* private key holder */
2266 int tot_values = 0;
2268 if (info == NULL)
2269 { /* final call */
2270 if (find_data->current <= *find_data->n_list)
2271 ret = 0;
2272 else
2273 ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
2275 *find_data->n_list = find_data->current;
2277 return ret;
2280 /* do not bother reading the token if basic fields do not match
2282 if (pkcs11_token_matches_info (&find_data->info, &info->tinfo, lib_info) <
2285 gnutls_assert ();
2286 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2289 if (find_data->info.type[0] != 0)
2291 class = pkcs11_strtype_to_class (find_data->info.type);
2292 if (class == CKO_CERTIFICATE)
2293 type = CKC_X_509;
2294 else
2295 type = -1;
2297 if (class == -1)
2299 gnutls_assert ();
2300 return GNUTLS_E_INVALID_REQUEST;
2305 memset (&plist, 0, sizeof (plist));
2307 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2309 ret = find_privkeys (pks, info, &plist);
2310 if (ret < 0)
2312 gnutls_assert ();
2313 return ret;
2316 if (plist.key_ids_size == 0)
2318 gnutls_assert ();
2319 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2323 cert_data = gnutls_malloc (MAX_CERT_SIZE);
2324 if (cert_data == NULL)
2326 gnutls_assert ();
2327 return GNUTLS_E_MEMORY_ERROR;
2330 /* Find objects with cert class and X.509 cert type. */
2332 tot_values = 0;
2334 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL
2335 || find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2337 class = CKO_CERTIFICATE;
2338 type = CKC_X_509;
2339 trusted = 1;
2341 a[tot_values].type = CKA_CLASS;
2342 a[tot_values].value = &class;
2343 a[tot_values].value_len = sizeof class;
2344 tot_values++;
2346 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2347 a[tot_values].value = &type;
2348 a[tot_values].value_len = sizeof type;
2349 tot_values++;
2352 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED)
2354 class = CKO_CERTIFICATE;
2355 type = CKC_X_509;
2356 trusted = 1;
2358 a[tot_values].type = CKA_CLASS;
2359 a[tot_values].value = &class;
2360 a[tot_values].value_len = sizeof class;
2361 tot_values++;
2363 a[tot_values].type = CKA_TRUSTED;
2364 a[tot_values].value = &trusted;
2365 a[tot_values].value_len = sizeof trusted;
2366 tot_values++;
2369 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY)
2371 class = CKO_PUBLIC_KEY;
2373 a[tot_values].type = CKA_CLASS;
2374 a[tot_values].value = &class;
2375 a[tot_values].value_len = sizeof class;
2376 tot_values++;
2378 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY)
2380 class = CKO_PRIVATE_KEY;
2382 a[tot_values].type = CKA_CLASS;
2383 a[tot_values].value = &class;
2384 a[tot_values].value_len = sizeof class;
2385 tot_values++;
2387 else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL)
2389 if (class != -1)
2391 a[tot_values].type = CKA_CLASS;
2392 a[tot_values].value = &class;
2393 a[tot_values].value_len = sizeof class;
2394 tot_values++;
2396 if (type != -1)
2398 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2399 a[tot_values].value = &type;
2400 a[tot_values].value_len = sizeof type;
2401 tot_values++;
2404 else
2406 gnutls_assert ();
2407 ret = GNUTLS_E_INVALID_REQUEST;
2408 goto fail;
2411 if (find_data->info.certid_raw_size != 0)
2413 a[tot_values].type = CKA_ID;
2414 a[tot_values].value = find_data->info.certid_raw;
2415 a[tot_values].value_len = find_data->info.certid_raw_size;
2416 tot_values++;
2419 rv = pakchois_find_objects_init (pks, a, tot_values);
2420 if (rv != CKR_OK)
2422 gnutls_assert ();
2423 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
2424 return pkcs11_rv_to_err (rv);
2427 while (pakchois_find_objects (pks, &obj, 1, &count) == CKR_OK && count == 1)
2429 gnutls_datum_t label, id, value;
2431 a[0].type = CKA_LABEL;
2432 a[0].value = label_tmp;
2433 a[0].value_len = sizeof label_tmp;
2435 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
2437 label.data = a[0].value;
2438 label.size = a[0].value_len;
2440 else
2442 label.data = NULL;
2443 label.size = 0;
2446 a[0].type = CKA_ID;
2447 a[0].value = certid_tmp;
2448 a[0].value_len = sizeof certid_tmp;
2450 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
2452 id.data = a[0].value;
2453 id.size = a[0].value_len;
2455 else
2457 id.data = NULL;
2458 id.size = 0;
2461 a[0].type = CKA_VALUE;
2462 a[0].value = cert_data;
2463 a[0].value_len = MAX_CERT_SIZE;
2464 if (pakchois_get_attribute_value (pks, obj, a, 1) == CKR_OK)
2466 value.data = a[0].value;
2467 value.size = a[0].value_len;
2469 else
2471 value.data = NULL;
2472 value.size = 0;
2475 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL)
2477 a[0].type = CKA_CLASS;
2478 a[0].value = &class;
2479 a[0].value_len = sizeof class;
2481 pakchois_get_attribute_value (pks, obj, a, 1);
2484 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2486 for (i = 0; i < plist.key_ids_size; i++)
2488 if (plist.key_ids[i].length !=
2489 a[1].value_len
2490 || memcmp (plist.key_ids[i].data,
2491 a[1].value, a[1].value_len) != 0)
2493 /* not found */
2494 continue;
2499 if (find_data->current < *find_data->n_list)
2501 ret =
2502 gnutls_pkcs11_obj_init (&find_data->p_list[find_data->current]);
2503 if (ret < 0)
2505 gnutls_assert ();
2506 goto fail;
2509 if (class == CKO_PUBLIC_KEY)
2511 ret =
2512 pkcs11_obj_import_pubkey (pks, obj,
2513 find_data->p_list
2514 [find_data->current],
2515 &id, &label,
2516 &info->tinfo, lib_info);
2518 else
2520 ret =
2521 pkcs11_obj_import (class,
2522 find_data->p_list
2523 [find_data->current],
2524 &value, &id, &label,
2525 &info->tinfo, lib_info);
2527 if (ret < 0)
2529 gnutls_assert ();
2530 goto fail;
2534 find_data->current++;
2538 gnutls_free (cert_data);
2539 pakchois_find_objects_final (pks);
2541 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* continue until all tokens have been checked */
2543 fail:
2544 gnutls_free (cert_data);
2545 pakchois_find_objects_final (pks);
2546 if (plist.key_ids != NULL)
2548 for (i = 0; i < plist.key_ids_size; i++)
2550 _gnutls_buffer_clear (&plist.key_ids[i]);
2552 gnutls_free (plist.key_ids);
2554 for (i = 0; i < find_data->current; i++)
2556 gnutls_pkcs11_obj_deinit (find_data->p_list[i]);
2558 find_data->current = 0;
2560 return ret;
2564 * gnutls_pkcs11_obj_list_import_url:
2565 * @p_list: An uninitialized object list (may be NULL)
2566 * @n_list: initially should hold the maximum size of the list. Will contain the actual size.
2567 * @url: A PKCS 11 url identifying a set of objects
2568 * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2569 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2571 * This function will initialize and set values to an object list
2572 * by using all objects identified by a PKCS 11 URL.
2574 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
2575 * negative error value.
2578 gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list,
2579 unsigned int *n_list,
2580 const char *url,
2581 gnutls_pkcs11_obj_attr_t attrs,
2582 unsigned int flags)
2584 int ret;
2585 struct crt_find_data_st find_data;
2587 /* fill in the find data structure */
2588 find_data.p_list = p_list;
2589 find_data.n_list = n_list;
2590 find_data.flags = attrs;
2591 find_data.current = 0;
2593 if (url == NULL || url[0] == 0)
2595 url = "pkcs11:";
2598 ret = pkcs11_url_to_info (url, &find_data.info);
2599 if (ret < 0)
2601 gnutls_assert ();
2602 return ret;
2605 ret =
2606 _pkcs11_traverse_tokens (find_objs, &find_data,
2607 pkcs11_obj_flags_to_int (flags));
2608 if (ret < 0)
2610 gnutls_assert ();
2611 return ret;
2614 return 0;
2618 * gnutls_x509_crt_import_pkcs11_url:
2619 * @crt: A certificate of type #gnutls_x509_crt_t
2620 * @url: A PKCS 11 url
2621 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2623 * This function will import a PKCS 11 certificate directly from a token
2624 * without involving the #gnutls_pkcs11_obj_t structure. This function will
2625 * fail if the certificate stored is not of X.509 type.
2627 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
2628 * negative error value.
2631 gnutls_x509_crt_import_pkcs11_url (gnutls_x509_crt_t crt,
2632 const char *url, unsigned int flags)
2634 gnutls_pkcs11_obj_t pcrt;
2635 int ret;
2637 ret = gnutls_pkcs11_obj_init (&pcrt);
2638 if (ret < 0)
2640 gnutls_assert ();
2641 return ret;
2644 ret = gnutls_pkcs11_obj_import_url (pcrt, url, flags);
2645 if (ret < 0)
2647 gnutls_assert ();
2648 goto cleanup;
2651 ret = gnutls_x509_crt_import (crt, &pcrt->raw, GNUTLS_X509_FMT_DER);
2652 if (ret < 0)
2654 gnutls_assert ();
2655 goto cleanup;
2658 ret = 0;
2659 cleanup:
2661 gnutls_pkcs11_obj_deinit (pcrt);
2663 return ret;
2668 * gnutls_x509_crt_import_pkcs11:
2669 * @crt: A certificate of type #gnutls_x509_crt_t
2670 * @pkcs11_crt: A PKCS 11 object that contains a certificate
2672 * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t
2673 * structure.
2675 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
2676 * negative error value.
2679 gnutls_x509_crt_import_pkcs11 (gnutls_x509_crt_t crt,
2680 gnutls_pkcs11_obj_t pkcs11_crt)
2682 return gnutls_x509_crt_import (crt, &pkcs11_crt->raw, GNUTLS_X509_FMT_DER);
2686 * gnutls_x509_crt_list_import_pkcs11:
2687 * @certs: A list of certificates of type #gnutls_x509_crt_t
2688 * @cert_max: The maximum size of the list
2689 * @objs: A list of PKCS 11 objects
2690 * @flags: 0 for now
2692 * This function will import a PKCS 11 certificate list to a list of
2693 * #gnutls_x509_crt_t structure. These must not be initialized.
2695 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
2696 * negative error value.
2699 gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs,
2700 unsigned int cert_max,
2701 gnutls_pkcs11_obj_t * const objs,
2702 unsigned int flags)
2704 int i, j;
2705 int ret;
2707 for (i = 0; i < cert_max; i++)
2709 ret = gnutls_x509_crt_init (&certs[i]);
2710 if (ret < 0)
2712 gnutls_assert ();
2713 goto cleanup;
2716 ret = gnutls_x509_crt_import_pkcs11 (certs[i], objs[i]);
2717 if (ret < 0)
2719 gnutls_assert ();
2720 goto cleanup;
2724 return 0;
2726 cleanup:
2727 for (j = 0; j < i; j++)
2729 gnutls_x509_crt_deinit (certs[j]);
2732 return ret;
2735 static int
2736 find_flags (pakchois_session_t * pks, struct token_info *info,
2737 struct ck_info *lib_info, void *input)
2739 struct flags_find_data_st *find_data = input;
2741 if (info == NULL)
2742 { /* we don't support multiple calls */
2743 gnutls_assert ();
2744 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2747 /* do not bother reading the token if basic fields do not match
2749 if (pkcs11_token_matches_info (&find_data->info, &info->tinfo, lib_info) <
2752 gnutls_assert ();
2753 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2756 /* found token! */
2758 find_data->slot_flags = info->sinfo.flags;
2760 return 0;
2764 * gnutls_pkcs11_token_get_flags:
2765 * @url: should contain a PKCS 11 URL
2766 * @flags: The output flags (GNUTLS_PKCS11_TOKEN_*)
2768 * This function will return information about the PKCS 11 token flags.
2770 * Returns: zero on success or a negative value on error.
2773 gnutls_pkcs11_token_get_flags (const char *url, unsigned int *flags)
2775 struct flags_find_data_st find_data;
2776 int ret;
2778 ret = pkcs11_url_to_info (url, &find_data.info);
2779 if (ret < 0)
2781 gnutls_assert ();
2782 return ret;
2785 ret = _pkcs11_traverse_tokens (find_flags, &find_data, 0);
2786 if (ret < 0)
2788 gnutls_assert ();
2789 return ret;
2792 *flags = 0;
2793 if (find_data.slot_flags & CKF_HW_SLOT)
2794 *flags |= GNUTLS_PKCS11_TOKEN_HW;
2796 return 0;
2802 * gnutls_pkcs11_token_get_mechanism:
2803 * @url: should contain a PKCS 11 URL
2804 * @idx: The index of the mechanism
2805 * @mechanism: The PKCS #11 mechanism ID
2807 * This function will return the names of the supported mechanisms
2808 * by the token. It should be called with an increasing index until
2809 * it return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
2811 * Returns: zero on success or a negative value on error.
2814 gnutls_pkcs11_token_get_mechanism (const char *url, int idx,
2815 unsigned long *mechanism)
2817 int ret;
2818 ck_rv_t rv;
2819 pakchois_module_t *module;
2820 ck_slot_id_t slot;
2821 struct token_info tinfo;
2822 struct pkcs11_url_info info;
2823 unsigned long count;
2824 ck_mechanism_type_t mlist[400];
2826 ret = pkcs11_url_to_info (url, &info);
2827 if (ret < 0)
2829 gnutls_assert ();
2830 return ret;
2834 ret = pkcs11_find_slot (&module, &slot, &info, &tinfo);
2835 if (ret < 0)
2837 gnutls_assert ();
2838 return ret;
2841 count = sizeof (mlist) / sizeof (mlist[0]);
2842 rv = pakchois_get_mechanism_list (module, slot, mlist, &count);
2843 if (rv != CKR_OK)
2845 gnutls_assert ();
2846 return pkcs11_rv_to_err (rv);
2849 if (idx >= count)
2851 gnutls_assert ();
2852 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2855 *mechanism = mlist[idx];
2857 return 0;
2862 const char *
2863 gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t type)
2865 switch (type)
2867 case GNUTLS_PKCS11_OBJ_X509_CRT:
2868 return "X.509 Certificate";
2869 case GNUTLS_PKCS11_OBJ_PUBKEY:
2870 return "Public key";
2871 case GNUTLS_PKCS11_OBJ_PRIVKEY:
2872 return "Private key";
2873 case GNUTLS_PKCS11_OBJ_SECRET_KEY:
2874 return "Secret key";
2875 case GNUTLS_PKCS11_OBJ_DATA:
2876 return "Data";
2877 case GNUTLS_PKCS11_OBJ_UNKNOWN:
2878 default:
2879 return "Unknown";
2884 pkcs11_token_matches_info (struct pkcs11_url_info *info,
2885 struct ck_token_info *tinfo,
2886 struct ck_info *lib_info)
2888 if (info->manufacturer[0] != 0)
2890 if (strcmp (info->manufacturer, tinfo->manufacturer_id) != 0)
2891 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2894 if (info->token[0] != 0)
2896 if (strcmp (info->token, tinfo->label) != 0)
2897 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2900 if (info->model[0] != 0)
2902 if (strcmp (info->model, tinfo->model) != 0)
2903 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2906 if (info->serial[0] != 0)
2908 if (strcmp (info->serial, tinfo->serial_number) != 0)
2909 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2912 if (info->lib_manufacturer[0] != 0)
2914 if (strcmp (info->lib_manufacturer, lib_info->manufacturer_id) != 0)
2915 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2918 if (info->lib_desc[0] != 0)
2920 if (strcmp (info->lib_desc, lib_info->library_description) != 0)
2921 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2924 if (info->lib_version[0] != 0)
2926 char version[16];
2928 snprintf (version, sizeof (version), "%u.%u",
2929 (unsigned int) lib_info->library_version.major,
2930 (unsigned int) lib_info->library_version.minor);
2931 if (strcmp (info->lib_version, version) != 0)
2932 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2935 return 0;