2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4 * Copyright (C) 2008 Joe Orton <joe@manyfish.co.uk>
5 * Copyright (C) 2013 Nikos Mavrogiannopoulos
7 * Authors: Nikos Mavrogiannopoulos, Stef Walter
9 * Inspired and some parts (pkcs11_login) based on neon PKCS #11 support
10 * by Joe Orton. More ideas came from the pkcs11-helper library by
13 * GnuTLS is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public License
15 * as published by the Free Software Foundation; either version 2.1 of
16 * the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>
27 #include <gnutls_int.h>
28 #include <gnutls/pkcs11.h>
30 #include <gnutls_errors.h>
31 #include <gnutls_datum.h>
32 #include <x509/common.h>
36 #include <pkcs11_int.h>
37 #include <p11-kit/p11-kit.h>
38 #include <p11-kit/pin.h>
43 #define MAX_PROVIDERS 16
45 /* XXX: try to eliminate this */
46 #define MAX_CERT_SIZE 32*1024
49 extern void *_gnutls_pkcs11_mutex;
51 struct gnutls_pkcs11_provider_st {
52 struct ck_function_list *module;
54 unsigned trusted; /* in the sense of p11-kit trusted:
55 * it can be used for verification */
59 struct find_flags_data_st {
60 struct p11_kit_uri *info;
61 unsigned int slot_flags;
65 struct find_url_data_st {
66 gnutls_pkcs11_obj_t crt;
69 struct find_obj_data_st {
70 gnutls_pkcs11_obj_t *p_list;
73 gnutls_pkcs11_obj_attr_t flags;
74 struct p11_kit_uri *info;
77 struct find_token_num {
78 struct p11_kit_uri *info;
79 unsigned int seq; /* which one we are looking for */
80 unsigned int current; /* which one are we now */
83 struct find_pkey_list_st {
84 gnutls_buffer_st *key_ids;
90 gnutls_datum_t issuer_dn;
91 gnutls_datum_t key_id;
92 gnutls_datum_t serial;
95 gnutls_pkcs11_obj_t obj;
96 gnutls_x509_crt_t crt; /* used when compare flag is specified */
101 static struct gnutls_pkcs11_provider_st providers[MAX_PROVIDERS];
102 static unsigned int active_providers = 0;
103 static unsigned int providers_initialized = 0;
105 static pid_t init_pid = -1;
108 gnutls_pkcs11_token_callback_t _gnutls_token_func;
109 void *_gnutls_token_data;
111 int pkcs11_rv_to_err(ck_rv_t rv)
116 case CKR_HOST_MEMORY:
117 return GNUTLS_E_MEMORY_ERROR;
118 case CKR_SLOT_ID_INVALID:
119 return GNUTLS_E_PKCS11_SLOT_ERROR;
120 case CKR_ARGUMENTS_BAD:
121 case CKR_MECHANISM_PARAM_INVALID:
122 return GNUTLS_E_INVALID_REQUEST;
123 case CKR_NEED_TO_CREATE_THREADS:
125 case CKR_FUNCTION_NOT_PARALLEL:
127 case CKR_MUTEX_NOT_LOCKED:
128 return GNUTLS_E_LOCKING_ERROR;
129 case CKR_ATTRIBUTE_READ_ONLY:
130 case CKR_ATTRIBUTE_SENSITIVE:
131 case CKR_ATTRIBUTE_TYPE_INVALID:
132 case CKR_ATTRIBUTE_VALUE_INVALID:
133 return GNUTLS_E_PKCS11_ATTRIBUTE_ERROR;
134 case CKR_DEVICE_ERROR:
135 case CKR_DEVICE_MEMORY:
136 case CKR_DEVICE_REMOVED:
137 return GNUTLS_E_PKCS11_DEVICE_ERROR;
138 case CKR_DATA_INVALID:
139 case CKR_DATA_LEN_RANGE:
140 case CKR_ENCRYPTED_DATA_INVALID:
141 case CKR_ENCRYPTED_DATA_LEN_RANGE:
142 case CKR_OBJECT_HANDLE_INVALID:
143 return GNUTLS_E_PKCS11_DATA_ERROR;
144 case CKR_FUNCTION_NOT_SUPPORTED:
145 case CKR_MECHANISM_INVALID:
146 return GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR;
147 case CKR_KEY_HANDLE_INVALID:
148 case CKR_KEY_SIZE_RANGE:
149 case CKR_KEY_TYPE_INCONSISTENT:
150 case CKR_KEY_NOT_NEEDED:
151 case CKR_KEY_CHANGED:
153 case CKR_KEY_INDIGESTIBLE:
154 case CKR_KEY_FUNCTION_NOT_PERMITTED:
155 case CKR_KEY_NOT_WRAPPABLE:
156 case CKR_KEY_UNEXTRACTABLE:
157 return GNUTLS_E_PKCS11_KEY_ERROR;
158 case CKR_PIN_INCORRECT:
159 case CKR_PIN_INVALID:
160 case CKR_PIN_LEN_RANGE:
161 return GNUTLS_E_PKCS11_PIN_ERROR;
162 case CKR_PIN_EXPIRED:
163 return GNUTLS_E_PKCS11_PIN_EXPIRED;
165 return GNUTLS_E_PKCS11_PIN_LOCKED;
166 case CKR_SESSION_CLOSED:
167 case CKR_SESSION_COUNT:
168 case CKR_SESSION_HANDLE_INVALID:
169 case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
170 case CKR_SESSION_READ_ONLY:
171 case CKR_SESSION_EXISTS:
172 case CKR_SESSION_READ_ONLY_EXISTS:
173 case CKR_SESSION_READ_WRITE_SO_EXISTS:
174 return GNUTLS_E_PKCS11_SESSION_ERROR;
175 case CKR_SIGNATURE_INVALID:
176 case CKR_SIGNATURE_LEN_RANGE:
177 return GNUTLS_E_PKCS11_SIGNATURE_ERROR;
178 case CKR_TOKEN_NOT_PRESENT:
179 case CKR_TOKEN_NOT_RECOGNIZED:
180 case CKR_TOKEN_WRITE_PROTECTED:
181 return GNUTLS_E_PKCS11_TOKEN_ERROR;
182 case CKR_USER_ALREADY_LOGGED_IN:
183 case CKR_USER_NOT_LOGGED_IN:
184 case CKR_USER_PIN_NOT_INITIALIZED:
185 case CKR_USER_TYPE_INVALID:
186 case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
187 case CKR_USER_TOO_MANY_TYPES:
188 return GNUTLS_E_PKCS11_USER_ERROR;
189 case CKR_BUFFER_TOO_SMALL:
190 return GNUTLS_E_SHORT_MEMORY_BUFFER;
192 return GNUTLS_E_PKCS11_ERROR;
197 static int scan_slots(struct gnutls_pkcs11_provider_st *p,
198 ck_slot_id_t * slots, unsigned long *nslots)
202 rv = pkcs11_get_slot_list(p->module, 1, slots, nslots);
205 return pkcs11_rv_to_err(rv);
211 pkcs11_add_module(const char* name, struct ck_function_list *module, const char *params)
216 if (active_providers >= MAX_PROVIDERS) {
218 return GNUTLS_E_CONSTRAINT_ERROR;
221 memset(&info, 0, sizeof(info));
222 pkcs11_get_module_info(module, &info);
224 /* initially check if this module is a duplicate */
225 for (i = 0; i < active_providers; i++) {
226 /* already loaded, skip the rest */
227 if (module == providers[i].module) {
228 _gnutls_debug_log("p11: module %s is already loaded.\n", name);
229 return GNUTLS_E_INT_RET_0;
234 providers[active_providers - 1].module = module;
235 providers[active_providers - 1].active = 1;
237 if (p11_kit_module_get_flags(module) & P11_KIT_MODULE_TRUSTED ||
238 (params != NULL && strstr(params, "trusted") != 0))
239 providers[active_providers - 1].trusted = 1;
241 memcpy(&providers[active_providers - 1].info, &info, sizeof(info));
246 int _gnutls_pkcs11_check_init(void)
250 ret = gnutls_mutex_lock(&_gnutls_pkcs11_mutex);
252 return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
259 if (providers_initialized != 0) {
262 if (init_pid != getpid()) {
263 /* if we are initialized but a fork is detected */
264 ret = gnutls_pkcs11_reinit();
268 gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
276 providers_initialized = 1;
277 _gnutls_debug_log("Initializing PKCS #11 modules\n");
278 ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO, NULL);
280 gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
283 return gnutls_assert_val(ret);
290 * gnutls_pkcs11_add_provider:
291 * @name: The filename of the module
292 * @params: should be NULL
294 * This function will load and add a PKCS 11 module to the module
295 * list used in gnutls. After this function is called the module will
296 * be used for PKCS 11 operations.
298 * When loading a module to be used for certificate verification,
299 * use the string 'trusted' as @params.
301 * Note that this function is not thread safe.
303 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
304 * negative error value.
308 int gnutls_pkcs11_add_provider(const char *name, const char *params)
310 struct ck_function_list *module;
313 module = p11_kit_module_load(name, P11_KIT_MODULE_CRITICAL);
314 if (module == NULL) {
316 _gnutls_debug_log("p11: Cannot load provider %s\n", name);
317 return GNUTLS_E_PKCS11_LOAD_ERROR;
321 ("p11: Initializing module: %s\n", name);
323 ret = p11_kit_module_initialize(module);
325 p11_kit_module_release(module);
327 return pkcs11_rv_to_err(ret);
330 ret = pkcs11_add_module(name, module, params);
332 if (ret == GNUTLS_E_INT_RET_0)
334 p11_kit_module_finalize(module);
335 p11_kit_module_release(module);
344 * gnutls_pkcs11_obj_get_info:
345 * @crt: should contain a #gnutls_pkcs11_obj_t structure
346 * @itype: Denotes the type of information requested
347 * @output: where output will be stored
348 * @output_size: contains the maximum size of the output and will be overwritten with actual
350 * This function will return information about the PKCS11 certificate
351 * such as the label, id as well as token information where the key is
352 * stored. When output is text it returns null terminated string
353 * although @output_size contains the size of the actual data only.
355 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
360 gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t crt,
361 gnutls_pkcs11_obj_info_t itype,
362 void *output, size_t * output_size)
364 return pkcs11_get_info(crt->info, itype, output, output_size);
368 pkcs11_get_info(struct p11_kit_uri *info,
369 gnutls_pkcs11_obj_info_t itype, void *output,
370 size_t * output_size)
372 struct ck_attribute *attr = NULL;
373 struct ck_version *version = NULL;
374 const uint8_t *str = NULL;
379 const char *data = NULL;
383 * Either attr, str or version is valid by the time switch
388 case GNUTLS_PKCS11_OBJ_ID:
389 attr = p11_kit_uri_get_attribute(info, CKA_ID);
391 case GNUTLS_PKCS11_OBJ_ID_HEX:
392 attr = p11_kit_uri_get_attribute(info, CKA_ID);
396 case GNUTLS_PKCS11_OBJ_LABEL:
397 attr = p11_kit_uri_get_attribute(info, CKA_LABEL);
400 case GNUTLS_PKCS11_OBJ_TOKEN_LABEL:
401 str = p11_kit_uri_get_token_info(info)->label;
404 case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL:
405 str = p11_kit_uri_get_token_info(info)->serial_number;
408 case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER:
409 str = p11_kit_uri_get_token_info(info)->manufacturer_id;
412 case GNUTLS_PKCS11_OBJ_TOKEN_MODEL:
413 str = p11_kit_uri_get_token_info(info)->model;
416 case GNUTLS_PKCS11_OBJ_LIBRARY_DESCRIPTION:
418 p11_kit_uri_get_module_info(info)->library_description;
421 case GNUTLS_PKCS11_OBJ_LIBRARY_VERSION:
423 &p11_kit_uri_get_module_info(info)->library_version;
425 case GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER:
426 str = p11_kit_uri_get_module_info(info)->manufacturer_id;
431 return GNUTLS_E_INVALID_REQUEST;
436 length = attr->value_len;
437 } else if (str != NULL) {
439 length = p11_kit_space_strlen(str, str_max);
441 } else if (version != NULL) {
444 snprintf(buf, sizeof(buf), "%d.%d",
445 (int) version->major, (int) version->minor);
450 ((uint8_t *) output)[0] = 0;
455 /* terminate is assumed with hexify */
456 if (*output_size < length * 3) {
457 *output_size = length * 3;
458 return GNUTLS_E_SHORT_MEMORY_BUFFER;
460 if (output && length > 0)
461 _gnutls_bin2hex(data, length, output, *output_size,
463 *output_size = length * 3;
466 if (*output_size < length + terminate) {
467 *output_size = length + terminate;
468 return GNUTLS_E_SHORT_MEMORY_BUFFER;
471 memcpy(output, data, length);
473 ((unsigned char *) output)[length] = '\0';
475 *output_size = length + terminate;
483 /* tries to load modules from /etc/gnutls/pkcs11.conf if it exists
485 static void compat_load(const char *configfile)
492 if (configfile == NULL)
493 configfile = "/etc/gnutls/pkcs11.conf";
495 fp = fopen(configfile, "r");
501 _gnutls_debug_log("Loading PKCS #11 libraries from %s\n",
503 while (fgets(line, sizeof(line), fp) != NULL) {
504 if (strncmp(line, "load", sizeof("load") - 1) == 0) {
506 p = strchr(line, '=');
511 p = strchr(line, '\n');
515 ret = gnutls_pkcs11_add_provider(library, NULL);
519 ("Cannot load provider: %s\n",
530 static int auto_load(void)
532 struct ck_function_list **modules;
536 modules = p11_kit_modules_load_and_initialize(0);
537 if (modules == NULL) {
540 ("Cannot initialize registered modules: %s\n",
542 return GNUTLS_E_PKCS11_LOAD_ERROR;
545 for (i = 0; modules[i] != NULL; i++) {
546 name = p11_kit_module_get_name(modules[i]);
548 ("p11: Initializing module: %s\n", name);
550 ret = pkcs11_add_module(name, modules[i], NULL);
554 ("Cannot load PKCS #11 module: %s\n", name);
565 * gnutls_pkcs11_init:
566 * @flags: An ORed sequence of %GNUTLS_PKCS11_FLAG_*
567 * @deprecated_config_file: either NULL or the location of a deprecated
570 * This function will initialize the PKCS 11 subsystem in gnutls. It will
571 * read configuration files if %GNUTLS_PKCS11_FLAG_AUTO is used or allow
572 * you to independently load PKCS 11 modules using gnutls_pkcs11_add_provider()
573 * if %GNUTLS_PKCS11_FLAG_MANUAL is specified.
575 * Normally you don't need to call this function since it is being called
576 * when the first PKCS 11 operation is requested using the %GNUTLS_PKCS11_FLAG_AUTO
577 * flag. If another flags are required then it must be called independently
578 * prior to any PKCS 11 operation.
580 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
581 * negative error value.
586 gnutls_pkcs11_init(unsigned int flags, const char *deprecated_config_file)
596 p11_kit_pin_register_callback(P11_KIT_PIN_FALLBACK,
597 p11_kit_pin_file_callback, NULL,
600 if (flags == GNUTLS_PKCS11_FLAG_MANUAL)
602 else if (flags & GNUTLS_PKCS11_FLAG_AUTO) {
603 if (deprecated_config_file == NULL)
606 compat_load(deprecated_config_file);
615 * gnutls_pkcs11_reinit:
617 * This function will reinitialize the PKCS 11 subsystem in gnutls.
618 * This is required by PKCS 11 when an application uses fork(). The
619 * reinitialization function must be called on the child.
621 * Note that since GnuTLS 3.3.0, the reinitialization of the PKCS #11
622 * subsystem occurs automatically after fork.
624 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
625 * negative error value.
629 int gnutls_pkcs11_reinit(void)
634 /* make sure that we don't call more than once after a fork */
635 if (init_pid == getpid())
638 for (i = 0; i < active_providers; i++) {
639 if (providers[i].module != NULL) {
640 rv = p11_kit_module_initialize(providers
643 providers[i].active = 1;
645 providers[i].active = 0;
647 ("Cannot re-initialize registered module '%s': %s\n",
648 providers[i].info.library_description,
649 p11_kit_strerror(rv));
661 * gnutls_pkcs11_deinit:
663 * This function will deinitialize the PKCS 11 subsystem in gnutls.
664 * This function is only needed if you need to deinitialize the
665 * subsystem without calling gnutls_global_deinit().
669 void gnutls_pkcs11_deinit(void)
680 for (i = 0; i < active_providers; i++) {
681 if (providers[i].active)
682 p11_kit_module_finalize(providers[i].module);
683 p11_kit_module_release(providers[i].module);
685 active_providers = 0;
686 providers_initialized = 0;
688 gnutls_pkcs11_set_pin_function(NULL, NULL);
689 gnutls_pkcs11_set_token_function(NULL, NULL);
690 p11_kit_pin_unregister_callback(P11_KIT_PIN_FALLBACK,
691 p11_kit_pin_file_callback, NULL);
695 * gnutls_pkcs11_set_token_function:
696 * @fn: The token callback
697 * @userdata: data to be supplied to callback
699 * This function will set a callback function to be used when a token
700 * needs to be inserted to continue PKCS 11 operations.
705 gnutls_pkcs11_set_token_function(gnutls_pkcs11_token_callback_t fn,
708 _gnutls_token_func = fn;
709 _gnutls_token_data = userdata;
712 int pkcs11_url_to_info(const char *url, struct p11_kit_uri **info)
718 *info = p11_kit_uri_new();
721 return GNUTLS_E_MEMORY_ERROR;
726 ret = p11_kit_uri_parse(url, P11_KIT_URI_FOR_ANY, *info);
729 p11_kit_uri_free(*info);
733 return ret == P11_KIT_URI_NO_MEMORY ?
734 GNUTLS_E_MEMORY_ERROR : GNUTLS_E_PARSING_ERROR;
741 pkcs11_info_to_url(struct p11_kit_uri *info,
742 gnutls_pkcs11_url_type_t detailed, char **url)
744 p11_kit_uri_type_t type = 0;
748 case GNUTLS_PKCS11_URL_GENERIC:
749 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN;
751 case GNUTLS_PKCS11_URL_LIB:
752 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE;
754 case GNUTLS_PKCS11_URL_LIB_VERSION:
756 P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE |
757 P11_KIT_URI_FOR_MODULE_WITH_VERSION;
761 ret = p11_kit_uri_format(info, type, url);
764 return ret == P11_KIT_URI_NO_MEMORY ?
765 GNUTLS_E_MEMORY_ERROR : GNUTLS_E_INTERNAL_ERROR;
772 * gnutls_pkcs11_obj_init:
773 * @obj: The structure to be initialized
775 * This function will initialize a pkcs11 certificate structure.
777 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
778 * negative error value.
782 int gnutls_pkcs11_obj_init(gnutls_pkcs11_obj_t * obj)
784 *obj = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_obj_st));
787 return GNUTLS_E_MEMORY_ERROR;
790 (*obj)->info = p11_kit_uri_new();
791 if ((*obj)->info == NULL) {
795 return GNUTLS_E_MEMORY_ERROR;
802 * gnutls_pkcs11_obj_set_pin_function:
803 * @obj: The object structure
805 * @userdata: data associated with the callback
807 * This function will set a callback function to be used when
808 * required to access the object. This function overrides the global
809 * set using gnutls_pkcs11_set_pin_function().
814 gnutls_pkcs11_obj_set_pin_function(gnutls_pkcs11_obj_t obj,
815 gnutls_pin_callback_t fn,
819 obj->pin.data = userdata;
823 * gnutls_pkcs11_obj_deinit:
824 * @obj: The structure to be initialized
826 * This function will deinitialize a certificate structure.
830 void gnutls_pkcs11_obj_deinit(gnutls_pkcs11_obj_t obj)
832 _gnutls_free_datum(&obj->raw);
833 p11_kit_uri_free(obj->info);
838 * gnutls_pkcs11_obj_export:
839 * @obj: Holds the object
840 * @output_data: will contain the object data
841 * @output_data_size: holds the size of output_data (and will be
842 * replaced by the actual size of parameters)
844 * This function will export the PKCS11 object data. It is normal for
845 * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
848 * If the buffer provided is not long enough to hold the output, then
849 * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
852 * Returns: In case of failure a negative error code will be
853 * returned, and %GNUTLS_E_SUCCESS (0) on success.
858 gnutls_pkcs11_obj_export(gnutls_pkcs11_obj_t obj,
859 void *output_data, size_t * output_data_size)
861 if (obj == NULL || obj->raw.data == NULL) {
863 return GNUTLS_E_INVALID_REQUEST;
866 if (output_data == NULL || *output_data_size < obj->raw.size) {
867 *output_data_size = obj->raw.size;
869 return GNUTLS_E_SHORT_MEMORY_BUFFER;
871 *output_data_size = obj->raw.size;
873 memcpy(output_data, obj->raw.data, obj->raw.size);
878 * gnutls_pkcs11_obj_export2:
879 * @obj: Holds the object
880 * @out: will contain the object data
882 * This function will export the PKCS11 object data. It is normal for
883 * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
886 * The output buffer is allocated using gnutls_malloc().
888 * Returns: In case of failure a negative error code will be
889 * returned, and %GNUTLS_E_SUCCESS (0) on success.
894 gnutls_pkcs11_obj_export2(gnutls_pkcs11_obj_t obj, gnutls_datum_t * out)
896 if (obj == NULL || obj->raw.data == NULL) {
898 return GNUTLS_E_INVALID_REQUEST;
901 return _gnutls_set_datum(out, obj->raw.data, obj->raw.size);
905 * gnutls_pkcs11_obj_export3:
906 * @obj: Holds the object
907 * @out: will contain the object data
908 * @fmt: The format of the exported data
910 * This function will export the PKCS11 object data. It is normal for
911 * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
914 * The output buffer is allocated using gnutls_malloc().
916 * Returns: In case of failure a negative error code will be
917 * returned, and %GNUTLS_E_SUCCESS (0) on success.
922 gnutls_pkcs11_obj_export3(gnutls_pkcs11_obj_t obj,
923 gnutls_x509_crt_fmt_t fmt, gnutls_datum_t * out)
927 if (obj == NULL || obj->raw.data == NULL) {
929 return GNUTLS_E_INVALID_REQUEST;
932 if (fmt == GNUTLS_X509_FMT_DER)
933 return _gnutls_set_datum(out, obj->raw.data,
935 else if (fmt == GNUTLS_X509_FMT_PEM) {
937 case GNUTLS_PKCS11_OBJ_X509_CRT:
939 gnutls_pem_base64_encode_alloc(PEM_X509_CERT2,
941 case GNUTLS_PKCS11_OBJ_PUBKEY:{
942 gnutls_pubkey_t pubkey;
944 ret = gnutls_pubkey_init(&pubkey);
946 return gnutls_assert_val(ret);
949 gnutls_pubkey_import_pkcs11(pubkey,
957 gnutls_pubkey_export2(pubkey, fmt,
961 gnutls_pubkey_deinit(pubkey);
965 return gnutls_pem_base64_encode_alloc("DATA",
970 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
975 pkcs11_find_slot(struct ck_function_list **module, ck_slot_id_t * slot,
976 struct p11_kit_uri *info, struct token_info *_tinfo)
980 unsigned long nslots;
981 ck_slot_id_t slots[MAX_SLOTS];
983 for (x = 0; x < active_providers; x++) {
984 if (providers[x].active == 0)
987 nslots = sizeof(slots) / sizeof(slots[0]);
988 ret = scan_slots(&providers[x], slots, &nslots);
994 for (z = 0; z < nslots; z++) {
995 struct token_info tinfo;
997 if (pkcs11_get_token_info
998 (providers[x].module, slots[z],
999 &tinfo.tinfo) != CKR_OK) {
1002 tinfo.sid = slots[z];
1003 tinfo.prov = &providers[x];
1005 if (pkcs11_get_slot_info
1006 (providers[x].module, slots[z],
1007 &tinfo.sinfo) != CKR_OK) {
1011 if (!p11_kit_uri_match_token_info
1012 (info, &tinfo.tinfo)
1013 || !p11_kit_uri_match_module_info(info,
1020 *module = providers[x].module;
1024 memcpy(_tinfo, &tinfo, sizeof(tinfo));
1031 return GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE;
1035 pkcs11_open_session(struct pkcs11_session_info *sinfo,
1036 struct pin_info_st *pin_info,
1037 struct p11_kit_uri *info, unsigned int flags)
1041 ck_session_handle_t pks = 0;
1042 struct ck_function_list *module;
1044 struct token_info tinfo;
1046 ret = pkcs11_find_slot(&module, &slot, info, &tinfo);
1052 rv = (module)->C_OpenSession(slot, ((flags & SESSION_WRITE)
1053 ? CKF_RW_SESSION : 0) |
1054 CKF_SERIAL_SESSION, NULL, NULL, &pks);
1057 return pkcs11_rv_to_err(rv);
1062 sinfo->module = module;
1064 memcpy(&sinfo->tinfo, &tinfo.tinfo, sizeof(sinfo->tinfo));
1066 if (flags & SESSION_LOGIN) {
1068 pkcs11_login(sinfo, pin_info, &tinfo, info,
1069 (flags & SESSION_SO) ? 1 : 0);
1072 pkcs11_close_session(sinfo);
1082 _pkcs11_traverse_tokens(find_func_t find_func, void *input,
1083 struct p11_kit_uri *info,
1084 struct pin_info_st *pin_info, unsigned int flags)
1087 unsigned int found = 0, x, z;
1089 ck_session_handle_t pks = 0;
1090 struct pkcs11_session_info sinfo;
1091 struct ck_function_list *module = NULL;
1092 unsigned long nslots;
1093 ck_slot_id_t slots[MAX_SLOTS];
1095 for (x = 0; x < active_providers; x++) {
1096 if (providers[x].active == 0)
1099 if (flags & SESSION_TRUSTED && providers[x].trusted == 0)
1102 nslots = sizeof(slots) / sizeof(slots[0]);
1103 ret = scan_slots(&providers[x], slots, &nslots);
1109 module = providers[x].module;
1110 for (z = 0; z < nslots; z++) {
1111 struct token_info tinfo;
1113 if (pkcs11_get_token_info(module, slots[z],
1114 &tinfo.tinfo) != CKR_OK) {
1117 tinfo.sid = slots[z];
1118 tinfo.prov = &providers[x];
1120 if (pkcs11_get_slot_info(module, slots[z],
1121 &tinfo.sinfo) != CKR_OK) {
1126 if (!p11_kit_uri_match_token_info
1127 (info, &tinfo.tinfo)
1128 || !p11_kit_uri_match_module_info(info,
1135 rv = (module)->C_OpenSession(slots[z],
1136 ((flags & SESSION_WRITE) ? CKF_RW_SESSION : 0)
1137 | CKF_SERIAL_SESSION,
1143 sinfo.module = module;
1146 if (flags & SESSION_LOGIN) {
1148 pkcs11_login(&sinfo, pin_info, &tinfo,
1149 info, (flags & SESSION_SO) ? 1 : 0);
1157 find_func(&sinfo, &tinfo, &providers[x].info, input);
1163 pkcs11_close_session(&sinfo);
1174 sinfo.module = module;
1176 ret = find_func(&sinfo, NULL, NULL, input);
1180 (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1185 if (pks != 0 && module != NULL) {
1186 pkcs11_close_session(&sinfo);
1192 /* imports an object from a token to a pkcs11_obj_t structure.
1195 pkcs11_obj_import(ck_object_class_t class, gnutls_pkcs11_obj_t obj,
1196 const gnutls_datum_t * data,
1197 const gnutls_datum_t * id,
1198 const gnutls_datum_t * label,
1199 struct ck_token_info *tinfo, struct ck_info *lib_info)
1201 struct ck_attribute attr;
1205 case CKO_CERTIFICATE:
1206 obj->type = GNUTLS_PKCS11_OBJ_X509_CRT;
1208 case CKO_PUBLIC_KEY:
1209 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1211 case CKO_PRIVATE_KEY:
1212 obj->type = GNUTLS_PKCS11_OBJ_PRIVKEY;
1214 case CKO_SECRET_KEY:
1215 obj->type = GNUTLS_PKCS11_OBJ_SECRET_KEY;
1218 obj->type = GNUTLS_PKCS11_OBJ_DATA;
1221 obj->type = GNUTLS_PKCS11_OBJ_UNKNOWN;
1224 attr.type = CKA_CLASS;
1225 attr.value = &class;
1226 attr.value_len = sizeof(class);
1227 ret = p11_kit_uri_set_attribute(obj->info, &attr);
1230 return GNUTLS_E_MEMORY_ERROR;
1233 if (data && data->data) {
1234 ret = _gnutls_set_datum(&obj->raw, data->data, data->size);
1241 /* copy the token and library info into the uri */
1242 memcpy(p11_kit_uri_get_token_info(obj->info), tinfo,
1243 sizeof(struct ck_token_info));
1244 memcpy(p11_kit_uri_get_module_info(obj->info), lib_info,
1245 sizeof(struct ck_info));
1247 if (label && label->data) {
1248 attr.type = CKA_LABEL;
1249 attr.value = label->data;
1250 attr.value_len = label->size;
1251 ret = p11_kit_uri_set_attribute(obj->info, &attr);
1254 return GNUTLS_E_MEMORY_ERROR;
1258 if (id && id->data) {
1260 attr.value = id->data;
1261 attr.value_len = id->size;
1262 ret = p11_kit_uri_set_attribute(obj->info, &attr);
1265 return GNUTLS_E_MEMORY_ERROR;
1272 #define MAX_PK_PARAM_SIZE 2048
1274 int pkcs11_read_pubkey(struct ck_function_list *module,
1275 ck_session_handle_t pks, ck_object_handle_t obj,
1276 ck_key_type_t key_type, gnutls_datum_t * pubkey)
1278 struct ck_attribute a[4];
1280 uint8_t *tmp2 = NULL;
1281 size_t tmp1_size, tmp2_size;
1284 tmp1_size = tmp2_size = MAX_PK_PARAM_SIZE;
1285 tmp1 = gnutls_malloc(tmp1_size);
1287 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1289 tmp2 = gnutls_malloc(tmp2_size);
1291 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1297 a[0].type = CKA_MODULUS;
1299 a[0].value_len = tmp1_size;
1300 a[1].type = CKA_PUBLIC_EXPONENT;
1302 a[1].value_len = tmp2_size;
1304 if (pkcs11_get_attribute_value(module, pks, obj, a, 2) ==
1307 pubkey[0].data = a[0].value;
1308 pubkey[0].size = a[0].value_len;
1310 pubkey[1].data = a[1].value;
1311 pubkey[1].size = a[1].value_len;
1314 ret = GNUTLS_E_PKCS11_ERROR;
1319 a[0].type = CKA_PRIME;
1321 a[0].value_len = tmp1_size;
1322 a[1].type = CKA_SUBPRIME;
1324 a[1].value_len = tmp2_size;
1326 if (pkcs11_get_attribute_value(module, pks, obj, a, 2) ==
1329 _gnutls_set_datum(&pubkey[0], a[0].value,
1334 _gnutls_set_datum(&pubkey
1340 _gnutls_free_datum(&pubkey[1]);
1341 _gnutls_free_datum(&pubkey[0]);
1342 ret = GNUTLS_E_MEMORY_ERROR;
1347 ret = GNUTLS_E_PKCS11_ERROR;
1351 a[0].type = CKA_BASE;
1353 a[0].value_len = tmp1_size;
1354 a[1].type = CKA_VALUE;
1356 a[1].value_len = tmp2_size;
1358 if (pkcs11_get_attribute_value(module, pks, obj, a, 2) ==
1360 pubkey[2].data = a[0].value;
1361 pubkey[2].size = a[0].value_len;
1363 pubkey[3].data = a[1].value;
1364 pubkey[3].size = a[1].value_len;
1368 ret = GNUTLS_E_PKCS11_ERROR;
1373 a[0].type = CKA_EC_PARAMS;
1375 a[0].value_len = tmp1_size;
1376 a[1].type = CKA_EC_POINT;
1378 a[1].value_len = tmp2_size;
1380 if (pkcs11_get_attribute_value(module, pks, obj, a, 2) ==
1383 pubkey[0].data = a[0].value;
1384 pubkey[0].size = a[0].value_len;
1386 pubkey[1].data = a[1].value;
1387 pubkey[1].size = a[1].value_len;
1390 ret = GNUTLS_E_PKCS11_ERROR;
1396 ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1410 pkcs11_obj_import_pubkey(struct ck_function_list *module,
1411 ck_session_handle_t pks,
1412 ck_object_handle_t obj,
1413 gnutls_pkcs11_obj_t crt,
1414 const gnutls_datum_t * id,
1415 const gnutls_datum_t * label,
1416 struct ck_token_info *tinfo,
1417 struct ck_info *lib_info)
1419 struct ck_attribute a[4];
1420 ck_key_type_t key_type;
1424 a[0].type = CKA_KEY_TYPE;
1425 a[0].value = &key_type;
1426 a[0].value_len = sizeof(key_type);
1428 if (pkcs11_get_attribute_value(module, pks, obj, a, 1) == CKR_OK) {
1429 crt->pk_algorithm = mech_to_pk(key_type);
1432 pkcs11_read_pubkey(module, pks, obj, key_type,
1435 return gnutls_assert_val(ret);
1438 /* read key usage flags */
1439 a[0].type = CKA_ENCRYPT;
1441 a[0].value_len = sizeof(tval);
1443 if (pkcs11_get_attribute_value(module, pks, obj, a, 1) == CKR_OK) {
1445 crt->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
1449 a[0].type = CKA_VERIFY;
1451 a[0].value_len = sizeof(tval);
1453 if (pkcs11_get_attribute_value(module, pks, obj, a, 1) == CKR_OK) {
1455 crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1456 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1457 | GNUTLS_KEY_NON_REPUDIATION;
1461 a[0].type = CKA_VERIFY_RECOVER;
1463 a[0].value_len = sizeof(tval);
1465 if (pkcs11_get_attribute_value(module, pks, obj, a, 1) == CKR_OK) {
1467 crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1468 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1469 | GNUTLS_KEY_NON_REPUDIATION;
1473 a[0].type = CKA_DERIVE;
1475 a[0].value_len = sizeof(tval);
1477 if (pkcs11_get_attribute_value(module, pks, obj, a, 1) == CKR_OK) {
1479 crt->key_usage |= GNUTLS_KEY_KEY_AGREEMENT;
1483 a[0].type = CKA_WRAP;
1485 a[0].value_len = sizeof(tval);
1487 if (pkcs11_get_attribute_value(module, pks, obj, a, 1) == CKR_OK) {
1489 crt->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
1493 return pkcs11_obj_import(CKO_PUBLIC_KEY, crt, NULL, id, label,
1498 find_obj_url(struct pkcs11_session_info *sinfo,
1499 struct token_info *info, struct ck_info *lib_info,
1502 struct find_url_data_st *find_data = input;
1503 struct ck_attribute a[4];
1504 struct ck_attribute *attr;
1505 ck_object_class_t class = -1;
1506 ck_certificate_type_t type = (ck_certificate_type_t) - 1;
1508 ck_object_handle_t obj;
1509 unsigned long count, a_vals;
1511 uint8_t *cert_data = NULL;
1512 char label_tmp[PKCS11_LABEL_SIZE];
1513 char id_tmp[PKCS11_ID_SIZE];
1515 if (info == NULL) { /* we don't support multiple calls */
1517 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1520 /* do not bother reading the token if basic fields do not match
1522 if (!p11_kit_uri_match_token_info
1523 (find_data->crt->info, &info->tinfo)
1524 || !p11_kit_uri_match_module_info(find_data->crt->info,
1527 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1531 attr = p11_kit_uri_get_attribute(find_data->crt->info, CKA_ID);
1533 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1537 attr = p11_kit_uri_get_attribute(find_data->crt->info, CKA_LABEL);
1539 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1545 return GNUTLS_E_INVALID_REQUEST;
1548 /* search the token for the id */
1550 cert_data = gnutls_malloc(MAX_CERT_SIZE);
1551 if (cert_data == NULL) {
1553 return GNUTLS_E_MEMORY_ERROR;
1556 /* Find objects with given class and type */
1557 attr = p11_kit_uri_get_attribute(find_data->crt->info, CKA_CLASS);
1560 && attr->value_len == sizeof(ck_object_class_t))
1561 class = *((ck_object_class_t *) attr->value);
1562 if (class == CKO_CERTIFICATE)
1564 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1568 if (type != (ck_certificate_type_t) - 1) {
1569 a[a_vals].type = CKA_CERTIFICATE_TYPE;
1570 a[a_vals].value = &type;
1571 a[a_vals].value_len = sizeof type;
1575 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
1579 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
1580 ret = pkcs11_rv_to_err(rv);
1584 while (pkcs11_find_objects
1585 (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK
1587 a[0].type = CKA_VALUE;
1588 a[0].value = cert_data;
1589 a[0].value_len = MAX_CERT_SIZE;
1590 a[1].type = CKA_LABEL;
1591 a[1].value = label_tmp;
1592 a[1].value_len = sizeof(label_tmp);
1594 a[2].value = id_tmp;
1595 a[2].value_len = sizeof(id_tmp);
1597 if (pkcs11_get_attribute_value
1598 (sinfo->module, sinfo->pks, obj, a, 3) == CKR_OK) {
1599 gnutls_datum_t id = { a[2].value, a[2].value_len };
1600 gnutls_datum_t data =
1601 { a[0].value, a[0].value_len };
1602 gnutls_datum_t label =
1603 { a[1].value, a[1].value_len };
1605 if (class == CKO_PUBLIC_KEY) {
1607 pkcs11_obj_import_pubkey(sinfo->module,
1616 pkcs11_obj_import(class,
1631 ("p11: Skipped cert, missing attrs.\n");
1637 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1643 gnutls_free(cert_data);
1644 pkcs11_find_objects_final(sinfo);
1649 unsigned int pkcs11_obj_flags_to_int(unsigned int flags)
1651 unsigned int ret_flags = 0;
1653 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN)
1654 ret_flags |= SESSION_LOGIN;
1655 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO)
1656 ret_flags |= SESSION_LOGIN | SESSION_SO;
1657 if (flags & GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE)
1658 ret_flags |= SESSION_TRUSTED;
1664 * gnutls_pkcs11_obj_import_url:
1665 * @obj: The structure to store the object
1666 * @url: a PKCS 11 url identifying the key
1667 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1669 * This function will "import" a PKCS 11 URL identifying an object (e.g. certificate)
1670 * to the #gnutls_pkcs11_obj_t structure. This does not involve any
1671 * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is
1672 * format agnostic. Only data are transferred.
1674 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1675 * negative error value.
1680 gnutls_pkcs11_obj_import_url(gnutls_pkcs11_obj_t obj, const char *url,
1684 struct find_url_data_st find_data;
1688 /* fill in the find data structure */
1689 find_data.crt = obj;
1691 ret = pkcs11_url_to_info(url, &obj->info);
1698 _pkcs11_traverse_tokens(find_obj_url, &find_data, obj->info,
1700 pkcs11_obj_flags_to_int(flags));
1711 find_token_num(struct pkcs11_session_info *sinfo,
1712 struct token_info *tinfo,
1713 struct ck_info *lib_info, void *input)
1715 struct find_token_num *find_data = input;
1717 if (tinfo == NULL) { /* we don't support multiple calls */
1719 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1722 if (find_data->current == find_data->seq) {
1723 memcpy(p11_kit_uri_get_token_info(find_data->info),
1724 &tinfo->tinfo, sizeof(struct ck_token_info));
1725 memcpy(p11_kit_uri_get_module_info(find_data->info),
1726 lib_info, sizeof(struct ck_info));
1730 find_data->current++;
1731 /* search the token for the id */
1734 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* non zero is enough */
1738 * gnutls_pkcs11_token_get_url:
1739 * @seq: sequence number starting from 0
1740 * @detailed: non zero if a detailed URL is required
1741 * @url: will contain an allocated url
1743 * This function will return the URL for each token available
1744 * in system. The url has to be released using gnutls_free()
1746 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
1747 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if the sequence number
1748 * exceeds the available tokens, otherwise a negative error value.
1753 gnutls_pkcs11_token_get_url(unsigned int seq,
1754 gnutls_pkcs11_url_type_t detailed, char **url)
1757 struct find_token_num tn;
1761 memset(&tn, 0, sizeof(tn));
1763 tn.info = p11_kit_uri_new();
1765 ret = _pkcs11_traverse_tokens(find_token_num, &tn, NULL, NULL, 0);
1767 p11_kit_uri_free(tn.info);
1772 ret = pkcs11_info_to_url(tn.info, detailed, url);
1773 p11_kit_uri_free(tn.info);
1785 * gnutls_pkcs11_token_get_info:
1786 * @url: should contain a PKCS 11 URL
1787 * @ttype: Denotes the type of information requested
1788 * @output: where output will be stored
1789 * @output_size: contains the maximum size of the output and will be overwritten with actual
1791 * This function will return information about the PKCS 11 token such
1792 * as the label, id, etc.
1794 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code
1800 gnutls_pkcs11_token_get_info(const char *url,
1801 gnutls_pkcs11_token_info_t ttype,
1802 void *output, size_t * output_size)
1804 struct p11_kit_uri *info = NULL;
1812 ret = pkcs11_url_to_info(url, &info);
1819 case GNUTLS_PKCS11_TOKEN_LABEL:
1820 str = p11_kit_uri_get_token_info(info)->label;
1823 case GNUTLS_PKCS11_TOKEN_SERIAL:
1824 str = p11_kit_uri_get_token_info(info)->serial_number;
1827 case GNUTLS_PKCS11_TOKEN_MANUFACTURER:
1828 str = p11_kit_uri_get_token_info(info)->manufacturer_id;
1831 case GNUTLS_PKCS11_TOKEN_MODEL:
1832 str = p11_kit_uri_get_token_info(info)->model;
1836 p11_kit_uri_free(info);
1838 return GNUTLS_E_INVALID_REQUEST;
1841 len = p11_kit_space_strlen(str, str_max);
1843 if (len + 1 > *output_size) {
1844 *output_size = len + 1;
1845 return GNUTLS_E_SHORT_MEMORY_BUFFER;
1848 memcpy(output, str, len);
1849 ((char *) output)[len] = '\0';
1855 p11_kit_uri_free(info);
1860 * gnutls_pkcs11_obj_export_url:
1861 * @obj: Holds the PKCS 11 certificate
1862 * @detailed: non zero if a detailed URL is required
1863 * @url: will contain an allocated url
1865 * This function will export a URL identifying the given certificate.
1867 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1868 * negative error value.
1873 gnutls_pkcs11_obj_export_url(gnutls_pkcs11_obj_t obj,
1874 gnutls_pkcs11_url_type_t detailed, char **url)
1878 ret = pkcs11_info_to_url(obj->info, detailed, url);
1888 * gnutls_pkcs11_obj_get_type:
1889 * @obj: Holds the PKCS 11 object
1891 * This function will return the type of the certificate being
1892 * stored in the structure.
1894 * Returns: The type of the certificate.
1898 gnutls_pkcs11_obj_type_t
1899 gnutls_pkcs11_obj_get_type(gnutls_pkcs11_obj_t obj)
1905 retrieve_pin_from_source(const char *pinfile,
1906 struct ck_token_info *token_info, int attempts,
1907 ck_user_type_t user_type,
1908 struct p11_kit_pin **pin)
1910 unsigned int flags = 0;
1911 struct p11_kit_uri *token_uri;
1912 struct p11_kit_pin *result;
1916 p11_kit_space_strdup(token_info->label,
1917 sizeof(token_info->label));
1918 if (label == NULL) {
1920 return GNUTLS_E_MEMORY_ERROR;
1923 token_uri = p11_kit_uri_new();
1924 if (token_uri == NULL) {
1927 return GNUTLS_E_MEMORY_ERROR;
1930 memcpy(p11_kit_uri_get_token_info(token_uri), token_info,
1931 sizeof(struct ck_token_info));
1934 flags |= P11_KIT_PIN_FLAGS_RETRY;
1935 if (user_type == CKU_USER) {
1936 flags |= P11_KIT_PIN_FLAGS_USER_LOGIN;
1937 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
1938 flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
1939 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
1940 flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
1941 } else if (user_type == CKU_SO) {
1942 flags |= P11_KIT_PIN_FLAGS_SO_LOGIN;
1943 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
1944 flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
1945 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
1946 flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
1947 } else if (user_type == CKU_CONTEXT_SPECIFIC) {
1948 flags |= P11_KIT_PIN_FLAGS_CONTEXT_LOGIN;
1951 result = p11_kit_pin_request(pinfile, token_uri, label, flags);
1952 p11_kit_uri_free(token_uri);
1955 if (result == NULL) {
1957 return GNUTLS_E_PKCS11_PIN_ERROR;
1965 retrieve_pin_from_callback(const struct pin_info_st *pin_info,
1966 struct ck_token_info *token_info,
1967 int attempts, ck_user_type_t user_type,
1968 struct p11_kit_pin **pin)
1970 char pin_value[GNUTLS_PKCS11_MAX_PIN_LEN];
1971 unsigned int flags = 0;
1974 struct p11_kit_uri *token_uri;
1978 p11_kit_space_strdup(token_info->label,
1979 sizeof(token_info->label));
1980 if (label == NULL) {
1982 return GNUTLS_E_MEMORY_ERROR;
1985 token_uri = p11_kit_uri_new();
1986 if (token_uri == NULL) {
1989 return GNUTLS_E_MEMORY_ERROR;
1992 memcpy(p11_kit_uri_get_token_info(token_uri), token_info,
1993 sizeof(struct ck_token_info));
1994 ret = pkcs11_info_to_url(token_uri, 1, &token_str);
1995 p11_kit_uri_free(token_uri);
2000 return GNUTLS_E_MEMORY_ERROR;
2003 if (user_type == CKU_USER) {
2004 flags |= GNUTLS_PIN_USER;
2005 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
2006 flags |= GNUTLS_PIN_COUNT_LOW;
2007 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
2008 flags |= GNUTLS_PIN_FINAL_TRY;
2009 } else if (user_type == CKU_SO) {
2010 flags |= GNUTLS_PIN_SO;
2011 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
2012 flags |= GNUTLS_PIN_COUNT_LOW;
2013 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
2014 flags |= GNUTLS_PIN_FINAL_TRY;
2018 flags |= GNUTLS_PIN_WRONG;
2020 if (pin_info && pin_info->cb)
2022 pin_info->cb(pin_info->data, attempts,
2023 (char *) token_str, label, flags,
2024 pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2025 else if (_gnutls_pin_func)
2027 _gnutls_pin_func(_gnutls_pin_data, attempts,
2028 (char *) token_str, label, flags,
2029 pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2031 ret = gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2037 return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2039 *pin = p11_kit_pin_new_for_string(pin_value);
2042 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2048 retrieve_pin(struct pin_info_st *pin_info, struct p11_kit_uri *info,
2049 struct ck_token_info *token_info, int attempts,
2050 ck_user_type_t user_type, struct p11_kit_pin **pin)
2052 const char *pinfile;
2053 int ret = GNUTLS_E_PKCS11_PIN_ERROR;
2057 /* Check if a pinfile is specified, and use that if possible */
2058 pinfile = p11_kit_uri_get_pinfile(info);
2059 if (pinfile != NULL) {
2060 _gnutls_debug_log("p11: Using pinfile to retrieve PIN\n");
2062 retrieve_pin_from_source(pinfile, token_info, attempts,
2066 /* The global gnutls pin callback */
2069 retrieve_pin_from_callback(pin_info, token_info,
2070 attempts, user_type, pin);
2072 /* Otherwise, PIN entry is necessary for login, so fail if there's
2078 ("p11: No suitable pin callback but login required.\n");
2085 pkcs11_login(struct pkcs11_session_info *sinfo,
2086 struct pin_info_st *pin_info,
2087 const struct token_info *tokinfo, struct p11_kit_uri *info,
2090 struct ck_session_info session_info;
2091 int attempt = 0, ret;
2092 ck_user_type_t user_type;
2095 user_type = (so == 0) ? CKU_USER : CKU_SO;
2096 if (so == 0 && (tokinfo->tinfo.flags & CKF_LOGIN_REQUIRED) == 0) {
2098 _gnutls_debug_log("p11: No login required.\n");
2102 /* For a token with a "protected" (out-of-band) authentication
2103 * path, calling login with a NULL username is all that is
2105 if (tokinfo->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
2106 rv = (sinfo->module)->C_Login(sinfo->pks,
2108 0) ? CKU_USER : CKU_SO,
2110 if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) {
2115 ("p11: Protected login failed.\n");
2116 ret = GNUTLS_E_PKCS11_ERROR;
2122 struct p11_kit_pin *pin;
2123 struct ck_token_info tinfo;
2125 memcpy(&tinfo, &tokinfo->tinfo, sizeof(tinfo));
2127 /* Check whether the session is already logged in, and if so, just skip */
2128 rv = (sinfo->module)->C_GetSessionInfo(sinfo->pks,
2131 && (session_info.state == CKS_RO_USER_FUNCTIONS
2132 || session_info.state == CKS_RW_USER_FUNCTIONS)) {
2137 /* If login has been attempted once already, check the token
2138 * status again, the flags might change. */
2140 if (pkcs11_get_token_info
2141 (tokinfo->prov->module, tokinfo->sid,
2142 &tinfo) != CKR_OK) {
2145 ("p11: GetTokenInfo failed\n");
2146 ret = GNUTLS_E_PKCS11_ERROR;
2152 retrieve_pin(pin_info, info, &tinfo, attempt++,
2159 rv = (sinfo->module)->C_Login(sinfo->pks, user_type,
2161 p11_kit_pin_get_value(pin,
2163 p11_kit_pin_get_length(pin));
2165 p11_kit_pin_unref(pin);
2167 while (rv == CKR_PIN_INCORRECT);
2169 _gnutls_debug_log("p11: Login result = %lu\n", rv);
2174 CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err(rv);
2180 int pkcs11_call_token_func(struct p11_kit_uri *info, const unsigned retry)
2182 struct ck_token_info *tinfo;
2186 tinfo = p11_kit_uri_get_token_info(info);
2187 label = p11_kit_space_strdup(tinfo->label, sizeof(tinfo->label));
2188 ret = (_gnutls_token_func) (_gnutls_token_data, label, retry);
2196 find_privkeys(struct pkcs11_session_info *sinfo,
2197 struct token_info *info, struct find_pkey_list_st *list)
2199 struct ck_attribute a[3];
2200 ck_object_class_t class;
2202 ck_object_handle_t obj;
2203 unsigned long count, current;
2204 char certid_tmp[PKCS11_ID_SIZE];
2206 class = CKO_PRIVATE_KEY;
2208 /* Find an object with private key class and a certificate ID
2209 * which matches the certificate. */
2210 /* FIXME: also match the cert subject. */
2211 a[0].type = CKA_CLASS;
2212 a[0].value = &class;
2213 a[0].value_len = sizeof class;
2215 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 1);
2218 return pkcs11_rv_to_err(rv);
2221 list->key_ids_size = 0;
2222 while (pkcs11_find_objects
2223 (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK
2225 list->key_ids_size++;
2228 pkcs11_find_objects_final(sinfo);
2230 if (list->key_ids_size == 0) {
2232 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2236 gnutls_malloc(sizeof(gnutls_buffer_st) * list->key_ids_size);
2237 if (list->key_ids == NULL) {
2239 return GNUTLS_E_MEMORY_ERROR;
2243 a[0].type = CKA_CLASS;
2244 a[0].value = &class;
2245 a[0].value_len = sizeof class;
2247 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 1);
2250 return pkcs11_rv_to_err(rv);
2254 while (pkcs11_find_objects
2255 (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK
2259 a[0].value = certid_tmp;
2260 a[0].value_len = sizeof(certid_tmp);
2262 _gnutls_buffer_init(&list->key_ids[current]);
2264 if (pkcs11_get_attribute_value
2265 (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK) {
2266 _gnutls_buffer_append_data(&list->key_ids[current],
2272 if (current > list->key_ids_size)
2276 pkcs11_find_objects_final(sinfo);
2278 list->key_ids_size = current - 1;
2283 /* Recover certificate list from tokens */
2287 find_objs(struct pkcs11_session_info *sinfo,
2288 struct token_info *info, struct ck_info *lib_info, void *input)
2290 struct find_obj_data_st *find_data = input;
2291 struct ck_attribute a[6];
2292 struct ck_attribute *attr;
2293 ck_object_class_t class = (ck_object_class_t) - 1;
2294 ck_certificate_type_t type = (ck_certificate_type_t) - 1;
2296 unsigned long category;
2298 ck_object_handle_t obj;
2299 unsigned long count;
2301 char certid_tmp[PKCS11_ID_SIZE];
2302 char label_tmp[PKCS11_LABEL_SIZE];
2304 struct find_pkey_list_st plist; /* private key holder */
2305 unsigned int i, tot_values = 0;
2307 if (info == NULL) { /* final call */
2308 if (find_data->current <= *find_data->n_list)
2311 ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
2313 *find_data->n_list = find_data->current;
2318 /* do not bother reading the token if basic fields do not match
2320 if (!p11_kit_uri_match_token_info(find_data->info, &info->tinfo) ||
2321 !p11_kit_uri_match_module_info(find_data->info, lib_info)) {
2323 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2326 memset(&plist, 0, sizeof(plist));
2328 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) {
2329 ret = find_privkeys(sinfo, info, &plist);
2335 if (plist.key_ids_size == 0) {
2337 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2341 /* Find objects with given class and type */
2342 attr = p11_kit_uri_get_attribute(find_data->info, CKA_CLASS);
2345 && attr->value_len == sizeof(ck_object_class_t))
2346 class = *((ck_object_class_t *) attr->value);
2347 if (class == CKO_CERTIFICATE)
2351 cert_data = gnutls_malloc(MAX_CERT_SIZE);
2352 if (cert_data == NULL) {
2354 return GNUTLS_E_MEMORY_ERROR;
2357 /* Find objects with cert class and X.509 cert type. */
2361 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL
2362 || find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2364 class = CKO_CERTIFICATE;
2368 a[tot_values].type = CKA_CLASS;
2369 a[tot_values].value = &class;
2370 a[tot_values].value_len = sizeof class;
2373 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2374 a[tot_values].value = &type;
2375 a[tot_values].value_len = sizeof type;
2378 } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED) {
2379 class = CKO_CERTIFICATE;
2383 a[tot_values].type = CKA_CLASS;
2384 a[tot_values].value = &class;
2385 a[tot_values].value_len = sizeof class;
2388 a[tot_values].type = CKA_TRUSTED;
2389 a[tot_values].value = &trusted;
2390 a[tot_values].value_len = sizeof trusted;
2393 } else if (find_data->flags ==
2394 GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED_CA) {
2395 class = CKO_CERTIFICATE;
2399 a[tot_values].type = CKA_CLASS;
2400 a[tot_values].value = &class;
2401 a[tot_values].value_len = sizeof class;
2404 a[tot_values].type = CKA_TRUSTED;
2405 a[tot_values].value = &trusted;
2406 a[tot_values].value_len = sizeof trusted;
2410 a[tot_values].type = CKA_CERTIFICATE_CATEGORY;
2411 a[tot_values].value = &category;
2412 a[tot_values].value_len = sizeof category;
2414 } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY) {
2415 class = CKO_PUBLIC_KEY;
2417 a[tot_values].type = CKA_CLASS;
2418 a[tot_values].value = &class;
2419 a[tot_values].value_len = sizeof class;
2421 } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY) {
2422 class = CKO_PRIVATE_KEY;
2424 a[tot_values].type = CKA_CLASS;
2425 a[tot_values].value = &class;
2426 a[tot_values].value_len = sizeof class;
2428 } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL) {
2429 if (class != (ck_object_class_t) - 1) {
2430 a[tot_values].type = CKA_CLASS;
2431 a[tot_values].value = &class;
2432 a[tot_values].value_len = sizeof class;
2435 if (type != (ck_certificate_type_t) - 1) {
2436 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2437 a[tot_values].value = &type;
2438 a[tot_values].value_len = sizeof type;
2443 ret = GNUTLS_E_INVALID_REQUEST;
2447 attr = p11_kit_uri_get_attribute(find_data->info, CKA_ID);
2449 memcpy(a + tot_values, attr, sizeof(struct ck_attribute));
2453 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
2457 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
2458 return pkcs11_rv_to_err(rv);
2461 while (pkcs11_find_objects
2462 (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK
2464 gnutls_datum_t label, id, value;
2466 a[0].type = CKA_LABEL;
2467 a[0].value = label_tmp;
2468 a[0].value_len = sizeof label_tmp;
2470 if (pkcs11_get_attribute_value
2471 (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK) {
2472 label.data = a[0].value;
2473 label.size = a[0].value_len;
2480 a[0].value = certid_tmp;
2481 a[0].value_len = sizeof certid_tmp;
2483 if (pkcs11_get_attribute_value
2484 (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK) {
2485 id.data = a[0].value;
2486 id.size = a[0].value_len;
2492 a[0].type = CKA_VALUE;
2493 a[0].value = cert_data;
2494 a[0].value_len = MAX_CERT_SIZE;
2495 if (pkcs11_get_attribute_value
2496 (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK) {
2497 value.data = a[0].value;
2498 value.size = a[0].value_len;
2504 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL) {
2505 a[0].type = CKA_CLASS;
2506 a[0].value = &class;
2507 a[0].value_len = sizeof class;
2509 rv = pkcs11_get_attribute_value(sinfo->module,
2510 sinfo->pks, obj, a, 1);
2516 if (find_data->flags ==
2517 GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) {
2518 for (i = 0; i < plist.key_ids_size; i++) {
2519 if (plist.key_ids[i].length !=
2521 || memcmp(plist.key_ids[i].data,
2523 a[1].value_len) != 0) {
2530 if (find_data->current < *find_data->n_list) {
2532 gnutls_pkcs11_obj_init(&find_data->p_list
2533 [find_data->current]);
2539 if (class == CKO_PUBLIC_KEY) {
2541 pkcs11_obj_import_pubkey(sinfo->module,
2545 [find_data->current],
2551 pkcs11_obj_import(class,
2553 [find_data->current],
2554 &value, &id, &label,
2564 find_data->current++;
2568 gnutls_free(cert_data);
2569 pkcs11_find_objects_final(sinfo);
2571 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* continue until all tokens have been checked */
2574 gnutls_free(cert_data);
2575 pkcs11_find_objects_final(sinfo);
2576 if (plist.key_ids != NULL) {
2577 for (i = 0; i < plist.key_ids_size; i++) {
2578 _gnutls_buffer_clear(&plist.key_ids[i]);
2580 gnutls_free(plist.key_ids);
2582 for (i = 0; i < find_data->current; i++) {
2583 gnutls_pkcs11_obj_deinit(find_data->p_list[i]);
2585 find_data->current = 0;
2591 * gnutls_pkcs11_obj_list_import_url:
2592 * @p_list: An uninitialized object list (may be NULL)
2593 * @n_list: initially should hold the maximum size of the list. Will contain the actual size.
2594 * @url: A PKCS 11 url identifying a set of objects
2595 * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2596 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2598 * This function will initialize and set values to an object list
2599 * by using all objects identified by a PKCS 11 URL.
2601 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2602 * negative error value.
2607 gnutls_pkcs11_obj_list_import_url(gnutls_pkcs11_obj_t * p_list,
2608 unsigned int *n_list,
2610 gnutls_pkcs11_obj_attr_t attrs,
2614 struct find_obj_data_st priv;
2618 memset(&priv, 0, sizeof(priv));
2620 /* fill in the find data structure */
2621 priv.p_list = p_list;
2622 priv.n_list = n_list;
2626 if (url == NULL || url[0] == 0) {
2630 ret = pkcs11_url_to_info(url, &priv.info);
2637 _pkcs11_traverse_tokens(find_objs, &priv, priv.info,
2638 NULL, pkcs11_obj_flags_to_int(flags));
2639 p11_kit_uri_free(priv.info);
2643 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2654 * gnutls_pkcs11_obj_list_import_url2:
2655 * @p_list: An uninitialized object list (may be NULL)
2656 * @n_list: It will contain the size of the list.
2657 * @url: A PKCS 11 url identifying a set of objects
2658 * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2659 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2661 * This function will initialize and set values to an object list
2662 * by using all objects identified by the PKCS 11 URL. The output
2663 * is stored in @p_list, which will be initialized.
2665 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2666 * negative error value.
2671 gnutls_pkcs11_obj_list_import_url2(gnutls_pkcs11_obj_t ** p_list,
2672 unsigned int *n_list,
2674 gnutls_pkcs11_obj_attr_t attrs,
2677 unsigned int init = 128;
2680 *p_list = gnutls_malloc(sizeof(gnutls_pkcs11_obj_t) * init);
2681 if (*p_list == NULL) {
2683 return GNUTLS_E_MEMORY_ERROR;
2687 gnutls_pkcs11_obj_list_import_url(*p_list, &init, url, attrs,
2689 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
2691 gnutls_realloc_fast(*p_list,
2692 sizeof(gnutls_pkcs11_obj_t) *
2694 if (*p_list == NULL)
2695 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2698 gnutls_pkcs11_obj_list_import_url(*p_list, &init, url,
2704 gnutls_free(*p_list);
2715 * gnutls_x509_crt_import_pkcs11_url:
2716 * @crt: A certificate of type #gnutls_x509_crt_t
2717 * @url: A PKCS 11 url
2718 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
2720 * This function will import a PKCS 11 certificate directly from a token
2721 * without involving the #gnutls_pkcs11_obj_t structure. This function will
2722 * fail if the certificate stored is not of X.509 type.
2724 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2725 * negative error value.
2730 gnutls_x509_crt_import_pkcs11_url(gnutls_x509_crt_t crt,
2731 const char *url, unsigned int flags)
2733 gnutls_pkcs11_obj_t pcrt;
2736 ret = gnutls_pkcs11_obj_init(&pcrt);
2743 gnutls_pkcs11_obj_set_pin_function(pcrt, crt->pin.cb,
2746 ret = gnutls_pkcs11_obj_import_url(pcrt, url, flags);
2752 ret = gnutls_x509_crt_import(crt, &pcrt->raw, GNUTLS_X509_FMT_DER);
2761 gnutls_pkcs11_obj_deinit(pcrt);
2767 * gnutls_x509_crt_import_pkcs11:
2768 * @crt: A certificate of type #gnutls_x509_crt_t
2769 * @pkcs11_crt: A PKCS 11 object that contains a certificate
2771 * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t
2774 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2775 * negative error value.
2780 gnutls_x509_crt_import_pkcs11(gnutls_x509_crt_t crt,
2781 gnutls_pkcs11_obj_t pkcs11_crt)
2783 return gnutls_x509_crt_import(crt, &pkcs11_crt->raw,
2784 GNUTLS_X509_FMT_DER);
2788 * gnutls_x509_crt_list_import_pkcs11:
2789 * @certs: A list of certificates of type #gnutls_x509_crt_t
2790 * @cert_max: The maximum size of the list
2791 * @objs: A list of PKCS 11 objects
2794 * This function will import a PKCS 11 certificate list to a list of
2795 * #gnutls_x509_crt_t structure. These must not be initialized.
2797 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2798 * negative error value.
2803 gnutls_x509_crt_list_import_pkcs11(gnutls_x509_crt_t * certs,
2804 unsigned int cert_max,
2805 gnutls_pkcs11_obj_t * const objs,
2811 for (i = 0; i < cert_max; i++) {
2812 ret = gnutls_x509_crt_init(&certs[i]);
2818 ret = gnutls_x509_crt_import_pkcs11(certs[i], objs[i]);
2828 for (j = 0; j < i; j++) {
2829 gnutls_x509_crt_deinit(certs[j]);
2836 find_flags(struct pkcs11_session_info *sinfo,
2837 struct token_info *info, struct ck_info *lib_info, void *input)
2839 struct find_flags_data_st *find_data = input;
2841 if (info == NULL) { /* we don't support multiple calls */
2843 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2846 /* do not bother reading the token if basic fields do not match
2848 if (!p11_kit_uri_match_token_info(find_data->info, &info->tinfo) ||
2849 !p11_kit_uri_match_module_info(find_data->info, lib_info)) {
2851 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2855 if (p11_kit_module_get_flags(sinfo->module) & P11_KIT_MODULE_TRUSTED)
2856 find_data->trusted = 1;
2858 find_data->trusted = 0;
2859 find_data->slot_flags = info->sinfo.flags;
2865 * gnutls_pkcs11_token_get_flags:
2866 * @url: should contain a PKCS 11 URL
2867 * @flags: The output flags (GNUTLS_PKCS11_TOKEN_*)
2869 * This function will return information about the PKCS 11 token flags.
2871 * The supported flags are: %GNUTLS_PKCS11_TOKEN_HW and %GNUTLS_PKCS11_TOKEN_TRUSTED.
2873 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
2877 int gnutls_pkcs11_token_get_flags(const char *url, unsigned int *flags)
2879 struct find_flags_data_st find_data;
2884 memset(&find_data, 0, sizeof(find_data));
2885 ret = pkcs11_url_to_info(url, &find_data.info);
2892 _pkcs11_traverse_tokens(find_flags, &find_data, find_data.info,
2894 p11_kit_uri_free(find_data.info);
2902 if (find_data.slot_flags & CKF_HW_SLOT)
2903 *flags |= GNUTLS_PKCS11_TOKEN_HW;
2905 if (find_data.trusted != 0)
2906 *flags |= GNUTLS_PKCS11_TOKEN_TRUSTED;
2913 * gnutls_pkcs11_token_get_mechanism:
2914 * @url: should contain a PKCS 11 URL
2915 * @idx: The index of the mechanism
2916 * @mechanism: The PKCS #11 mechanism ID
2918 * This function will return the names of the supported mechanisms
2919 * by the token. It should be called with an increasing index until
2920 * it return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
2922 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
2927 gnutls_pkcs11_token_get_mechanism(const char *url, unsigned int idx,
2928 unsigned long *mechanism)
2932 struct ck_function_list *module;
2934 struct token_info tinfo;
2935 struct p11_kit_uri *info = NULL;
2936 unsigned long count;
2937 ck_mechanism_type_t mlist[400];
2941 ret = pkcs11_url_to_info(url, &info);
2947 ret = pkcs11_find_slot(&module, &slot, info, &tinfo);
2948 p11_kit_uri_free(info);
2955 count = sizeof(mlist) / sizeof(mlist[0]);
2956 rv = pkcs11_get_mechanism_list(module, slot, mlist, &count);
2959 return pkcs11_rv_to_err(rv);
2964 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2967 *mechanism = mlist[idx];
2974 * gnutls_pkcs11_type_get_name:
2975 * @type: Holds the PKCS 11 object type, a #gnutls_pkcs11_obj_type_t.
2977 * This function will return a human readable description of the
2978 * PKCS11 object type @obj. It will return "Unknown" for unknown
2981 * Returns: human readable string labeling the PKCS11 object type
2986 const char *gnutls_pkcs11_type_get_name(gnutls_pkcs11_obj_type_t type)
2989 case GNUTLS_PKCS11_OBJ_X509_CRT:
2990 return "X.509 Certificate";
2991 case GNUTLS_PKCS11_OBJ_PUBKEY:
2992 return "Public key";
2993 case GNUTLS_PKCS11_OBJ_PRIVKEY:
2994 return "Private key";
2995 case GNUTLS_PKCS11_OBJ_SECRET_KEY:
2996 return "Secret key";
2997 case GNUTLS_PKCS11_OBJ_DATA:
2999 case GNUTLS_PKCS11_OBJ_UNKNOWN:
3005 #ifndef CKA_X_DISTRUSTED
3006 # define CKA_X_VENDOR (CKA_VENDOR_DEFINED | 0x58444700UL)
3007 # define CKA_X_DISTRUSTED (CKA_X_VENDOR + 100)
3011 find_cert(struct pkcs11_session_info *sinfo,
3012 struct token_info *info, struct ck_info *lib_info, void *input)
3014 struct ck_attribute a[10];
3015 ck_object_class_t class = -1;
3016 ck_certificate_type_t type = (ck_certificate_type_t) - 1;
3018 ck_object_handle_t obj;
3019 unsigned long count, a_vals;
3021 uint8_t *cert_data = NULL;
3022 struct find_cert_st *priv = input;
3023 char label_tmp[PKCS11_LABEL_SIZE];
3024 char id_tmp[PKCS11_ID_SIZE];
3025 unsigned tries, i, finalized;
3026 ck_bool_t trusted = 1;
3030 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3033 /* the DISTRUSTED flag is p11-kit module specific */
3034 if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) {
3035 if (memcmp(lib_info->manufacturer_id, "PKCS#11 Kit", 11) != 0) {
3037 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3041 if (priv->dn.size == 0 && priv->key_id.size == 0 && priv->issuer_dn.size == 0 &&
3042 priv->serial.size == 0)
3043 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
3045 /* search the token for the key ID */
3047 cert_data = gnutls_malloc(MAX_CERT_SIZE);
3048 if (cert_data == NULL) {
3050 return GNUTLS_E_MEMORY_ERROR;
3053 /* Find objects with given class and type */
3055 if (priv->key_id.size > 0 && priv->dn.size > 0)
3060 for (i = 0; i < tries; i++) {
3063 class = CKO_CERTIFICATE;
3064 a[a_vals].type = CKA_CLASS;
3065 a[a_vals].value = &class;
3066 a[a_vals].value_len = sizeof class;
3069 if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED) {
3070 a[a_vals].type = CKA_TRUSTED;
3071 a[a_vals].value = &trusted;
3072 a[a_vals].value_len = sizeof trusted;
3076 if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) {
3077 a[a_vals].type = CKA_X_DISTRUSTED;
3078 a[a_vals].value = &trusted;
3079 a[a_vals].value_len = sizeof trusted;
3083 if (priv->need_import != 0) {
3085 a[a_vals].type = CKA_CERTIFICATE_TYPE;
3086 a[a_vals].value = &type;
3087 a[a_vals].value_len = sizeof type;
3091 if (i == 0 && priv->key_id.size > 0) {
3092 a[a_vals].type = CKA_ID;
3093 a[a_vals].value = priv->key_id.data;
3094 a[a_vals].value_len = priv->key_id.size;
3098 if (priv->dn.size > 0) {
3099 a[a_vals].type = CKA_SUBJECT;
3100 a[a_vals].value = priv->dn.data;
3101 a[a_vals].value_len = priv->dn.size;
3105 if (priv->serial.size > 0) {
3106 a[a_vals].type = CKA_SERIAL_NUMBER;
3107 a[a_vals].value = priv->serial.data;
3108 a[a_vals].value_len = priv->serial.size;
3112 if (priv->issuer_dn.size > 0) {
3113 a[a_vals].type = CKA_ISSUER;
3114 a[a_vals].value = priv->issuer_dn.data;
3115 a[a_vals].value_len = priv->issuer_dn.size;
3120 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
3125 ("p11: FindObjectsInit failed.\n");
3126 ret = pkcs11_rv_to_err(rv);
3130 while (pkcs11_find_objects
3131 (sinfo->module, sinfo->pks, &obj, 1,
3132 &count) == CKR_OK && count == 1) {
3134 if (priv->need_import == 0 && !(priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE)) {
3139 a[0].type = CKA_VALUE;
3140 a[0].value = cert_data;
3141 a[0].value_len = MAX_CERT_SIZE;
3143 a[1].type = CKA_LABEL;
3144 a[1].value = label_tmp;
3145 a[1].value_len = sizeof(label_tmp);
3148 a[2].value = id_tmp;
3149 a[2].value_len = sizeof(id_tmp);
3151 if (pkcs11_get_attribute_value
3152 (sinfo->module, sinfo->pks, obj, a,
3155 { a[2].value, a[2].value_len };
3156 gnutls_datum_t data =
3157 { a[0].value, a[0].value_len };
3158 gnutls_datum_t label =
3159 { a[1].value, a[1].value_len };
3161 if (priv->need_import != 0) {
3163 pkcs11_obj_import(class, priv->obj,
3173 if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE) {
3174 if (priv->crt == NULL) {
3179 if (_gnutls_check_if_same_cert2(priv->crt, &data) == 0) {
3189 ("p11: Skipped cert, missing attrs.\n");
3193 pkcs11_find_objects_final(sinfo);
3202 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3208 gnutls_free(cert_data);
3210 pkcs11_find_objects_final(sinfo);
3216 * gnutls_pkcs11_get_raw_issuer:
3217 * @url: A PKCS 11 url identifying a token
3218 * @cert: is the certificate to find issuer for
3219 * @issuer: Will hold the issuer if any in an allocated buffer.
3220 * @fmt: The format of the exported issuer.
3221 * @flags: Use zero or flags from %GNUTLS_PKCS11_OBJ_FLAG.
3223 * This function will return the issuer of a given certificate, if it
3224 * is stored in the token. By default only marked as trusted issuers
3225 * are retuned. If any issuer should be returned specify
3226 * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY in @flags.
3228 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3229 * negative error value.
3233 int gnutls_pkcs11_get_raw_issuer(const char *url, gnutls_x509_crt_t cert,
3234 gnutls_datum_t * issuer,
3235 gnutls_x509_crt_fmt_t fmt,
3239 struct find_cert_st priv;
3240 uint8_t id[PKCS11_ID_SIZE];
3242 struct p11_kit_uri *info = NULL;
3246 memset(&priv, 0, sizeof(priv));
3248 if (url == NULL || url[0] == 0) {
3252 ret = pkcs11_url_to_info(url, &info);
3258 id_size = sizeof(id);
3260 gnutls_x509_crt_get_authority_key_id(cert, id, &id_size, NULL);
3262 priv.key_id.data = id;
3263 priv.key_id.size = id_size;
3266 priv.dn.data = cert->raw_issuer_dn.data;
3267 priv.dn.size = cert->raw_issuer_dn.size;
3269 if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY))
3270 flags |= GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED;
3274 ret = gnutls_pkcs11_obj_init(&priv.obj);
3279 priv.need_import = 1;
3282 _pkcs11_traverse_tokens(find_cert, &priv, info,
3283 NULL, pkcs11_obj_flags_to_int(flags));
3289 ret = gnutls_pkcs11_obj_export3(priv.obj, fmt, issuer);
3299 gnutls_pkcs11_obj_deinit(priv.obj);
3301 p11_kit_uri_free(info);
3307 * gnutls_pkcs11_crt_is_known:
3308 * @url: A PKCS 11 url identifying a token
3309 * @cert: is the certificate to find issuer for
3310 * @issuer: Will hold the issuer if any in an allocated buffer.
3311 * @fmt: The format of the exported issuer.
3312 * @flags: Use zero or flags from %GNUTLS_PKCS11_OBJ_FLAG.
3314 * This function will check whether the provided certificate is stored
3315 * in the specified token. This is useful in combination with
3316 * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED or
3317 * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED,
3318 * to check whether a CA is present or a certificate is blacklisted in
3319 * a trust PKCS #11 module.
3321 * This function can be used with a @url of "pkcs11:", and in that case all modules
3322 * will be searched. To restrict the modules to the marked as trusted in p11-kit
3323 * use the %GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE flag.
3325 * Note that the flag %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED is
3326 * specific to p11-kit trust modules.
3328 * Returns: If the certificate exists non-zero is returned, otherwise zero.
3332 int gnutls_pkcs11_crt_is_known(const char *url, gnutls_x509_crt_t cert,
3336 struct find_cert_st priv;
3337 uint8_t serial[ASN1_MAX_TL_SIZE+64];
3339 uint8_t tag[ASN1_MAX_TL_SIZE];
3340 unsigned int tag_size;
3341 struct p11_kit_uri *info = NULL;
3343 PKCS11_CHECK_INIT_RET(0);
3345 memset(&priv, 0, sizeof(priv));
3347 if (url == NULL || url[0] == 0) {
3351 ret = pkcs11_url_to_info(url, &info);
3357 /* Attempt searching using the issuer DN + serial number */
3358 serial_size = sizeof(serial) - sizeof(tag);
3360 gnutls_x509_crt_get_serial(cert, serial+sizeof(tag), &serial_size);
3366 /* PKCS#11 requires a DER encoded serial, wtf. $@(*$@ */
3367 tag_size = sizeof(tag);
3368 ret = asn1_encode_simple_der(ASN1_ETYPE_INTEGER, serial+sizeof(tag), serial_size,
3370 if (ret != ASN1_SUCCESS) {
3375 memcpy(serial+sizeof(tag)-tag_size, tag, tag_size);
3377 priv.serial.data = serial+sizeof(tag)-tag_size;
3378 priv.serial.size = serial_size + tag_size;
3381 priv.issuer_dn.data = cert->raw_issuer_dn.data;
3382 priv.issuer_dn.size = cert->raw_issuer_dn.size;
3384 /* when looking for a trusted certificate, we always fully compare
3386 if (flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED)
3387 flags |= GNUTLS_PKCS11_OBJ_FLAG_COMPARE;
3392 _pkcs11_traverse_tokens(find_cert, &priv, info,
3393 NULL, pkcs11_obj_flags_to_int(flags));
3394 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
3395 /* attempt searching with the subject DN only */
3396 memset(&priv, 0, sizeof(priv));
3400 priv.dn.data = cert->raw_dn.data;
3401 priv.dn.size = cert->raw_dn.size;
3403 _pkcs11_traverse_tokens(find_cert, &priv, info,
3404 NULL, pkcs11_obj_flags_to_int(flags));
3416 p11_kit_uri_free(info);