2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010-2014 Free Software Foundation, Inc.
4 * Copyright (C) 2008 Joe Orton <joe@manyfish.co.uk>
5 * Copyright (C) 2013 Nikos Mavrogiannopoulos
6 * Copyright (C) 2014 Red Hat
8 * Authors: Nikos Mavrogiannopoulos, Stef Walter
10 * Inspired and some parts (pkcs11_login) based on neon PKCS #11 support
11 * by Joe Orton. More ideas came from the pkcs11-helper library by
14 * GnuTLS is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public License
16 * as published by the Free Software Foundation; either version 2.1 of
17 * the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public License
25 * along with this program. If not, see <http://www.gnu.org/licenses/>
28 #include <gnutls_int.h>
29 #include <gnutls/pkcs11.h>
31 #include <gnutls_errors.h>
32 #include <gnutls_datum.h>
33 #include <x509/common.h>
37 #include <pkcs11_int.h>
38 #include <p11-kit/p11-kit.h>
40 #include <p11-kit/pin.h>
45 #define MAX_PROVIDERS 16
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 obj;
67 bool overwrite_exts; /* only valid if looking for a certificate */
70 struct find_obj_data_st {
71 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));
247 * - negative error code on error,
249 * - 1 on success (and a fork was detected)
251 int _gnutls_pkcs11_check_init(void)
255 ret = gnutls_mutex_lock(&_gnutls_pkcs11_mutex);
257 return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
264 if (providers_initialized != 0) {
267 if (init_pid != getpid()) {
268 /* if we are initialized but a fork is detected */
269 ret = gnutls_pkcs11_reinit();
275 gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
283 providers_initialized = 1;
284 _gnutls_debug_log("Initializing PKCS #11 modules\n");
285 ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO, NULL);
287 gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
290 return gnutls_assert_val(ret);
297 * gnutls_pkcs11_add_provider:
298 * @name: The filename of the module
299 * @params: should be NULL
301 * This function will load and add a PKCS 11 module to the module
302 * list used in gnutls. After this function is called the module will
303 * be used for PKCS 11 operations.
305 * When loading a module to be used for certificate verification,
306 * use the string 'trusted' as @params.
308 * Note that this function is not thread safe.
310 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
311 * negative error value.
315 int gnutls_pkcs11_add_provider(const char *name, const char *params)
317 struct ck_function_list *module;
320 module = p11_kit_module_load(name, P11_KIT_MODULE_CRITICAL);
321 if (module == NULL) {
323 _gnutls_debug_log("p11: Cannot load provider %s\n", name);
324 return GNUTLS_E_PKCS11_LOAD_ERROR;
328 ("p11: Initializing module: %s\n", name);
330 ret = p11_kit_module_initialize(module);
332 p11_kit_module_release(module);
334 return pkcs11_rv_to_err(ret);
337 ret = pkcs11_add_module(name, module, params);
339 if (ret == GNUTLS_E_INT_RET_0)
341 p11_kit_module_finalize(module);
342 p11_kit_module_release(module);
351 * gnutls_pkcs11_obj_set_info:
352 * @obj: should contain a #gnutls_pkcs11_obj_t structure
353 * @itype: Denotes the type of information to be set
354 * @data: the data to set
355 * @data_size: the size of data
356 * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
358 * This function will set attributes on the provided object.
359 * Available options for @itype are %GNUTLS_PKCS11_OBJ_LABEL,
360 * %GNUTLS_PKCS11_OBJ_ID_HEX, and %GNUTLS_PKCS11_OBJ_ID.
362 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
367 gnutls_pkcs11_obj_set_info(gnutls_pkcs11_obj_t obj,
368 gnutls_pkcs11_obj_info_t itype,
369 const void *data, size_t data_size,
372 struct p11_kit_uri *info = obj->info;
373 struct pkcs11_session_info sinfo;
374 struct ck_attribute *attr;
375 struct ck_attribute a[4];
376 ck_certificate_type_t type = -1;
377 ck_object_class_t class = CKO_CERTIFICATE;
378 ck_object_handle_t pkobj[2];
389 pkcs11_open_session(&sinfo, NULL, info,
391 pkcs11_obj_flags_to_int(flags));
397 /* find the object that matches the URL */
399 attr = p11_kit_uri_get_attribute(info, CKA_ID);
401 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
405 attr = p11_kit_uri_get_attribute(info, CKA_LABEL);
407 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
413 ret = GNUTLS_E_INVALID_REQUEST;
417 /* Find objects with given class and type */
418 attr = p11_kit_uri_get_attribute(info, CKA_CLASS);
421 && attr->value_len == sizeof(ck_object_class_t))
422 class = *((ck_object_class_t *) attr->value);
423 if (class == CKO_CERTIFICATE)
425 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
429 if (type != (ck_certificate_type_t) - 1) {
430 a[a_vals].type = CKA_CERTIFICATE_TYPE;
431 a[a_vals].value = &type;
432 a[a_vals].value_len = sizeof type;
436 rv = pkcs11_find_objects_init(sinfo.module, sinfo.pks, a,
440 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
441 ret = pkcs11_rv_to_err(rv);
445 rv = pkcs11_find_objects(sinfo.module, sinfo.pks, pkobj, 2, &count);
448 _gnutls_debug_log("p11: FindObjects failed.\n");
449 ret = pkcs11_rv_to_err(rv);
453 if (count > 1 || count == 0) {
456 _gnutls_debug_log("p11: More than one objects match (%d)\n", (int)count);
457 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
462 case GNUTLS_PKCS11_OBJ_ID_HEX:
464 ret = _gnutls_hex2bin(data, data_size, (uint8_t*)tmp, &size);
472 case GNUTLS_PKCS11_OBJ_ID:
474 a[0].value = (void*)data;
475 a[0].value_len = data_size;
477 rv = pkcs11_set_attribute_value(sinfo.module, sinfo.pks, pkobj[0], a, 1);
480 _gnutls_debug_log("p11: set_attribute_value failed.\n");
481 ret = pkcs11_rv_to_err(rv);
486 case GNUTLS_PKCS11_OBJ_LABEL:
487 a[0].type = CKA_LABEL;
488 a[0].value = (void*)data;
489 a[0].value_len = data_size;
491 rv = pkcs11_set_attribute_value(sinfo.module, sinfo.pks, pkobj[0], a, 1);
494 _gnutls_debug_log("p11: set_attribute_value failed.\n");
495 ret = pkcs11_rv_to_err(rv);
502 return GNUTLS_E_INVALID_REQUEST;
507 pkcs11_close_session(&sinfo);
512 * gnutls_pkcs11_obj_get_info:
513 * @obj: should contain a #gnutls_pkcs11_obj_t structure
514 * @itype: Denotes the type of information requested
515 * @output: where output will be stored
516 * @output_size: contains the maximum size of the output and will be overwritten with actual
518 * This function will return information about the PKCS11 certificate
519 * such as the label, id as well as token information where the key is
520 * stored. When output is text it returns null terminated string
521 * although @output_size contains the size of the actual data only.
523 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
528 gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t obj,
529 gnutls_pkcs11_obj_info_t itype,
530 void *output, size_t * output_size)
532 return pkcs11_get_info(obj->info, itype, output, output_size);
536 pkcs11_get_info(struct p11_kit_uri *info,
537 gnutls_pkcs11_obj_info_t itype, void *output,
538 size_t * output_size)
540 struct ck_attribute *attr = NULL;
541 struct ck_version *version = NULL;
542 const uint8_t *str = NULL;
547 const char *data = NULL;
551 * Either attr, str or version is valid by the time switch
556 case GNUTLS_PKCS11_OBJ_ID:
557 attr = p11_kit_uri_get_attribute(info, CKA_ID);
559 case GNUTLS_PKCS11_OBJ_ID_HEX:
560 attr = p11_kit_uri_get_attribute(info, CKA_ID);
564 case GNUTLS_PKCS11_OBJ_LABEL:
565 attr = p11_kit_uri_get_attribute(info, CKA_LABEL);
568 case GNUTLS_PKCS11_OBJ_TOKEN_LABEL:
569 str = p11_kit_uri_get_token_info(info)->label;
572 case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL:
573 str = p11_kit_uri_get_token_info(info)->serial_number;
576 case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER:
577 str = p11_kit_uri_get_token_info(info)->manufacturer_id;
580 case GNUTLS_PKCS11_OBJ_TOKEN_MODEL:
581 str = p11_kit_uri_get_token_info(info)->model;
584 case GNUTLS_PKCS11_OBJ_LIBRARY_DESCRIPTION:
586 p11_kit_uri_get_module_info(info)->library_description;
589 case GNUTLS_PKCS11_OBJ_LIBRARY_VERSION:
591 &p11_kit_uri_get_module_info(info)->library_version;
593 case GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER:
594 str = p11_kit_uri_get_module_info(info)->manufacturer_id;
599 return GNUTLS_E_INVALID_REQUEST;
604 length = attr->value_len;
605 } else if (str != NULL) {
607 length = p11_kit_space_strlen(str, str_max);
609 } else if (version != NULL) {
612 snprintf(buf, sizeof(buf), "%d.%d",
613 (int) version->major, (int) version->minor);
618 ((uint8_t *) output)[0] = 0;
623 /* terminate is assumed with hexify */
624 if (*output_size < length * 3) {
625 *output_size = length * 3;
626 return GNUTLS_E_SHORT_MEMORY_BUFFER;
628 if (output && length > 0)
629 _gnutls_bin2hex(data, length, output, *output_size,
631 *output_size = length * 3;
634 if (*output_size < length + terminate) {
635 *output_size = length + terminate;
636 return GNUTLS_E_SHORT_MEMORY_BUFFER;
639 memcpy(output, data, length);
641 ((unsigned char *) output)[length] = '\0';
643 *output_size = length + terminate;
651 /* tries to load modules from /etc/gnutls/pkcs11.conf if it exists
653 static void compat_load(const char *configfile)
660 if (configfile == NULL)
661 configfile = "/etc/gnutls/pkcs11.conf";
663 fp = fopen(configfile, "r");
669 _gnutls_debug_log("Loading PKCS #11 libraries from %s\n",
671 while (fgets(line, sizeof(line), fp) != NULL) {
672 if (strncmp(line, "load", sizeof("load") - 1) == 0) {
674 p = strchr(line, '=');
679 p = strchr(line, '\n');
683 ret = gnutls_pkcs11_add_provider(library, NULL);
687 ("Cannot load provider: %s\n",
698 static int auto_load(void)
700 struct ck_function_list **modules;
704 modules = p11_kit_modules_load_and_initialize(0);
705 if (modules == NULL) {
708 ("Cannot initialize registered modules: %s\n",
710 return GNUTLS_E_PKCS11_LOAD_ERROR;
713 for (i = 0; modules[i] != NULL; i++) {
714 name = p11_kit_module_get_name(modules[i]);
716 ("p11: Initializing module: %s\n", name);
718 ret = pkcs11_add_module(name, modules[i], NULL);
722 ("Cannot load PKCS #11 module: %s\n", name);
733 * gnutls_pkcs11_init:
734 * @flags: An ORed sequence of %GNUTLS_PKCS11_FLAG_*
735 * @deprecated_config_file: either NULL or the location of a deprecated
738 * This function will initialize the PKCS 11 subsystem in gnutls. It will
739 * read configuration files if %GNUTLS_PKCS11_FLAG_AUTO is used or allow
740 * you to independently load PKCS 11 modules using gnutls_pkcs11_add_provider()
741 * if %GNUTLS_PKCS11_FLAG_MANUAL is specified.
743 * Normally you don't need to call this function since it is being called
744 * when the first PKCS 11 operation is requested using the %GNUTLS_PKCS11_FLAG_AUTO
745 * flag. If another flags are required then it must be called independently
746 * prior to any PKCS 11 operation.
748 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
749 * negative error value.
754 gnutls_pkcs11_init(unsigned int flags, const char *deprecated_config_file)
764 p11_kit_pin_register_callback(P11_KIT_PIN_FALLBACK,
765 p11_kit_pin_file_callback, NULL,
768 if (flags == GNUTLS_PKCS11_FLAG_MANUAL)
770 else if (flags & GNUTLS_PKCS11_FLAG_AUTO) {
771 if (deprecated_config_file == NULL)
774 compat_load(deprecated_config_file);
783 * gnutls_pkcs11_reinit:
785 * This function will reinitialize the PKCS 11 subsystem in gnutls.
786 * This is required by PKCS 11 when an application uses fork(). The
787 * reinitialization function must be called on the child.
789 * Note that since GnuTLS 3.3.0, the reinitialization of the PKCS #11
790 * subsystem occurs automatically after fork.
792 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
793 * negative error value.
797 int gnutls_pkcs11_reinit(void)
802 /* make sure that we don't call more than once after a fork */
803 if (init_pid == getpid())
806 for (i = 0; i < active_providers; i++) {
807 if (providers[i].module != NULL) {
808 rv = p11_kit_module_initialize(providers
810 if (rv == CKR_OK || rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) {
811 providers[i].active = 1;
813 providers[i].active = 0;
815 ("Cannot re-initialize registered module '%.*s': %s\n",
816 (int)32, providers[i].info.library_description,
817 p11_kit_strerror(rv));
829 * gnutls_pkcs11_deinit:
831 * This function will deinitialize the PKCS 11 subsystem in gnutls.
832 * This function is only needed if you need to deinitialize the
833 * subsystem without calling gnutls_global_deinit().
837 void gnutls_pkcs11_deinit(void)
848 for (i = 0; i < active_providers; i++) {
849 if (providers[i].active)
850 p11_kit_module_finalize(providers[i].module);
851 p11_kit_module_release(providers[i].module);
853 active_providers = 0;
854 providers_initialized = 0;
856 gnutls_pkcs11_set_pin_function(NULL, NULL);
857 gnutls_pkcs11_set_token_function(NULL, NULL);
858 p11_kit_pin_unregister_callback(P11_KIT_PIN_FALLBACK,
859 p11_kit_pin_file_callback, NULL);
863 * gnutls_pkcs11_set_token_function:
864 * @fn: The token callback
865 * @userdata: data to be supplied to callback
867 * This function will set a callback function to be used when a token
868 * needs to be inserted to continue PKCS 11 operations.
873 gnutls_pkcs11_set_token_function(gnutls_pkcs11_token_callback_t fn,
876 _gnutls_token_func = fn;
877 _gnutls_token_data = userdata;
880 int pkcs11_url_to_info(const char *url, struct p11_kit_uri **info, unsigned flags)
886 *info = p11_kit_uri_new();
889 return GNUTLS_E_MEMORY_ERROR;
894 ret = p11_kit_uri_parse(url, P11_KIT_URI_FOR_ANY, *info);
897 p11_kit_uri_free(*info);
901 return ret == P11_KIT_URI_NO_MEMORY ?
902 GNUTLS_E_MEMORY_ERROR : GNUTLS_E_PARSING_ERROR;
905 /* check for incomplete URIs */
906 if (p11_kit_uri_get_attribute (*info, CKA_CLASS) == NULL) {
907 struct ck_attribute at;
908 ck_object_class_t klass;
910 if (flags & GNUTLS_PKCS11_OBJ_FLAG_EXPECT_CERT) {
911 klass = CKO_CERTIFICATE;
914 at.value_len = sizeof (klass);
915 p11_kit_uri_set_attribute (*info, &at);
916 } else if (flags & GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY) {
917 klass = CKO_PRIVATE_KEY;
920 at.value_len = sizeof (klass);
921 p11_kit_uri_set_attribute (*info, &at);
929 pkcs11_info_to_url(struct p11_kit_uri *info,
930 gnutls_pkcs11_url_type_t detailed, char **url)
932 p11_kit_uri_type_t type = 0;
936 case GNUTLS_PKCS11_URL_GENERIC:
937 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN;
939 case GNUTLS_PKCS11_URL_LIB:
940 type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE;
942 case GNUTLS_PKCS11_URL_LIB_VERSION:
944 P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE |
945 P11_KIT_URI_FOR_MODULE_WITH_VERSION;
949 ret = p11_kit_uri_format(info, type, url);
952 return ret == P11_KIT_URI_NO_MEMORY ?
953 GNUTLS_E_MEMORY_ERROR : GNUTLS_E_INTERNAL_ERROR;
960 * gnutls_pkcs11_obj_init:
961 * @obj: The structure to be initialized
963 * This function will initialize a pkcs11 certificate structure.
965 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
966 * negative error value.
970 int gnutls_pkcs11_obj_init(gnutls_pkcs11_obj_t * obj)
972 *obj = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_obj_st));
975 return GNUTLS_E_MEMORY_ERROR;
978 (*obj)->info = p11_kit_uri_new();
979 if ((*obj)->info == NULL) {
983 return GNUTLS_E_MEMORY_ERROR;
990 * gnutls_pkcs11_obj_set_pin_function:
991 * @obj: The object structure
993 * @userdata: data associated with the callback
995 * This function will set a callback function to be used when
996 * required to access the object. This function overrides the global
997 * set using gnutls_pkcs11_set_pin_function().
1002 gnutls_pkcs11_obj_set_pin_function(gnutls_pkcs11_obj_t obj,
1003 gnutls_pin_callback_t fn,
1007 obj->pin.data = userdata;
1011 * gnutls_pkcs11_obj_deinit:
1012 * @obj: The structure to be initialized
1014 * This function will deinitialize a certificate structure.
1018 void gnutls_pkcs11_obj_deinit(gnutls_pkcs11_obj_t obj)
1021 for (i=0;i<obj->pubkey_size;i++)
1022 _gnutls_free_datum(&obj->pubkey[i]);
1023 _gnutls_free_datum(&obj->raw);
1024 p11_kit_uri_free(obj->info);
1029 * gnutls_pkcs11_obj_export:
1030 * @obj: Holds the object
1031 * @output_data: will contain the object data
1032 * @output_data_size: holds the size of output_data (and will be
1033 * replaced by the actual size of parameters)
1035 * This function will export the PKCS11 object data. It is normal for
1036 * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
1039 * If the buffer provided is not long enough to hold the output, then
1040 * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
1043 * Returns: In case of failure a negative error code will be
1044 * returned, and %GNUTLS_E_SUCCESS (0) on success.
1049 gnutls_pkcs11_obj_export(gnutls_pkcs11_obj_t obj,
1050 void *output_data, size_t * output_data_size)
1052 if (obj == NULL || obj->raw.data == NULL) {
1054 return GNUTLS_E_INVALID_REQUEST;
1057 if (output_data == NULL || *output_data_size < obj->raw.size) {
1058 *output_data_size = obj->raw.size;
1060 return GNUTLS_E_SHORT_MEMORY_BUFFER;
1062 *output_data_size = obj->raw.size;
1064 memcpy(output_data, obj->raw.data, obj->raw.size);
1069 * gnutls_pkcs11_obj_export2:
1070 * @obj: Holds the object
1071 * @out: will contain the object data
1073 * This function will export the PKCS11 object data. It is normal for
1074 * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
1077 * The output buffer is allocated using gnutls_malloc().
1079 * Returns: In case of failure a negative error code will be
1080 * returned, and %GNUTLS_E_SUCCESS (0) on success.
1085 gnutls_pkcs11_obj_export2(gnutls_pkcs11_obj_t obj, gnutls_datum_t * out)
1087 if (obj == NULL || obj->raw.data == NULL) {
1089 return GNUTLS_E_INVALID_REQUEST;
1092 return _gnutls_set_datum(out, obj->raw.data, obj->raw.size);
1096 * gnutls_pkcs11_obj_export3:
1097 * @obj: Holds the object
1098 * @out: will contain the object data
1099 * @fmt: The format of the exported data
1101 * This function will export the PKCS11 object data. It is normal for
1102 * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST
1105 * The output buffer is allocated using gnutls_malloc().
1107 * Returns: In case of failure a negative error code will be
1108 * returned, and %GNUTLS_E_SUCCESS (0) on success.
1113 gnutls_pkcs11_obj_export3(gnutls_pkcs11_obj_t obj,
1114 gnutls_x509_crt_fmt_t fmt, gnutls_datum_t * out)
1118 if (obj == NULL || obj->raw.data == NULL) {
1120 return GNUTLS_E_INVALID_REQUEST;
1123 if (fmt == GNUTLS_X509_FMT_DER)
1124 return _gnutls_set_datum(out, obj->raw.data,
1126 else if (fmt == GNUTLS_X509_FMT_PEM) {
1127 switch (obj->type) {
1128 case GNUTLS_PKCS11_OBJ_X509_CRT:
1130 gnutls_pem_base64_encode_alloc(PEM_X509_CERT2,
1132 case GNUTLS_PKCS11_OBJ_PUBKEY:{
1133 gnutls_pubkey_t pubkey;
1135 ret = gnutls_pubkey_init(&pubkey);
1137 return gnutls_assert_val(ret);
1140 gnutls_pubkey_import_pkcs11(pubkey,
1148 gnutls_pubkey_export2(pubkey, fmt,
1152 gnutls_pubkey_deinit(pubkey);
1156 return gnutls_pem_base64_encode_alloc("DATA",
1161 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1166 pkcs11_find_slot(struct ck_function_list **module, ck_slot_id_t * slot,
1167 struct p11_kit_uri *info, struct token_info *_tinfo)
1171 unsigned long nslots;
1172 ck_slot_id_t slots[MAX_SLOTS];
1174 for (x = 0; x < active_providers; x++) {
1175 if (providers[x].active == 0)
1178 nslots = sizeof(slots) / sizeof(slots[0]);
1179 ret = scan_slots(&providers[x], slots, &nslots);
1185 for (z = 0; z < nslots; z++) {
1186 struct token_info tinfo;
1188 if (pkcs11_get_token_info
1189 (providers[x].module, slots[z],
1190 &tinfo.tinfo) != CKR_OK) {
1193 tinfo.sid = slots[z];
1194 tinfo.prov = &providers[x];
1196 if (pkcs11_get_slot_info
1197 (providers[x].module, slots[z],
1198 &tinfo.sinfo) != CKR_OK) {
1202 if (!p11_kit_uri_match_token_info
1203 (info, &tinfo.tinfo)
1204 || !p11_kit_uri_match_module_info(info,
1211 *module = providers[x].module;
1215 memcpy(_tinfo, &tinfo, sizeof(tinfo));
1222 return GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE;
1226 pkcs11_open_session(struct pkcs11_session_info *sinfo,
1227 struct pin_info_st *pin_info,
1228 struct p11_kit_uri *info, unsigned int flags)
1232 ck_session_handle_t pks = 0;
1233 struct ck_function_list *module;
1235 struct token_info tinfo;
1237 ret = pkcs11_find_slot(&module, &slot, info, &tinfo);
1243 rv = (module)->C_OpenSession(slot, ((flags & SESSION_WRITE)
1244 ? CKF_RW_SESSION : 0) |
1245 CKF_SERIAL_SESSION, NULL, NULL, &pks);
1248 return pkcs11_rv_to_err(rv);
1253 sinfo->module = module;
1256 memcpy(&sinfo->tinfo, &tinfo.tinfo, sizeof(sinfo->tinfo));
1258 if (flags & SESSION_LOGIN) {
1260 pkcs11_login(sinfo, pin_info, info,
1261 (flags & SESSION_SO) ? 1 : 0, 0);
1264 pkcs11_close_session(sinfo);
1274 _pkcs11_traverse_tokens(find_func_t find_func, void *input,
1275 struct p11_kit_uri *info,
1276 struct pin_info_st *pin_info, unsigned int flags)
1279 unsigned int found = 0, x, z;
1281 ck_session_handle_t pks = 0;
1282 struct pkcs11_session_info sinfo;
1283 struct ck_function_list *module = NULL;
1284 unsigned long nslots;
1285 ck_slot_id_t slots[MAX_SLOTS];
1287 for (x = 0; x < active_providers; x++) {
1288 if (providers[x].active == 0)
1291 if (flags & SESSION_TRUSTED && providers[x].trusted == 0)
1294 nslots = sizeof(slots) / sizeof(slots[0]);
1295 ret = scan_slots(&providers[x], slots, &nslots);
1301 module = providers[x].module;
1302 for (z = 0; z < nslots; z++) {
1303 struct token_info tinfo;
1305 if (pkcs11_get_token_info(module, slots[z],
1306 &tinfo.tinfo) != CKR_OK) {
1309 tinfo.sid = slots[z];
1310 tinfo.prov = &providers[x];
1312 if (pkcs11_get_slot_info(module, slots[z],
1313 &tinfo.sinfo) != CKR_OK) {
1318 if (!p11_kit_uri_match_token_info
1319 (info, &tinfo.tinfo)
1320 || !p11_kit_uri_match_module_info(info,
1327 rv = (module)->C_OpenSession(slots[z],
1328 ((flags & SESSION_WRITE) ? CKF_RW_SESSION : 0)
1329 | CKF_SERIAL_SESSION,
1335 sinfo.module = module;
1337 sinfo.sid = tinfo.sid;
1338 memcpy(&sinfo.tinfo, &tinfo.tinfo, sizeof(sinfo.tinfo));
1340 if (flags & SESSION_LOGIN) {
1342 pkcs11_login(&sinfo, pin_info,
1343 info, (flags & SESSION_SO) ? 1 : 0,
1352 find_func(&sinfo, &tinfo, &providers[x].info, input);
1358 pkcs11_close_session(&sinfo);
1369 sinfo.module = module;
1371 ret = find_func(&sinfo, NULL, NULL, input);
1375 (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1380 if (pks != 0 && module != NULL) {
1381 pkcs11_close_session(&sinfo);
1387 /* imports an object from a token to a pkcs11_obj_t structure.
1390 pkcs11_obj_import(ck_object_class_t class, gnutls_pkcs11_obj_t obj,
1391 const gnutls_datum_t * data,
1392 const gnutls_datum_t * id,
1393 const gnutls_datum_t * label,
1394 struct ck_token_info *tinfo, struct ck_info *lib_info)
1396 struct ck_attribute attr;
1400 case CKO_CERTIFICATE:
1401 obj->type = GNUTLS_PKCS11_OBJ_X509_CRT;
1403 case CKO_X_CERTIFICATE_EXTENSION:
1404 obj->type = GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION;
1406 case CKO_PUBLIC_KEY:
1407 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1409 case CKO_PRIVATE_KEY:
1410 obj->type = GNUTLS_PKCS11_OBJ_PRIVKEY;
1412 case CKO_SECRET_KEY:
1413 obj->type = GNUTLS_PKCS11_OBJ_SECRET_KEY;
1416 obj->type = GNUTLS_PKCS11_OBJ_DATA;
1419 _gnutls_debug_log("unknown pkcs11 object class %x\n", (unsigned)class);
1420 obj->type = GNUTLS_PKCS11_OBJ_UNKNOWN;
1423 attr.type = CKA_CLASS;
1424 attr.value = &class;
1425 attr.value_len = sizeof(class);
1426 ret = p11_kit_uri_set_attribute(obj->info, &attr);
1429 return GNUTLS_E_MEMORY_ERROR;
1432 if (data && data->data && data->size) {
1433 ret = _gnutls_set_datum(&obj->raw, data->data, data->size);
1440 /* copy the token and library info into the uri */
1441 memcpy(p11_kit_uri_get_token_info(obj->info), tinfo,
1442 sizeof(struct ck_token_info));
1443 memcpy(p11_kit_uri_get_module_info(obj->info), lib_info,
1444 sizeof(struct ck_info));
1446 if (label && label->data && label->size) {
1447 attr.type = CKA_LABEL;
1448 attr.value = label->data;
1449 attr.value_len = label->size;
1450 ret = p11_kit_uri_set_attribute(obj->info, &attr);
1453 return GNUTLS_E_MEMORY_ERROR;
1457 if (id && id->data && id->size) {
1459 attr.value = id->data;
1460 attr.value_len = id->size;
1461 ret = p11_kit_uri_set_attribute(obj->info, &attr);
1464 return GNUTLS_E_MEMORY_ERROR;
1471 #define MAX_PK_PARAM_SIZE 2048
1473 int pkcs11_read_pubkey(struct ck_function_list *module,
1474 ck_session_handle_t pks, ck_object_handle_t obj,
1475 ck_key_type_t key_type, gnutls_pkcs11_obj_t pobj)
1477 struct ck_attribute a[4];
1479 uint8_t *tmp2 = NULL;
1480 size_t tmp1_size, tmp2_size;
1484 tmp1_size = tmp2_size = MAX_PK_PARAM_SIZE;
1485 tmp1 = gnutls_malloc(tmp1_size);
1487 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1489 tmp2 = gnutls_malloc(tmp2_size);
1491 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1497 a[0].type = CKA_MODULUS;
1499 a[0].value_len = tmp1_size;
1500 a[1].type = CKA_PUBLIC_EXPONENT;
1502 a[1].value_len = tmp2_size;
1504 if (pkcs11_get_attribute_value(module, pks, obj, a, 2) ==
1507 pobj->pubkey[0].data = a[0].value;
1508 pobj->pubkey[0].size = a[0].value_len;
1510 pobj->pubkey[1].data = a[1].value;
1511 pobj->pubkey[1].size = a[1].value_len;
1513 pobj->pubkey_size = 2;
1516 ret = GNUTLS_E_PKCS11_ERROR;
1521 a[0].type = CKA_PRIME;
1523 a[0].value_len = tmp1_size;
1524 a[1].type = CKA_SUBPRIME;
1526 a[1].value_len = tmp2_size;
1528 if ((rv = pkcs11_get_attribute_value(module, pks, obj, a, 2)) ==
1531 _gnutls_set_datum(&pobj->pubkey[0], a[0].value,
1536 _gnutls_set_datum(&pobj->pubkey
1542 _gnutls_free_datum(&pobj->pubkey[1]);
1543 _gnutls_free_datum(&pobj->pubkey[0]);
1544 ret = GNUTLS_E_MEMORY_ERROR;
1548 pobj->pubkey_size = 2;
1551 ret = pkcs11_rv_to_err(rv);
1555 a[0].type = CKA_BASE;
1557 a[0].value_len = tmp1_size;
1558 a[1].type = CKA_VALUE;
1560 a[1].value_len = tmp2_size;
1562 if ((rv = pkcs11_get_attribute_value(module, pks, obj, a, 2)) ==
1564 pobj->pubkey[2].data = a[0].value;
1565 pobj->pubkey[2].size = a[0].value_len;
1567 pobj->pubkey[3].data = a[1].value;
1568 pobj->pubkey[3].size = a[1].value_len;
1570 pobj->pubkey_size = 4;
1573 ret = pkcs11_rv_to_err(rv);
1578 a[0].type = CKA_EC_PARAMS;
1580 a[0].value_len = tmp1_size;
1582 a[1].type = CKA_EC_POINT;
1584 a[1].value_len = tmp2_size;
1586 if ((rv = pkcs11_get_attribute_value(module, pks, obj, a, 2)) ==
1589 pobj->pubkey[0].data = a[0].value;
1590 pobj->pubkey[0].size = a[0].value_len;
1592 pobj->pubkey[1].data = a[1].value;
1593 pobj->pubkey[1].size = a[1].value_len;
1595 pobj->pubkey_size = 2;
1599 ret = pkcs11_rv_to_err(rv);
1605 _gnutls_debug_log("requested reading public key of unsupported type %u\n", (unsigned)key_type);
1606 ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1620 pkcs11_obj_import_pubkey(struct ck_function_list *module,
1621 ck_session_handle_t pks,
1622 ck_object_handle_t ctx,
1623 gnutls_pkcs11_obj_t pobj,
1624 gnutls_datum_t *data,
1625 const gnutls_datum_t *id,
1626 const gnutls_datum_t *label,
1627 struct ck_token_info *tinfo,
1628 struct ck_info *lib_info)
1630 struct ck_attribute a[4];
1631 ck_key_type_t key_type;
1635 a[0].type = CKA_KEY_TYPE;
1636 a[0].value = &key_type;
1637 a[0].value_len = sizeof(key_type);
1639 if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1640 pobj->pk_algorithm = mech_to_pk(key_type);
1643 pkcs11_read_pubkey(module, pks, ctx, key_type,
1646 return gnutls_assert_val(ret);
1649 /* read key usage flags */
1650 a[0].type = CKA_ENCRYPT;
1652 a[0].value_len = sizeof(tval);
1654 if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1656 pobj->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
1660 a[0].type = CKA_VERIFY;
1662 a[0].value_len = sizeof(tval);
1664 if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1666 pobj->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1667 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1668 | GNUTLS_KEY_NON_REPUDIATION;
1672 a[0].type = CKA_VERIFY_RECOVER;
1674 a[0].value_len = sizeof(tval);
1676 if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1678 pobj->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1679 GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1680 | GNUTLS_KEY_NON_REPUDIATION;
1684 a[0].type = CKA_DERIVE;
1686 a[0].value_len = sizeof(tval);
1688 if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1690 pobj->key_usage |= GNUTLS_KEY_KEY_AGREEMENT;
1694 a[0].type = CKA_WRAP;
1696 a[0].value_len = sizeof(tval);
1698 if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1700 pobj->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
1704 ret = pkcs11_obj_import(CKO_PUBLIC_KEY, pobj, data, id, label,
1710 pkcs11_import_object(ck_object_handle_t obj, ck_object_class_t class,
1711 struct pkcs11_session_info *sinfo,
1712 struct token_info *info, struct ck_info *lib_info,
1713 gnutls_pkcs11_obj_t pobj)
1717 struct ck_attribute a[4];
1718 unsigned long category = 0;
1719 char label_tmp[PKCS11_LABEL_SIZE];
1720 char id_tmp[PKCS11_ID_SIZE];
1721 gnutls_datum_t id, label, data = {NULL, 0};
1723 /* now figure out flags */
1725 a[0].type = CKA_WRAP;
1727 a[0].value_len = sizeof(b);
1729 rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1730 if (rv == CKR_OK && b != 0)
1731 pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP;
1733 a[0].type = CKA_UNWRAP;
1735 a[0].value_len = sizeof(b);
1737 rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1738 if (rv == CKR_OK && b != 0)
1739 pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP;
1741 a[0].type = CKA_PRIVATE;
1743 a[0].value_len = sizeof(b);
1745 rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1746 if (rv == CKR_OK && b != 0)
1747 pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE;
1749 a[0].type = CKA_TRUSTED;
1751 a[0].value_len = sizeof(b);
1753 rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1754 if (rv == CKR_OK && b != 0)
1755 pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED;
1757 a[0].type = CKA_SENSITIVE;
1759 a[0].value_len = sizeof(b);
1761 rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1762 if (rv == CKR_OK && b != 0)
1763 pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE;
1765 a[0].type = CKA_CERTIFICATE_CATEGORY;
1766 a[0].value = &category;
1767 a[0].value_len = sizeof(category);
1769 rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 1);
1770 if (rv == CKR_OK && category == 2)
1771 pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_CA;
1773 /* now recover the object label/id */
1774 a[0].type = CKA_LABEL;
1775 a[0].value = label_tmp;
1776 a[0].value_len = sizeof(label_tmp);
1777 rv = pkcs11_get_attribute_value
1778 (sinfo->module, sinfo->pks, obj, a, 1);
1784 label.data = a[0].value;
1785 label.size = a[0].value_len;
1789 a[0].value = id_tmp;
1790 a[0].value_len = sizeof(id_tmp);
1791 rv = pkcs11_get_attribute_value
1792 (sinfo->module, sinfo->pks, obj, a, 1);
1798 id.data = a[0].value;
1799 id.size = a[0].value_len;
1802 if (label.data == NULL && id.data == NULL)
1803 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1805 rv = pkcs11_get_attribute_avalue
1806 (sinfo->module, sinfo->pks, obj, CKA_VALUE, &data);
1809 /* data will be null */
1812 if (class == CKO_PUBLIC_KEY) {
1814 pkcs11_obj_import_pubkey(sinfo->module,
1824 pkcs11_obj_import(class,
1837 gnutls_free(data.data);
1842 find_obj_url_cb(struct pkcs11_session_info *sinfo,
1843 struct token_info *info, struct ck_info *lib_info,
1846 struct find_url_data_st *find_data = input;
1847 struct ck_attribute a[4];
1848 struct ck_attribute *attr;
1849 ck_object_class_t class = -1;
1850 ck_certificate_type_t type = (ck_certificate_type_t) - 1;
1852 ck_object_handle_t obj = CK_INVALID_HANDLE;
1853 unsigned long count, a_vals;
1856 if (info == NULL) { /* we don't support multiple calls */
1858 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1861 /* do not bother reading the token if basic fields do not match
1863 if (!p11_kit_uri_match_token_info
1864 (find_data->obj->info, &info->tinfo)
1865 || !p11_kit_uri_match_module_info(find_data->obj->info,
1868 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1872 attr = p11_kit_uri_get_attribute(find_data->obj->info, CKA_ID);
1874 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1878 attr = p11_kit_uri_get_attribute(find_data->obj->info, CKA_LABEL);
1880 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1886 return GNUTLS_E_INVALID_REQUEST;
1889 /* Find objects with given class and type */
1890 attr = p11_kit_uri_get_attribute(find_data->obj->info, CKA_CLASS);
1893 && attr->value_len == sizeof(ck_object_class_t))
1894 class = *((ck_object_class_t *) attr->value);
1895 if (class == CKO_CERTIFICATE)
1897 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1901 if (type != (ck_certificate_type_t) - 1) {
1902 a[a_vals].type = CKA_CERTIFICATE_TYPE;
1903 a[a_vals].value = &type;
1904 a[a_vals].value_len = sizeof type;
1909 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
1913 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
1914 ret = pkcs11_rv_to_err(rv);
1918 if (pkcs11_find_objects(sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK &&
1920 ret = pkcs11_import_object(obj, class, sinfo, info, lib_info, find_data->obj);
1926 ("p11: Skipped object, missing attrs.\n");
1931 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1937 pkcs11_find_objects_final(sinfo);
1939 if (ret == 0 && find_data->overwrite_exts && find_data->obj->raw.size > 0 && obj != CK_INVALID_HANDLE) {
1940 gnutls_datum_t spki;
1941 rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, obj, CKA_PUBLIC_KEY_INFO, &spki);
1943 ret = pkcs11_override_cert_exts(sinfo, &spki, &find_data->obj->raw);
1944 gnutls_free(spki.data);
1955 unsigned int pkcs11_obj_flags_to_int(unsigned int flags)
1957 unsigned int ret_flags = 0;
1959 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN)
1960 ret_flags |= SESSION_LOGIN;
1961 if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO)
1962 ret_flags |= SESSION_LOGIN | SESSION_SO;
1963 if (flags & GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE)
1964 ret_flags |= SESSION_TRUSTED;
1970 * gnutls_pkcs11_obj_import_url:
1971 * @obj: The structure to store the object
1972 * @url: a PKCS 11 url identifying the key
1973 * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
1975 * This function will "import" a PKCS 11 URL identifying an object (e.g. certificate)
1976 * to the #gnutls_pkcs11_obj_t structure. This does not involve any
1977 * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is
1978 * format agnostic. Only data are transferred.
1980 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1981 * negative error value.
1986 gnutls_pkcs11_obj_import_url(gnutls_pkcs11_obj_t obj, const char *url,
1990 struct find_url_data_st find_data;
1993 memset(&find_data, 0, sizeof(find_data));
1995 /* fill in the find data structure */
1996 find_data.obj = obj;
1998 ret = pkcs11_url_to_info(url, &obj->info, flags);
2004 if (flags & GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT) {
2005 find_data.overwrite_exts = 1;
2009 _pkcs11_traverse_tokens(find_obj_url_cb, &find_data, obj->info,
2011 pkcs11_obj_flags_to_int(flags));
2021 find_token_num_cb(struct pkcs11_session_info *sinfo,
2022 struct token_info *tinfo,
2023 struct ck_info *lib_info, void *input)
2025 struct find_token_num *find_data = input;
2027 if (tinfo == NULL) { /* we don't support multiple calls */
2029 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2032 if (find_data->current == find_data->seq) {
2033 memcpy(p11_kit_uri_get_token_info(find_data->info),
2034 &tinfo->tinfo, sizeof(struct ck_token_info));
2035 memcpy(p11_kit_uri_get_module_info(find_data->info),
2036 lib_info, sizeof(struct ck_info));
2040 find_data->current++;
2041 /* search the token for the id */
2044 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* non zero is enough */
2048 * gnutls_pkcs11_token_get_url:
2049 * @seq: sequence number starting from 0
2050 * @detailed: non zero if a detailed URL is required
2051 * @url: will contain an allocated url
2053 * This function will return the URL for each token available
2054 * in system. The url has to be released using gnutls_free()
2056 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
2057 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if the sequence number
2058 * exceeds the available tokens, otherwise a negative error value.
2063 gnutls_pkcs11_token_get_url(unsigned int seq,
2064 gnutls_pkcs11_url_type_t detailed, char **url)
2067 struct find_token_num tn;
2071 memset(&tn, 0, sizeof(tn));
2073 tn.info = p11_kit_uri_new();
2075 ret = _pkcs11_traverse_tokens(find_token_num_cb, &tn, NULL, NULL, 0);
2077 p11_kit_uri_free(tn.info);
2082 ret = pkcs11_info_to_url(tn.info, detailed, url);
2083 p11_kit_uri_free(tn.info);
2095 * gnutls_pkcs11_token_get_info:
2096 * @url: should contain a PKCS 11 URL
2097 * @ttype: Denotes the type of information requested
2098 * @output: where output will be stored
2099 * @output_size: contains the maximum size of the output and will be overwritten with actual
2101 * This function will return information about the PKCS 11 token such
2102 * as the label, id, etc.
2104 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code
2110 gnutls_pkcs11_token_get_info(const char *url,
2111 gnutls_pkcs11_token_info_t ttype,
2112 void *output, size_t * output_size)
2114 struct p11_kit_uri *info = NULL;
2122 ret = pkcs11_url_to_info(url, &info, 0);
2129 case GNUTLS_PKCS11_TOKEN_LABEL:
2130 str = p11_kit_uri_get_token_info(info)->label;
2133 case GNUTLS_PKCS11_TOKEN_SERIAL:
2134 str = p11_kit_uri_get_token_info(info)->serial_number;
2137 case GNUTLS_PKCS11_TOKEN_MANUFACTURER:
2138 str = p11_kit_uri_get_token_info(info)->manufacturer_id;
2141 case GNUTLS_PKCS11_TOKEN_MODEL:
2142 str = p11_kit_uri_get_token_info(info)->model;
2146 p11_kit_uri_free(info);
2148 return GNUTLS_E_INVALID_REQUEST;
2151 len = p11_kit_space_strlen(str, str_max);
2153 if (len + 1 > *output_size) {
2154 *output_size = len + 1;
2155 return GNUTLS_E_SHORT_MEMORY_BUFFER;
2158 memcpy(output, str, len);
2159 ((char *) output)[len] = '\0';
2165 p11_kit_uri_free(info);
2170 * gnutls_pkcs11_obj_export_url:
2171 * @obj: Holds the PKCS 11 certificate
2172 * @detailed: non zero if a detailed URL is required
2173 * @url: will contain an allocated url
2175 * This function will export a URL identifying the given certificate.
2177 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2178 * negative error value.
2183 gnutls_pkcs11_obj_export_url(gnutls_pkcs11_obj_t obj,
2184 gnutls_pkcs11_url_type_t detailed, char **url)
2188 ret = pkcs11_info_to_url(obj->info, detailed, url);
2198 * gnutls_pkcs11_obj_get_type:
2199 * @obj: Holds the PKCS 11 object
2201 * This function will return the type of the object being
2202 * stored in the structure.
2204 * Returns: The type of the object
2208 gnutls_pkcs11_obj_type_t
2209 gnutls_pkcs11_obj_get_type(gnutls_pkcs11_obj_t obj)
2215 retrieve_pin_from_source(const char *pinfile,
2216 struct ck_token_info *token_info, int attempts,
2217 ck_user_type_t user_type,
2218 struct p11_kit_pin **pin)
2220 unsigned int flags = 0;
2221 struct p11_kit_uri *token_uri;
2222 struct p11_kit_pin *result;
2226 p11_kit_space_strdup(token_info->label,
2227 sizeof(token_info->label));
2228 if (label == NULL) {
2230 return GNUTLS_E_MEMORY_ERROR;
2233 token_uri = p11_kit_uri_new();
2234 if (token_uri == NULL) {
2237 return GNUTLS_E_MEMORY_ERROR;
2240 memcpy(p11_kit_uri_get_token_info(token_uri), token_info,
2241 sizeof(struct ck_token_info));
2244 flags |= P11_KIT_PIN_FLAGS_RETRY;
2245 if (user_type == CKU_USER) {
2246 flags |= P11_KIT_PIN_FLAGS_USER_LOGIN;
2247 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
2248 flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
2249 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
2250 flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
2251 } else if (user_type == CKU_SO) {
2252 flags |= P11_KIT_PIN_FLAGS_SO_LOGIN;
2253 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
2254 flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
2255 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
2256 flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
2257 } else if (user_type == CKU_CONTEXT_SPECIFIC) {
2258 flags |= P11_KIT_PIN_FLAGS_CONTEXT_LOGIN;
2261 result = p11_kit_pin_request(pinfile, token_uri, label, flags);
2262 p11_kit_uri_free(token_uri);
2265 if (result == NULL) {
2267 return GNUTLS_E_PKCS11_PIN_ERROR;
2275 retrieve_pin_from_callback(const struct pin_info_st *pin_info,
2276 struct ck_token_info *token_info,
2277 int attempts, ck_user_type_t user_type,
2278 struct p11_kit_pin **pin)
2280 char pin_value[GNUTLS_PKCS11_MAX_PIN_LEN];
2281 unsigned int flags = 0;
2284 struct p11_kit_uri *token_uri;
2288 p11_kit_space_strdup(token_info->label,
2289 sizeof(token_info->label));
2290 if (label == NULL) {
2292 return GNUTLS_E_MEMORY_ERROR;
2295 token_uri = p11_kit_uri_new();
2296 if (token_uri == NULL) {
2299 return GNUTLS_E_MEMORY_ERROR;
2302 memcpy(p11_kit_uri_get_token_info(token_uri), token_info,
2303 sizeof(struct ck_token_info));
2304 ret = pkcs11_info_to_url(token_uri, 1, &token_str);
2305 p11_kit_uri_free(token_uri);
2310 return GNUTLS_E_MEMORY_ERROR;
2313 if (user_type == CKU_USER || user_type == CKU_CONTEXT_SPECIFIC) {
2314 flags |= GNUTLS_PIN_USER;
2316 if (user_type == CKU_CONTEXT_SPECIFIC)
2317 flags |= GNUTLS_PIN_CONTEXT_SPECIFIC;
2318 if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
2319 flags |= GNUTLS_PIN_COUNT_LOW;
2320 if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
2321 flags |= GNUTLS_PIN_FINAL_TRY;
2322 } else if (user_type == CKU_SO) {
2323 flags |= GNUTLS_PIN_SO;
2324 if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
2325 flags |= GNUTLS_PIN_COUNT_LOW;
2326 if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
2327 flags |= GNUTLS_PIN_FINAL_TRY;
2331 flags |= GNUTLS_PIN_WRONG;
2333 if (pin_info && pin_info->cb)
2335 pin_info->cb(pin_info->data, attempts,
2336 (char *) token_str, label, flags,
2337 pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2338 else if (_gnutls_pin_func)
2340 _gnutls_pin_func(_gnutls_pin_data, attempts,
2341 (char *) token_str, label, flags,
2342 pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2344 ret = gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2350 return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2352 *pin = p11_kit_pin_new_for_string(pin_value);
2355 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2361 retrieve_pin(struct pin_info_st *pin_info, struct p11_kit_uri *info,
2362 struct ck_token_info *token_info, int attempts,
2363 ck_user_type_t user_type, struct p11_kit_pin **pin)
2365 const char *pinfile;
2366 int ret = GNUTLS_E_PKCS11_PIN_ERROR;
2370 #ifdef P11_KIT_HAS_PIN_VALUE
2371 /* First check for pin-value field */
2372 pinfile = p11_kit_uri_get_pin_value(info);
2373 if (pinfile != NULL) {
2374 _gnutls_debug_log("p11: Using pin-value to retrieve PIN\n");
2375 *pin = p11_kit_pin_new_for_string(pinfile);
2378 } else { /* try pin-source */
2379 /* Check if a pinfile is specified, and use that if possible */
2380 pinfile = p11_kit_uri_get_pin_source(info);
2381 if (pinfile != NULL) {
2382 _gnutls_debug_log("p11: Using pin-source to retrieve PIN\n");
2384 retrieve_pin_from_source(pinfile, token_info, attempts,
2389 /* Check if a pinfile is specified, and use that if possible */
2390 pinfile = p11_kit_uri_get_pinfile(info);
2391 if (pinfile != NULL) {
2392 _gnutls_debug_log("p11: Using pinfile to retrieve PIN\n");
2394 retrieve_pin_from_source(pinfile, token_info, attempts,
2399 /* The global gnutls pin callback */
2402 retrieve_pin_from_callback(pin_info, token_info,
2403 attempts, user_type, pin);
2405 /* Otherwise, PIN entry is necessary for login, so fail if there's
2411 ("p11: No suitable pin callback but login required.\n");
2418 pkcs11_login(struct pkcs11_session_info *sinfo,
2419 struct pin_info_st *pin_info,
2420 struct p11_kit_uri *info,
2424 struct ck_session_info session_info;
2425 int attempt = 0, ret;
2426 ck_user_type_t user_type;
2431 user_type = CKU_USER;
2433 user_type = CKU_CONTEXT_SPECIFIC;
2437 if (so == 0 && (sinfo->tinfo.flags & CKF_LOGIN_REQUIRED) == 0) {
2439 _gnutls_debug_log("p11: No login required.\n");
2443 /* For a token with a "protected" (out-of-band) authentication
2444 * path, calling login with a NULL username is all that is
2446 if (sinfo->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
2447 rv = (sinfo->module)->C_Login(sinfo->pks,
2450 if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) {
2455 ("p11: Protected login failed.\n");
2456 ret = GNUTLS_E_PKCS11_ERROR;
2462 struct p11_kit_pin *pin;
2463 struct ck_token_info tinfo;
2465 memcpy(&tinfo, &sinfo->tinfo, sizeof(tinfo));
2467 /* Check whether the session is already logged in, and if so, just skip */
2468 rv = (sinfo->module)->C_GetSessionInfo(sinfo->pks,
2470 if (rv == CKR_OK && reauth == 0 &&
2471 (session_info.state == CKS_RO_USER_FUNCTIONS
2472 || session_info.state == CKS_RW_USER_FUNCTIONS)) {
2477 /* If login has been attempted once already, check the token
2478 * status again, the flags might change. */
2480 if (pkcs11_get_token_info
2481 (sinfo->module, sinfo->sid,
2482 &tinfo) != CKR_OK) {
2485 ("p11: GetTokenInfo failed\n");
2486 ret = GNUTLS_E_PKCS11_ERROR;
2492 retrieve_pin(pin_info, info, &tinfo, attempt++,
2499 rv = (sinfo->module)->C_Login(sinfo->pks, user_type,
2501 p11_kit_pin_get_value(pin,
2503 p11_kit_pin_get_length(pin));
2505 p11_kit_pin_unref(pin);
2507 while (rv == CKR_PIN_INCORRECT);
2509 _gnutls_debug_log("p11: Login result = %lu\n", rv);
2514 CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err(rv);
2520 int pkcs11_call_token_func(struct p11_kit_uri *info, const unsigned retry)
2522 struct ck_token_info *tinfo;
2526 tinfo = p11_kit_uri_get_token_info(info);
2527 label = p11_kit_space_strdup(tinfo->label, sizeof(tinfo->label));
2528 ret = (_gnutls_token_func) (_gnutls_token_data, label, retry);
2536 find_privkeys(struct pkcs11_session_info *sinfo,
2537 struct token_info *info, struct find_pkey_list_st *list)
2539 struct ck_attribute a[3];
2540 ck_object_class_t class;
2542 ck_object_handle_t obj;
2543 unsigned long count, current;
2544 char certid_tmp[PKCS11_ID_SIZE];
2546 class = CKO_PRIVATE_KEY;
2548 /* Find an object with private key class and a certificate ID
2549 * which matches the certificate. */
2550 /* FIXME: also match the cert subject. */
2551 a[0].type = CKA_CLASS;
2552 a[0].value = &class;
2553 a[0].value_len = sizeof class;
2555 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 1);
2558 return pkcs11_rv_to_err(rv);
2561 list->key_ids_size = 0;
2562 while (pkcs11_find_objects
2563 (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK
2565 list->key_ids_size++;
2568 pkcs11_find_objects_final(sinfo);
2570 if (list->key_ids_size == 0) {
2572 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2576 gnutls_malloc(sizeof(gnutls_buffer_st) * list->key_ids_size);
2577 if (list->key_ids == NULL) {
2579 return GNUTLS_E_MEMORY_ERROR;
2583 a[0].type = CKA_CLASS;
2584 a[0].value = &class;
2585 a[0].value_len = sizeof class;
2587 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 1);
2590 return pkcs11_rv_to_err(rv);
2594 while (pkcs11_find_objects
2595 (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK
2599 a[0].value = certid_tmp;
2600 a[0].value_len = sizeof(certid_tmp);
2602 _gnutls_buffer_init(&list->key_ids[current]);
2604 if (pkcs11_get_attribute_value
2605 (sinfo->module, sinfo->pks, obj, a, 1) == CKR_OK) {
2606 _gnutls_buffer_append_data(&list->key_ids[current],
2612 if (current > list->key_ids_size)
2616 pkcs11_find_objects_final(sinfo);
2618 list->key_ids_size = current - 1;
2623 /* Recover certificate list from tokens */
2625 #define OBJECTS_A_TIME 8*1024
2628 find_objs_cb(struct pkcs11_session_info *sinfo,
2629 struct token_info *info, struct ck_info *lib_info, void *input)
2631 struct find_obj_data_st *find_data = input;
2632 struct ck_attribute a[16];
2633 struct ck_attribute *attr;
2634 ck_object_class_t class = (ck_object_class_t) -1;
2635 ck_certificate_type_t type = (ck_certificate_type_t) -1;
2637 unsigned long category;
2639 ck_object_handle_t *objs = NULL;
2640 unsigned long count;
2641 char certid_tmp[PKCS11_ID_SIZE];
2643 struct find_pkey_list_st plist; /* private key holder */
2644 unsigned int i, tot_values = 0;
2651 /* do not bother reading the token if basic fields do not match
2653 if (!p11_kit_uri_match_token_info(find_data->info, &info->tinfo) ||
2654 !p11_kit_uri_match_module_info(find_data->info, lib_info)) {
2656 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2659 memset(&plist, 0, sizeof(plist));
2661 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) {
2662 ret = find_privkeys(sinfo, info, &plist);
2668 if (plist.key_ids_size == 0) {
2670 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2674 /* Find objects with given class and type */
2675 attr = p11_kit_uri_get_attribute(find_data->info, CKA_CLASS);
2678 && attr->value_len == sizeof(ck_object_class_t))
2679 class = *((ck_object_class_t *) attr->value);
2680 if (class == CKO_CERTIFICATE)
2684 /* Find objects with cert class and X.509 cert type. */
2688 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL
2689 || find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY)
2691 class = CKO_CERTIFICATE;
2695 a[tot_values].type = CKA_CLASS;
2696 a[tot_values].value = &class;
2697 a[tot_values].value_len = sizeof class;
2700 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2701 a[tot_values].value = &type;
2702 a[tot_values].value_len = sizeof type;
2705 } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_MATCH) {
2706 if (class != (ck_object_class_t)-1) {
2707 a[tot_values].type = CKA_CLASS;
2708 a[tot_values].value = &class;
2709 a[tot_values].value_len = sizeof class;
2713 } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED) {
2714 class = CKO_CERTIFICATE;
2718 a[tot_values].type = CKA_CLASS;
2719 a[tot_values].value = &class;
2720 a[tot_values].value_len = sizeof class;
2723 a[tot_values].type = CKA_TRUSTED;
2724 a[tot_values].value = &trusted;
2725 a[tot_values].value_len = sizeof trusted;
2728 } else if (find_data->flags ==
2729 GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED_CA) {
2730 class = CKO_CERTIFICATE;
2734 a[tot_values].type = CKA_CLASS;
2735 a[tot_values].value = &class;
2736 a[tot_values].value_len = sizeof class;
2739 a[tot_values].type = CKA_TRUSTED;
2740 a[tot_values].value = &trusted;
2741 a[tot_values].value_len = sizeof trusted;
2745 a[tot_values].type = CKA_CERTIFICATE_CATEGORY;
2746 a[tot_values].value = &category;
2747 a[tot_values].value_len = sizeof category;
2749 } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY) {
2750 class = CKO_PUBLIC_KEY;
2752 a[tot_values].type = CKA_CLASS;
2753 a[tot_values].value = &class;
2754 a[tot_values].value_len = sizeof class;
2756 } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY) {
2757 class = CKO_PRIVATE_KEY;
2759 a[tot_values].type = CKA_CLASS;
2760 a[tot_values].value = &class;
2761 a[tot_values].value_len = sizeof class;
2763 } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL) {
2764 if (class != (ck_object_class_t) - 1) {
2765 a[tot_values].type = CKA_CLASS;
2766 a[tot_values].value = &class;
2767 a[tot_values].value_len = sizeof class;
2770 if (type != (ck_certificate_type_t) - 1) {
2771 a[tot_values].type = CKA_CERTIFICATE_TYPE;
2772 a[tot_values].value = &type;
2773 a[tot_values].value_len = sizeof type;
2778 ret = GNUTLS_E_INVALID_REQUEST;
2782 attr = p11_kit_uri_get_attribute(find_data->info, CKA_ID);
2784 a[tot_values].type = CKA_ID;
2785 a[tot_values].value = attr->value;
2786 a[tot_values].value_len = attr->value_len;
2790 attr = p11_kit_uri_get_attribute(find_data->info, CKA_LABEL);
2792 a[tot_values].type = CKA_LABEL;
2793 a[tot_values].value = attr->value;
2794 a[tot_values].value_len = attr->value_len;
2798 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
2802 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
2803 return pkcs11_rv_to_err(rv);
2806 objs = gnutls_malloc(OBJECTS_A_TIME*sizeof(objs[0]));
2808 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2812 while (pkcs11_find_objects
2813 (sinfo->module, sinfo->pks, objs, OBJECTS_A_TIME, &count) == CKR_OK
2818 find_data->p_list = gnutls_realloc_fast(find_data->p_list, (find_data->current+count)*sizeof(find_data->p_list[0]));
2819 if (find_data->p_list == NULL) {
2820 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2824 for (j=0;j<count;j++) {
2826 a[0].value = certid_tmp;
2827 a[0].value_len = sizeof certid_tmp;
2829 if (pkcs11_get_attribute_value
2830 (sinfo->module, sinfo->pks, objs[j], a, 1) == CKR_OK) {
2831 id.data = a[0].value;
2832 id.size = a[0].value_len;
2838 if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL ||
2839 find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_MATCH) {
2840 a[0].type = CKA_CLASS;
2841 a[0].value = &class;
2842 a[0].value_len = sizeof class;
2844 rv = pkcs11_get_attribute_value(sinfo->module,
2845 sinfo->pks, objs[j], a, 1);
2851 if (find_data->flags ==
2852 GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) {
2853 for (i = 0; i < plist.key_ids_size; i++) {
2854 if (plist.key_ids[i].length !=
2856 || memcmp(plist.key_ids[i].data,
2866 gnutls_pkcs11_obj_init(&find_data->p_list
2867 [find_data->current]);
2873 ret = pkcs11_import_object(objs[j], class, sinfo,
2875 find_data->p_list[find_data->current]);
2878 /* skip the failed object */
2882 find_data->current++;
2887 pkcs11_find_objects_final(sinfo);
2889 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* continue until all tokens have been checked */
2893 pkcs11_find_objects_final(sinfo);
2894 if (plist.key_ids != NULL) {
2895 for (i = 0; i < plist.key_ids_size; i++) {
2896 _gnutls_buffer_clear(&plist.key_ids[i]);
2898 gnutls_free(plist.key_ids);
2900 if (find_data->p_list != NULL) {
2901 for (i = 0; i < find_data->current; i++) {
2902 gnutls_pkcs11_obj_deinit(find_data->p_list[i]);
2904 gnutls_free(find_data->p_list);
2906 find_data->p_list = NULL;
2907 find_data->current = 0;
2913 * gnutls_pkcs11_obj_list_import_url:
2914 * @p_list: An uninitialized object list (may be NULL)
2915 * @n_list: initially should hold the maximum size of the list. Will contain the actual size.
2916 * @url: A PKCS 11 url identifying a set of objects
2917 * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2918 * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
2920 * This function will initialize and set values to an object list
2921 * by using all objects identified by a PKCS 11 URL.
2923 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2924 * negative error value.
2929 gnutls_pkcs11_obj_list_import_url(gnutls_pkcs11_obj_t * p_list,
2930 unsigned int *n_list,
2932 gnutls_pkcs11_obj_attr_t attrs,
2936 struct find_obj_data_st priv;
2941 memset(&priv, 0, sizeof(priv));
2943 /* fill in the find data structure */
2946 if (url == NULL || url[0] == 0) {
2950 ret = pkcs11_url_to_info(url, &priv.info, flags);
2957 _pkcs11_traverse_tokens(find_objs_cb, &priv, priv.info,
2958 NULL, pkcs11_obj_flags_to_int(flags));
2959 p11_kit_uri_free(priv.info);
2963 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2970 if (priv.current > *n_list) {
2971 *n_list = priv.current;
2972 for (i=0;i<priv.current;i++) {
2973 gnutls_pkcs11_obj_deinit(priv.p_list[i]);
2975 gnutls_free(priv.p_list);
2976 return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
2979 *n_list = priv.current;
2981 memcpy(p_list, priv.p_list, priv.current*sizeof(p_list[0]));
2982 gnutls_free(priv.p_list);
2988 * gnutls_pkcs11_obj_list_import_url2:
2989 * @p_list: An uninitialized object list (may be NULL)
2990 * @n_list: It will contain the size of the list.
2991 * @url: A PKCS 11 url identifying a set of objects
2992 * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output
2993 * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
2995 * This function will initialize and set values to an object list
2996 * by using all objects identified by the PKCS 11 URL. The output
2997 * is stored in @p_list, which will be initialized.
2999 * All returned objects must be deinitialized using gnutls_pkcs11_obj_deinit(),
3000 * and @p_list must be free'd using gnutls_free().
3002 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3003 * negative error value.
3008 gnutls_pkcs11_obj_list_import_url2(gnutls_pkcs11_obj_t ** p_list,
3009 unsigned int *n_list,
3011 gnutls_pkcs11_obj_attr_t attrs,
3015 struct find_obj_data_st priv;
3019 memset(&priv, 0, sizeof(priv));
3021 /* fill in the find data structure */
3024 if (url == NULL || url[0] == 0) {
3028 ret = pkcs11_url_to_info(url, &priv.info, flags);
3035 _pkcs11_traverse_tokens(find_objs_cb, &priv, priv.info,
3036 NULL, pkcs11_obj_flags_to_int(flags));
3037 p11_kit_uri_free(priv.info);
3041 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
3049 *n_list = priv.current;
3050 *p_list = priv.p_list;
3056 * gnutls_x509_crt_import_pkcs11_url:
3057 * @crt: A certificate of type #gnutls_x509_crt_t
3058 * @url: A PKCS 11 url
3059 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
3061 * This function will import a PKCS 11 certificate directly from a token
3062 * without involving the #gnutls_pkcs11_obj_t structure. This function will
3063 * fail if the certificate stored is not of X.509 type.
3065 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3066 * negative error value.
3071 gnutls_x509_crt_import_pkcs11_url(gnutls_x509_crt_t crt,
3072 const char *url, unsigned int flags)
3074 gnutls_pkcs11_obj_t pcrt;
3077 ret = gnutls_pkcs11_obj_init(&pcrt);
3084 gnutls_pkcs11_obj_set_pin_function(pcrt, crt->pin.cb,
3087 ret = gnutls_pkcs11_obj_import_url(pcrt, url, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_CERT);
3093 ret = gnutls_x509_crt_import(crt, &pcrt->raw, GNUTLS_X509_FMT_DER);
3102 gnutls_pkcs11_obj_deinit(pcrt);
3108 * gnutls_x509_crt_import_pkcs11:
3109 * @crt: A certificate of type #gnutls_x509_crt_t
3110 * @pkcs11_crt: A PKCS 11 object that contains a certificate
3112 * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t
3115 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3116 * negative error value.
3121 gnutls_x509_crt_import_pkcs11(gnutls_x509_crt_t crt,
3122 gnutls_pkcs11_obj_t pkcs11_crt)
3124 return gnutls_x509_crt_import(crt, &pkcs11_crt->raw,
3125 GNUTLS_X509_FMT_DER);
3129 * gnutls_x509_crt_list_import_pkcs11:
3130 * @certs: A list of certificates of type #gnutls_x509_crt_t
3131 * @cert_max: The maximum size of the list
3132 * @objs: A list of PKCS 11 objects
3135 * This function will import a PKCS 11 certificate list to a list of
3136 * #gnutls_x509_crt_t structure. These must not be initialized.
3138 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3139 * negative error value.
3144 gnutls_x509_crt_list_import_pkcs11(gnutls_x509_crt_t * certs,
3145 unsigned int cert_max,
3146 gnutls_pkcs11_obj_t * const objs,
3152 for (i = 0; i < cert_max; i++) {
3153 ret = gnutls_x509_crt_init(&certs[i]);
3159 ret = gnutls_x509_crt_import_pkcs11(certs[i], objs[i]);
3169 for (j = 0; j < i; j++) {
3170 gnutls_x509_crt_deinit(certs[j]);
3177 find_flags_cb(struct pkcs11_session_info *sinfo,
3178 struct token_info *info, struct ck_info *lib_info, void *input)
3180 struct find_flags_data_st *find_data = input;
3182 if (info == NULL) { /* we don't support multiple calls */
3184 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3187 /* do not bother reading the token if basic fields do not match
3189 if (!p11_kit_uri_match_token_info(find_data->info, &info->tinfo) ||
3190 !p11_kit_uri_match_module_info(find_data->info, lib_info)) {
3192 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3196 if (p11_kit_module_get_flags(sinfo->module) & P11_KIT_MODULE_TRUSTED)
3197 find_data->trusted = 1;
3199 find_data->trusted = 0;
3200 find_data->slot_flags = info->sinfo.flags;
3206 * gnutls_pkcs11_token_get_flags:
3207 * @url: should contain a PKCS 11 URL
3208 * @flags: The output flags (GNUTLS_PKCS11_TOKEN_*)
3210 * This function will return information about the PKCS 11 token flags.
3212 * The supported flags are: %GNUTLS_PKCS11_TOKEN_HW and %GNUTLS_PKCS11_TOKEN_TRUSTED.
3214 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
3218 int gnutls_pkcs11_token_get_flags(const char *url, unsigned int *flags)
3220 struct find_flags_data_st find_data;
3225 memset(&find_data, 0, sizeof(find_data));
3226 ret = pkcs11_url_to_info(url, &find_data.info, 0);
3233 _pkcs11_traverse_tokens(find_flags_cb, &find_data, find_data.info,
3235 p11_kit_uri_free(find_data.info);
3243 if (find_data.slot_flags & CKF_HW_SLOT)
3244 *flags |= GNUTLS_PKCS11_TOKEN_HW;
3246 if (find_data.trusted != 0)
3247 *flags |= GNUTLS_PKCS11_TOKEN_TRUSTED;
3254 * gnutls_pkcs11_token_get_mechanism:
3255 * @url: should contain a PKCS 11 URL
3256 * @idx: The index of the mechanism
3257 * @mechanism: The PKCS #11 mechanism ID
3259 * This function will return the names of the supported mechanisms
3260 * by the token. It should be called with an increasing index until
3261 * it return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
3263 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
3268 gnutls_pkcs11_token_get_mechanism(const char *url, unsigned int idx,
3269 unsigned long *mechanism)
3273 struct ck_function_list *module;
3275 struct token_info tinfo;
3276 struct p11_kit_uri *info = NULL;
3277 unsigned long count;
3278 ck_mechanism_type_t mlist[400];
3282 ret = pkcs11_url_to_info(url, &info, 0);
3288 ret = pkcs11_find_slot(&module, &slot, info, &tinfo);
3289 p11_kit_uri_free(info);
3296 count = sizeof(mlist) / sizeof(mlist[0]);
3297 rv = pkcs11_get_mechanism_list(module, slot, mlist, &count);
3300 return pkcs11_rv_to_err(rv);
3305 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3308 *mechanism = mlist[idx];
3315 * gnutls_pkcs11_type_get_name:
3316 * @type: Holds the PKCS 11 object type, a #gnutls_pkcs11_obj_type_t.
3318 * This function will return a human readable description of the
3319 * PKCS11 object type @obj. It will return "Unknown" for unknown
3322 * Returns: human readable string labeling the PKCS11 object type
3327 const char *gnutls_pkcs11_type_get_name(gnutls_pkcs11_obj_type_t type)
3330 case GNUTLS_PKCS11_OBJ_X509_CRT:
3331 return "X.509 Certificate";
3332 case GNUTLS_PKCS11_OBJ_PUBKEY:
3333 return "Public key";
3334 case GNUTLS_PKCS11_OBJ_PRIVKEY:
3335 return "Private key";
3336 case GNUTLS_PKCS11_OBJ_SECRET_KEY:
3337 return "Secret key";
3338 case GNUTLS_PKCS11_OBJ_DATA:
3340 case GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION:
3341 return "X.509 certificate extension";
3342 case GNUTLS_PKCS11_OBJ_UNKNOWN:
3349 int check_found_cert(struct find_cert_st *priv, gnutls_datum_t *data, time_t now)
3351 gnutls_x509_crt_t tcrt = NULL;
3354 ret = gnutls_x509_crt_init(&tcrt);
3360 ret = gnutls_x509_crt_import(tcrt, data, GNUTLS_X509_FMT_DER);
3366 if (priv->key_id.size > 0 &&
3367 !_gnutls_check_valid_key_id(&priv->key_id, tcrt, now)) {
3373 if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE) {
3374 if (priv->crt == NULL) {
3380 if (_gnutls_check_if_same_cert(priv->crt, tcrt) == 0) {
3387 if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY) {
3388 if (priv->crt == NULL) {
3394 if (_gnutls_check_if_same_key(priv->crt, tcrt, 1) == 0) {
3404 gnutls_x509_crt_deinit(tcrt);
3409 find_cert_cb(struct pkcs11_session_info *sinfo,
3410 struct token_info *info, struct ck_info *lib_info, void *input)
3412 struct ck_attribute a[10];
3413 ck_object_class_t class = -1;
3414 ck_certificate_type_t type = (ck_certificate_type_t) - 1;
3416 ck_object_handle_t obj;
3417 unsigned long count, a_vals;
3419 struct find_cert_st *priv = input;
3420 char label_tmp[PKCS11_LABEL_SIZE];
3421 char id_tmp[PKCS11_ID_SIZE];
3422 gnutls_datum_t data = {NULL, 0};
3423 unsigned tries, i, finalized;
3424 ck_bool_t trusted = 1;
3426 gnutls_datum_t label = {NULL,0}, id = {NULL,0};
3430 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3433 /* the DISTRUSTED flag is p11-kit module specific */
3434 if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) {
3435 if (memcmp(lib_info->manufacturer_id, "PKCS#11 Kit", 11) != 0) {
3437 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3441 if (priv->dn.size == 0 && priv->key_id.size == 0 && priv->issuer_dn.size == 0 &&
3442 priv->serial.size == 0)
3443 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
3445 /* Find objects with given class and type */
3447 if (priv->key_id.size > 0 && priv->dn.size > 0)
3452 now = gnutls_time(0);
3453 for (i = 0; i < tries; i++) {
3456 class = CKO_CERTIFICATE;
3457 a[a_vals].type = CKA_CLASS;
3458 a[a_vals].value = &class;
3459 a[a_vals].value_len = sizeof class;
3462 if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED) {
3463 a[a_vals].type = CKA_TRUSTED;
3464 a[a_vals].value = &trusted;
3465 a[a_vals].value_len = sizeof trusted;
3469 if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) {
3470 a[a_vals].type = CKA_X_DISTRUSTED;
3471 a[a_vals].value = &trusted;
3472 a[a_vals].value_len = sizeof trusted;
3476 if (priv->need_import != 0) {
3478 a[a_vals].type = CKA_CERTIFICATE_TYPE;
3479 a[a_vals].value = &type;
3480 a[a_vals].value_len = sizeof type;
3484 if (i == 0 && priv->key_id.size > 0) {
3485 a[a_vals].type = CKA_ID;
3486 a[a_vals].value = priv->key_id.data;
3487 a[a_vals].value_len = priv->key_id.size;
3491 if (priv->dn.size > 0) {
3492 a[a_vals].type = CKA_SUBJECT;
3493 a[a_vals].value = priv->dn.data;
3494 a[a_vals].value_len = priv->dn.size;
3498 if (priv->serial.size > 0) {
3499 a[a_vals].type = CKA_SERIAL_NUMBER;
3500 a[a_vals].value = priv->serial.data;
3501 a[a_vals].value_len = priv->serial.size;
3505 if (priv->issuer_dn.size > 0) {
3506 a[a_vals].type = CKA_ISSUER;
3507 a[a_vals].value = priv->issuer_dn.data;
3508 a[a_vals].value_len = priv->issuer_dn.size;
3513 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
3518 ("p11: FindObjectsInit failed.\n");
3519 ret = pkcs11_rv_to_err(rv);
3523 while (pkcs11_find_objects
3524 (sinfo->module, sinfo->pks, &obj, 1,
3525 &count) == CKR_OK && count == 1) {
3527 if (priv->need_import == 0 && !(priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE)
3528 && !(priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY)) {
3533 /* data will contain the certificate */
3534 rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, obj, CKA_VALUE, &data);
3537 ret = check_found_cert(priv, &data, now);
3539 _gnutls_free_datum(&data);
3543 a[0].type = CKA_LABEL;
3544 a[0].value = label_tmp;
3545 a[0].value_len = sizeof(label_tmp);
3548 a[1].value = id_tmp;
3549 a[1].value_len = sizeof(id_tmp);
3551 if (pkcs11_get_attribute_value(sinfo->module, sinfo->pks, obj, a, 2) == CKR_OK) {
3552 label.data = a[0].value;
3553 label.size = a[0].value_len;
3554 id.data = a[1].value;
3555 id.size = a[1].value_len;
3560 _gnutls_free_datum(&data);
3562 ("p11: Skipped cert, missing attrs.\n");
3567 pkcs11_find_objects_final(sinfo);
3571 if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT && data.size > 0) {
3572 gnutls_datum_t spki;
3573 rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, obj, CKA_PUBLIC_KEY_INFO, &spki);
3575 ret = pkcs11_override_cert_exts(sinfo, &spki, &data);
3576 gnutls_free(spki.data);
3584 if (priv->need_import != 0) {
3586 pkcs11_obj_import(class, priv->obj,
3601 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3607 gnutls_free(data.data);
3609 pkcs11_find_objects_final(sinfo);
3615 * gnutls_pkcs11_get_raw_issuer:
3616 * @url: A PKCS 11 url identifying a token
3617 * @cert: is the certificate to find issuer for
3618 * @issuer: Will hold the issuer if any in an allocated buffer.
3619 * @fmt: The format of the exported issuer.
3620 * @flags: Use zero or flags from %GNUTLS_PKCS11_OBJ_FLAG.
3622 * This function will return the issuer of a given certificate, if it
3623 * is stored in the token. By default only marked as trusted issuers
3624 * are retuned. If any issuer should be returned specify
3625 * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY in @flags.
3627 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3628 * negative error value.
3632 int gnutls_pkcs11_get_raw_issuer(const char *url, gnutls_x509_crt_t cert,
3633 gnutls_datum_t * issuer,
3634 gnutls_x509_crt_fmt_t fmt,
3638 struct find_cert_st priv;
3639 uint8_t id[PKCS11_ID_SIZE];
3641 struct p11_kit_uri *info = NULL;
3645 memset(&priv, 0, sizeof(priv));
3647 if (url == NULL || url[0] == 0) {
3651 ret = pkcs11_url_to_info(url, &info, flags);
3657 id_size = sizeof(id);
3659 gnutls_x509_crt_get_authority_key_id(cert, id, &id_size, NULL);
3661 priv.key_id.data = id;
3662 priv.key_id.size = id_size;
3665 priv.dn.data = cert->raw_issuer_dn.data;
3666 priv.dn.size = cert->raw_issuer_dn.size;
3668 if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY))
3669 flags |= GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED;
3673 ret = gnutls_pkcs11_obj_init(&priv.obj);
3678 priv.need_import = 1;
3681 _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
3682 NULL, pkcs11_obj_flags_to_int(flags));
3688 ret = gnutls_pkcs11_obj_export3(priv.obj, fmt, issuer);
3698 gnutls_pkcs11_obj_deinit(priv.obj);
3700 p11_kit_uri_free(info);
3706 * gnutls_pkcs11_crt_is_known:
3707 * @url: A PKCS 11 url identifying a token
3708 * @cert: is the certificate to find issuer for
3709 * @issuer: Will hold the issuer if any in an allocated buffer.
3710 * @fmt: The format of the exported issuer.
3711 * @flags: Use zero or flags from %GNUTLS_PKCS11_OBJ_FLAG.
3713 * This function will check whether the provided certificate is stored
3714 * in the specified token. This is useful in combination with
3715 * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED or
3716 * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED,
3717 * to check whether a CA is present or a certificate is blacklisted in
3718 * a trust PKCS #11 module.
3720 * This function can be used with a @url of "pkcs11:", and in that case all modules
3721 * will be searched. To restrict the modules to the marked as trusted in p11-kit
3722 * use the %GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE flag.
3724 * Note that the flag %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED is
3725 * specific to p11-kit trust modules.
3727 * Returns: If the certificate exists non-zero is returned, otherwise zero.
3731 int gnutls_pkcs11_crt_is_known(const char *url, gnutls_x509_crt_t cert,
3735 struct find_cert_st priv;
3736 uint8_t serial[128];
3738 struct p11_kit_uri *info = NULL;
3740 PKCS11_CHECK_INIT_RET(0);
3742 memset(&priv, 0, sizeof(priv));
3744 if (url == NULL || url[0] == 0) {
3748 ret = pkcs11_url_to_info(url, &info, 0);
3754 /* Attempt searching using the issuer DN + serial number */
3755 serial_size = sizeof(serial);
3757 gnutls_x509_crt_get_serial(cert, serial, &serial_size);
3764 ret = _gnutls_x509_ext_gen_number(serial, serial_size, &priv.serial);
3773 priv.issuer_dn.data = cert->raw_issuer_dn.data;
3774 priv.issuer_dn.size = cert->raw_issuer_dn.size;
3776 /* assume PKCS11_OBJ_FLAG_COMPARE everywhere but DISTRUST info */
3777 if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) && !(flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY)) {
3778 flags |= GNUTLS_PKCS11_OBJ_FLAG_COMPARE;
3784 _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
3785 NULL, pkcs11_obj_flags_to_int(flags));
3786 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
3787 _gnutls_debug_log("crt_is_known: did not find cert, using issuer DN + serial, using DN only\n");
3788 /* attempt searching with the subject DN only */
3790 gnutls_free(priv.serial.data);
3791 memset(&priv, 0, sizeof(priv));
3795 priv.dn.data = cert->raw_dn.data;
3796 priv.dn.size = cert->raw_dn.size;
3798 _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
3799 NULL, pkcs11_obj_flags_to_int(flags));
3803 _gnutls_debug_log("crt_is_known: did not find any cert\n");
3812 p11_kit_uri_free(info);
3813 gnutls_free(priv.serial.data);
3819 * gnutls_pkcs11_obj_get_flags:
3820 * @obj: The structure that holds the object
3821 * @oflags: Will hold the output flags
3823 * This function will return the flags of the object being
3824 * stored in the structure. The @oflags are the %GNUTLS_PKCS11_OBJ_FLAG_MARK
3827 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3828 * negative error value.
3833 gnutls_pkcs11_obj_get_flags(gnutls_pkcs11_obj_t obj, unsigned int *oflags)
3835 *oflags = obj->flags;
3841 * gnutls_pkcs11_obj_flags_get_str:
3842 * @flags: holds the flags
3844 * This function given an or-sequence of %GNUTLS_PKCS11_OBJ_FLAG_MARK,
3845 * will return an allocated string with its description. The string
3846 * needs to be deallocated using gnutls_free().
3848 * Returns: If flags is zero %NULL is returned, otherwise an allocated string.
3852 char *gnutls_pkcs11_obj_flags_get_str(unsigned int flags)
3854 gnutls_buffer_st str;
3861 _gnutls_buffer_init(&str);
3862 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP)
3863 _gnutls_buffer_append_str(&str, "CKA_WRAP/UNWRAP; ");
3865 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA)
3866 _gnutls_buffer_append_str(&str, "CKA_CERTIFICATE_CATEGORY=CA; ");
3868 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE)
3869 _gnutls_buffer_append_str(&str, "CKA_PRIVATE; ");
3871 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED)
3872 _gnutls_buffer_append_str(&str, "CKA_TRUSTED; ");
3874 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
3875 _gnutls_buffer_append_str(&str, "CKA_SENSITIVE; ");
3877 ret = _gnutls_buffer_to_datum(&str, &out);
3883 return (char*)out.data;