2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010 Free Software Foundation
4 * Copyright (C) 2008, Joe Orton <joe@manyfish.co.uk>
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
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,
28 #include <gnutls_int.h>
29 #include <gnutls/pkcs11.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
;
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
;
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
;
82 pkcs11_rv_to_err (ck_rv_t rv
)
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
:
97 case CKR_FUNCTION_NOT_PARALLEL
:
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
:
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
;
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
;
164 return GNUTLS_E_PKCS11_ERROR
;
170 pkcs11_rescan_slots (void)
174 pakchois_get_slot_list (providers
[active_providers
- 1].module
, 0,
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
)
197 return GNUTLS_E_CONSTRAINT_ERROR
;
201 if (pakchois_module_load_abs
202 (&providers
[active_providers
- 1].module
, name
) != CKR_OK
)
205 _gnutls_debug_log ("p11: Cannot load provider %s\n", name
);
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
)
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
)
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
)
234 gnutls_free (providers
[active_providers
- 1].slots
);
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
);
256 pakchois_module_destroy (providers
[active_providers
- 1].module
);
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
;
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
;
302 memcpy (output
, info
->certid_raw
, info
->certid_raw_size
);
303 *output_size
= info
->certid_raw_size
;
306 case GNUTLS_PKCS11_OBJ_ID_HEX
:
309 case GNUTLS_PKCS11_OBJ_LABEL
:
312 case GNUTLS_PKCS11_OBJ_TOKEN_LABEL
:
315 case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL
:
318 case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER
:
319 str
= info
->manufacturer
;
321 case GNUTLS_PKCS11_OBJ_TOKEN_MODEL
:
324 case GNUTLS_PKCS11_OBJ_LIBRARY_DESCRIPTION
:
325 str
= info
->lib_desc
;
327 case GNUTLS_PKCS11_OBJ_LIBRARY_VERSION
:
328 str
= info
->lib_version
;
330 case GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER
:
331 str
= info
->lib_manufacturer
;
335 return GNUTLS_E_INVALID_REQUEST
;
340 if (len
+ 1 > *output_size
)
342 *output_size
= len
+ 1;
343 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
346 strcpy (output
, str
);
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
)
384 if (flags
== GNUTLS_PKCS11_FLAG_MANUAL
)
392 if (configfile
== NULL
)
393 configfile
= "/etc/gnutls/pkcs11.conf";
395 fp
= fopen (configfile
, "r");
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)
408 p
= strchr (line
, '=');
414 p
= strchr (line
, '\n');
420 ret
= gnutls_pkcs11_add_provider (library
, NULL
);
424 _gnutls_debug_log ("Cannot load provider: %s\n", library
);
435 * gnutls_pkcs11_deinit:
437 * This function will deinitialize the PKCS 11 subsystem in gnutls.
441 gnutls_pkcs11_deinit (void)
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
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.
490 gnutls_pkcs11_set_pin_function (gnutls_pkcs11_pin_callback_t fn
,
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.
509 gnutls_pkcs11_set_token_function (gnutls_pkcs11_token_callback_t fn
,
513 token_data
= userdata
;
517 unescape_string (char *output
, const char *input
, size_t * size
,
520 gnutls_buffer_st str
;
525 _gnutls_buffer_init (&str
);
527 /* find terminator */
528 p
= strchr (input
, terminator
);
532 len
= strlen (input
);
534 ret
= _gnutls_buffer_append_data (&str
, input
, len
);
541 ret
= _gnutls_buffer_unescape (&str
);
548 ret
= _gnutls_buffer_append_data (&str
, "", 1);
555 _gnutls_buffer_pop_data (&str
, output
, size
);
557 _gnutls_buffer_clear (&str
);
563 pkcs11_url_to_info (const char *url
, struct pkcs11_url_info
*info
)
569 memset (info
, 0, sizeof (*info
));
571 if (strstr (url
, "pkcs11:") == NULL
)
573 ret
= GNUTLS_E_PARSING_ERROR
;
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
, ';');
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
, ';');
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
, ';');
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
, ';');
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
, ';');
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
, ';');
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
, ';');
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
, ';');
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
, ';');
687 if (((p1
= strstr (url
, ";id=")) != NULL
)
688 || ((p1
= strstr (url
, ":id=")) != NULL
))
690 p1
+= sizeof (";id=") - 1;
692 if ((p2
= strchr (p1
, ';')) == NULL
)
701 if (l
> sizeof (info
->id
) - 1)
704 ret
= GNUTLS_E_PARSING_ERROR
;
707 memcpy (info
->id
, p1
, l
);
711 info
->certid_raw_size
= sizeof (info
->certid_raw
);
713 _gnutls_hex2bin (info
->id
, strlen (info
->id
),
714 info
->certid_raw
, &info
->certid_raw_size
);
730 #define INVALID_CHARS "\\/\"'%&#@!?$* <>{}[]()`|:;,.+-"
733 append (gnutls_buffer_st
* dest
, const char *tname
,
734 const char *p11name
, int init
)
736 gnutls_buffer_st tmpstr
;
739 _gnutls_buffer_init (&tmpstr
);
740 if ((ret
= _gnutls_buffer_append_str (&tmpstr
, tname
)) < 0)
746 ret
= _gnutls_buffer_escape (&tmpstr
, INVALID_CHARS
);
753 if ((ret
= _gnutls_buffer_append_data (&tmpstr
, "", 1)) < 0)
760 _gnutls_buffer_append_printf (dest
, "%s%s=%s",
761 (init
!= 0) ? ";" : "", p11name
,
771 _gnutls_buffer_clear (&tmpstr
);
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
;
786 _gnutls_buffer_init (&str
);
788 _gnutls_buffer_append_str (&str
, "pkcs11:");
792 ret
= append (&str
, info
->token
, "token", init
);
803 ret
= append (&str
, info
->serial
, "serial", init
);
814 ret
= append (&str
, info
->model
, "model", init
);
824 if (info
->manufacturer
[0])
826 ret
= append (&str
, info
->manufacturer
, "manufacturer", init
);
837 ret
= append (&str
, info
->label
, "object", init
);
848 ret
= append (&str
, info
->type
, "objecttype", init
);
857 if (detailed
> GNUTLS_PKCS11_URL_GENERIC
)
859 if (info
->lib_manufacturer
[0])
862 append (&str
, info
->lib_manufacturer
, "library-manufacturer",
872 if (info
->lib_desc
[0])
874 ret
= append (&str
, info
->lib_desc
, "library-description", init
);
884 if (detailed
> GNUTLS_PKCS11_URL_LIB
)
886 if (info
->lib_version
[0])
888 ret
= append (&str
, info
->lib_version
, "library-version", init
);
898 if (info
->id
[0] != 0)
900 ret
= _gnutls_buffer_append_printf (&str
, ";id=%s", info
->id
);
908 _gnutls_buffer_append_data (&str
, "", 1);
915 _gnutls_buffer_clear (&str
);
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
));
935 return GNUTLS_E_MEMORY_ERROR
;
942 * gnutls_pkcs11_obj_deinit:
943 * @key: The structure to be initialized
945 * This function will deinitialize a certificate structure.
948 gnutls_pkcs11_obj_deinit (gnutls_pkcs11_obj_t crt
)
950 _gnutls_free_datum (&crt
->raw
);
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
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
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
)
982 return GNUTLS_E_INVALID_REQUEST
;
985 if (output_data
== NULL
|| *output_data_size
< obj
->raw
.size
)
987 *output_data_size
= obj
->raw
.size
;
989 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
991 *output_data_size
= obj
->raw
.size
;
993 memcpy (output_data
, obj
->raw
.data
, obj
->raw
.size
);
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
)
1007 else if (ptr
== str
+ len
- 1)
1008 str
[len
- 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
)
1019 pakchois_session_t
*pks
;
1020 ck_object_handle_t obj
;
1021 ck_object_class_t
class;
1022 struct ck_attribute a
[4];
1024 unsigned long count
;
1027 class = pkcs11_strtype_to_class (info
->type
);
1031 return GNUTLS_E_INVALID_REQUEST
;
1034 ret
= pkcs11_open_session (&pks
, info
, flags
& SESSION_LOGIN
);
1041 a
[a_vals
].type
= CKA_CLASS
;
1042 a
[a_vals
].value
= &class;
1043 a
[a_vals
].value_len
= sizeof class;
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
;
1054 rv
= pakchois_find_objects_init (pks
, a
, a_vals
);
1058 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
1059 ret
= pkcs11_rv_to_err (rv
);
1063 if (pakchois_find_objects (pks
, &obj
, 1, &count
) == CKR_OK
&& count
== 1)
1067 pakchois_find_objects_final (pks
);
1072 pakchois_find_objects_final (pks
);
1074 pakchois_close_session (pks
);
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
)
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
)
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
)
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)
1130 *module
= providers
[x
].module
;
1131 *slot
= providers
[x
].slots
[z
];
1134 memcpy (_tinfo
, &tinfo
, sizeof (tinfo
));
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
)
1150 pakchois_session_t
*pks
= NULL
;
1151 pakchois_module_t
*module
;
1153 struct token_info tinfo
;
1155 ret
= pkcs11_find_slot (&module
, &slot
, info
, &tinfo
);
1162 rv
= pakchois_open_session (module
,
1164 ((flags
& SESSION_WRITE
)
1165 ? CKF_RW_SESSION
: 0) |
1166 CKF_SERIAL_SESSION
, NULL
, NULL
, &pks
);
1170 return pkcs11_rv_to_err (rv
);
1173 if (flags
& SESSION_LOGIN
)
1175 ret
= pkcs11_login (pks
, &tinfo
, (flags
& SESSION_SO
) ? 1 : 0);
1179 pakchois_close_session (pks
);
1191 _pkcs11_traverse_tokens (find_func_t find_func
, void *input
,
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
)
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
)
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
);
1235 if (flags
& SESSION_LOGIN
)
1237 ret
= pkcs11_login (pks
, &info
, (flags
& SESSION_SO
) ? 1 : 0);
1245 ret
= find_func (pks
, &info
, &providers
[x
].info
, input
);
1254 pakchois_close_session (pks
);
1265 ret
= find_func (pks
, NULL
, NULL
, input
);
1274 pakchois_close_session (pks
);
1281 pkcs11_obj_type_to_str (gnutls_pkcs11_obj_type_t type
)
1285 case GNUTLS_PKCS11_OBJ_X509_CRT
:
1287 case GNUTLS_PKCS11_OBJ_PUBKEY
:
1289 case GNUTLS_PKCS11_OBJ_PRIVKEY
:
1291 case GNUTLS_PKCS11_OBJ_SECRET_KEY
:
1293 case GNUTLS_PKCS11_OBJ_DATA
:
1295 case GNUTLS_PKCS11_OBJ_UNKNOWN
:
1301 /* imports a raw certificate from a token to a pkcs11_obj_t structure.
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
)
1315 case CKO_CERTIFICATE
:
1316 obj
->type
= GNUTLS_PKCS11_OBJ_X509_CRT
;
1318 case CKO_PUBLIC_KEY
:
1319 obj
->type
= GNUTLS_PKCS11_OBJ_PUBKEY
;
1321 case CKO_PRIVATE_KEY
:
1322 obj
->type
= GNUTLS_PKCS11_OBJ_PRIVKEY
;
1324 case CKO_SECRET_KEY
:
1325 obj
->type
= GNUTLS_PKCS11_OBJ_SECRET_KEY
;
1328 obj
->type
= GNUTLS_PKCS11_OBJ_DATA
;
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
);
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
);
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;
1378 s
= _gnutls_bin2hex (id
->data
, id
->size
, obj
->info
.id
,
1379 sizeof (obj
->info
.id
), ":");
1383 return GNUTLS_E_PKCS11_ERROR
;
1386 memmove (obj
->info
.certid_raw
, id
->data
, id
->size
);
1387 obj
->info
.certid_raw_size
= id
->size
;
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
;
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
)
1419 a
[0].type
= CKA_MODULUS
;
1421 a
[0].value_len
= sizeof (tmp1
);
1422 a
[1].type
= CKA_PUBLIC_EXPONENT
;
1424 a
[1].value_len
= sizeof (tmp2
);
1426 if (pakchois_get_attribute_value (pks
, obj
, a
, 2) == CKR_OK
)
1430 _gnutls_set_datum (&crt
->pubkey
[0],
1431 a
[0].value
, a
[0].value_len
);
1435 _gnutls_set_datum (&crt
->pubkey
1436 [1], a
[1].value
, a
[1].value_len
);
1441 _gnutls_free_datum (&crt
->pubkey
[1]);
1442 _gnutls_free_datum (&crt
->pubkey
[0]);
1443 return GNUTLS_E_MEMORY_ERROR
;
1449 return GNUTLS_E_PKCS11_ERROR
;
1451 crt
->pk_algorithm
= GNUTLS_PK_RSA
;
1454 a
[0].type
= CKA_PRIME
;
1456 a
[0].value_len
= sizeof (tmp1
);
1457 a
[1].type
= CKA_SUBPRIME
;
1459 a
[1].value_len
= sizeof (tmp2
);
1461 if (pakchois_get_attribute_value (pks
, obj
, a
, 2) == CKR_OK
)
1464 _gnutls_set_datum (&crt
->pubkey
[0],
1465 a
[0].value
, a
[0].value_len
);
1469 _gnutls_set_datum (&crt
->pubkey
1470 [1], a
[1].value
, a
[1].value_len
);
1475 _gnutls_free_datum (&crt
->pubkey
[1]);
1476 _gnutls_free_datum (&crt
->pubkey
[0]);
1477 return GNUTLS_E_MEMORY_ERROR
;
1483 return GNUTLS_E_PKCS11_ERROR
;
1486 a
[0].type
= CKA_BASE
;
1488 a
[0].value_len
= sizeof (tmp1
);
1489 a
[1].type
= CKA_VALUE
;
1491 a
[1].value_len
= sizeof (tmp2
);
1493 if (pakchois_get_attribute_value (pks
, obj
, a
, 2) == CKR_OK
)
1496 _gnutls_set_datum (&crt
->pubkey
[2],
1497 a
[0].value
, a
[0].value_len
);
1501 _gnutls_set_datum (&crt
->pubkey
1502 [3], a
[1].value
, a
[1].value_len
);
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
;
1517 return GNUTLS_E_PKCS11_ERROR
;
1519 crt
->pk_algorithm
= GNUTLS_PK_RSA
;
1523 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
1527 /* read key usage flags */
1528 a
[0].type
= CKA_ENCRYPT
;
1530 a
[0].value_len
= sizeof (tval
);
1532 if (pakchois_get_attribute_value (pks
, obj
, a
, 1) == CKR_OK
)
1536 crt
->key_usage
|= GNUTLS_KEY_DATA_ENCIPHERMENT
;
1540 a
[0].type
= CKA_VERIFY
;
1542 a
[0].value_len
= sizeof (tval
);
1544 if (pakchois_get_attribute_value (pks
, obj
, a
, 1) == CKR_OK
)
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
;
1556 a
[0].value_len
= sizeof (tval
);
1558 if (pakchois_get_attribute_value (pks
, obj
, a
, 1) == CKR_OK
)
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
;
1570 a
[0].value_len
= sizeof (tval
);
1572 if (pakchois_get_attribute_value (pks
, obj
, a
, 1) == CKR_OK
)
1576 crt
->key_usage
|= GNUTLS_KEY_KEY_AGREEMENT
;
1580 a
[0].type
= CKA_WRAP
;
1582 a
[0].value_len
= sizeof (tval
);
1584 if (pakchois_get_attribute_value (pks
, obj
, a
, 1) == CKR_OK
)
1588 crt
->key_usage
|= GNUTLS_KEY_KEY_ENCIPHERMENT
;
1592 return pkcs11_obj_import (CKO_PUBLIC_KEY
, crt
, NULL
, id
, label
,
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)
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;
1639 ck_object_handle_t obj
;
1640 unsigned long count
, a_vals
;
1642 opaque
*cert_data
= NULL
;
1643 char label_tmp
[PKCS11_LABEL_SIZE
];
1646 { /* we don't support multiple calls */
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)
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
)
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
)
1679 return GNUTLS_E_MEMORY_ERROR
;
1682 /* Find objects with given class and type */
1685 a
[0].value
= find_data
->crt
->info
.certid_raw
;
1686 a
[0].value_len
= find_data
->crt
->info
.certid_raw_size
;
1692 a
[a_vals
].type
= CKA_CLASS
;
1693 a
[a_vals
].value
= &class;
1694 a
[a_vals
].value_len
= sizeof class;
1700 a
[a_vals
].type
= CKA_CERTIFICATE_TYPE
;
1701 a
[a_vals
].value
= &type
;
1702 a
[a_vals
].value_len
= sizeof type
;
1706 rv
= pakchois_find_objects_init (pks
, a
, a_vals
);
1710 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
1711 ret
= pkcs11_rv_to_err (rv
);
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
)
1736 pkcs11_obj_import_pubkey (pks
, obj
,
1739 &info
->tinfo
, lib_info
);
1744 pkcs11_obj_import (class,
1747 &info
->tinfo
, lib_info
);
1760 _gnutls_debug_log ("pk11: Skipped cert, missing attrs.\n");
1767 ret
= GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
1775 gnutls_free (cert_data
);
1776 pakchois_find_objects_final (pks
);
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
;
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
,
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
);
1824 _pkcs11_traverse_tokens (find_obj_url
, &find_data
,
1825 pkcs11_obj_flags_to_int (flags
));
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 */
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
;
1851 { /* we don't support multiple calls */
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
);
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
)
1898 struct token_num tn
;
1900 memset (&tn
, 0, sizeof (tn
));
1903 ret
= _pkcs11_traverse_tokens (find_token_num
, &tn
, 0);
1910 ret
= pkcs11_info_to_url (&tn
.info
, detailed
, url
);
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
)
1940 struct pkcs11_url_info info
;
1943 ret
= pkcs11_url_to_info (url
, &info
);
1952 case GNUTLS_PKCS11_TOKEN_LABEL
:
1955 case GNUTLS_PKCS11_TOKEN_SERIAL
:
1958 case GNUTLS_PKCS11_TOKEN_MANUFACTURER
:
1959 str
= info
.manufacturer
;
1961 case GNUTLS_PKCS11_TOKEN_MODEL
:
1966 return GNUTLS_E_INVALID_REQUEST
;
1971 if (len
+ 1 > *output_size
)
1973 *output_size
= len
+ 1;
1974 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
1977 strcpy (output
, str
);
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
)
2001 ret
= pkcs11_info_to_url (&cert
->info
, detailed
, url
);
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
)
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
;
2039 struct pkcs11_url_info uinfo
;
2042 if (so
== 0 && (info
->tinfo
.flags
& CKF_LOGIN_REQUIRED
) == 0)
2045 _gnutls_debug_log ("pk11: No login required.\n");
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
);
2061 /* For a token with a "protected" (out-of-band) authentication
2062 * path, calling login with a NULL username is all that is
2064 if (info
->tinfo
.flags
& CKF_PROTECTED_AUTHENTICATION_PATH
)
2066 if (pakchois_login (pks
, (so
== 0) ? CKU_USER
: CKU_SO
, NULL
, 0) ==
2074 _gnutls_debug_log ("pk11: Protected login failed.\n");
2075 ret
= GNUTLS_E_PKCS11_ERROR
;
2080 /* Otherwise, PIN entry is necessary for login, so fail if there's
2085 _gnutls_debug_log ("pk11: No pin callback but login required.\n");
2086 ret
= GNUTLS_E_PKCS11_ERROR
;
2092 struct ck_token_info tinfo
;
2093 char pin
[GNUTLS_PKCS11_MAX_PIN_LEN
];
2096 /* If login has been attempted once already, check the token
2097 * status again, the flags might change. */
2100 if (pakchois_get_token_info
2101 (info
->prov
->module
, info
->sid
, &tinfo
) != CKR_OK
)
2104 _gnutls_debug_log ("pk11: GetTokenInfo failed\n");
2105 ret
= GNUTLS_E_PKCS11_ERROR
;
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
;
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
++,
2130 (char *) info
->tinfo
.label
, flags
, pin
, sizeof (pin
));
2134 ret
= GNUTLS_E_PKCS11_PIN_ERROR
;
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
);
2152 || rv
== CKR_USER_ALREADY_LOGGED_IN
) ? 0 : pkcs11_rv_to_err (rv
);
2155 gnutls_free (token_url
);
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;
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);
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)
2197 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
2201 gnutls_malloc (sizeof (gnutls_buffer_st
) * list
->key_ids_size
);
2202 if (list
->key_ids
== NULL
)
2205 return GNUTLS_E_MEMORY_ERROR
;
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);
2217 return pkcs11_rv_to_err (rv
);
2221 while (pakchois_find_objects (pks
, &obj
, 1, &count
) == CKR_OK
&& count
== 1)
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
);
2237 if (current
> list
->key_ids_size
)
2241 pakchois_find_objects_final (pks
);
2243 list
->key_ids_size
= current
- 1;
2248 /* Recover certificate list from tokens */
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
;
2261 ck_object_handle_t obj
;
2262 unsigned long count
;
2264 char certid_tmp
[PKCS11_ID_SIZE
];
2265 char label_tmp
[PKCS11_LABEL_SIZE
];
2267 struct pkey_list plist
; /* private key holder */
2272 if (find_data
->current
<= *find_data
->n_list
)
2275 ret
= GNUTLS_E_SHORT_MEMORY_BUFFER
;
2277 *find_data
->n_list
= find_data
->current
;
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
) <
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
)
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
);
2318 if (plist
.key_ids_size
== 0)
2321 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
2325 cert_data
= gnutls_malloc (MAX_CERT_SIZE
);
2326 if (cert_data
== NULL
)
2329 return GNUTLS_E_MEMORY_ERROR
;
2332 /* Find objects with cert class and X.509 cert type. */
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
;
2343 a
[tot_values
].type
= CKA_CLASS
;
2344 a
[tot_values
].value
= &class;
2345 a
[tot_values
].value_len
= sizeof class;
2348 a
[tot_values
].type
= CKA_CERTIFICATE_TYPE
;
2349 a
[tot_values
].value
= &type
;
2350 a
[tot_values
].value_len
= sizeof type
;
2354 else if (find_data
->flags
== GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED
)
2356 class = CKO_CERTIFICATE
;
2360 a
[tot_values
].type
= CKA_CLASS
;
2361 a
[tot_values
].value
= &class;
2362 a
[tot_values
].value_len
= sizeof class;
2365 a
[tot_values
].type
= CKA_TRUSTED
;
2366 a
[tot_values
].value
= &trusted
;
2367 a
[tot_values
].value_len
= sizeof trusted
;
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;
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;
2389 else if (find_data
->flags
== GNUTLS_PKCS11_OBJ_ATTR_ALL
)
2393 a
[tot_values
].type
= CKA_CLASS
;
2394 a
[tot_values
].value
= &class;
2395 a
[tot_values
].value_len
= sizeof class;
2400 a
[tot_values
].type
= CKA_CERTIFICATE_TYPE
;
2401 a
[tot_values
].value
= &type
;
2402 a
[tot_values
].value_len
= sizeof type
;
2409 ret
= GNUTLS_E_INVALID_REQUEST
;
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
;
2421 rv
= pakchois_find_objects_init (pks
, a
, tot_values
);
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
;
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
;
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
;
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
!=
2492 || memcmp (plist
.key_ids
[i
].data
,
2493 a
[1].value
, a
[1].value_len
) != 0)
2501 if (find_data
->current
< *find_data
->n_list
)
2504 gnutls_pkcs11_obj_init (&find_data
->p_list
[find_data
->current
]);
2511 if (class == CKO_PUBLIC_KEY
)
2514 pkcs11_obj_import_pubkey (pks
, obj
,
2516 [find_data
->current
],
2518 &info
->tinfo
, lib_info
);
2523 pkcs11_obj_import (class,
2525 [find_data
->current
],
2526 &value
, &id
, &label
,
2527 &info
->tinfo
, lib_info
);
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 */
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;
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
,
2583 gnutls_pkcs11_obj_attr_t attrs
,
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)
2600 ret
= pkcs11_url_to_info (url
, &find_data
.info
);
2608 _pkcs11_traverse_tokens (find_objs
, &find_data
,
2609 pkcs11_obj_flags_to_int (flags
));
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
;
2639 ret
= gnutls_pkcs11_obj_init (&pcrt
);
2646 ret
= gnutls_pkcs11_obj_import_url (pcrt
, url
, flags
);
2653 ret
= gnutls_x509_crt_import (crt
, &pcrt
->raw
, GNUTLS_X509_FMT_DER
);
2663 gnutls_pkcs11_obj_deinit (pcrt
);
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
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
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
,
2709 for (i
= 0; i
< cert_max
; i
++)
2711 ret
= gnutls_x509_crt_init (&certs
[i
]);
2718 ret
= gnutls_x509_crt_import_pkcs11 (certs
[i
], objs
[i
]);
2729 for (j
= 0; j
< i
; j
++)
2731 gnutls_x509_crt_deinit (certs
[j
]);
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
;
2744 { /* we don't support multiple calls */
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
) <
2755 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
2760 find_data
->slot_flags
= info
->sinfo
.flags
;
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
;
2780 ret
= pkcs11_url_to_info (url
, &find_data
.info
);
2787 ret
= _pkcs11_traverse_tokens (find_flags
, &find_data
, 0);
2795 if (find_data
.slot_flags
& CKF_HW_SLOT
)
2796 *flags
|= GNUTLS_PKCS11_TOKEN_HW
;
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
)
2821 pakchois_module_t
*module
;
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
);
2836 ret
= pkcs11_find_slot (&module
, &slot
, &info
, &tinfo
);
2843 count
= sizeof (mlist
) / sizeof (mlist
[0]);
2844 rv
= pakchois_get_mechanism_list (module
, slot
, mlist
, &count
);
2848 return pkcs11_rv_to_err (rv
);
2854 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
2857 *mechanism
= mlist
[idx
];
2865 gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t 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
:
2879 case GNUTLS_PKCS11_OBJ_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)
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
;