1 /*
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-2017 Red Hat
7  *
8  * Authors: Nikos Mavrogiannopoulos, Stef Walter
9  *
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
12  * Alon Bar-Lev.
13  *
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.
18  *
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.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with this program.  If not, see <https://www.gnu.org/licenses/>
26  */
27 
28 #include "gnutls_int.h"
29 #include <gnutls/pkcs11.h>
30 #include <string.h>
31 #include "errors.h"
32 #include <datum.h>
33 #include <x509/common.h>
34 #include <locks.h>
35 
36 #include <pin.h>
37 #include <pkcs11_int.h>
38 #include "pkcs11x.h"
39 #include <system-keys.h>
40 #include "x509/x509_int.h"
41 
42 #include <atfork.h>
43 
44 #define MAX_PROVIDERS 16
45 
46 #define MAX_SLOTS 48
47 
48 extern void *_gnutls_pkcs11_mutex;
49 
50 struct gnutls_pkcs11_provider_st {
51 	struct ck_function_list *module;
52 	unsigned active;
53 	unsigned custom_init;
54 	unsigned trusted; /* in the sense of p11-kit trusted:
55 			   * it can be used for verification */
56 	struct ck_info info;
57 };
58 
59 struct find_flags_data_st {
60 	struct p11_kit_uri *info;
61 	unsigned int slot_flags; /* Slot Information Flags */
62 	unsigned int token_flags; /* Token Information Flags */
63 	unsigned int trusted;
64 };
65 
66 struct find_single_obj_st {
67 	gnutls_pkcs11_obj_t obj;
68 	bool overwrite_exts; /* only valid if looking for a certificate */
69 };
70 
71 struct find_obj_session_st {
72 	gnutls_pkcs11_obj_t obj;
73 	struct ck_function_list *ptr;
74 	ck_session_handle_t pks;
75 	ck_object_handle_t ohandle;
76 	unsigned long slot_id;
77 };
78 
79 struct find_multi_obj_st {
80 	gnutls_pkcs11_obj_t *p_list;
81 	unsigned int current;
82 	unsigned int flags;
83 	struct p11_kit_uri *info;
84 	bool overwrite_exts; /* only valid if looking for a certificate */
85 };
86 
87 struct find_token_num {
88 	struct p11_kit_uri *info;
89 	unsigned int seq;	/* which one we are looking for */
90 	unsigned int current;	/* which one are we now */
91 };
92 
93 struct find_token_modname {
94 	struct p11_kit_uri *info;
95 	char *modname;
96 	void *ptr;
97 	unsigned long slot_id;
98 };
99 
100 struct find_pkey_list_st {
101 	gnutls_buffer_st *key_ids;
102 	size_t key_ids_size;
103 };
104 
105 struct find_cert_st {
106 	gnutls_datum_t dn;
107 	gnutls_datum_t issuer_dn;
108 	gnutls_datum_t key_id;
109 	gnutls_datum_t serial;
110 
111 	unsigned need_import;
112 	gnutls_pkcs11_obj_t obj;
113 	gnutls_x509_crt_t crt; /* used when compare flag is specified */
114 	unsigned flags;
115 };
116 
117 
118 static struct gnutls_pkcs11_provider_st providers[MAX_PROVIDERS];
119 static unsigned int active_providers = 0;
120 
121 static init_level_t providers_initialized = PROV_UNINITIALIZED;
122 static unsigned int pkcs11_forkid = 0;
123 
124 static int _gnutls_pkcs11_reinit(void);
125 
126 gnutls_pkcs11_token_callback_t _gnutls_token_func;
127 void *_gnutls_token_data;
128 
129 static int auto_load(unsigned trusted);
130 
pkcs11_rv_to_err(ck_rv_t rv)131 int pkcs11_rv_to_err(ck_rv_t rv)
132 {
133 	switch (rv) {
134 	case CKR_OK:
135 		return 0;
136 	case CKR_HOST_MEMORY:
137 		return GNUTLS_E_MEMORY_ERROR;
138 	case CKR_SLOT_ID_INVALID:
139 		return GNUTLS_E_PKCS11_SLOT_ERROR;
140 	case CKR_ARGUMENTS_BAD:
141 	case CKR_MECHANISM_PARAM_INVALID:
142 		return GNUTLS_E_INVALID_REQUEST;
143 	case CKR_NEED_TO_CREATE_THREADS:
144 	case CKR_CANT_LOCK:
145 	case CKR_FUNCTION_NOT_PARALLEL:
146 	case CKR_MUTEX_BAD:
147 	case CKR_MUTEX_NOT_LOCKED:
148 		return GNUTLS_E_LOCKING_ERROR;
149 	case CKR_ATTRIBUTE_READ_ONLY:
150 	case CKR_ATTRIBUTE_SENSITIVE:
151 	case CKR_ATTRIBUTE_TYPE_INVALID:
152 	case CKR_ATTRIBUTE_VALUE_INVALID:
153 		return GNUTLS_E_PKCS11_ATTRIBUTE_ERROR;
154 	case CKR_DEVICE_ERROR:
155 	case CKR_DEVICE_MEMORY:
156 	case CKR_DEVICE_REMOVED:
157 		return GNUTLS_E_PKCS11_DEVICE_ERROR;
158 	case CKR_DATA_INVALID:
159 	case CKR_DATA_LEN_RANGE:
160 	case CKR_ENCRYPTED_DATA_INVALID:
161 	case CKR_ENCRYPTED_DATA_LEN_RANGE:
162 	case CKR_OBJECT_HANDLE_INVALID:
163 		return GNUTLS_E_PKCS11_DATA_ERROR;
164 	case CKR_FUNCTION_NOT_SUPPORTED:
165 	case CKR_MECHANISM_INVALID:
166 		return GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR;
167 	case CKR_KEY_HANDLE_INVALID:
168 	case CKR_KEY_SIZE_RANGE:
169 	case CKR_KEY_TYPE_INCONSISTENT:
170 	case CKR_KEY_NOT_NEEDED:
171 	case CKR_KEY_CHANGED:
172 	case CKR_KEY_NEEDED:
173 	case CKR_KEY_INDIGESTIBLE:
174 	case CKR_KEY_FUNCTION_NOT_PERMITTED:
175 	case CKR_KEY_NOT_WRAPPABLE:
176 	case CKR_KEY_UNEXTRACTABLE:
177 		return GNUTLS_E_PKCS11_KEY_ERROR;
178 	case CKR_PIN_INCORRECT:
179 	case CKR_PIN_INVALID:
180 	case CKR_PIN_LEN_RANGE:
181 		return GNUTLS_E_PKCS11_PIN_ERROR;
182 	case CKR_PIN_EXPIRED:
183 		return GNUTLS_E_PKCS11_PIN_EXPIRED;
184 	case CKR_PIN_LOCKED:
185 		return GNUTLS_E_PKCS11_PIN_LOCKED;
186 	case CKR_SESSION_CLOSED:
187 	case CKR_SESSION_COUNT:
188 	case CKR_SESSION_HANDLE_INVALID:
189 	case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
190 	case CKR_SESSION_READ_ONLY:
191 	case CKR_SESSION_EXISTS:
192 	case CKR_SESSION_READ_ONLY_EXISTS:
193 	case CKR_SESSION_READ_WRITE_SO_EXISTS:
194 		return GNUTLS_E_PKCS11_SESSION_ERROR;
195 	case CKR_SIGNATURE_INVALID:
196 	case CKR_SIGNATURE_LEN_RANGE:
197 		return GNUTLS_E_PKCS11_SIGNATURE_ERROR;
198 	case CKR_TOKEN_NOT_PRESENT:
199 	case CKR_TOKEN_NOT_RECOGNIZED:
200 	case CKR_TOKEN_WRITE_PROTECTED:
201 		return GNUTLS_E_PKCS11_TOKEN_ERROR;
202 	case CKR_USER_ALREADY_LOGGED_IN:
203 	case CKR_USER_NOT_LOGGED_IN:
204 	case CKR_USER_PIN_NOT_INITIALIZED:
205 	case CKR_USER_TYPE_INVALID:
206 	case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
207 	case CKR_USER_TOO_MANY_TYPES:
208 		return GNUTLS_E_PKCS11_USER_ERROR;
209 	case CKR_BUFFER_TOO_SMALL:
210 		return GNUTLS_E_SHORT_MEMORY_BUFFER;
211 	default:
212 		return GNUTLS_E_PKCS11_ERROR;
213 	}
214 }
215 
216 
scan_slots(struct gnutls_pkcs11_provider_st * p,ck_slot_id_t * slots,unsigned long * nslots)217 static int scan_slots(struct gnutls_pkcs11_provider_st *p,
218 		      ck_slot_id_t * slots, unsigned long *nslots)
219 {
220 	ck_rv_t rv;
221 
222 	rv = pkcs11_get_slot_list(p->module, 1, slots, nslots);
223 	if (rv != CKR_OK) {
224 		gnutls_assert();
225 		return pkcs11_rv_to_err(rv);
226 	}
227 	return 0;
228 }
229 
230 static int
pkcs11_add_module(const char * name,struct ck_function_list * module,unsigned custom_init,const char * params)231 pkcs11_add_module(const char* name, struct ck_function_list *module, unsigned custom_init, const char *params)
232 {
233 	unsigned int i;
234 	struct ck_info info;
235 
236 	if (active_providers >= MAX_PROVIDERS) {
237 		gnutls_assert();
238 		return GNUTLS_E_CONSTRAINT_ERROR;
239 	}
240 
241 	memset(&info, 0, sizeof(info));
242 	pkcs11_get_module_info(module, &info);
243 
244 	/* initially check if this module is a duplicate */
245 	for (i = 0; i < active_providers; i++) {
246 		/* already loaded, skip the rest */
247 		if (module == providers[i].module ||
248 		    memcmp(&info, &providers[i].info, sizeof(info)) == 0) {
249 			_gnutls_debug_log("p11: module %s is already loaded.\n", name);
250 			return GNUTLS_E_INT_RET_0;
251 		}
252 	}
253 
254 	active_providers++;
255 	providers[active_providers - 1].module = module;
256 	providers[active_providers - 1].active = 1;
257 	providers[active_providers - 1].trusted = 0;
258 	providers[active_providers - 1].custom_init = custom_init;
259 
260 	if (p11_kit_module_get_flags(module) & P11_KIT_MODULE_TRUSTED ||
261 		(params != NULL && strstr(params, "trusted") != 0))
262 		providers[active_providers - 1].trusted = 1;
263 
264 	memcpy(&providers[active_providers - 1].info, &info, sizeof(info));
265 
266 	return 0;
267 }
268 
269 /* Returns:
270  *  - negative error code on error,
271  *  - 0 on success
272  *  - 1 on success (and a fork was detected - cb was run)
273  *
274  * The output value of the callback will be returned if it is
275  * a negative one (indicating failure).
276 */
_gnutls_pkcs11_check_init(init_level_t req_level,void * priv,pkcs11_reinit_function cb)277 int _gnutls_pkcs11_check_init(init_level_t req_level, void *priv, pkcs11_reinit_function cb)
278 {
279 	int ret, sret = 0;
280 
281 	ret = gnutls_mutex_lock(&_gnutls_pkcs11_mutex);
282 	if (ret != 0)
283 		return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
284 
285 	if (providers_initialized > PROV_UNINITIALIZED) {
286 		ret = 0;
287 
288 		if (_gnutls_detect_fork(pkcs11_forkid)) {
289 			/* if we are initialized but a fork is detected */
290 			ret = _gnutls_pkcs11_reinit();
291 			if (ret == 0) {
292 				sret = 1;
293 				if (cb) {
294 					int ret2 = cb(priv);
295 					if (ret2 < 0)
296 						ret = ret2;
297 				}
298 				pkcs11_forkid = _gnutls_get_forkid();
299 			}
300 		}
301 
302 		if (ret < 0) {
303 			gnutls_assert();
304 			goto cleanup;
305 		}
306 	}
307 
308 	/* Possible Transitions: PROV_UNINITIALIZED -> PROV_INIT_MANUAL -> PROV_INIT_MANUAL_TRUSTED
309 	 * PROV_UNINITIALIZED -> PROV_INIT_TRUSTED -> PROV_INIT_ALL
310 	 *
311 	 * request for PROV_INIT_TRUSTED may result to PROV_INIT_MANUAL_TRUSTED
312 	 * request for PROV_INIT_ALL may result to PROV_INIT_MANUAL or PROV_INIT_MANUAL_TRUSTED
313 	 */
314 	switch(req_level) {
315 		case PROV_UNINITIALIZED:
316 		case PROV_INIT_MANUAL:
317 			break;
318 		case PROV_INIT_TRUSTED:
319 		case PROV_INIT_MANUAL_TRUSTED:
320 			if (providers_initialized < PROV_INIT_MANUAL_TRUSTED) {
321 				_gnutls_debug_log("Initializing needed PKCS #11 modules\n");
322 				ret = auto_load(1);
323 				if (ret < 0) {
324 					gnutls_assert();
325 				}
326 
327 				if (providers_initialized == PROV_INIT_MANUAL)
328 					providers_initialized = PROV_INIT_MANUAL_TRUSTED;
329 				else
330 					providers_initialized = PROV_INIT_TRUSTED;
331 
332 				goto cleanup;
333 			}
334 			break;
335 		case PROV_INIT_ALL:
336 			if (providers_initialized == PROV_INIT_TRUSTED ||
337 			    providers_initialized == PROV_UNINITIALIZED) {
338 				_gnutls_debug_log("Initializing all PKCS #11 modules\n");
339 				ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO, NULL);
340 				if (ret < 0) {
341 					gnutls_assert();
342 				}
343 
344 				providers_initialized = PROV_INIT_ALL;
345 				goto cleanup;
346 			}
347 			break;
348 	}
349 
350 	ret = sret;
351 
352  cleanup:
353 	gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
354 
355 	return ret;
356 }
357 
358 
359 /**
360  * gnutls_pkcs11_add_provider:
361  * @name: The filename of the module
362  * @params: should be NULL or a known string (see description)
363  *
364  * This function will load and add a PKCS 11 module to the module
365  * list used in gnutls. After this function is called the module will
366  * be used for PKCS 11 operations.
367  *
368  * When loading a module to be used for certificate verification,
369  * use the string 'trusted' as @params.
370  *
371  * Note that this function is not thread safe.
372  *
373  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
374  *   negative error value.
375  *
376  * Since: 2.12.0
377  **/
gnutls_pkcs11_add_provider(const char * name,const char * params)378 int gnutls_pkcs11_add_provider(const char *name, const char *params)
379 {
380 	struct ck_function_list *module;
381 	unsigned custom_init = 0, flags = 0;
382 	struct ck_c_initialize_args args;
383 	const char *p;
384 	int ret;
385 
386 	if (params && (p = strstr(params, "p11-kit:")) != 0) {
387 		memset (&args, 0, sizeof (args));
388 		args.reserved = (char*)(p + sizeof("p11-kit:")-1);
389 		args.flags = CKF_OS_LOCKING_OK;
390 
391 		custom_init = 1;
392 		flags = P11_KIT_MODULE_UNMANAGED;
393 	}
394 
395 	module = p11_kit_module_load(name, P11_KIT_MODULE_CRITICAL|flags);
396 	if (module == NULL) {
397 		gnutls_assert();
398 		_gnutls_debug_log("p11: Cannot load provider %s\n", name);
399 		return GNUTLS_E_PKCS11_LOAD_ERROR;
400 	}
401 
402 	_gnutls_debug_log
403 		    ("p11: Initializing module: %s\n", name);
404 
405 	/* check if we have special information for a p11-kit trust module */
406 	if (custom_init) {
407 		ret = module->C_Initialize(&args);
408 	} else {
409 		ret = p11_kit_module_initialize(module);
410 	}
411 
412 	if (ret != CKR_OK) {
413 		p11_kit_module_release(module);
414 		gnutls_assert();
415 		return pkcs11_rv_to_err(ret);
416 	}
417 
418 	ret = pkcs11_add_module(name, module, custom_init, params);
419 	if (ret != 0) {
420 		if (ret == GNUTLS_E_INT_RET_0)
421 			ret = 0;
422 		if (!custom_init)
423 			p11_kit_module_finalize(module);
424 		else
425 			module->C_Finalize(NULL);
426 		p11_kit_module_release(module);
427 		gnutls_assert();
428 	}
429 
430 	return ret;
431 }
432 
433 static
add_obj_attrs(struct p11_kit_uri * info,struct ck_attribute a[4],unsigned * a_vals,ck_object_class_t * class,ck_certificate_type_t * type)434 int add_obj_attrs(struct p11_kit_uri *info, struct ck_attribute a[4], unsigned *a_vals, ck_object_class_t *class, ck_certificate_type_t *type)
435 {
436 	struct ck_attribute *attr;
437 
438 	*type = -1;
439 	*class = CKO_CERTIFICATE;
440 
441 	/* find the object that matches the URL */
442 	*a_vals = 0;
443 	attr = p11_kit_uri_get_attribute(info, CKA_ID);
444 	if (attr) {
445 		memcpy(a + (*a_vals), attr, sizeof(struct ck_attribute));
446 		(*a_vals)++;
447 	}
448 
449 	attr = p11_kit_uri_get_attribute(info, CKA_LABEL);
450 	if (attr) {
451 		memcpy(a + (*a_vals), attr, sizeof(struct ck_attribute));
452 		(*a_vals)++;
453 	}
454 
455 	if (!(*a_vals)) {
456 		gnutls_assert();
457 		return GNUTLS_E_INVALID_REQUEST;
458 	}
459 
460 	/* Find objects with given class and type */
461 	attr = p11_kit_uri_get_attribute(info, CKA_CLASS);
462 	if (attr) {
463 		if (attr->value
464 		    && attr->value_len == sizeof(ck_object_class_t))
465 			memcpy(class, attr->value, sizeof(ck_object_class_t));
466 		if (*class == CKO_CERTIFICATE)
467 			*type = CKC_X_509;
468 		memcpy(a + (*a_vals), attr, sizeof(struct ck_attribute));
469 		(*a_vals)++;
470 	}
471 
472 	if (*type != (ck_certificate_type_t) - 1) {
473 		a[(*a_vals)].type = CKA_CERTIFICATE_TYPE;
474 		a[(*a_vals)].value = type;
475 		a[(*a_vals)].value_len = sizeof *type;
476 		(*a_vals)++;
477 	}
478 
479 	return 0;
480 }
481 
482 /**
483  * gnutls_pkcs11_obj_set_info:
484  * @obj: should contain a #gnutls_pkcs11_obj_t type
485  * @itype: Denotes the type of information to be set
486  * @data: the data to set
487  * @data_size: the size of data
488  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
489  *
490  * This function will set attributes on the provided object.
491  * Available options for @itype are %GNUTLS_PKCS11_OBJ_LABEL,
492  * %GNUTLS_PKCS11_OBJ_ID_HEX, and %GNUTLS_PKCS11_OBJ_ID.
493  *
494  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
495  *
496  * Since: 3.4.0
497  **/
498 int
gnutls_pkcs11_obj_set_info(gnutls_pkcs11_obj_t obj,gnutls_pkcs11_obj_info_t itype,const void * data,size_t data_size,unsigned flags)499 gnutls_pkcs11_obj_set_info(gnutls_pkcs11_obj_t obj,
500 			   gnutls_pkcs11_obj_info_t itype,
501 			   const void *data, size_t data_size,
502 			   unsigned flags)
503 {
504 	struct p11_kit_uri *info = obj->info;
505 	struct pkcs11_session_info sinfo;
506 	struct ck_attribute a[4];
507 	ck_object_handle_t ctx[2];
508 	ck_certificate_type_t type;
509 	ck_object_class_t class;
510 	unsigned long count;
511 	size_t size;
512 	unsigned a_vals;
513 	char tmp[128];
514 	ck_rv_t rv;
515 	int ret;
516 
517 	PKCS11_CHECK_INIT;
518 
519 	ret =
520 	    pkcs11_open_session(&sinfo, NULL, info,
521 				SESSION_WRITE |
522 				pkcs11_obj_flags_to_int(flags));
523 	if (ret < 0) {
524 		gnutls_assert();
525 		return ret;
526 	}
527 
528 	ret = add_obj_attrs(info, a, &a_vals, &class, &type);
529 	if (ret < 0) {
530 		gnutls_assert();
531 		goto cleanup;
532 	}
533 
534 	rv = pkcs11_find_objects_init(sinfo.module, sinfo.pks, a,
535 				      a_vals);
536 	if (rv != CKR_OK) {
537 		gnutls_assert();
538 		_gnutls_debug_log("p11: FindObjectsInit failed.\n");
539 		ret = pkcs11_rv_to_err(rv);
540 		goto cleanup;
541 	}
542 
543 	rv = pkcs11_find_objects(sinfo.module, sinfo.pks, ctx, 2, &count);
544 	if (rv != CKR_OK) {
545 		gnutls_assert();
546 		_gnutls_debug_log("p11: FindObjects failed.\n");
547 		ret = pkcs11_rv_to_err(rv);
548 		goto cleanup;
549 	}
550 
551 	if (count > 1 || count == 0) {
552 		gnutls_assert();
553 		if (count > 1)
554 			_gnutls_debug_log("p11: More than one objects match (%d)\n", (int)count);
555 		ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
556 		goto cleanup;
557 	}
558 
559 	switch (itype) {
560 	case GNUTLS_PKCS11_OBJ_ID_HEX:
561 		size = sizeof(tmp);
562 		ret = _gnutls_hex2bin(data, data_size, (uint8_t*)tmp, &size);
563 		if (ret < 0) {
564 			gnutls_assert();
565 			goto cleanup;
566 		}
567 		data = tmp;
568 		data_size = size;
569 
570 		FALLTHROUGH;
571 	case GNUTLS_PKCS11_OBJ_ID:
572 		a[0].type = CKA_ID;
573 		a[0].value = (void*)data;
574 		a[0].value_len = data_size;
575 
576 		rv = pkcs11_set_attribute_value(sinfo.module, sinfo.pks, ctx[0], a, 1);
577 		if (rv != CKR_OK) {
578 			gnutls_assert();
579 			_gnutls_debug_log("p11: set_attribute_value failed.\n");
580 			ret = pkcs11_rv_to_err(rv);
581 			goto cleanup;
582 		}
583 
584 		break;
585 	case GNUTLS_PKCS11_OBJ_LABEL:
586 		a[0].type = CKA_LABEL;
587 		a[0].value = (void*)data;
588 		a[0].value_len = data_size;
589 
590 		rv = pkcs11_set_attribute_value(sinfo.module, sinfo.pks, ctx[0], a, 1);
591 		if (rv != CKR_OK) {
592 			gnutls_assert();
593 			_gnutls_debug_log("p11: set_attribute_value failed.\n");
594 			ret = pkcs11_rv_to_err(rv);
595 			goto cleanup;
596 		}
597 
598 		break;
599 	default:
600 		gnutls_assert();
601 		return GNUTLS_E_INVALID_REQUEST;
602 	}
603 
604 	ret = 0;
605  cleanup:
606 	pkcs11_close_session(&sinfo);
607 	return ret;
608 }
609 
610 /**
611  * gnutls_pkcs11_obj_get_info:
612  * @obj: should contain a #gnutls_pkcs11_obj_t type
613  * @itype: Denotes the type of information requested
614  * @output: where output will be stored
615  * @output_size: contains the maximum size of the output buffer and will be
616  *     overwritten with the actual size.
617  *
618  * This function will return information about the PKCS11 certificate
619  * such as the label, id as well as token information where the key is
620  * stored.
621  *
622  * When output is text, a null terminated string is written to @output and its
623  * string length is written to @output_size (without null terminator). If the
624  * buffer is too small, @output_size will contain the expected buffer size
625  * (with null terminator for text) and return %GNUTLS_E_SHORT_MEMORY_BUFFER.
626  *
627  * In versions previously to 3.6.0 this function included the null terminator
628  * to @output_size. After 3.6.0 the output size doesn't include the terminator character.
629  *
630  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
631  *
632  * Since: 2.12.0
633  **/
634 int
gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t obj,gnutls_pkcs11_obj_info_t itype,void * output,size_t * output_size)635 gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t obj,
636 			   gnutls_pkcs11_obj_info_t itype,
637 			   void *output, size_t * output_size)
638 {
639 	return pkcs11_get_info(obj->info, itype, output, output_size);
640 }
641 
642 static int
find_obj_session_cb(struct ck_function_list * module,struct pkcs11_session_info * sinfo,struct ck_token_info * tinfo,struct ck_info * lib_info,void * input)643 find_obj_session_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo,
644 		    struct ck_token_info *tinfo, struct ck_info *lib_info,
645 		    void *input)
646 {
647 	struct find_obj_session_st *find_data = input;
648 	struct ck_attribute a[4];
649 	ck_rv_t rv;
650 	ck_object_handle_t ctx = CK_INVALID_HANDLE;
651 	unsigned long count;
652 	unsigned a_vals;
653         ck_certificate_type_t type;
654         ck_object_class_t class;
655 	int found = 0, ret;
656 
657 	if (tinfo == NULL) {	/* we don't support multiple calls */
658 		gnutls_assert();
659 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
660 	}
661 
662 	/* do not bother reading the token if basic fields do not match
663 	 */
664 	if (!p11_kit_uri_match_token_info(find_data->obj->info, tinfo) ||
665 	    !p11_kit_uri_match_module_info(find_data->obj->info,
666 					      lib_info)) {
667 		gnutls_assert();
668 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
669 	}
670 
671 	ret = add_obj_attrs(find_data->obj->info, a, &a_vals, &class, &type);
672 	if (ret < 0)
673 		return gnutls_assert_val(ret);
674 
675 	rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
676 				      a_vals);
677 	if (rv != CKR_OK) {
678 		gnutls_assert();
679 		_gnutls_debug_log("p11: FindObjectsInit failed.\n");
680 		ret = pkcs11_rv_to_err(rv);
681 		goto cleanup;
682 	}
683 
684 	if (pkcs11_find_objects(sinfo->module, sinfo->pks, &ctx, 1, &count) == CKR_OK &&
685 	    count == 1) {
686 		find_data->ptr = sinfo->module;
687 		find_data->pks = sinfo->pks;
688 		find_data->slot_id = sinfo->sid;
689 		find_data->ohandle = ctx;
690 		found = 1;
691 	}
692 
693 	if (found == 0) {
694 		gnutls_assert();
695 		if (count > 1)
696 			ret = GNUTLS_E_TOO_MANY_MATCHES;
697 		else
698 			ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
699 
700 	} else {
701 		ret = 0;
702 	}
703 
704  cleanup:
705 	pkcs11_find_objects_final(sinfo);
706 
707 	return ret;
708 }
709 
710 
711 /**
712  * gnutls_pkcs11_obj_get_ptr:
713  * @obj: should contain a #gnutls_pkcs11_obj_t type
714  * @ptr: will contain the CK_FUNCTION_LIST_PTR pointer (may be %NULL)
715  * @session: will contain the CK_SESSION_HANDLE of the object
716  * @ohandle: will contain the CK_OBJECT_HANDLE of the object
717  * @slot_id: the identifier of the slot (may be %NULL)
718  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
719  *
720  * Obtains the PKCS#11 session handles of an object. @session and @ohandle
721  * must be deinitialized by the caller. The returned pointers are
722  * independent of the @obj lifetime.
723  *
724  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code
725  * on error.
726  *
727  * Since: 3.6.3
728  **/
729 int
gnutls_pkcs11_obj_get_ptr(gnutls_pkcs11_obj_t obj,void ** ptr,void ** session,void ** ohandle,unsigned long * slot_id,unsigned int flags)730 gnutls_pkcs11_obj_get_ptr(gnutls_pkcs11_obj_t obj, void **ptr,
731 			  void **session, void **ohandle,
732 			  unsigned long *slot_id,
733 			  unsigned int flags)
734 {
735 	int ret;
736 	struct find_obj_session_st find_data;
737 
738 	PKCS11_CHECK_INIT;
739 	memset(&find_data, 0, sizeof(find_data));
740 
741 	find_data.obj = obj;
742 
743 	ret =
744 	    _pkcs11_traverse_tokens(find_obj_session_cb, &find_data, obj->info,
745 				    &obj->pin,
746 				    SESSION_NO_CLOSE|pkcs11_obj_flags_to_int(flags));
747 	if (ret < 0) {
748 		gnutls_assert();
749 		return ret;
750 	}
751 
752 	if (ptr)
753 		*ptr = find_data.ptr;
754 
755 	*ohandle = (void*)find_data.ohandle;
756 	*session = (void*)find_data.pks;
757 
758 	if (slot_id)
759 		*slot_id = find_data.slot_id;
760 
761 	return 0;
762 }
763 
764 int
pkcs11_get_info(struct p11_kit_uri * info,gnutls_pkcs11_obj_info_t itype,void * output,size_t * output_size)765 pkcs11_get_info(struct p11_kit_uri *info,
766 		gnutls_pkcs11_obj_info_t itype, void *output,
767 		size_t * output_size)
768 {
769 	struct ck_attribute *attr = NULL;
770 	struct ck_version *version = NULL;
771 	const uint8_t *str = NULL;
772 	size_t str_max = 0;
773 	int terminate = 0;
774 	int hexify = 0;
775 	size_t length = 0;
776 	const char *data = NULL;
777 	char buf[32];
778 
779 	/*
780 	 * Either attr, str or version is valid by the time switch
781 	 * finishes
782 	 */
783 
784 	switch (itype) {
785 	case GNUTLS_PKCS11_OBJ_ID:
786 		attr = p11_kit_uri_get_attribute(info, CKA_ID);
787 		break;
788 	case GNUTLS_PKCS11_OBJ_ID_HEX:
789 		attr = p11_kit_uri_get_attribute(info, CKA_ID);
790 		hexify = 1;
791 		terminate = 1;
792 		break;
793 	case GNUTLS_PKCS11_OBJ_LABEL:
794 		attr = p11_kit_uri_get_attribute(info, CKA_LABEL);
795 		terminate = 1;
796 		break;
797 	case GNUTLS_PKCS11_OBJ_TOKEN_LABEL:
798 		str = p11_kit_uri_get_token_info(info)->label;
799 		str_max = 32;
800 		break;
801 	case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL:
802 		str = p11_kit_uri_get_token_info(info)->serial_number;
803 		str_max = 16;
804 		break;
805 	case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER:
806 		str = p11_kit_uri_get_token_info(info)->manufacturer_id;
807 		str_max = 32;
808 		break;
809 	case GNUTLS_PKCS11_OBJ_TOKEN_MODEL:
810 		str = p11_kit_uri_get_token_info(info)->model;
811 		str_max = 16;
812 		break;
813 	case GNUTLS_PKCS11_OBJ_LIBRARY_DESCRIPTION:
814 		str =
815 		    p11_kit_uri_get_module_info(info)->library_description;
816 		str_max = 32;
817 		break;
818 	case GNUTLS_PKCS11_OBJ_LIBRARY_VERSION:
819 		version =
820 		    &p11_kit_uri_get_module_info(info)->library_version;
821 		break;
822 	case GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER:
823 		str = p11_kit_uri_get_module_info(info)->manufacturer_id;
824 		str_max = 32;
825 		break;
826 	default:
827 		gnutls_assert();
828 		return GNUTLS_E_INVALID_REQUEST;
829 	}
830 
831 	if (attr != NULL) {
832 		data = attr->value;
833 		length = attr->value_len;
834 	} else if (str != NULL) {
835 		data = (void *) str;
836 		length = p11_kit_space_strlen(str, str_max);
837 		terminate = 1;
838 	} else if (version != NULL) {
839 		data = buf;
840 		length =
841 		    snprintf(buf, sizeof(buf), "%d.%d",
842 			     (int) version->major, (int) version->minor);
843 		terminate = 1;
844 	} else {
845 		*output_size = 0;
846 		if (output)
847 			((uint8_t *) output)[0] = 0;
848 		return 0;
849 	}
850 
851 	if (hexify) {
852 		/* terminate is assumed with hexify */
853 		if (*output_size < length * 3) {
854 			*output_size = length * 3;
855 			return GNUTLS_E_SHORT_MEMORY_BUFFER;
856 		}
857 		if (output && length > 0)
858 			_gnutls_bin2hex(data, length, output, *output_size,
859 					":");
860 		*output_size = length * 3;
861 		return 0;
862 	} else {
863 		if (*output_size < length + terminate) {
864 			*output_size = length + terminate;
865 			return GNUTLS_E_SHORT_MEMORY_BUFFER;
866 		}
867 		if (output) {
868 			memcpy(output, data, length);
869 			if (terminate)
870 				((unsigned char *) output)[length] = '\0';
871 		}
872 		*output_size = length;
873 	}
874 
875 	return 0;
876 }
877 
878 static int init = 0;
879 
880 /* tries to load modules from /usr/local/etc/gnutls/pkcs11.conf if it exists
881  */
compat_load(const char * configfile)882 static void compat_load(const char *configfile)
883 {
884 	FILE *fp;
885 	int ret;
886 	char line[512];
887 	const char *library;
888 
889 	if (configfile == NULL)
890 		configfile = "/usr/local/etc/gnutls/pkcs11.conf";
891 
892 	fp = fopen(configfile, "re");
893 	if (fp == NULL) {
894 		gnutls_assert();
895 		return;
896 	}
897 
898 	_gnutls_debug_log("Loading PKCS #11 libraries from %s\n",
899 			  configfile);
900 	while (fgets(line, sizeof(line), fp) != NULL) {
901 		if (strncmp(line, "load", sizeof("load") - 1) == 0) {
902 			char *p;
903 			p = strchr(line, '=');
904 			if (p == NULL)
905 				continue;
906 
907 			library = ++p;
908 			p = strchr(line, '\n');
909 			if (p != NULL)
910 				*p = 0;
911 
912 			ret = gnutls_pkcs11_add_provider(library, NULL);
913 			if (ret < 0) {
914 				gnutls_assert();
915 				_gnutls_debug_log
916 				    ("Cannot load provider: %s\n",
917 				     library);
918 				continue;
919 			}
920 		}
921 	}
922 	fclose(fp);
923 
924 	return;
925 }
926 
auto_load(unsigned trusted)927 static int auto_load(unsigned trusted)
928 {
929 	struct ck_function_list **modules;
930 	int i, ret;
931 	char* name;
932 
933 	modules = p11_kit_modules_load_and_initialize(trusted?P11_KIT_MODULE_TRUSTED:0);
934 	if (modules == NULL) {
935 		gnutls_assert();
936 		_gnutls_debug_log
937 		    ("Cannot initialize registered modules: %s\n",
938 		     p11_kit_message());
939 		return GNUTLS_E_PKCS11_LOAD_ERROR;
940 	}
941 
942 	for (i = 0; modules[i] != NULL; i++) {
943 		name = p11_kit_module_get_name(modules[i]);
944 		_gnutls_debug_log
945 			    ("p11: Initializing module: %s\n", name);
946 
947 		ret = pkcs11_add_module(name, modules[i], 0, NULL);
948 		if (ret < 0) {
949 			gnutls_assert();
950 			_gnutls_debug_log
951 			    ("Cannot load PKCS #11 module: %s\n", name);
952 		}
953 		free(name);
954 	}
955 
956 	/* Shallow free */
957 	free(modules);
958 	return 0;
959 }
960 
961 /**
962  * gnutls_pkcs11_init:
963  * @flags: An ORed sequence of %GNUTLS_PKCS11_FLAG_*
964  * @deprecated_config_file: either NULL or the location of a deprecated
965  *     configuration file
966  *
967  * This function will initialize the PKCS 11 subsystem in gnutls. It will
968  * read configuration files if %GNUTLS_PKCS11_FLAG_AUTO is used or allow
969  * you to independently load PKCS 11 modules using gnutls_pkcs11_add_provider()
970  * if %GNUTLS_PKCS11_FLAG_MANUAL is specified.
971  *
972  * You don't need to call this function since GnuTLS 3.3.0 because it is being called
973  * during the first request PKCS 11 operation. That call will assume the %GNUTLS_PKCS11_FLAG_AUTO
974  * flag. If another flags are required then it must be called independently
975  * prior to any PKCS 11 operation.
976  *
977  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
978  *   negative error value.
979  *
980  * Since: 2.12.0
981  **/
982 int
gnutls_pkcs11_init(unsigned int flags,const char * deprecated_config_file)983 gnutls_pkcs11_init(unsigned int flags, const char *deprecated_config_file)
984 {
985 	int ret = 0;
986 
987 	if (init != 0) {
988 		init++;
989 		return 0;
990 	}
991 	init++;
992 
993 	pkcs11_forkid = _gnutls_get_forkid();
994 
995 	p11_kit_pin_register_callback(P11_KIT_PIN_FALLBACK,
996 				      p11_kit_pin_file_callback, NULL,
997 				      NULL);
998 
999 	if (flags == GNUTLS_PKCS11_FLAG_MANUAL) {
1000 		/* if manual configuration is requested then don't
1001 		 * bother loading any other providers */
1002 		providers_initialized = PROV_INIT_MANUAL;
1003 		return 0;
1004 	 } else if (flags & GNUTLS_PKCS11_FLAG_AUTO) {
1005 		if (deprecated_config_file == NULL)
1006 			ret = auto_load(0);
1007 
1008 		compat_load(deprecated_config_file);
1009 
1010 		providers_initialized = PROV_INIT_ALL;
1011 
1012 		return ret;
1013 	} else if (flags & GNUTLS_PKCS11_FLAG_AUTO_TRUSTED) {
1014 		ret = auto_load(1);
1015 
1016 		providers_initialized = PROV_INIT_TRUSTED;
1017 
1018 		return ret;
1019 	}
1020 
1021 	return 0;
1022 }
1023 
_gnutls_pkcs11_reinit(void)1024 static int _gnutls_pkcs11_reinit(void)
1025 {
1026 	unsigned i;
1027 	ck_rv_t rv;
1028 
1029 	for (i = 0; i < active_providers; i++) {
1030 		if (providers[i].module != NULL) {
1031 			rv = p11_kit_module_initialize(providers
1032 						       [i].module);
1033 			if (rv == CKR_OK || rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) {
1034 				providers[i].active = 1;
1035 			} else {
1036 				providers[i].active = 0;
1037 				_gnutls_debug_log
1038 				    ("Cannot re-initialize registered module '%.*s': %s\n",
1039 				     (int)32, providers[i].info.library_description,
1040 				     p11_kit_strerror(rv));
1041 			}
1042 		}
1043 	}
1044 
1045 	return 0;
1046 }
1047 
1048 /**
1049  * gnutls_pkcs11_reinit:
1050  *
1051  * This function will reinitialize the PKCS 11 subsystem in gnutls.
1052  * This is required by PKCS 11 when an application uses fork(). The
1053  * reinitialization function must be called on the child.
1054  *
1055  * Note that since GnuTLS 3.3.0, the reinitialization of the PKCS #11
1056  * subsystem occurs automatically after fork.
1057  *
1058  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1059  *   negative error value.
1060  *
1061  * Since: 3.0
1062  **/
gnutls_pkcs11_reinit(void)1063 int gnutls_pkcs11_reinit(void)
1064 {
1065 	int ret;
1066 
1067 	/* make sure that we don't call more than once after a fork */
1068 	if (_gnutls_detect_fork(pkcs11_forkid) == 0)
1069 		return 0;
1070 
1071 	ret = _gnutls_pkcs11_reinit();
1072 
1073 	pkcs11_forkid = _gnutls_get_forkid();
1074 
1075 	return ret;
1076 }
1077 
1078 /**
1079  * gnutls_pkcs11_deinit:
1080  *
1081  * This function will deinitialize the PKCS 11 subsystem in gnutls.
1082  * This function is only needed if you need to deinitialize the
1083  * subsystem without calling gnutls_global_deinit().
1084  *
1085  * Since: 2.12.0
1086  **/
gnutls_pkcs11_deinit(void)1087 void gnutls_pkcs11_deinit(void)
1088 {
1089 	unsigned int i;
1090 
1091 	if (init == 0)
1092 		return;
1093 
1094 	init--;
1095 	if (init > 0)
1096 		return;
1097 
1098 	for (i = 0; i < active_providers; i++) {
1099 		if (providers[i].active) {
1100 
1101 			if (!providers[i].custom_init)
1102 				p11_kit_module_finalize(providers[i].module);
1103 			else
1104 				providers[i].module->C_Finalize(NULL);
1105 		}
1106 		p11_kit_module_release(providers[i].module);
1107 	}
1108 	active_providers = 0;
1109 	providers_initialized = PROV_UNINITIALIZED;
1110 
1111 	gnutls_pkcs11_set_pin_function(NULL, NULL);
1112 	gnutls_pkcs11_set_token_function(NULL, NULL);
1113 	p11_kit_pin_unregister_callback(P11_KIT_PIN_FALLBACK,
1114 					p11_kit_pin_file_callback, NULL);
1115 }
1116 
1117 /**
1118  * gnutls_pkcs11_set_token_function:
1119  * @fn: The token callback
1120  * @userdata: data to be supplied to callback
1121  *
1122  * This function will set a callback function to be used when a token
1123  * needs to be inserted to continue PKCS 11 operations.
1124  *
1125  * Since: 2.12.0
1126  **/
1127 void
gnutls_pkcs11_set_token_function(gnutls_pkcs11_token_callback_t fn,void * userdata)1128 gnutls_pkcs11_set_token_function(gnutls_pkcs11_token_callback_t fn,
1129 				 void *userdata)
1130 {
1131 	_gnutls_token_func = fn;
1132 	_gnutls_token_data = userdata;
1133 }
1134 
pkcs11_url_to_info(const char * url,struct p11_kit_uri ** info,unsigned flags)1135 int pkcs11_url_to_info(const char *url, struct p11_kit_uri **info, unsigned flags)
1136 {
1137 	int allocated = 0;
1138 	int ret;
1139 	struct ck_attribute at;
1140 	ck_object_class_t klass;
1141 
1142 	if (*info == NULL) {
1143 		*info = p11_kit_uri_new();
1144 		if (*info == NULL) {
1145 			gnutls_assert();
1146 			return GNUTLS_E_MEMORY_ERROR;
1147 		}
1148 		allocated = 1;
1149 	}
1150 
1151 	ret = p11_kit_uri_parse(url, P11_KIT_URI_FOR_ANY, *info);
1152 	if (ret < 0) {
1153 		if (allocated) {
1154 			p11_kit_uri_free(*info);
1155 			*info = NULL;
1156 		}
1157 		gnutls_assert();
1158 		return ret == P11_KIT_URI_NO_MEMORY ?
1159 		    GNUTLS_E_MEMORY_ERROR : GNUTLS_E_PARSING_ERROR;
1160 	}
1161 
1162 	/* check for incomplete/invalid URIs */
1163 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_EXPECT_CERT) {
1164 		klass = CKO_CERTIFICATE;
1165 		at.type = CKA_CLASS;
1166 		at.value = &klass;
1167 		at.value_len = sizeof (klass);
1168 		p11_kit_uri_set_attribute (*info, &at);
1169 	} else if (flags & GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY) {
1170 		klass = CKO_PRIVATE_KEY;
1171 		at.type = CKA_CLASS;
1172 		at.value = &klass;
1173 		at.value_len = sizeof (klass);
1174 		p11_kit_uri_set_attribute (*info, &at);
1175 	} else if (flags & GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PUBKEY) {
1176 		klass = CKO_PUBLIC_KEY;
1177 		at.type = CKA_CLASS;
1178 		at.value = &klass;
1179 		at.value_len = sizeof (klass);
1180 		p11_kit_uri_set_attribute (*info, &at);
1181 	}
1182 
1183 	return 0;
1184 }
1185 
1186 int
pkcs11_info_to_url(struct p11_kit_uri * info,gnutls_pkcs11_url_type_t detailed,char ** url)1187 pkcs11_info_to_url(struct p11_kit_uri *info,
1188 		   gnutls_pkcs11_url_type_t detailed, char **url)
1189 {
1190 	p11_kit_uri_type_t type = 0;
1191 	int ret;
1192 
1193 	switch (detailed) {
1194 	case GNUTLS_PKCS11_URL_GENERIC:
1195 		type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN;
1196 		break;
1197 	case GNUTLS_PKCS11_URL_LIB:
1198 		type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE;
1199 		break;
1200 	case GNUTLS_PKCS11_URL_LIB_VERSION:
1201 		type =
1202 		    P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE |
1203 		    P11_KIT_URI_FOR_MODULE_WITH_VERSION;
1204 		break;
1205 	}
1206 
1207 	ret = p11_kit_uri_format(info, type, url);
1208 	if (ret < 0) {
1209 		gnutls_assert();
1210 		return ret == P11_KIT_URI_NO_MEMORY ?
1211 		    GNUTLS_E_MEMORY_ERROR : GNUTLS_E_INTERNAL_ERROR;
1212 	}
1213 
1214 	return 0;
1215 }
1216 
1217 /**
1218  * gnutls_pkcs11_obj_init:
1219  * @obj: A pointer to the type to be initialized
1220  *
1221  * This function will initialize a pkcs11 certificate structure.
1222  *
1223  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1224  *   negative error value.
1225  *
1226  * Since: 2.12.0
1227  **/
gnutls_pkcs11_obj_init(gnutls_pkcs11_obj_t * obj)1228 int gnutls_pkcs11_obj_init(gnutls_pkcs11_obj_t * obj)
1229 {
1230 	*obj = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_obj_st));
1231 	if (*obj == NULL) {
1232 		gnutls_assert();
1233 		return GNUTLS_E_MEMORY_ERROR;
1234 	}
1235 
1236 	(*obj)->info = p11_kit_uri_new();
1237 	if ((*obj)->info == NULL) {
1238 		gnutls_free(*obj);
1239 		gnutls_assert();
1240 		return GNUTLS_E_MEMORY_ERROR;
1241 	}
1242 
1243 	return 0;
1244 }
1245 
1246 /**
1247  * gnutls_pkcs11_obj_set_pin_function:
1248  * @obj: The object structure
1249  * @fn: the callback
1250  * @userdata: data associated with the callback
1251  *
1252  * This function will set a callback function to be used when
1253  * required to access the object. This function overrides the global
1254  * set using gnutls_pkcs11_set_pin_function().
1255  *
1256  * Since: 3.1.0
1257  **/
1258 void
gnutls_pkcs11_obj_set_pin_function(gnutls_pkcs11_obj_t obj,gnutls_pin_callback_t fn,void * userdata)1259 gnutls_pkcs11_obj_set_pin_function(gnutls_pkcs11_obj_t obj,
1260 				   gnutls_pin_callback_t fn,
1261 				   void *userdata)
1262 {
1263 	obj->pin.cb = fn;
1264 	obj->pin.data = userdata;
1265 }
1266 
1267 /**
1268  * gnutls_pkcs11_obj_deinit:
1269  * @obj: The type to be deinitialized
1270  *
1271  * This function will deinitialize a certificate structure.
1272  *
1273  * Since: 2.12.0
1274  **/
gnutls_pkcs11_obj_deinit(gnutls_pkcs11_obj_t obj)1275 void gnutls_pkcs11_obj_deinit(gnutls_pkcs11_obj_t obj)
1276 {
1277 	unsigned i;
1278 	for (i=0;i<obj->pubkey_size;i++)
1279 		_gnutls_free_datum(&obj->pubkey[i]);
1280 	_gnutls_free_datum(&obj->raw);
1281 	p11_kit_uri_free(obj->info);
1282 	free(obj);
1283 }
1284 
1285 /**
1286  * gnutls_pkcs11_obj_export:
1287  * @obj: Holds the object
1288  * @output_data: will contain the object data
1289  * @output_data_size: holds the size of output_data (and will be
1290  *   replaced by the actual size of parameters)
1291  *
1292  * This function will export the PKCS11 object data.  It is normal for
1293  * data to be inaccessible and in that case %GNUTLS_E_INVALID_REQUEST
1294  * will be returned.
1295  *
1296  * If the buffer provided is not long enough to hold the output, then
1297  * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
1298  * be returned.
1299  *
1300  * Returns: In case of failure a negative error code will be
1301  *   returned, and %GNUTLS_E_SUCCESS (0) on success.
1302  *
1303  * Since: 2.12.0
1304  **/
1305 int
gnutls_pkcs11_obj_export(gnutls_pkcs11_obj_t obj,void * output_data,size_t * output_data_size)1306 gnutls_pkcs11_obj_export(gnutls_pkcs11_obj_t obj,
1307 			 void *output_data, size_t * output_data_size)
1308 {
1309 	if (obj == NULL || obj->raw.data == NULL) {
1310 		gnutls_assert();
1311 		return GNUTLS_E_INVALID_REQUEST;
1312 	}
1313 
1314 	if (output_data == NULL || *output_data_size < obj->raw.size) {
1315 		*output_data_size = obj->raw.size;
1316 		gnutls_assert();
1317 		return GNUTLS_E_SHORT_MEMORY_BUFFER;
1318 	}
1319 	*output_data_size = obj->raw.size;
1320 
1321 	memcpy(output_data, obj->raw.data, obj->raw.size);
1322 	return 0;
1323 }
1324 
1325 /**
1326  * gnutls_pkcs11_obj_export2:
1327  * @obj: Holds the object
1328  * @out: will contain the object data
1329  *
1330  * This function will export the PKCS11 object data.  It is normal for
1331  * data to be inaccessible and in that case %GNUTLS_E_INVALID_REQUEST
1332  * will be returned.
1333  *
1334  * The output buffer is allocated using gnutls_malloc().
1335  *
1336  * Returns: In case of failure a negative error code will be
1337  *   returned, and %GNUTLS_E_SUCCESS (0) on success.
1338  *
1339  * Since: 3.1.3
1340  **/
1341 int
gnutls_pkcs11_obj_export2(gnutls_pkcs11_obj_t obj,gnutls_datum_t * out)1342 gnutls_pkcs11_obj_export2(gnutls_pkcs11_obj_t obj, gnutls_datum_t * out)
1343 {
1344 	return gnutls_pkcs11_obj_export3(obj, GNUTLS_X509_FMT_DER, out);
1345 }
1346 
1347 /**
1348  * gnutls_pkcs11_obj_export3:
1349  * @obj: Holds the object
1350  * @out: will contain the object data
1351  * @fmt: The format of the exported data
1352  *
1353  * This function will export the PKCS11 object data.  It is normal for
1354  * data to be inaccessible and in that case %GNUTLS_E_INVALID_REQUEST
1355  * will be returned.
1356  *
1357  * The output buffer is allocated using gnutls_malloc().
1358  *
1359  * Returns: In case of failure a negative error code will be
1360  *   returned, and %GNUTLS_E_SUCCESS (0) on success.
1361  *
1362  * Since: 3.2.7
1363  **/
1364 int
gnutls_pkcs11_obj_export3(gnutls_pkcs11_obj_t obj,gnutls_x509_crt_fmt_t fmt,gnutls_datum_t * out)1365 gnutls_pkcs11_obj_export3(gnutls_pkcs11_obj_t obj,
1366 			  gnutls_x509_crt_fmt_t fmt, gnutls_datum_t * out)
1367 {
1368 	int ret;
1369 
1370 	if (obj == NULL) {
1371 		gnutls_assert();
1372 		return GNUTLS_E_INVALID_REQUEST;
1373 	}
1374 
1375 	switch (obj->type) {
1376 	case GNUTLS_PKCS11_OBJ_X509_CRT:
1377 		if (obj->raw.data == NULL)
1378 			return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1379 
1380 		if (fmt == GNUTLS_X509_FMT_PEM) {
1381 			return
1382 			    gnutls_pem_base64_encode2(PEM_X509_CERT2,
1383 						      &obj->raw, out);
1384 		} else {
1385 			return _gnutls_set_datum(out, obj->raw.data,
1386 						 obj->raw.size);
1387 		}
1388 	case GNUTLS_PKCS11_OBJ_PUBKEY:{
1389 			/* that approach allows to return a public key even if
1390 			 * CKA_VALUE is not set */
1391 			gnutls_pubkey_t pubkey;
1392 
1393 			ret = gnutls_pubkey_init(&pubkey);
1394 			if (ret < 0)
1395 				return gnutls_assert_val(ret);
1396 
1397 			ret =
1398 			    gnutls_pubkey_import_pkcs11(pubkey,
1399 							obj, 0);
1400 			if (ret < 0) {
1401 				gnutls_assert();
1402 				goto pcleanup;
1403 			}
1404 
1405 			ret =
1406 			    gnutls_pubkey_export2(pubkey, fmt,
1407 						  out);
1408 
1409 		      pcleanup:
1410 			gnutls_pubkey_deinit(pubkey);
1411 			return ret;
1412 		}
1413 	default:
1414 		if (obj->raw.data == NULL)
1415 			return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1416 
1417 		if (fmt == GNUTLS_X509_FMT_PEM) {
1418 			return gnutls_pem_base64_encode2("DATA",
1419 							 &obj->raw,
1420 							 out);
1421 		} else {
1422 			return _gnutls_set_datum(out, obj->raw.data,
1423 						 obj->raw.size);
1424 		}
1425 	}
1426 }
1427 
1428 
1429 int
pkcs11_find_slot(struct ck_function_list ** module,ck_slot_id_t * slot,struct p11_kit_uri * info,struct ck_token_info * _tinfo,struct ck_slot_info * _slot_info,unsigned int * trusted)1430 pkcs11_find_slot(struct ck_function_list **module, ck_slot_id_t * slot,
1431 		 struct p11_kit_uri *info,
1432 		 struct ck_token_info *_tinfo,
1433 		 struct ck_slot_info *_slot_info,
1434 		 unsigned int *trusted)
1435 {
1436 	unsigned int x, z;
1437 	int ret;
1438 	unsigned long nslots;
1439 	ck_slot_id_t slots[MAX_SLOTS];
1440 
1441 	for (x = 0; x < active_providers; x++) {
1442 		if (providers[x].active == 0)
1443 			continue;
1444 
1445 		if (!p11_kit_uri_match_module_info(info,
1446 					      &providers[x].info)) {
1447 			continue;
1448 		}
1449 
1450 		nslots = sizeof(slots) / sizeof(slots[0]);
1451 		ret = scan_slots(&providers[x], slots, &nslots);
1452 		if (ret < 0) {
1453 			gnutls_assert();
1454 			continue;
1455 		}
1456 
1457 		for (z = 0; z < nslots; z++) {
1458 			struct ck_token_info tinfo;
1459 			struct ck_slot_info sinfo;
1460 
1461 			if (pkcs11_get_token_info
1462 			    (providers[x].module, slots[z],
1463 			     &tinfo) != CKR_OK) {
1464 				continue;
1465 			}
1466 
1467 			if (!p11_kit_uri_match_token_info(info, &tinfo)) {
1468 				continue;
1469 			}
1470 
1471 			if (pkcs11_get_slot_info
1472 			    (providers[x].module, slots[z], &sinfo) != CKR_OK) {
1473 				continue;
1474 			}
1475 
1476 			/* ok found */
1477 			*module = providers[x].module;
1478 			*slot = slots[z];
1479 
1480 			if (trusted)
1481 				*trusted = providers[x].trusted;
1482 
1483 			if (_tinfo != NULL)
1484 				memcpy(_tinfo, &tinfo, sizeof(tinfo));
1485 
1486 			if (_slot_info != NULL)
1487 				memcpy(_slot_info, &sinfo, sizeof(sinfo));
1488 
1489 			return 0;
1490 		}
1491 	}
1492 
1493 	gnutls_assert();
1494 	return GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE;
1495 }
1496 
1497 int
pkcs11_open_session(struct pkcs11_session_info * sinfo,struct pin_info_st * pin_info,struct p11_kit_uri * info,unsigned int flags)1498 pkcs11_open_session(struct pkcs11_session_info *sinfo,
1499 		    struct pin_info_st *pin_info,
1500 		    struct p11_kit_uri *info, unsigned int flags)
1501 {
1502 	ck_rv_t rv;
1503 	int ret;
1504 	ck_session_handle_t pks = 0;
1505 	struct ck_function_list *module;
1506 	ck_slot_id_t slot;
1507 	struct ck_token_info tinfo;
1508 
1509 	memset(sinfo, 0, sizeof(*sinfo));
1510 
1511 	ret = pkcs11_find_slot(&module, &slot, info, &tinfo,
1512 				&sinfo->slot_info,
1513 				&sinfo->trusted);
1514 	if (ret < 0) {
1515 		gnutls_assert();
1516 		return ret;
1517 	}
1518 
1519 	rv = (module)->C_OpenSession(slot, ((flags & SESSION_WRITE)
1520 					    ? CKF_RW_SESSION : 0) |
1521 				     CKF_SERIAL_SESSION, NULL, NULL, &pks);
1522 	if (rv != CKR_OK) {
1523 		gnutls_assert();
1524 		return pkcs11_rv_to_err(rv);
1525 	}
1526 
1527 	/* ok found */
1528 	sinfo->pks = pks;
1529 	sinfo->module = module;
1530 	sinfo->sid = slot;
1531 	sinfo->init = 1;
1532 	memcpy(&sinfo->tinfo, &tinfo, sizeof(sinfo->tinfo));
1533 
1534 	ret =
1535 	    pkcs11_login(sinfo, pin_info, info,
1536 			 flags);
1537 	if (ret < 0) {
1538 		gnutls_assert();
1539 		pkcs11_close_session(sinfo);
1540 		return ret;
1541 	}
1542 
1543 	return 0;
1544 }
1545 
1546 
1547 int
_pkcs11_traverse_tokens(find_func_t find_func,void * input,struct p11_kit_uri * info,struct pin_info_st * pin_info,unsigned int flags)1548 _pkcs11_traverse_tokens(find_func_t find_func, void *input,
1549 			struct p11_kit_uri *info,
1550 			struct pin_info_st *pin_info, unsigned int flags)
1551 {
1552 	ck_rv_t rv;
1553 	unsigned int found = 0, x, z;
1554 	int ret;
1555 	ck_session_handle_t pks = 0;
1556 	struct pkcs11_session_info sinfo;
1557 	struct ck_function_list *module = NULL;
1558 	unsigned long nslots;
1559 	ck_slot_id_t slots[MAX_SLOTS];
1560 
1561 	for (x = 0; x < active_providers; x++) {
1562 		if (providers[x].active == 0)
1563 			continue;
1564 
1565 		if (flags & SESSION_TRUSTED && providers[x].trusted == 0)
1566 			continue;
1567 
1568 		if (info && !p11_kit_uri_match_module_info(info, &providers[x].info)) {
1569 			continue;
1570 		}
1571 
1572 		nslots = sizeof(slots) / sizeof(slots[0]);
1573 		ret = scan_slots(&providers[x], slots, &nslots);
1574 		if (ret < 0) {
1575 			gnutls_assert();
1576 			continue;
1577 		}
1578 
1579 		module = providers[x].module;
1580 		for (z = 0; z < nslots; z++) {
1581 			struct ck_token_info l_tinfo;
1582 			struct ck_slot_info l_sinfo;
1583 
1584 			if (pkcs11_get_token_info(module, slots[z],
1585 						  &l_tinfo) != CKR_OK) {
1586 				continue;
1587 			}
1588 
1589 			if (info && !p11_kit_uri_match_token_info(info, &l_tinfo)) {
1590 				continue;
1591 			}
1592 
1593 			if (pkcs11_get_slot_info(module, slots[z],
1594 						 &l_sinfo) != CKR_OK) {
1595 				continue;
1596 			}
1597 
1598 			rv = (module)->C_OpenSession(slots[z],
1599 						     ((flags & SESSION_WRITE) ? CKF_RW_SESSION : 0)
1600 						     | CKF_SERIAL_SESSION,
1601 						     NULL, NULL, &pks);
1602 			if (rv != CKR_OK) {
1603 				continue;
1604 			}
1605 
1606 			memset(&sinfo, 0, sizeof(sinfo));
1607 			sinfo.module = module;
1608 			sinfo.pks = pks;
1609 			sinfo.sid = slots[z];
1610 			sinfo.trusted = providers[x].trusted;
1611 
1612 			memcpy(&sinfo.tinfo, &l_tinfo, sizeof(sinfo.tinfo));
1613 			memcpy(&sinfo.slot_info, &l_sinfo, sizeof(sinfo.slot_info));
1614 
1615 			ret =
1616 			    pkcs11_login(&sinfo, pin_info,
1617 					 info, flags);
1618 			if (ret < 0) {
1619 				gnutls_assert();
1620 				pkcs11_close_session(&sinfo);
1621 
1622 				/* treat the error as fatal only if
1623 				 * the token requires login */
1624 				if (l_tinfo.flags & CKF_LOGIN_REQUIRED)
1625 					return ret;
1626 				continue;
1627 			}
1628 
1629 			ret =
1630 			    find_func(providers[x].module, &sinfo, &l_tinfo, &providers[x].info, input);
1631 
1632 			if (ret == 0) {
1633 				found = 1;
1634 				goto finish;
1635 			} else {
1636 				pkcs11_close_session(&sinfo);
1637 				pks = 0;
1638 			}
1639 		}
1640 	}
1641 
1642       finish:
1643 	/* final call */
1644 
1645 	if (found == 0) {
1646 		if (module) {
1647 			sinfo.module = module;
1648 			sinfo.pks = pks;
1649 			ret = find_func(providers[x].module, &sinfo, NULL, NULL, input);
1650 		} else
1651 			ret =
1652 			    gnutls_assert_val
1653 			    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1654 	} else {
1655 		ret = 0;
1656 	}
1657 
1658 	if (pks != 0 && module != NULL) {
1659 		if (ret != 0 || !(flags & SESSION_NO_CLOSE))
1660 			pkcs11_close_session(&sinfo);
1661 	}
1662 
1663 	return ret;
1664 }
1665 
pkcs11_type_to_class(gnutls_pkcs11_obj_type_t type)1666 ck_object_class_t pkcs11_type_to_class(gnutls_pkcs11_obj_type_t type)
1667 {
1668 	switch (type) {
1669 	case GNUTLS_PKCS11_OBJ_X509_CRT:
1670 		return CKO_CERTIFICATE;
1671 	case GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION:
1672 		return CKO_X_CERTIFICATE_EXTENSION;
1673 	case GNUTLS_PKCS11_OBJ_PUBKEY:
1674 		return CKO_PUBLIC_KEY;
1675 	case GNUTLS_PKCS11_OBJ_PRIVKEY:
1676 		return CKO_PRIVATE_KEY;
1677 	case GNUTLS_PKCS11_OBJ_SECRET_KEY:
1678 		return CKO_SECRET_KEY;
1679 	case GNUTLS_PKCS11_OBJ_DATA:
1680 		return CKO_DATA;
1681 	default:
1682 		return -1;
1683 	}
1684 }
1685 
pkcs11_class_to_type(ck_object_class_t class)1686 static gnutls_pkcs11_obj_type_t pkcs11_class_to_type(ck_object_class_t class)
1687 {
1688 	switch (class) {
1689 	case CKO_CERTIFICATE:
1690 		return GNUTLS_PKCS11_OBJ_X509_CRT;
1691 	case CKO_X_CERTIFICATE_EXTENSION:
1692 		return GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION;
1693 	case CKO_PUBLIC_KEY:
1694 		return GNUTLS_PKCS11_OBJ_PUBKEY;
1695 	case CKO_PRIVATE_KEY:
1696 		return GNUTLS_PKCS11_OBJ_PRIVKEY;
1697 	case CKO_SECRET_KEY:
1698 		return GNUTLS_PKCS11_OBJ_SECRET_KEY;
1699 	case CKO_DATA:
1700 		return GNUTLS_PKCS11_OBJ_DATA;
1701 	default:
1702 		_gnutls_debug_log("unknown pkcs11 object class %x\n", (unsigned)class);
1703 		return GNUTLS_PKCS11_OBJ_UNKNOWN;
1704 	}
1705 }
1706 
1707 /* imports an object from a token to a pkcs11_obj_t type.
1708  */
1709 static int
pkcs11_obj_import(ck_object_class_t class,gnutls_pkcs11_obj_t obj,const gnutls_datum_t * data,const gnutls_datum_t * id,const gnutls_datum_t * label,struct ck_token_info * tinfo,struct ck_info * lib_info)1710 pkcs11_obj_import(ck_object_class_t class, gnutls_pkcs11_obj_t obj,
1711 		  const gnutls_datum_t * data,
1712 		  const gnutls_datum_t * id,
1713 		  const gnutls_datum_t * label,
1714 		  struct ck_token_info *tinfo, struct ck_info *lib_info)
1715 {
1716 	struct ck_attribute attr;
1717 	int ret;
1718 
1719 	obj->type = pkcs11_class_to_type(class);
1720 
1721 	attr.type = CKA_CLASS;
1722 	attr.value = &class;
1723 	attr.value_len = sizeof(class);
1724 	ret = p11_kit_uri_set_attribute(obj->info, &attr);
1725 	if (ret < 0) {
1726 		gnutls_assert();
1727 		return GNUTLS_E_MEMORY_ERROR;
1728 	}
1729 
1730 	if (data && data->data && data->size) {
1731 		ret = _gnutls_set_datum(&obj->raw, data->data, data->size);
1732 		if (ret < 0) {
1733 			gnutls_assert();
1734 			return ret;
1735 		}
1736 	}
1737 
1738 	/* copy the token and library info into the uri */
1739 	memcpy(p11_kit_uri_get_token_info(obj->info), tinfo,
1740 	       sizeof(struct ck_token_info));
1741 	memcpy(p11_kit_uri_get_module_info(obj->info), lib_info,
1742 	       sizeof(struct ck_info));
1743 
1744 	if (label && label->data && label->size) {
1745 		attr.type = CKA_LABEL;
1746 		attr.value = label->data;
1747 		attr.value_len = label->size;
1748 		ret = p11_kit_uri_set_attribute(obj->info, &attr);
1749 		if (ret < 0) {
1750 			gnutls_assert();
1751 			return GNUTLS_E_MEMORY_ERROR;
1752 		}
1753 	}
1754 
1755 	if (id && id->data && id->size) {
1756 		attr.type = CKA_ID;
1757 		attr.value = id->data;
1758 		attr.value_len = id->size;
1759 		ret = p11_kit_uri_set_attribute(obj->info, &attr);
1760 		if (ret < 0) {
1761 			gnutls_assert();
1762 			return GNUTLS_E_MEMORY_ERROR;
1763 		}
1764 	}
1765 
1766 	return 0;
1767 }
1768 
pkcs11_read_pubkey(struct ck_function_list * module,ck_session_handle_t pks,ck_object_handle_t ctx,ck_key_type_t key_type,gnutls_pkcs11_obj_t pobj)1769 int pkcs11_read_pubkey(struct ck_function_list *module,
1770 		       ck_session_handle_t pks, ck_object_handle_t ctx,
1771 		       ck_key_type_t key_type, gnutls_pkcs11_obj_t pobj)
1772 {
1773 	struct ck_attribute a[4];
1774 	uint8_t *tmp1;
1775 	uint8_t *tmp2 = NULL;
1776 	size_t tmp1_size, tmp2_size;
1777 	int ret;
1778 	ck_rv_t rv;
1779 
1780 	tmp1_size = tmp2_size = MAX_PK_PARAM_SIZE;
1781 	tmp1 = gnutls_calloc(1, tmp1_size);
1782 	if (tmp1 == NULL)
1783 		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1784 
1785 	tmp2 = gnutls_calloc(1, tmp2_size);
1786 	if (tmp2 == NULL) {
1787 		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1788 		goto cleanup;
1789 	}
1790 
1791 	switch (key_type) {
1792 	case CKK_RSA:
1793 		a[0].type = CKA_MODULUS;
1794 		a[0].value = tmp1;
1795 		a[0].value_len = tmp1_size;
1796 		a[1].type = CKA_PUBLIC_EXPONENT;
1797 		a[1].value = tmp2;
1798 		a[1].value_len = tmp2_size;
1799 
1800 		if (pkcs11_get_attribute_value(module, pks, ctx, a, 2) ==
1801 		    CKR_OK) {
1802 
1803 			pobj->pubkey[0].data = a[0].value;
1804 			pobj->pubkey[0].size = a[0].value_len;
1805 
1806 			pobj->pubkey[1].data = a[1].value;
1807 			pobj->pubkey[1].size = a[1].value_len;
1808 
1809 			pobj->pubkey_size = 2;
1810 		} else {
1811 			gnutls_assert();
1812 			ret = GNUTLS_E_PKCS11_ERROR;
1813 			goto cleanup;
1814 		}
1815 		break;
1816 	case CKK_DSA:
1817 		a[0].type = CKA_PRIME;
1818 		a[0].value = tmp1;
1819 		a[0].value_len = tmp1_size;
1820 		a[1].type = CKA_SUBPRIME;
1821 		a[1].value = tmp2;
1822 		a[1].value_len = tmp2_size;
1823 
1824 		if ((rv = pkcs11_get_attribute_value(module, pks, ctx, a, 2)) ==
1825 		    CKR_OK) {
1826 			ret =
1827 			    _gnutls_set_datum(&pobj->pubkey[0], a[0].value,
1828 					      a[0].value_len);
1829 
1830 			if (ret >= 0)
1831 				ret =
1832 				    _gnutls_set_datum(&pobj->pubkey
1833 						      [1], a[1].value,
1834 						      a[1].value_len);
1835 
1836 			if (ret < 0) {
1837 				gnutls_assert();
1838 				_gnutls_free_datum(&pobj->pubkey[1]);
1839 				_gnutls_free_datum(&pobj->pubkey[0]);
1840 				ret = GNUTLS_E_MEMORY_ERROR;
1841 				goto cleanup;
1842 			}
1843 
1844 			pobj->pubkey_size = 2;
1845 		} else {
1846 			gnutls_assert();
1847 			ret = pkcs11_rv_to_err(rv);
1848 			goto cleanup;
1849 		}
1850 
1851 		a[0].type = CKA_BASE;
1852 		a[0].value = tmp1;
1853 		a[0].value_len = tmp1_size;
1854 		a[1].type = CKA_VALUE;
1855 		a[1].value = tmp2;
1856 		a[1].value_len = tmp2_size;
1857 
1858 		if ((rv = pkcs11_get_attribute_value(module, pks, ctx, a, 2)) ==
1859 		    CKR_OK) {
1860 			pobj->pubkey[2].data = a[0].value;
1861 			pobj->pubkey[2].size = a[0].value_len;
1862 
1863 			pobj->pubkey[3].data = a[1].value;
1864 			pobj->pubkey[3].size = a[1].value_len;
1865 
1866 			pobj->pubkey_size = 4;
1867 		} else {
1868 			gnutls_assert();
1869 			ret = pkcs11_rv_to_err(rv);
1870 			goto cleanup;
1871 		}
1872 		break;
1873 	case CKK_ECDSA:
1874 		a[0].type = CKA_EC_PARAMS;
1875 		a[0].value = tmp1;
1876 		a[0].value_len = tmp1_size;
1877 
1878 		a[1].type = CKA_EC_POINT;
1879 		a[1].value = tmp2;
1880 		a[1].value_len = tmp2_size;
1881 
1882 		if ((rv = pkcs11_get_attribute_value(module, pks, ctx, a, 2)) ==
1883 		    CKR_OK) {
1884 
1885 			pobj->pubkey[0].data = a[0].value;
1886 			pobj->pubkey[0].size = a[0].value_len;
1887 
1888 			pobj->pubkey[1].data = a[1].value;
1889 			pobj->pubkey[1].size = a[1].value_len;
1890 
1891 			pobj->pubkey_size = 2;
1892 		} else {
1893 			gnutls_assert();
1894 
1895 			ret = pkcs11_rv_to_err(rv);
1896 			goto cleanup;
1897 		}
1898 
1899 		break;
1900 #ifdef HAVE_CKM_EDDSA
1901 	case CKK_EC_EDWARDS:
1902 		a[0].type = CKA_EC_PARAMS;
1903 		a[0].value = tmp1;
1904 		a[0].value_len = tmp1_size;
1905 
1906 		a[1].type = CKA_EC_POINT;
1907 		a[1].value = tmp2;
1908 		a[1].value_len = tmp2_size;
1909 
1910 		if ((rv = pkcs11_get_attribute_value(module, pks, ctx, a, 2)) ==
1911 		    CKR_OK) {
1912 
1913 			pobj->pubkey[0].data = a[0].value;
1914 			pobj->pubkey[0].size = a[0].value_len;
1915 
1916 			pobj->pubkey[1].data = a[1].value;
1917 			pobj->pubkey[1].size = a[1].value_len;
1918 
1919 			pobj->pubkey_size = 2;
1920 		} else {
1921 			gnutls_assert();
1922 
1923 			ret = pkcs11_rv_to_err(rv);
1924 			goto cleanup;
1925 		}
1926 
1927 		break;
1928 #endif
1929 	default:
1930 		_gnutls_debug_log("requested reading public key of unsupported type %u\n", (unsigned)key_type);
1931 		ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1932 		goto cleanup;
1933 	}
1934 
1935 	return 0;
1936 
1937 cleanup:
1938 	gnutls_free(tmp1);
1939 	gnutls_free(tmp2);
1940 
1941 	return ret;
1942 }
1943 
1944 static int
pkcs11_obj_import_pubkey(struct ck_function_list * module,ck_session_handle_t pks,ck_object_handle_t ctx,gnutls_pkcs11_obj_t pobj,gnutls_datum_t * data,const gnutls_datum_t * id,const gnutls_datum_t * label,struct ck_token_info * tinfo,struct ck_info * lib_info)1945 pkcs11_obj_import_pubkey(struct ck_function_list *module,
1946 			 ck_session_handle_t pks,
1947 			 ck_object_handle_t ctx,
1948 			 gnutls_pkcs11_obj_t pobj,
1949 			 gnutls_datum_t *data,
1950 			 const gnutls_datum_t *id,
1951 			 const gnutls_datum_t *label,
1952 			 struct ck_token_info *tinfo,
1953 			 struct ck_info *lib_info)
1954 {
1955 	struct ck_attribute a[4];
1956 	ck_key_type_t key_type;
1957 	int ret;
1958 	ck_bool_t tval;
1959 
1960 	a[0].type = CKA_KEY_TYPE;
1961 	a[0].value = &key_type;
1962 	a[0].value_len = sizeof(key_type);
1963 
1964 	if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1965 		pobj->pk_algorithm = key_type_to_pk(key_type);
1966 
1967 		ret =
1968 		    pkcs11_read_pubkey(module, pks, ctx, key_type,
1969 				       pobj);
1970 		if (ret < 0)
1971 			return gnutls_assert_val(ret);
1972 	}
1973 
1974 	/* read key usage flags */
1975 	a[0].type = CKA_ENCRYPT;
1976 	a[0].value = &tval;
1977 	a[0].value_len = sizeof(tval);
1978 
1979 	if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1980 		if (tval != 0) {
1981 			pobj->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
1982 		}
1983 	}
1984 
1985 	a[0].type = CKA_VERIFY;
1986 	a[0].value = &tval;
1987 	a[0].value_len = sizeof(tval);
1988 
1989 	if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1990 		if (tval != 0) {
1991 			pobj->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
1992 			    GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
1993 			    | GNUTLS_KEY_NON_REPUDIATION;
1994 		}
1995 	}
1996 
1997 	a[0].type = CKA_VERIFY_RECOVER;
1998 	a[0].value = &tval;
1999 	a[0].value_len = sizeof(tval);
2000 
2001 	if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
2002 		if (tval != 0) {
2003 			pobj->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE |
2004 			    GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN
2005 			    | GNUTLS_KEY_NON_REPUDIATION;
2006 		}
2007 	}
2008 
2009 	a[0].type = CKA_DERIVE;
2010 	a[0].value = &tval;
2011 	a[0].value_len = sizeof(tval);
2012 
2013 	if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
2014 		if (tval != 0) {
2015 			pobj->key_usage |= GNUTLS_KEY_KEY_AGREEMENT;
2016 		}
2017 	}
2018 
2019 	a[0].type = CKA_WRAP;
2020 	a[0].value = &tval;
2021 	a[0].value_len = sizeof(tval);
2022 
2023 	if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
2024 		if (tval != 0) {
2025 			pobj->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
2026 		}
2027 	}
2028 
2029 	ret = pkcs11_obj_import(CKO_PUBLIC_KEY, pobj, data, id, label,
2030 				 tinfo, lib_info);
2031 	return ret;
2032 }
2033 
2034 static int
pkcs11_import_object(ck_object_handle_t ctx,ck_object_class_t class,struct pkcs11_session_info * sinfo,struct ck_token_info * tinfo,struct ck_info * lib_info,gnutls_pkcs11_obj_t pobj)2035 pkcs11_import_object(ck_object_handle_t ctx, ck_object_class_t class,
2036 		     struct pkcs11_session_info *sinfo,
2037 		     struct ck_token_info *tinfo, struct ck_info *lib_info,
2038 		     gnutls_pkcs11_obj_t pobj)
2039 {
2040 	ck_bool_t b;
2041 	int rv, ret;
2042 	struct ck_attribute a[4];
2043 	unsigned long category = 0;
2044 	char label_tmp[PKCS11_LABEL_SIZE];
2045 	char id_tmp[PKCS11_ID_SIZE];
2046 	gnutls_datum_t id, label, data = {NULL, 0};
2047 
2048 	/* now figure out flags */
2049 	pobj->flags = 0;
2050 	a[0].type = CKA_WRAP;
2051 	a[0].value = &b;
2052 	a[0].value_len = sizeof(b);
2053 
2054 	rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2055 	if (rv == CKR_OK && b != 0)
2056 		pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP;
2057 
2058 	a[0].type = CKA_UNWRAP;
2059 	a[0].value = &b;
2060 	a[0].value_len = sizeof(b);
2061 
2062 	rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2063 	if (rv == CKR_OK && b != 0)
2064 		pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP;
2065 
2066 	a[0].type = CKA_PRIVATE;
2067 	a[0].value = &b;
2068 	a[0].value_len = sizeof(b);
2069 
2070 	rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2071 	if (rv == CKR_OK && b != 0)
2072 		pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE;
2073 
2074 	a[0].type = CKA_TRUSTED;
2075 	a[0].value = &b;
2076 	a[0].value_len = sizeof(b);
2077 
2078 	rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2079 	if (rv == CKR_OK && b != 0)
2080 		pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED;
2081 
2082 	if (sinfo->trusted) { /* only p11-kit "trusted" modules support this flag */
2083 		a[0].type = CKA_X_DISTRUSTED;
2084 		a[0].value = &b;
2085 		a[0].value_len = sizeof(b);
2086 
2087 		rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2088 		if (rv == CKR_OK && b != 0)
2089 			pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_DISTRUSTED;
2090 	}
2091 
2092 	a[0].type = CKA_SENSITIVE;
2093 	a[0].value = &b;
2094 	a[0].value_len = sizeof(b);
2095 
2096 	rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2097 	if (rv == CKR_OK) {
2098 		if (b != 0)
2099 			pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE;
2100 		else
2101 			pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE;
2102 	}
2103 
2104 	a[0].type = CKA_EXTRACTABLE;
2105 	a[0].value = &b;
2106 	a[0].value_len = sizeof(b);
2107 
2108 	rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2109 	if (rv == CKR_OK && b != 0)
2110 		pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_EXTRACTABLE;
2111 
2112 	a[0].type = CKA_NEVER_EXTRACTABLE;
2113 	a[0].value = &b;
2114 	a[0].value_len = sizeof(b);
2115 
2116 	rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2117 	if (rv == CKR_OK && b != 0)
2118 		pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_NEVER_EXTRACTABLE;
2119 
2120 	a[0].type = CKA_CERTIFICATE_CATEGORY;
2121 	a[0].value = &category;
2122 	a[0].value_len = sizeof(category);
2123 
2124 	rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2125 	if (rv == CKR_OK && category == 2)
2126 		pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_CA;
2127 
2128 	a[0].type = CKA_ALWAYS_AUTHENTICATE;
2129 	a[0].value = &b;
2130 	a[0].value_len = sizeof(b);
2131 
2132 	rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2133 	if (rv == CKR_OK && b != 0)
2134 		pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH;
2135 
2136 	/* now recover the object label/id */
2137 	a[0].type = CKA_LABEL;
2138 	a[0].value = label_tmp;
2139 	a[0].value_len = sizeof(label_tmp);
2140 	rv = pkcs11_get_attribute_value
2141 	    (sinfo->module, sinfo->pks, ctx, a, 1);
2142 	if (rv != CKR_OK) {
2143 		gnutls_assert();
2144 		label.data = NULL;
2145 		label.size = 0;
2146 	} else {
2147 		label.data = a[0].value;
2148 		label.size = a[0].value_len;
2149 	}
2150 
2151 	a[0].type = CKA_ID;
2152 	a[0].value = id_tmp;
2153 	a[0].value_len = sizeof(id_tmp);
2154 	rv = pkcs11_get_attribute_value
2155 	    (sinfo->module, sinfo->pks, ctx, a, 1);
2156 	if (rv != CKR_OK) {
2157 		gnutls_assert();
2158 		id.data = NULL;
2159 		id.size = 0;
2160 	} else {
2161 		id.data = a[0].value;
2162 		id.size = a[0].value_len;
2163 	}
2164 
2165 	if (label.data == NULL && id.data == NULL)
2166 		return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
2167 
2168 	rv = pkcs11_get_attribute_avalue
2169 	    (sinfo->module, sinfo->pks, ctx, CKA_VALUE, &data);
2170 	if (rv != CKR_OK) {
2171 		gnutls_assert();
2172 		/* data will be null */
2173 	}
2174 
2175 	if (class == CKO_PUBLIC_KEY) {
2176 		ret =
2177 		    pkcs11_obj_import_pubkey(sinfo->module,
2178 					     sinfo->pks,
2179 					     ctx,
2180 					     pobj,
2181 					     &data,
2182 					     &id, &label,
2183 					     tinfo,
2184 					     lib_info);
2185 	} else {
2186 		ret =
2187 		    pkcs11_obj_import(class,
2188 				      pobj,
2189 				      &data, &id, &label,
2190 				      tinfo,
2191 				      lib_info);
2192 	}
2193 	if (ret < 0) {
2194 		gnutls_assert();
2195 		goto cleanup;
2196 	}
2197 
2198 	ret = 0;
2199  cleanup:
2200 	gnutls_free(data.data);
2201 	return ret;
2202 }
2203 
2204 static int
find_single_obj_cb(struct ck_function_list * module,struct pkcs11_session_info * sinfo,struct ck_token_info * tinfo,struct ck_info * lib_info,void * input)2205 find_single_obj_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo,
2206 	     struct ck_token_info *tinfo, struct ck_info *lib_info,
2207 	     void *input)
2208 {
2209 	struct find_single_obj_st *find_data = input;
2210 	struct ck_attribute a[4];
2211 	ck_certificate_type_t type;
2212 	ck_object_class_t class;
2213 	ck_rv_t rv;
2214 	ck_object_handle_t ctx = CK_INVALID_HANDLE;
2215 	unsigned long count;
2216 	unsigned a_vals;
2217 	int found = 0, ret;
2218 
2219 	if (tinfo == NULL) {	/* we don't support multiple calls */
2220 		gnutls_assert();
2221 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2222 	}
2223 
2224 	/* do not bother reading the token if basic fields do not match
2225 	 */
2226 	if (!p11_kit_uri_match_token_info
2227 	    (find_data->obj->info, tinfo)
2228 	    || !p11_kit_uri_match_module_info(find_data->obj->info,
2229 					      lib_info)) {
2230 		gnutls_assert();
2231 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2232 	}
2233 
2234 	ret = add_obj_attrs(find_data->obj->info, a, &a_vals, &class, &type);
2235 	if (ret < 0)
2236 		return gnutls_assert_val(ret);
2237 
2238 	rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
2239 				      a_vals);
2240 	if (rv != CKR_OK) {
2241 		gnutls_assert();
2242 		_gnutls_debug_log("p11: FindObjectsInit failed.\n");
2243 		ret = pkcs11_rv_to_err(rv);
2244 		goto cleanup;
2245 	}
2246 
2247 	if (pkcs11_find_objects(sinfo->module, sinfo->pks, &ctx, 1, &count) == CKR_OK &&
2248 	    count == 1) {
2249 		ret = pkcs11_import_object(ctx, class, sinfo, tinfo, lib_info, find_data->obj);
2250 		if (ret >= 0) {
2251 			found = 1;
2252 		}
2253 	} else {
2254 		_gnutls_debug_log
2255 		    ("p11: Skipped object, missing attrs.\n");
2256 	}
2257 
2258 	if (found == 0) {
2259 		gnutls_assert();
2260 		ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2261 	} else {
2262 		ret = 0;
2263 	}
2264 
2265       cleanup:
2266 	pkcs11_find_objects_final(sinfo);
2267 
2268 	if (ret == 0 && find_data->overwrite_exts && find_data->obj->raw.size > 0 && ctx != CK_INVALID_HANDLE) {
2269 		gnutls_datum_t spki;
2270 		rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, ctx, CKA_PUBLIC_KEY_INFO, &spki);
2271 		if (rv == CKR_OK) {
2272 			ret = pkcs11_override_cert_exts(sinfo, &spki, &find_data->obj->raw);
2273 			gnutls_free(spki.data);
2274 			if (ret < 0) {
2275 				gnutls_assert();
2276 				return ret;
2277 			}
2278 		}
2279 	}
2280 
2281 	return ret;
2282 }
2283 
pkcs11_obj_flags_to_int(unsigned int flags)2284 unsigned int pkcs11_obj_flags_to_int(unsigned int flags)
2285 {
2286 	unsigned int ret_flags = 0;
2287 
2288 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN)
2289 		ret_flags |= SESSION_LOGIN | SESSION_FORCE_LOGIN;
2290 
2291 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO)
2292 		ret_flags |= SESSION_LOGIN | SESSION_SO | SESSION_FORCE_LOGIN | SESSION_WRITE;
2293 
2294 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE)
2295 		ret_flags |= SESSION_TRUSTED;
2296 
2297 	return ret_flags;
2298 }
2299 
2300 /**
2301  * gnutls_pkcs11_obj_import_url:
2302  * @obj: The structure to store the object
2303  * @url: a PKCS 11 url identifying the key
2304  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
2305  *
2306  * This function will "import" a PKCS 11 URL identifying an object (e.g. certificate)
2307  * to the #gnutls_pkcs11_obj_t type. This does not involve any
2308  * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is
2309  * format agnostic. Only data are transferred.
2310  *
2311  * If the flag %GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT is specified
2312  * any certificate read, will have its extensions overwritten by any
2313  * stapled extensions in the trust module.
2314  *
2315  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2316  *   negative error value.
2317  *
2318  * Since: 2.12.0
2319  **/
2320 int
gnutls_pkcs11_obj_import_url(gnutls_pkcs11_obj_t obj,const char * url,unsigned int flags)2321 gnutls_pkcs11_obj_import_url(gnutls_pkcs11_obj_t obj, const char *url,
2322 			     unsigned int flags)
2323 {
2324 	int ret;
2325 	struct find_single_obj_st find_data;
2326 
2327 	PKCS11_CHECK_INIT;
2328 	memset(&find_data, 0, sizeof(find_data));
2329 
2330 	/* fill in the find data structure */
2331 	find_data.obj = obj;
2332 
2333 	ret = pkcs11_url_to_info(url, &obj->info, flags);
2334 	if (ret < 0) {
2335 		gnutls_assert();
2336 		return ret;
2337 	}
2338 
2339 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT) {
2340 		find_data.overwrite_exts = 1;
2341 	}
2342 
2343 	ret =
2344 	    _pkcs11_traverse_tokens(find_single_obj_cb, &find_data, obj->info,
2345 				    &obj->pin,
2346 				    pkcs11_obj_flags_to_int(flags));
2347 	if (ret < 0) {
2348 		gnutls_assert();
2349 		return ret;
2350 	}
2351 
2352 	return 0;
2353 }
2354 
2355 static int
find_token_num_cb(struct ck_function_list * module,struct pkcs11_session_info * sinfo,struct ck_token_info * tinfo,struct ck_info * lib_info,void * input)2356 find_token_num_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo,
2357 		  struct ck_token_info *tinfo,
2358 		  struct ck_info *lib_info, void *input)
2359 {
2360 	struct find_token_num *find_data = input;
2361 
2362 	if (tinfo == NULL) {	/* we don't support multiple calls */
2363 		gnutls_assert();
2364 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2365 	}
2366 
2367 	if (find_data->current == find_data->seq) {
2368 		memcpy(p11_kit_uri_get_token_info(find_data->info),
2369 		       tinfo, sizeof(struct ck_token_info));
2370 		memcpy(p11_kit_uri_get_module_info(find_data->info),
2371 		       lib_info, sizeof(struct ck_info));
2372 		return 0;
2373 	}
2374 
2375 	find_data->current++;
2376 	/* search the token for the id */
2377 
2378 
2379 	return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;	/* non zero is enough */
2380 }
2381 
2382 static int
find_token_modname_cb(struct ck_function_list * module,struct pkcs11_session_info * sinfo,struct ck_token_info * tinfo,struct ck_info * lib_info,void * input)2383 find_token_modname_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo,
2384 		      struct ck_token_info *tinfo,
2385 		      struct ck_info *lib_info, void *input)
2386 {
2387 	struct find_token_modname *find_data = input;
2388 
2389 	if (tinfo == NULL) {	/* we don't support multiple calls */
2390 		gnutls_assert();
2391 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2392 	}
2393 
2394 	if (!p11_kit_uri_match_token_info(find_data->info, tinfo)
2395 	    || !p11_kit_uri_match_module_info(find_data->info,
2396 					      lib_info)) {
2397 		gnutls_assert();
2398 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2399 	}
2400 
2401 	find_data->modname = p11_kit_config_option(module, "module");
2402 	find_data->ptr = module;
2403 	find_data->slot_id = sinfo->sid;
2404 	return 0;
2405 }
2406 
2407 /* Internal symbol used by tests */
2408 int
2409 _gnutls_pkcs11_token_get_url(unsigned int seq,
2410 			     gnutls_pkcs11_url_type_t detailed, char **url,
2411 			     unsigned flags);
2412 
2413 /**
2414  * _gnutls_pkcs11_token_get_url:
2415  * @seq: sequence number starting from 0
2416  * @detailed: non zero if a detailed URL is required
2417  * @url: will contain an allocated url
2418  * @flags: zero or 1. When 1 no initialization is performed.
2419  *
2420  * This function will return the URL for each token available
2421  * in system. The url has to be released using gnutls_free()
2422  *
2423  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
2424  * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if the sequence number
2425  * exceeds the available tokens, otherwise a negative error value.
2426  *
2427  **/
2428 int
_gnutls_pkcs11_token_get_url(unsigned int seq,gnutls_pkcs11_url_type_t detailed,char ** url,unsigned flags)2429 _gnutls_pkcs11_token_get_url(unsigned int seq,
2430 			     gnutls_pkcs11_url_type_t detailed, char **url,
2431 			     unsigned flags)
2432 {
2433 	int ret;
2434 	struct find_token_num tn;
2435 
2436 	if (!(flags & 1)) {
2437 		PKCS11_CHECK_INIT;
2438 	}
2439 
2440 	memset(&tn, 0, sizeof(tn));
2441 	tn.seq = seq;
2442 	tn.info = p11_kit_uri_new();
2443 
2444 	ret = _pkcs11_traverse_tokens(find_token_num_cb, &tn, NULL, NULL, 0);
2445 	if (ret < 0) {
2446 		p11_kit_uri_free(tn.info);
2447 		gnutls_assert();
2448 		return ret;
2449 	}
2450 
2451 	ret = pkcs11_info_to_url(tn.info, detailed, url);
2452 	p11_kit_uri_free(tn.info);
2453 
2454 	if (ret < 0) {
2455 		gnutls_assert();
2456 		return ret;
2457 	}
2458 
2459 	return 0;
2460 }
2461 
2462 /**
2463  * gnutls_pkcs11_token_get_url:
2464  * @seq: sequence number starting from 0
2465  * @detailed: non zero if a detailed URL is required
2466  * @url: will contain an allocated url
2467  *
2468  * This function will return the URL for each token available
2469  * in system. The url has to be released using gnutls_free()
2470  *
2471  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
2472  * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if the sequence number
2473  * exceeds the available tokens, otherwise a negative error value.
2474  *
2475  * Since: 2.12.0
2476  **/
2477 int
gnutls_pkcs11_token_get_url(unsigned int seq,gnutls_pkcs11_url_type_t detailed,char ** url)2478 gnutls_pkcs11_token_get_url(unsigned int seq,
2479 			    gnutls_pkcs11_url_type_t detailed, char **url)
2480 {
2481 	return _gnutls_pkcs11_token_get_url(seq, detailed, url, 0);
2482 }
2483 
2484 /**
2485  * gnutls_pkcs11_token_get_info:
2486  * @url: should contain a PKCS 11 URL
2487  * @ttype: Denotes the type of information requested
2488  * @output: where output will be stored
2489  * @output_size: contains the maximum size of the output buffer and will be
2490  *     overwritten with the actual size.
2491  *
2492  * This function will return information about the PKCS 11 token such
2493  * as the label, id, etc.
2494  *
2495  * When output is text, a null terminated string is written to @output and its
2496  * string length is written to @output_size (without null terminator). If the
2497  * buffer is too small, @output_size will contain the expected buffer size
2498  * (with null terminator for text) and return %GNUTLS_E_SHORT_MEMORY_BUFFER.
2499  *
2500  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code
2501  * on error.
2502  *
2503  * Since: 2.12.0
2504  **/
2505 int
gnutls_pkcs11_token_get_info(const char * url,gnutls_pkcs11_token_info_t ttype,void * output,size_t * output_size)2506 gnutls_pkcs11_token_get_info(const char *url,
2507 			     gnutls_pkcs11_token_info_t ttype,
2508 			     void *output, size_t * output_size)
2509 {
2510 	struct p11_kit_uri *info = NULL;
2511 	const uint8_t *str;
2512 	char *temp_str = NULL;
2513 	size_t len;
2514 	int ret;
2515 
2516 	PKCS11_CHECK_INIT;
2517 
2518 	ret = pkcs11_url_to_info(url, &info, 0);
2519 	if (ret < 0) {
2520 		gnutls_assert();
2521 		return ret;
2522 	}
2523 
2524 	switch (ttype) {
2525 	case GNUTLS_PKCS11_TOKEN_LABEL:
2526 		str = p11_kit_uri_get_token_info(info)->label;
2527 		len = p11_kit_space_strlen(str, 32);
2528 		break;
2529 	case GNUTLS_PKCS11_TOKEN_SERIAL:
2530 		str = p11_kit_uri_get_token_info(info)->serial_number;
2531 		len = p11_kit_space_strlen(str, 16);
2532 		break;
2533 	case GNUTLS_PKCS11_TOKEN_MANUFACTURER:
2534 		str = p11_kit_uri_get_token_info(info)->manufacturer_id;
2535 		len = p11_kit_space_strlen(str, 32);
2536 		break;
2537 	case GNUTLS_PKCS11_TOKEN_MODEL:
2538 		str = p11_kit_uri_get_token_info(info)->model;
2539 		len = p11_kit_space_strlen(str, 16);
2540 		break;
2541 	case GNUTLS_PKCS11_TOKEN_MODNAME: {
2542 		struct find_token_modname tn;
2543 
2544 		memset(&tn, 0, sizeof(tn));
2545 		tn.info = info;
2546 
2547 		ret = _pkcs11_traverse_tokens(find_token_modname_cb, &tn, NULL, NULL, 0);
2548 		if (ret < 0) {
2549 			gnutls_assert();
2550 			goto cleanup;
2551 		}
2552 
2553 		temp_str = tn.modname;
2554 		if (temp_str) {
2555 			str = (uint8_t *)temp_str;
2556 			len = strlen(temp_str);
2557 		} else {
2558 			gnutls_assert();
2559 			len = 0;
2560 		}
2561 		break;
2562 	}
2563 	default:
2564 		gnutls_assert();
2565 		ret = GNUTLS_E_INVALID_REQUEST;
2566 		goto cleanup;
2567 	}
2568 
2569 	if (len < *output_size) {
2570 		if (len)
2571 			memcpy(output, str, len);
2572 		((char *) output)[len] = '\0';
2573 		*output_size = len;
2574 		ret = 0;
2575 	} else {
2576 		*output_size = len + 1;
2577 		ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
2578 	}
2579 
2580  cleanup:
2581 	free(temp_str);
2582 	p11_kit_uri_free(info);
2583 	return ret;
2584 }
2585 
2586 /**
2587  * gnutls_pkcs11_token_get_ptr:
2588  * @url: should contain a PKCS#11 URL identifying a token
2589  * @ptr: will contain the CK_FUNCTION_LIST_PTR pointer
2590  * @slot_id: will contain the slot_id (may be %NULL)
2591  * @flags: should be zero
2592  *
2593  * This function will return the function pointer of the specified
2594  * token by the URL. The returned pointers are valid until
2595  * gnutls is deinitialized, c.f. _global_deinit().
2596  *
2597  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code
2598  * on error.
2599  *
2600  * Since: 3.6.3
2601  **/
2602 int
gnutls_pkcs11_token_get_ptr(const char * url,void ** ptr,unsigned long * slot_id,unsigned int flags)2603 gnutls_pkcs11_token_get_ptr(const char *url, void **ptr, unsigned long *slot_id,
2604 			    unsigned int flags)
2605 {
2606 	struct p11_kit_uri *info = NULL;
2607 	int ret;
2608 	struct find_token_modname tn;
2609 
2610 	PKCS11_CHECK_INIT;
2611 
2612 	ret = pkcs11_url_to_info(url, &info, 0);
2613 	if (ret < 0) {
2614 		gnutls_assert();
2615 		return ret;
2616 	}
2617 
2618 	memset(&tn, 0, sizeof(tn));
2619 	tn.info = info;
2620 
2621 	ret = _pkcs11_traverse_tokens(find_token_modname_cb, &tn, NULL, NULL, 0);
2622 	if (ret < 0) {
2623 		gnutls_assert();
2624 		goto cleanup;
2625 	}
2626 
2627 	if (ptr)
2628 		*ptr = tn.ptr;
2629 	if (slot_id)
2630 		*slot_id = tn.slot_id;
2631 
2632 	ret = 0;
2633 
2634  cleanup:
2635 	free(tn.modname);
2636 	p11_kit_uri_free(info);
2637 	return ret;
2638 }
2639 
2640 /**
2641  * gnutls_pkcs11_obj_export_url:
2642  * @obj: Holds the PKCS 11 certificate
2643  * @detailed: non zero if a detailed URL is required
2644  * @url: will contain an allocated url
2645  *
2646  * This function will export a URL identifying the given object.
2647  *
2648  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2649  *   negative error value.
2650  *
2651  * Since: 2.12.0
2652  **/
2653 int
gnutls_pkcs11_obj_export_url(gnutls_pkcs11_obj_t obj,gnutls_pkcs11_url_type_t detailed,char ** url)2654 gnutls_pkcs11_obj_export_url(gnutls_pkcs11_obj_t obj,
2655 			     gnutls_pkcs11_url_type_t detailed, char **url)
2656 {
2657 	int ret;
2658 
2659 	ret = pkcs11_info_to_url(obj->info, detailed, url);
2660 	if (ret < 0) {
2661 		gnutls_assert();
2662 		return ret;
2663 	}
2664 
2665 	return 0;
2666 }
2667 
2668 /**
2669  * gnutls_pkcs11_obj_get_type:
2670  * @obj: Holds the PKCS 11 object
2671  *
2672  * This function will return the type of the object being
2673  * stored in the structure.
2674  *
2675  * Returns: The type of the object
2676  *
2677  * Since: 2.12.0
2678  **/
2679 gnutls_pkcs11_obj_type_t
gnutls_pkcs11_obj_get_type(gnutls_pkcs11_obj_t obj)2680 gnutls_pkcs11_obj_get_type(gnutls_pkcs11_obj_t obj)
2681 {
2682 	return obj->type;
2683 }
2684 
2685 static int
retrieve_pin_from_source(const char * pinfile,struct ck_token_info * token_info,int attempts,ck_user_type_t user_type,struct p11_kit_pin ** pin)2686 retrieve_pin_from_source(const char *pinfile,
2687 			 struct ck_token_info *token_info, int attempts,
2688 			 ck_user_type_t user_type,
2689 			 struct p11_kit_pin **pin)
2690 {
2691 	unsigned int flags = 0;
2692 	struct p11_kit_uri *token_uri;
2693 	struct p11_kit_pin *result;
2694 	char *label;
2695 
2696 	label =
2697 	    p11_kit_space_strdup(token_info->label,
2698 				 sizeof(token_info->label));
2699 	if (label == NULL) {
2700 		gnutls_assert();
2701 		return GNUTLS_E_MEMORY_ERROR;
2702 	}
2703 
2704 	token_uri = p11_kit_uri_new();
2705 	if (token_uri == NULL) {
2706 		free(label);
2707 		gnutls_assert();
2708 		return GNUTLS_E_MEMORY_ERROR;
2709 	}
2710 
2711 	memcpy(p11_kit_uri_get_token_info(token_uri), token_info,
2712 	       sizeof(struct ck_token_info));
2713 
2714 	if (attempts)
2715 		flags |= P11_KIT_PIN_FLAGS_RETRY;
2716 	if (user_type == CKU_USER) {
2717 		flags |= P11_KIT_PIN_FLAGS_USER_LOGIN;
2718 		if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
2719 			flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
2720 		if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
2721 			flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
2722 	} else if (user_type == CKU_SO) {
2723 		flags |= P11_KIT_PIN_FLAGS_SO_LOGIN;
2724 		if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
2725 			flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
2726 		if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
2727 			flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
2728 	} else if (user_type == CKU_CONTEXT_SPECIFIC) {
2729 		flags |= P11_KIT_PIN_FLAGS_CONTEXT_LOGIN;
2730 	}
2731 
2732 	result = p11_kit_pin_request(pinfile, token_uri, label, flags);
2733 	p11_kit_uri_free(token_uri);
2734 	free(label);
2735 
2736 	if (result == NULL) {
2737 		gnutls_assert();
2738 		return GNUTLS_E_PKCS11_PIN_ERROR;
2739 	}
2740 
2741 	*pin = result;
2742 	return 0;
2743 }
2744 
2745 static int
retrieve_pin_from_callback(const struct pin_info_st * pin_info,struct ck_token_info * token_info,int attempts,ck_user_type_t user_type,struct p11_kit_pin ** pin)2746 retrieve_pin_from_callback(const struct pin_info_st *pin_info,
2747 			   struct ck_token_info *token_info,
2748 			   int attempts, ck_user_type_t user_type,
2749 			   struct p11_kit_pin **pin)
2750 {
2751 	char pin_value[GNUTLS_PKCS11_MAX_PIN_LEN];
2752 	unsigned int flags = 0;
2753 	char *token_str;
2754 	char *label;
2755 	struct p11_kit_uri *token_uri;
2756 	int ret = 0;
2757 
2758 	label =
2759 	    p11_kit_space_strdup(token_info->label,
2760 				 sizeof(token_info->label));
2761 	if (label == NULL) {
2762 		gnutls_assert();
2763 		return GNUTLS_E_MEMORY_ERROR;
2764 	}
2765 
2766 	token_uri = p11_kit_uri_new();
2767 	if (token_uri == NULL) {
2768 		free(label);
2769 		gnutls_assert();
2770 		return GNUTLS_E_MEMORY_ERROR;
2771 	}
2772 
2773 	memcpy(p11_kit_uri_get_token_info(token_uri), token_info,
2774 	       sizeof(struct ck_token_info));
2775 	ret = pkcs11_info_to_url(token_uri, 1, &token_str);
2776 	p11_kit_uri_free(token_uri);
2777 
2778 	if (ret < 0) {
2779 		free(label);
2780 		gnutls_assert();
2781 		return GNUTLS_E_MEMORY_ERROR;
2782 	}
2783 
2784 	if (user_type == CKU_USER || user_type == CKU_CONTEXT_SPECIFIC) {
2785 		flags |= GNUTLS_PIN_USER;
2786 
2787 		if (user_type == CKU_CONTEXT_SPECIFIC)
2788 			flags |= GNUTLS_PIN_CONTEXT_SPECIFIC;
2789 		if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
2790 			flags |= GNUTLS_PIN_COUNT_LOW;
2791 		if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
2792 			flags |= GNUTLS_PIN_FINAL_TRY;
2793 	} else if (user_type == CKU_SO) {
2794 		flags |= GNUTLS_PIN_SO;
2795 		if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
2796 			flags |= GNUTLS_PIN_COUNT_LOW;
2797 		if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
2798 			flags |= GNUTLS_PIN_FINAL_TRY;
2799 	}
2800 
2801 	if (attempts > 0)
2802 		flags |= GNUTLS_PIN_WRONG;
2803 
2804 	if (pin_info && pin_info->cb)
2805 		ret =
2806 		    pin_info->cb(pin_info->data, attempts,
2807 				 (char *) token_str, label, flags,
2808 				 pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2809 	else if (_gnutls_pin_func)
2810 		ret =
2811 		    _gnutls_pin_func(_gnutls_pin_data, attempts,
2812 				     (char *) token_str, label, flags,
2813 				     pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2814 	else
2815 		ret = gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2816 
2817 	free(token_str);
2818 	free(label);
2819 
2820 	if (ret < 0)
2821 		return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2822 
2823 	*pin = p11_kit_pin_new_for_string(pin_value);
2824 
2825 	if (*pin == NULL)
2826 		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2827 
2828 	return 0;
2829 }
2830 
2831 int
pkcs11_retrieve_pin(struct pin_info_st * pin_info,struct p11_kit_uri * info,struct ck_token_info * token_info,int attempts,ck_user_type_t user_type,struct p11_kit_pin ** pin)2832 pkcs11_retrieve_pin(struct pin_info_st *pin_info, struct p11_kit_uri *info,
2833 		    struct ck_token_info *token_info, int attempts,
2834 		    ck_user_type_t user_type, struct p11_kit_pin **pin)
2835 {
2836 	const char *pinfile;
2837 	int ret = GNUTLS_E_PKCS11_PIN_ERROR;
2838 
2839 	*pin = NULL;
2840 
2841 	/* First check for pin-value field */
2842 	pinfile = p11_kit_uri_get_pin_value(info);
2843 	if (pinfile != NULL) {
2844 		if (attempts > 0) {
2845 			_gnutls_debug_log("p11: refusing more than a single attempts with pin-value\n");
2846 			return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2847 		}
2848 
2849 		_gnutls_debug_log("p11: Using pin-value to retrieve PIN\n");
2850 		*pin = p11_kit_pin_new_for_string(pinfile);
2851 		if (*pin != NULL)
2852 			ret = 0;
2853 	} else { /* try pin-source */
2854 		/* Check if a pinfile is specified, and use that if possible */
2855 		pinfile = p11_kit_uri_get_pin_source(info);
2856 		if (pinfile != NULL) {
2857 			if (attempts > 0) {
2858 				_gnutls_debug_log("p11: refusing more than a single attempts with pin-source\n");
2859 				return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2860 			}
2861 
2862 			_gnutls_debug_log("p11: Using pin-source to retrieve PIN\n");
2863 			ret =
2864 			    retrieve_pin_from_source(pinfile, token_info, attempts,
2865 						     user_type, pin);
2866 		}
2867 	}
2868 
2869 	/* The global gnutls pin callback */
2870 	if (ret < 0)
2871 		ret =
2872 		    retrieve_pin_from_callback(pin_info, token_info,
2873 					       attempts, user_type, pin);
2874 
2875 	/* Otherwise, PIN entry is necessary for login, so fail if there's
2876 	 * no callback. */
2877 
2878 	if (ret < 0) {
2879 		gnutls_assert();
2880 		_gnutls_debug_log
2881 		    ("p11: No suitable pin callback but login required.\n");
2882 	}
2883 
2884 	return ret;
2885 }
2886 
2887 int
pkcs11_login(struct pkcs11_session_info * sinfo,struct pin_info_st * pin_info,struct p11_kit_uri * info,unsigned flags)2888 pkcs11_login(struct pkcs11_session_info *sinfo,
2889 	     struct pin_info_st *pin_info,
2890 	     struct p11_kit_uri *info,
2891 	     unsigned flags)
2892 {
2893 	struct ck_session_info session_info;
2894 	int attempt = 0, ret;
2895 	ck_user_type_t user_type;
2896 	ck_rv_t rv;
2897 
2898 	if (!(flags & SESSION_LOGIN)) {
2899 		_gnutls_debug_log("p11: No login requested.\n");
2900 		return 0;
2901 	}
2902 
2903 	if (flags & SESSION_SO) {
2904 		user_type = CKU_SO;
2905 	} else if (flags & SESSION_CONTEXT_SPECIFIC) {
2906 		user_type = CKU_CONTEXT_SPECIFIC;
2907 	} else {
2908 		user_type = CKU_USER;
2909 	}
2910 
2911 	if (!(flags & (SESSION_FORCE_LOGIN|SESSION_SO)) &&
2912 	    !(sinfo->tinfo.flags & CKF_LOGIN_REQUIRED)) {
2913 		gnutls_assert();
2914 		_gnutls_debug_log("p11: No login required in token.\n");
2915 		return 0;
2916 	}
2917 
2918 	/* For a token with a "protected" (out-of-band) authentication
2919 	 * path, calling login with a NULL username is all that is
2920 	 * required. */
2921 	if (sinfo->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
2922 		rv = (sinfo->module)->C_Login(sinfo->pks,
2923 					      user_type,
2924 					      NULL, 0);
2925 		if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) {
2926 			return 0;
2927 		} else {
2928 			gnutls_assert();
2929 			_gnutls_debug_log
2930 			    ("p11: Protected login failed.\n");
2931 			ret = pkcs11_rv_to_err(rv);
2932 			goto cleanup;
2933 		}
2934 	}
2935 
2936 	do {
2937 		struct p11_kit_pin *pin;
2938 		struct ck_token_info tinfo;
2939 
2940 		memcpy(&tinfo, &sinfo->tinfo, sizeof(tinfo));
2941 
2942 		if (!(flags & SESSION_CONTEXT_SPECIFIC)) {
2943 			/* Check whether the session is already logged in, and if so, just skip */
2944 			rv = (sinfo->module)->C_GetSessionInfo(sinfo->pks,
2945 							       &session_info);
2946 			if (rv == CKR_OK) {
2947 				if (flags & SESSION_SO) {
2948 					if (session_info.state == CKS_RW_SO_FUNCTIONS) {
2949 						ret = 0;
2950 						_gnutls_debug_log
2951 						    ("p11: Already logged in as SO\n");
2952 						goto cleanup;
2953 					}
2954 				} else if (session_info.state == CKS_RO_USER_FUNCTIONS
2955 					|| session_info.state == CKS_RW_USER_FUNCTIONS) {
2956 					ret = 0;
2957 					_gnutls_debug_log
2958 					    ("p11: Already logged in as user\n");
2959 					goto cleanup;
2960 				}
2961 			}
2962 		}
2963 
2964 		/* If login has been attempted once already, check the token
2965 		 * status again, the flags might change. */
2966 		if (attempt) {
2967 			rv = pkcs11_get_token_info(sinfo->module, sinfo->sid,
2968 				     &tinfo);
2969 			if (rv != CKR_OK) {
2970 				gnutls_assert();
2971 				_gnutls_debug_log
2972 				    ("p11: GetTokenInfo failed\n");
2973 
2974 				ret = pkcs11_rv_to_err(rv);
2975 				goto cleanup;
2976 			}
2977 		}
2978 
2979 		ret =
2980 		    pkcs11_retrieve_pin(pin_info, info, &tinfo, attempt++,
2981 					user_type, &pin);
2982 		if (ret < 0) {
2983 			gnutls_assert();
2984 			goto cleanup;
2985 		}
2986 
2987 		rv = (sinfo->module)->C_Login(sinfo->pks, user_type,
2988 					      (unsigned char *)
2989 					      p11_kit_pin_get_value(pin,
2990 								    NULL),
2991 					      p11_kit_pin_get_length(pin));
2992 
2993 		p11_kit_pin_unref(pin);
2994 	}
2995 	while (rv == CKR_PIN_INCORRECT);
2996 
2997 	_gnutls_debug_log("p11: Login result = %s (%lu)\n", (rv==0)?"ok":p11_kit_strerror(rv), rv);
2998 
2999 	ret = (rv == CKR_OK || rv ==
3000 	       CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err(rv);
3001 
3002  cleanup:
3003 	return ret;
3004 }
3005 
pkcs11_call_token_func(struct p11_kit_uri * info,const unsigned retry)3006 int pkcs11_call_token_func(struct p11_kit_uri *info, const unsigned retry)
3007 {
3008 	struct ck_token_info *tinfo;
3009 	char *label;
3010 	int ret = 0;
3011 
3012 	tinfo = p11_kit_uri_get_token_info(info);
3013 	label = p11_kit_space_strdup(tinfo->label, sizeof(tinfo->label));
3014 	ret = (_gnutls_token_func) (_gnutls_token_data, label, retry);
3015 	free(label);
3016 
3017 	return ret;
3018 }
3019 
3020 
3021 static int
find_privkeys(struct pkcs11_session_info * sinfo,struct ck_token_info * tinfo,struct find_pkey_list_st * list)3022 find_privkeys(struct pkcs11_session_info *sinfo,
3023 	      struct ck_token_info *tinfo, struct find_pkey_list_st *list)
3024 {
3025 	struct ck_attribute a[3];
3026 	ck_object_class_t class;
3027 	ck_rv_t rv;
3028 	ck_object_handle_t ctx;
3029 	unsigned long count, current;
3030 	char certid_tmp[PKCS11_ID_SIZE];
3031 	int ret;
3032 
3033 	class = CKO_PRIVATE_KEY;
3034 
3035 	/* Find an object with private key class and a certificate ID
3036 	 * which matches the certificate. */
3037 	a[0].type = CKA_CLASS;
3038 	a[0].value = &class;
3039 	a[0].value_len = sizeof class;
3040 
3041 	rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 1);
3042 	if (rv != CKR_OK) {
3043 		gnutls_assert();
3044 		return pkcs11_rv_to_err(rv);
3045 	}
3046 
3047 	list->key_ids_size = 0;
3048 	while (pkcs11_find_objects
3049 	       (sinfo->module, sinfo->pks, &ctx, 1, &count) == CKR_OK
3050 	       && count == 1) {
3051 		list->key_ids_size++;
3052 	}
3053 
3054 	pkcs11_find_objects_final(sinfo);
3055 
3056 	if (list->key_ids_size == 0) {
3057 		gnutls_assert();
3058 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3059 	}
3060 
3061 	list->key_ids =
3062 	    gnutls_malloc(sizeof(gnutls_buffer_st) * list->key_ids_size);
3063 	if (list->key_ids == NULL) {
3064 		gnutls_assert();
3065 		return GNUTLS_E_MEMORY_ERROR;
3066 	}
3067 
3068 	/* actual search */
3069 	a[0].type = CKA_CLASS;
3070 	a[0].value = &class;
3071 	a[0].value_len = sizeof class;
3072 
3073 	rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 1);
3074 	if (rv != CKR_OK) {
3075 		gnutls_assert();
3076 		return pkcs11_rv_to_err(rv);
3077 	}
3078 
3079 	current = 0;
3080 	while (pkcs11_find_objects
3081 	       (sinfo->module, sinfo->pks, &ctx, 1, &count) == CKR_OK
3082 	       && count == 1) {
3083 
3084 		a[0].type = CKA_ID;
3085 		a[0].value = certid_tmp;
3086 		a[0].value_len = sizeof(certid_tmp);
3087 
3088 		_gnutls_buffer_init(&list->key_ids[current]);
3089 
3090 		if (pkcs11_get_attribute_value
3091 		    (sinfo->module, sinfo->pks, ctx, a, 1) == CKR_OK) {
3092 			ret = _gnutls_buffer_append_data(&list->key_ids[current],
3093 						   a[0].value,
3094 						   a[0].value_len);
3095 			if (ret < 0)
3096 				return gnutls_assert_val(ret);
3097 			current++;
3098 		}
3099 
3100 		if (current > list->key_ids_size)
3101 			break;
3102 	}
3103 
3104 	pkcs11_find_objects_final(sinfo);
3105 
3106 	list->key_ids_size = current - 1;
3107 
3108 	return 0;
3109 }
3110 
3111 /* Recover certificate list from tokens */
3112 
3113 #define OBJECTS_A_TIME 8*1024
3114 
3115 static int
find_multi_objs_cb(struct ck_function_list * module,struct pkcs11_session_info * sinfo,struct ck_token_info * tinfo,struct ck_info * lib_info,void * input)3116 find_multi_objs_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo,
3117 	  struct ck_token_info *tinfo, struct ck_info *lib_info, void *input)
3118 {
3119 	struct find_multi_obj_st *find_data = input;
3120 	struct ck_attribute a[16];
3121 	struct ck_attribute *attr;
3122 	ck_object_class_t class = (ck_object_class_t) -1;
3123 	ck_certificate_type_t type = (ck_certificate_type_t) -1;
3124 	ck_bool_t trusted;
3125 	unsigned long category;
3126 	ck_rv_t rv;
3127 	ck_object_handle_t *ctx = NULL;
3128 	unsigned long count;
3129 	char certid_tmp[PKCS11_ID_SIZE];
3130 	int ret;
3131 	struct find_pkey_list_st plist;	/* private key holder */
3132 	unsigned int i, tot_values = 0, class_set = 0;
3133 	unsigned start_elem;
3134 
3135 	if (tinfo == NULL) {
3136 		gnutls_assert();
3137 		return 0;
3138 	}
3139 
3140 	/* do not bother reading the token if basic fields do not match
3141 	 */
3142 	if (!p11_kit_uri_match_token_info(find_data->info, tinfo) ||
3143 	    !p11_kit_uri_match_module_info(find_data->info, lib_info)) {
3144 		gnutls_assert();
3145 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3146 	}
3147 
3148 	memset(&plist, 0, sizeof(plist));
3149 
3150 	if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_WITH_PRIVKEY) {
3151 		ret = find_privkeys(sinfo, tinfo, &plist);
3152 		if (ret < 0) {
3153 			gnutls_assert();
3154 			return ret;
3155 		}
3156 
3157 		if (plist.key_ids_size == 0) {
3158 			gnutls_assert();
3159 			return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3160 		}
3161 	}
3162 
3163 	/* Find objects with given class and type */
3164 	attr = p11_kit_uri_get_attribute(find_data->info, CKA_CLASS);
3165 	if (attr) {
3166 		if (attr->value
3167 		    && attr->value_len == sizeof(ck_object_class_t))
3168 			class = *((ck_object_class_t *) attr->value);
3169 		if (class == CKO_CERTIFICATE)
3170 			type = CKC_X_509;
3171 	}
3172 
3173 	if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_CRT) {
3174 		class = CKO_CERTIFICATE;
3175 
3176 		a[tot_values].type = CKA_CLASS;
3177 		a[tot_values].value = &class;
3178 		a[tot_values].value_len = sizeof class;
3179 		tot_values++;
3180 		class_set = 1;
3181 
3182 		type = CKC_X_509;
3183 		a[tot_values].type = CKA_CERTIFICATE_TYPE;
3184 		a[tot_values].value = &type;
3185 		a[tot_values].value_len = sizeof type;
3186 		tot_values++;
3187 		_gnutls_assert_log("p11 attrs: CKA_CLASS (CERT), CKA_CERTIFICATE_TYPE\n");
3188 	}
3189 
3190 	if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_PUBKEY) {
3191 		class = CKO_PUBLIC_KEY;
3192 
3193 		a[tot_values].type = CKA_CLASS;
3194 		a[tot_values].value = &class;
3195 		a[tot_values].value_len = sizeof class;
3196 		tot_values++;
3197 		class_set = 1;
3198 		_gnutls_assert_log("p11 attrs: CKA_CLASS (PUBLIC KEY)\n");
3199 	}
3200 
3201 	if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY) {
3202 		class = CKO_PRIVATE_KEY;
3203 
3204 		a[tot_values].type = CKA_CLASS;
3205 		a[tot_values].value = &class;
3206 		a[tot_values].value_len = sizeof class;
3207 		tot_values++;
3208 		class_set = 1;
3209 		_gnutls_assert_log("p11 attrs: CKA_CLASS (PRIVATE KEY)\n");
3210 	}
3211 
3212 	if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
3213 		trusted = 1;
3214 		a[tot_values].type = CKA_TRUSTED;
3215 		a[tot_values].value = &trusted;
3216 		a[tot_values].value_len = sizeof trusted;
3217 		tot_values++;
3218 		_gnutls_assert_log("p11 attrs: CKA_TRUSTED\n");
3219 	}
3220 
3221 	if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_DISTRUSTED) {
3222 		if (!sinfo->trusted) { /* only p11-kit trust modules support this */
3223 			gnutls_assert();
3224 			return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3225 		}
3226 
3227 		trusted = 1;
3228 		a[tot_values].type = CKA_X_DISTRUSTED;
3229 		a[tot_values].value = &trusted;
3230 		a[tot_values].value_len = sizeof trusted;
3231 		tot_values++;
3232 		_gnutls_assert_log("p11 attrs: CKA_X_DISTRUSTED\n");
3233 	}
3234 
3235 	if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA) {
3236 		category = 2;
3237 		a[tot_values].type = CKA_CERTIFICATE_CATEGORY;
3238 		a[tot_values].value = &category;
3239 		a[tot_values].value_len = sizeof category;
3240 		tot_values++;
3241 		_gnutls_assert_log("p11 attrs: CKA_CERTIFICATE_CATEGORY=CA\n");
3242 	}
3243 
3244 	if (class_set == 0 && class != (ck_object_class_t)-1) {
3245 		a[tot_values].type = CKA_CLASS;
3246 		a[tot_values].value = &class;
3247 		a[tot_values].value_len = sizeof class;
3248 		tot_values++;
3249 		class_set = 1;
3250 		_gnutls_assert_log("p11 attrs: CKA_CLASS\n");
3251 	}
3252 
3253 	attr = p11_kit_uri_get_attribute(find_data->info, CKA_ID);
3254 	if (attr) {
3255 		a[tot_values].type = CKA_ID;
3256 		a[tot_values].value = attr->value;
3257 		a[tot_values].value_len = attr->value_len;
3258 		tot_values++;
3259 		_gnutls_assert_log("p11 attrs: CKA_ID\n");
3260 	}
3261 
3262 	attr = p11_kit_uri_get_attribute(find_data->info, CKA_LABEL);
3263 	if (attr) {
3264 		a[tot_values].type = CKA_LABEL;
3265 		a[tot_values].value = attr->value;
3266 		a[tot_values].value_len = attr->value_len;
3267 		tot_values++;
3268 		_gnutls_assert_log("p11 attrs: CKA_LABEL\n");
3269 	}
3270 
3271 	rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
3272 				      tot_values);
3273 	if (rv != CKR_OK) {
3274 		gnutls_assert();
3275 		_gnutls_debug_log("p11: FindObjectsInit failed.\n");
3276 		return pkcs11_rv_to_err(rv);
3277 	}
3278 
3279 	ctx = gnutls_malloc(OBJECTS_A_TIME*sizeof(ctx[0]));
3280 	if (ctx == NULL) {
3281 		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
3282 		goto fail;
3283 	}
3284 
3285 	start_elem = find_data->current;
3286 
3287 	while (pkcs11_find_objects
3288 	       (sinfo->module, sinfo->pks, ctx, OBJECTS_A_TIME, &count) == CKR_OK
3289 	       && count > 0) {
3290 		unsigned j;
3291 		gnutls_datum_t id;
3292 
3293 		find_data->p_list = gnutls_realloc_fast(find_data->p_list, (find_data->current+count)*sizeof(find_data->p_list[0]));
3294 		if (find_data->p_list == NULL) {
3295 			ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
3296 			goto fail;
3297 		}
3298 
3299 		for (j=0;j<count;j++) {
3300 			a[0].type = CKA_ID;
3301 			a[0].value = certid_tmp;
3302 			a[0].value_len = sizeof certid_tmp;
3303 
3304 			if (pkcs11_get_attribute_value
3305 			    (sinfo->module, sinfo->pks, ctx[j], a, 1) == CKR_OK) {
3306 				id.data = a[0].value;
3307 				id.size = a[0].value_len;
3308 			} else {
3309 				id.data = NULL;
3310 				id.size = 0;
3311 			}
3312 
3313 			if (class_set == 0) {
3314 				a[0].type = CKA_CLASS;
3315 				a[0].value = &class;
3316 				a[0].value_len = sizeof class;
3317 
3318 				rv = pkcs11_get_attribute_value(sinfo->module,
3319 							   sinfo->pks, ctx[j], a, 1);
3320 				if (rv != CKR_OK) {
3321 					class = -1;
3322 				}
3323 			}
3324 
3325 			if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_WITH_PRIVKEY) {
3326 				for (i = 0; i < plist.key_ids_size; i++) {
3327 					if (plist.key_ids[i].length !=
3328 					    id.size
3329 					    || memcmp(plist.key_ids[i].data,
3330 						      id.data,
3331 						      id.size) != 0) {
3332 						/* not found */
3333 						continue;
3334 					}
3335 				}
3336 			}
3337 
3338 			ret =
3339 			    gnutls_pkcs11_obj_init(&find_data->p_list
3340 						   [find_data->current]);
3341 			if (ret < 0) {
3342 				gnutls_assert();
3343 				goto fail;
3344 			}
3345 
3346 			ret = pkcs11_import_object(ctx[j], class, sinfo,
3347 					     tinfo, lib_info,
3348 					     find_data->p_list[find_data->current]);
3349 			if (ret < 0) {
3350 				gnutls_assert();
3351 				/* skip the failed object */
3352 				continue;
3353 			}
3354 
3355 			find_data->current++;
3356 		}
3357 	}
3358 
3359 	pkcs11_find_objects_final(sinfo);
3360 
3361 	/* we can have only a search state going on, so we can only overwrite extensions
3362 	 * after we have read everything. */
3363 	if (find_data->overwrite_exts) {
3364 		for (i=start_elem;i<find_data->current;i++) {
3365 			if (find_data->p_list[i]->raw.size > 0) {
3366 				gnutls_datum_t spki;
3367 				rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, ctx[i], CKA_PUBLIC_KEY_INFO, &spki);
3368 				if (rv == CKR_OK) {
3369 					ret = pkcs11_override_cert_exts(sinfo, &spki, &find_data->p_list[i]->raw);
3370 					gnutls_free(spki.data);
3371 					if (ret < 0) {
3372 						gnutls_assert();
3373 						goto fail;
3374 					}
3375 				}
3376 			}
3377 		}
3378 	}
3379 	gnutls_free(ctx);
3380 
3381 	return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;	/* continue until all tokens have been checked */
3382 
3383       fail:
3384 	gnutls_free(ctx);
3385 	pkcs11_find_objects_final(sinfo);
3386 	if (plist.key_ids != NULL) {
3387 		for (i = 0; i < plist.key_ids_size; i++) {
3388 			_gnutls_buffer_clear(&plist.key_ids[i]);
3389 		}
3390 		gnutls_free(plist.key_ids);
3391 	}
3392 	if (find_data->p_list != NULL) {
3393 		for (i = 0; i < find_data->current; i++) {
3394 			gnutls_pkcs11_obj_deinit(find_data->p_list[i]);
3395 		}
3396 		gnutls_free(find_data->p_list);
3397 	}
3398 	find_data->p_list = NULL;
3399 	find_data->current = 0;
3400 
3401 	return ret;
3402 }
3403 
3404 /**
3405  * gnutls_pkcs11_obj_list_import_url3:
3406  * @p_list: An uninitialized object list (may be %NULL)
3407  * @n_list: Initially should hold the maximum size of the list. Will contain the actual size.
3408  * @url: A PKCS 11 url identifying a set of objects
3409  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
3410  *
3411  * This function will initialize and set values to an object list
3412  * by using all objects identified by a PKCS 11 URL.
3413  *
3414  * This function will enumerate all the objects specified by the PKCS#11 URL
3415  * provided. It expects an already allocated @p_list which has *@n_list elements,
3416  * and that value will be updated to the actual number of present objects. The
3417  * @p_list objects will be initialized and set by this function.
3418  * To obtain a list of all available objects use a @url of 'pkcs11:'.
3419  *
3420  * All returned objects must be deinitialized using gnutls_pkcs11_obj_deinit().
3421  *
3422  * The supported in this function @flags are %GNUTLS_PKCS11_OBJ_FLAG_LOGIN,
3423  * %GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO, %GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE,
3424  * %GNUTLS_PKCS11_OBJ_FLAG_CRT, %GNUTLS_PKCS11_OBJ_FLAG_PUBKEY, %GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY,
3425  * %GNUTLS_PKCS11_OBJ_FLAG_WITH_PRIVKEY, %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA,
3426  * %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED, and since 3.5.1 the %GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT.
3427  *
3428  * On versions of GnuTLS prior to 3.4.0 the equivalent function was
3429  * gnutls_pkcs11_obj_list_import_url(). That is also available on this version
3430  * as a macro which maps to this function.
3431  *
3432  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3433  *   negative error value.
3434  *
3435  * Since: 3.4.0
3436  **/
3437 int
gnutls_pkcs11_obj_list_import_url3(gnutls_pkcs11_obj_t * p_list,unsigned int * n_list,const char * url,unsigned int flags)3438 gnutls_pkcs11_obj_list_import_url3(gnutls_pkcs11_obj_t * p_list,
3439 				  unsigned int *n_list,
3440 				  const char *url,
3441 				  unsigned int flags)
3442 {
3443 	gnutls_pkcs11_obj_t *list1 = NULL;
3444 	unsigned int n_list1, i;
3445 	int ret;
3446 
3447 	ret = gnutls_pkcs11_obj_list_import_url4(&list1, &n_list1, url, flags);
3448 	if (ret < 0)
3449 		return gnutls_assert_val(ret);
3450 
3451 	if (n_list1 > *n_list) {
3452 		*n_list = n_list1;
3453 		for (i=0;i<n_list1;i++) {
3454 			gnutls_pkcs11_obj_deinit(list1[i]);
3455 		}
3456 		gnutls_free(list1);
3457 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
3458 	}
3459 
3460 	*n_list = n_list1;
3461 	if (p_list && list1)
3462 		memcpy(p_list, list1, n_list1*sizeof(p_list[0]));
3463 	gnutls_free(list1);
3464 
3465 	return 0;
3466 }
3467 
3468 /**
3469  * gnutls_pkcs11_obj_list_import_url4:
3470  * @p_list: An uninitialized object list (may be NULL)
3471  * @n_list: It will contain the size of the list.
3472  * @url: A PKCS 11 url identifying a set of objects
3473  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
3474  *
3475  * This function will enumerate all the objects specified by the PKCS#11 URL
3476  * provided. It will initialize and set values to the object pointer list (@p_list)
3477  * provided. To obtain a list of all available objects use a @url of 'pkcs11:'.
3478  *
3479  * All returned objects must be deinitialized using gnutls_pkcs11_obj_deinit(),
3480  * and @p_list must be deinitialized using gnutls_free().
3481  *
3482  * The supported in this function @flags are %GNUTLS_PKCS11_OBJ_FLAG_LOGIN,
3483  * %GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO, %GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE,
3484  * %GNUTLS_PKCS11_OBJ_FLAG_CRT, %GNUTLS_PKCS11_OBJ_FLAG_PUBKEY, %GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY,
3485  * %GNUTLS_PKCS11_OBJ_FLAG_WITH_PRIVKEY, %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA,
3486  * %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED, and since 3.5.1 the %GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT.
3487  *
3488  * On versions of GnuTLS prior to 3.4.0 the equivalent function was
3489  * gnutls_pkcs11_obj_list_import_url2(). That is also available on this version
3490  * as a macro which maps to this function.
3491  *
3492  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3493  *   negative error value.
3494  *
3495  * Since: 3.4.0
3496  **/
3497 int
gnutls_pkcs11_obj_list_import_url4(gnutls_pkcs11_obj_t ** p_list,unsigned int * n_list,const char * url,unsigned int flags)3498 gnutls_pkcs11_obj_list_import_url4(gnutls_pkcs11_obj_t ** p_list,
3499 				   unsigned int *n_list,
3500 				   const char *url,
3501 				   unsigned int flags)
3502 {
3503 	int ret;
3504 	struct find_multi_obj_st priv;
3505 
3506 	PKCS11_CHECK_INIT_FLAGS(flags);
3507 
3508 	memset(&priv, 0, sizeof(priv));
3509 
3510 	/* fill in the find data structure */
3511 	priv.flags = flags;
3512 
3513 	if (url == NULL || url[0] == 0) {
3514 		url = "pkcs11:";
3515 	}
3516 
3517 	ret = pkcs11_url_to_info(url, &priv.info, flags);
3518 	if (ret < 0) {
3519 		gnutls_assert();
3520 		return ret;
3521 	}
3522 
3523 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT) {
3524 		priv.overwrite_exts = 1;
3525 	}
3526 
3527 	ret =
3528 	    _pkcs11_traverse_tokens(find_multi_objs_cb, &priv, priv.info,
3529 				    NULL, pkcs11_obj_flags_to_int(flags));
3530 	p11_kit_uri_free(priv.info);
3531 
3532 	if (ret < 0) {
3533 		gnutls_assert();
3534 		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
3535 			*p_list = NULL;
3536 			*n_list = 0;
3537 			ret = 0;
3538 		}
3539 		return ret;
3540 	}
3541 
3542 	*n_list = priv.current;
3543 	*p_list = priv.p_list;
3544 
3545 	return 0;
3546 }
3547 
3548 /**
3549  * gnutls_x509_crt_import_pkcs11:
3550  * @crt: A certificate of type #gnutls_x509_crt_t
3551  * @pkcs11_crt: A PKCS 11 object that contains a certificate
3552  *
3553  * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t
3554  * structure.
3555  *
3556  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3557  *   negative error value.
3558  *
3559  * Since: 2.12.0
3560  **/
3561 int
gnutls_x509_crt_import_pkcs11(gnutls_x509_crt_t crt,gnutls_pkcs11_obj_t pkcs11_crt)3562 gnutls_x509_crt_import_pkcs11(gnutls_x509_crt_t crt,
3563 			      gnutls_pkcs11_obj_t pkcs11_crt)
3564 {
3565 	return gnutls_x509_crt_import(crt, &pkcs11_crt->raw,
3566 				      GNUTLS_X509_FMT_DER);
3567 }
3568 
3569 /*-
3570  * _gnutls_x509_crt_import_pkcs11_url:
3571  * @crt: A certificate of type #gnutls_x509_crt_t
3572  * @url: A PKCS 11 url
3573  * @flags: One of GNUTLS_PKCS11_OBJ_* flags
3574  *
3575  * This function will import a PKCS 11 certificate directly from a token
3576  * without involving the #gnutls_pkcs11_obj_t type. This function will
3577  * fail if the certificate stored is not of X.509 type.
3578  *
3579  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3580  *   negative error value.
3581  *
3582  * Since: 2.12.0
3583  -*/
3584 int
_gnutls_x509_crt_import_pkcs11_url(gnutls_x509_crt_t crt,const char * url,unsigned int flags)3585 _gnutls_x509_crt_import_pkcs11_url(gnutls_x509_crt_t crt,
3586 				  const char *url, unsigned int flags)
3587 {
3588 	gnutls_pkcs11_obj_t pcrt;
3589 	int ret;
3590 
3591 	ret = gnutls_pkcs11_obj_init(&pcrt);
3592 	if (ret < 0) {
3593 		gnutls_assert();
3594 		return ret;
3595 	}
3596 
3597 	if (crt->pin.cb)
3598 		gnutls_pkcs11_obj_set_pin_function(pcrt, crt->pin.cb,
3599 						   crt->pin.data);
3600 
3601 	ret = gnutls_pkcs11_obj_import_url(pcrt, url, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_CERT);
3602 	if (ret < 0) {
3603 		gnutls_assert();
3604 		goto cleanup;
3605 	}
3606 
3607 	ret = gnutls_x509_crt_import(crt, &pcrt->raw, GNUTLS_X509_FMT_DER);
3608 	if (ret < 0) {
3609 		gnutls_assert();
3610 		goto cleanup;
3611 	}
3612 
3613 
3614 	ret = 0;
3615  cleanup:
3616 
3617 	gnutls_pkcs11_obj_deinit(pcrt);
3618 	return ret;
3619 }
3620 
3621 /**
3622  * gnutls_x509_crt_list_import_pkcs11:
3623  * @certs: A list of certificates of type #gnutls_x509_crt_t
3624  * @cert_max: The maximum size of the list
3625  * @objs: A list of PKCS 11 objects
3626  * @flags: 0 for now
3627  *
3628  * This function will import a PKCS 11 certificate list to a list of
3629  * #gnutls_x509_crt_t type. These must not be initialized.
3630  *
3631  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
3632  *   negative error value.
3633  *
3634  * Since: 2.12.0
3635  **/
3636 int
gnutls_x509_crt_list_import_pkcs11(gnutls_x509_crt_t * certs,unsigned int cert_max,gnutls_pkcs11_obj_t * const objs,unsigned int flags)3637 gnutls_x509_crt_list_import_pkcs11(gnutls_x509_crt_t * certs,
3638 				   unsigned int cert_max,
3639 				   gnutls_pkcs11_obj_t * const objs,
3640 				   unsigned int flags)
3641 {
3642 	unsigned int i, j;
3643 	int ret;
3644 
3645 	for (i = 0; i < cert_max; i++) {
3646 		ret = gnutls_x509_crt_init(&certs[i]);
3647 		if (ret < 0) {
3648 			gnutls_assert();
3649 			goto cleanup;
3650 		}
3651 
3652 		ret = gnutls_x509_crt_import_pkcs11(certs[i], objs[i]);
3653 		if (ret < 0) {
3654 			gnutls_assert();
3655 			goto cleanup;
3656 		}
3657 	}
3658 
3659 	return 0;
3660 
3661       cleanup:
3662 	for (j = 0; j < i; j++) {
3663 		gnutls_x509_crt_deinit(certs[j]);
3664 	}
3665 
3666 	return ret;
3667 }
3668 
3669 static int
find_flags_cb(struct ck_function_list * module,struct pkcs11_session_info * sinfo,struct ck_token_info * tinfo,struct ck_info * lib_info,void * input)3670 find_flags_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo,
3671 	   struct ck_token_info *tinfo, struct ck_info *lib_info, void *input)
3672 {
3673 	struct find_flags_data_st *find_data = input;
3674 
3675 	if (tinfo == NULL) {	/* we don't support multiple calls */
3676 		gnutls_assert();
3677 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3678 	}
3679 
3680 	/* do not bother reading the token if basic fields do not match
3681 	 */
3682 	if (!p11_kit_uri_match_token_info(find_data->info, tinfo) ||
3683 	    !p11_kit_uri_match_module_info(find_data->info, lib_info)) {
3684 		gnutls_assert();
3685 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3686 	}
3687 
3688 	/* found token! */
3689 	if (p11_kit_module_get_flags(sinfo->module) & P11_KIT_MODULE_TRUSTED)
3690 		find_data->trusted = 1;
3691 	else
3692 		find_data->trusted = 0;
3693 	find_data->slot_flags = sinfo->slot_info.flags;
3694 	find_data->token_flags = sinfo->tinfo.flags;
3695 
3696 	return 0;
3697 }
3698 
3699 /**
3700  * gnutls_pkcs11_token_get_flags:
3701  * @url: should contain a PKCS 11 URL
3702  * @flags: The output flags (GNUTLS_PKCS11_TOKEN_*)
3703  *
3704  * This function will return information about the PKCS 11 token flags.
3705  *
3706  * The supported flags are: %GNUTLS_PKCS11_TOKEN_HW and %GNUTLS_PKCS11_TOKEN_TRUSTED.
3707  *
3708  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
3709  *
3710  * Since: 2.12.0
3711  **/
gnutls_pkcs11_token_get_flags(const char * url,unsigned int * flags)3712 int gnutls_pkcs11_token_get_flags(const char *url, unsigned int *flags)
3713 {
3714 	struct find_flags_data_st find_data;
3715 	int ret;
3716 
3717 	PKCS11_CHECK_INIT;
3718 
3719 	memset(&find_data, 0, sizeof(find_data));
3720 	ret = pkcs11_url_to_info(url, &find_data.info, 0);
3721 	if (ret < 0) {
3722 		gnutls_assert();
3723 		return ret;
3724 	}
3725 
3726 	ret =
3727 	    _pkcs11_traverse_tokens(find_flags_cb, &find_data, find_data.info,
3728 				    NULL, 0);
3729 	p11_kit_uri_free(find_data.info);
3730 
3731 	if (ret < 0) {
3732 		gnutls_assert();
3733 		return ret;
3734 	}
3735 
3736 	*flags = 0;
3737 
3738 	/* read slot flags */
3739 	if (find_data.slot_flags & CKF_HW_SLOT)
3740 		*flags |= GNUTLS_PKCS11_TOKEN_HW;
3741 
3742 	/* read token flags */
3743 	if (find_data.token_flags & CKF_RNG)
3744 		*flags |= GNUTLS_PKCS11_TOKEN_RNG;
3745 
3746 	if (find_data.token_flags & CKF_LOGIN_REQUIRED)
3747 		*flags |= GNUTLS_PKCS11_TOKEN_LOGIN_REQUIRED;
3748 
3749 	if (find_data.token_flags & CKF_PROTECTED_AUTHENTICATION_PATH)
3750 		*flags |= GNUTLS_PKCS11_TOKEN_PROTECTED_AUTHENTICATION_PATH;
3751 
3752 	if (find_data.token_flags & CKF_TOKEN_INITIALIZED)
3753 		*flags |= GNUTLS_PKCS11_TOKEN_INITIALIZED;
3754 
3755 	if (find_data.token_flags & CKF_USER_PIN_COUNT_LOW)
3756 		*flags |= GNUTLS_PKCS11_TOKEN_USER_PIN_COUNT_LOW;
3757 
3758 	if (find_data.token_flags & CKF_USER_PIN_FINAL_TRY)
3759 		*flags |= GNUTLS_PKCS11_TOKEN_USER_PIN_FINAL_TRY;
3760 
3761 	if (find_data.token_flags & CKF_USER_PIN_LOCKED)
3762 		*flags |= GNUTLS_PKCS11_TOKEN_USER_PIN_LOCKED;
3763 
3764 	if (find_data.token_flags & CKF_SO_PIN_COUNT_LOW)
3765 		*flags |= GNUTLS_PKCS11_TOKEN_SO_PIN_COUNT_LOW;
3766 
3767 	if (find_data.token_flags & CKF_SO_PIN_FINAL_TRY)
3768 		*flags |= GNUTLS_PKCS11_TOKEN_SO_PIN_FINAL_TRY;
3769 
3770 	if (find_data.token_flags & CKF_SO_PIN_LOCKED)
3771 		*flags |= GNUTLS_PKCS11_TOKEN_SO_PIN_LOCKED;
3772 
3773 	if (find_data.token_flags & CKF_USER_PIN_INITIALIZED)
3774 		*flags |= GNUTLS_PKCS11_TOKEN_USER_PIN_INITIALIZED;
3775 
3776 #ifdef CKF_ERROR_STATE
3777 	if (find_data.token_flags & CKF_ERROR_STATE)
3778 		*flags |= GNUTLS_PKCS11_TOKEN_ERROR_STATE;
3779 #endif
3780 
3781 	/* other flags */
3782 	if (find_data.trusted != 0)
3783 		*flags |= GNUTLS_PKCS11_TOKEN_TRUSTED;
3784 
3785 	return 0;
3786 
3787 }
3788 
3789 /**
3790  * gnutls_pkcs11_token_get_mechanism:
3791  * @url: should contain a PKCS 11 URL
3792  * @idx: The index of the mechanism
3793  * @mechanism: The PKCS #11 mechanism ID
3794  *
3795  * This function will return the names of the supported mechanisms
3796  * by the token. It should be called with an increasing index until
3797  * it return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
3798  *
3799  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
3800  *
3801  * Since: 2.12.0
3802  **/
3803 int
gnutls_pkcs11_token_get_mechanism(const char * url,unsigned int idx,unsigned long * mechanism)3804 gnutls_pkcs11_token_get_mechanism(const char *url, unsigned int idx,
3805 				  unsigned long *mechanism)
3806 {
3807 	int ret;
3808 	ck_rv_t rv;
3809 	struct ck_function_list *module;
3810 	ck_slot_id_t slot;
3811 	struct ck_token_info tinfo;
3812 	struct p11_kit_uri *info = NULL;
3813 	unsigned long count;
3814 	ck_mechanism_type_t mlist[400];
3815 
3816 	PKCS11_CHECK_INIT;
3817 
3818 	ret = pkcs11_url_to_info(url, &info, 0);
3819 	if (ret < 0) {
3820 		gnutls_assert();
3821 		return ret;
3822 	}
3823 
3824 	ret = pkcs11_find_slot(&module, &slot, info, &tinfo, NULL, NULL);
3825 	p11_kit_uri_free(info);
3826 
3827 	if (ret < 0) {
3828 		gnutls_assert();
3829 		return ret;
3830 	}
3831 
3832 	count = sizeof(mlist) / sizeof(mlist[0]);
3833 	rv = pkcs11_get_mechanism_list(module, slot, mlist, &count);
3834 	if (rv != CKR_OK) {
3835 		gnutls_assert();
3836 		return pkcs11_rv_to_err(rv);
3837 	}
3838 
3839 	if (idx >= count) {
3840 		gnutls_assert();
3841 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3842 	}
3843 
3844 	*mechanism = mlist[idx];
3845 
3846 	return 0;
3847 }
3848 
3849 /**
3850  * gnutls_pkcs11_token_check_mechanism:
3851  * @url: should contain a PKCS 11 URL
3852  * @mechanism: The PKCS #11 mechanism ID
3853  * @ptr: if set it should point to a CK_MECHANISM_INFO struct
3854  * @psize: the size of CK_MECHANISM_INFO struct (for safety)
3855  * @flags: must be zero
3856  *
3857  * This function will return whether a mechanism is supported
3858  * by the given token. If the mechanism is supported and
3859  * @ptr is set, it will be updated with the token information.
3860  *
3861  * Returns: Non-zero if the mechanism is supported or zero otherwise.
3862  *
3863  * Since: 3.6.0
3864  **/
3865 unsigned
gnutls_pkcs11_token_check_mechanism(const char * url,unsigned long mechanism,void * ptr,unsigned psize,unsigned flags)3866 gnutls_pkcs11_token_check_mechanism(const char *url,
3867 				    unsigned long mechanism,
3868 				    void *ptr, unsigned psize, unsigned flags)
3869 {
3870 	int ret;
3871 	ck_rv_t rv;
3872 	struct ck_function_list *module;
3873 	ck_slot_id_t slot;
3874 	struct ck_token_info tinfo;
3875 	struct p11_kit_uri *info = NULL;
3876 	struct ck_mechanism_info minfo;
3877 
3878 	PKCS11_CHECK_INIT;
3879 
3880 	ret = pkcs11_url_to_info(url, &info, 0);
3881 	if (ret < 0) {
3882 		gnutls_assert();
3883 		return ret;
3884 	}
3885 
3886 	ret = pkcs11_find_slot(&module, &slot, info, &tinfo, NULL, NULL);
3887 	p11_kit_uri_free(info);
3888 
3889 	if (ret < 0) {
3890 		gnutls_assert();
3891 		return ret;
3892 	}
3893 
3894 	rv = pkcs11_get_mechanism_info(module, slot, mechanism, &minfo);
3895 	if (rv != CKR_OK) {
3896 		gnutls_assert();
3897 		return 0;
3898 	}
3899 
3900 	if (ptr) {
3901 		if (sizeof(minfo) > psize)
3902 			return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
3903 		else if (sizeof(minfo) < psize)
3904 			memset(ptr, 0, psize);
3905 		memcpy(ptr, &minfo, sizeof(minfo));
3906 	}
3907 
3908 	return 1;
3909 }
3910 
3911 /**
3912  * gnutls_pkcs11_type_get_name:
3913  * @type: Holds the PKCS 11 object type, a #gnutls_pkcs11_obj_type_t.
3914  *
3915  * This function will return a human readable description of the
3916  * PKCS11 object type @obj.  It will return "Unknown" for unknown
3917  * types.
3918  *
3919  * Returns: human readable string labeling the PKCS11 object type
3920  * @type.
3921  *
3922  * Since: 2.12.0
3923  **/
gnutls_pkcs11_type_get_name(gnutls_pkcs11_obj_type_t type)3924 const char *gnutls_pkcs11_type_get_name(gnutls_pkcs11_obj_type_t type)
3925 {
3926 	switch (type) {
3927 	case GNUTLS_PKCS11_OBJ_X509_CRT:
3928 		return "X.509 Certificate";
3929 	case GNUTLS_PKCS11_OBJ_PUBKEY:
3930 		return "Public key";
3931 	case GNUTLS_PKCS11_OBJ_PRIVKEY:
3932 		return "Private key";
3933 	case GNUTLS_PKCS11_OBJ_SECRET_KEY:
3934 		return "Secret key";
3935 	case GNUTLS_PKCS11_OBJ_DATA:
3936 		return "Data";
3937 	case GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION:
3938 		return "X.509 certificate extension";
3939 	case GNUTLS_PKCS11_OBJ_UNKNOWN:
3940 	default:
3941 		return "Unknown";
3942 	}
3943 }
3944 
3945 static
check_found_cert(struct find_cert_st * priv,ck_object_handle_t ctx,gnutls_datum_t * data,time_t now,ck_object_handle_t * cand_ctx)3946 int check_found_cert(struct find_cert_st *priv,
3947 		     ck_object_handle_t ctx,
3948 		     gnutls_datum_t *data,
3949 		     time_t now,
3950 		     ck_object_handle_t *cand_ctx)
3951 {
3952 	gnutls_x509_crt_t tcrt = NULL;
3953 	unsigned has_ski;
3954 	int ret;
3955 
3956 	ret = gnutls_x509_crt_init(&tcrt);
3957 	if (ret < 0) {
3958 		gnutls_assert();
3959 		return ret;
3960 	}
3961 
3962 	ret = gnutls_x509_crt_import(tcrt, data, GNUTLS_X509_FMT_DER);
3963 	if (ret < 0) {
3964 		gnutls_assert();
3965 		goto cleanup;
3966 	}
3967 
3968 	if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE) {
3969 		if (priv->crt == NULL) {
3970 			gnutls_assert();
3971 			ret = -1;
3972 			goto cleanup;
3973 		}
3974 
3975 		if (gnutls_x509_crt_equals(priv->crt, tcrt) == 0) {
3976 			/* doesn't match */
3977 			_gnutls_debug_log("check_found_cert: cert doesn't match the expected\n");
3978 			ret = -1;
3979 			goto cleanup;
3980 		}
3981 	}
3982 
3983 	if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY) {
3984 		if (priv->crt == NULL) {
3985 			gnutls_assert();
3986 			ret = -1;
3987 			goto cleanup;
3988 		}
3989 
3990 		if (_gnutls_check_if_same_key(priv->crt, tcrt, 1) == 0) {
3991 			/* doesn't match */
3992 			_gnutls_debug_log("check_found_cert: cert key doesn't match the expected key\n");
3993 			ret = -1;
3994 			goto cleanup;
3995 		}
3996 	}
3997 
3998 	if (priv->key_id.size > 0 &&
3999 	    !_gnutls_check_valid_key_id(&priv->key_id, tcrt, now, &has_ski)) {
4000 		gnutls_assert();
4001 		if (has_ski) {
4002 			_gnutls_debug_log("check_found_cert: cert has invalid key ID\n");
4003 			ret = -1;
4004 		} else {
4005 			/* That's a possible match; there can be CA certificates without
4006 			 * an SKI, which match a cert which has AKI. */
4007 			*cand_ctx = ctx;
4008 		}
4009 		goto cleanup;
4010 	}
4011 
4012 	ret = 0;
4013 cleanup:
4014 	if (tcrt != NULL)
4015 		gnutls_x509_crt_deinit(tcrt);
4016 	return ret;
4017 }
4018 
get_data_and_attrs(struct pkcs11_session_info * sinfo,ck_object_handle_t object,gnutls_datum_t * data,char * label,size_t label_size,uint8_t * id,size_t id_size,gnutls_datum_t * o_label,gnutls_datum_t * o_id)4019 static int get_data_and_attrs(struct pkcs11_session_info *sinfo,
4020 			      ck_object_handle_t object, gnutls_datum_t *data,
4021 			      char *label, size_t label_size,
4022 			      uint8_t *id, size_t id_size,
4023 			      gnutls_datum_t *o_label, gnutls_datum_t *o_id)
4024 {
4025 	ck_rv_t rv;
4026 	struct ck_attribute a[2];
4027 
4028 	/* data will contain the certificate */
4029 	rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, object, CKA_VALUE, data);
4030 	if (rv == CKR_OK) {
4031 		a[0].type = CKA_LABEL;
4032 		a[0].value = label;
4033 		a[0].value_len = label_size;
4034 
4035 		a[1].type = CKA_ID;
4036 		a[1].value = id;
4037 		a[1].value_len = id_size;
4038 
4039 		if (pkcs11_get_attribute_value(sinfo->module, sinfo->pks, object, a,
4040 				     2) == CKR_OK) {
4041 			o_label->data = a[0].value;
4042 			o_label->size = a[0].value_len;
4043 			o_id->data = a[1].value;
4044 			o_id->size = a[1].value_len;
4045 
4046 			return 0;
4047 		} else {
4048 			_gnutls_free_datum(data);
4049 			_gnutls_debug_log
4050 				    ("p11: Skipped cert, missing attrs.\n");
4051 		}
4052 	}
4053 
4054 	return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
4055 }
4056 
4057 static int
find_cert_cb(struct ck_function_list * module,struct pkcs11_session_info * sinfo,struct ck_token_info * tinfo,struct ck_info * lib_info,void * input)4058 find_cert_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo,
4059 	    struct ck_token_info *tinfo, struct ck_info *lib_info, void *input)
4060 {
4061 	struct ck_attribute a[10];
4062 	ck_object_class_t class = -1;
4063 	ck_certificate_type_t type = (ck_certificate_type_t) - 1;
4064 	ck_rv_t rv;
4065 	ck_object_handle_t ctx, cand_ctx = CK_INVALID_HANDLE;
4066 	unsigned long count, a_vals;
4067 	int found = 0, ret;
4068 	struct find_cert_st *priv = input;
4069 	char label_tmp[PKCS11_LABEL_SIZE];
4070 	uint8_t id_tmp[PKCS11_ID_SIZE];
4071 	gnutls_datum_t data = {NULL, 0};
4072 	unsigned finalized;
4073 	int i, tries;
4074 	ck_bool_t trusted = 1;
4075 	time_t now;
4076 	gnutls_datum_t label = {NULL,0}, id = {NULL,0};
4077 
4078 	if (tinfo == NULL) {
4079 		gnutls_assert();
4080 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
4081 	}
4082 
4083 	/* the DISTRUSTED flag is p11-kit module specific */
4084 	if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) {
4085 		if (memcmp(lib_info->manufacturer_id, "PKCS#11 Kit", 11) != 0) {
4086 			gnutls_assert();
4087 			return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
4088 		}
4089 	}
4090 
4091 	if (priv->dn.size == 0 && priv->key_id.size == 0 && priv->issuer_dn.size == 0 &&
4092 		priv->serial.size == 0)
4093 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
4094 
4095 	/* Find objects with given class and type */
4096 
4097 	if (priv->key_id.size > 0 && priv->dn.size > 0)
4098 		tries = 2;
4099 	else
4100 		tries = 1;
4101 
4102 	now = gnutls_time(0);
4103 	for (i = 0; i < tries; i++) {
4104 
4105 		a_vals = 0;
4106 		class = CKO_CERTIFICATE;
4107 		a[a_vals].type = CKA_CLASS;
4108 		a[a_vals].value = &class;
4109 		a[a_vals].value_len = sizeof class;
4110 		a_vals++;
4111 
4112 		if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED) {
4113 			a[a_vals].type = CKA_TRUSTED;
4114 			a[a_vals].value = &trusted;
4115 			a[a_vals].value_len = sizeof trusted;
4116 			a_vals++;
4117 		}
4118 
4119 		if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) {
4120 			if (!sinfo->trusted) /* only p11-kit "trusted" modules support this flag */
4121 				return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
4122 
4123 			a[a_vals].type = CKA_X_DISTRUSTED;
4124 			a[a_vals].value = &trusted;
4125 			a[a_vals].value_len = sizeof trusted;
4126 			a_vals++;
4127 		}
4128 
4129 		if (priv->need_import != 0) {
4130 			type = CKC_X_509;
4131 			a[a_vals].type = CKA_CERTIFICATE_TYPE;
4132 			a[a_vals].value = &type;
4133 			a[a_vals].value_len = sizeof type;
4134 			a_vals++;
4135 		}
4136 
4137 		if (i == 0 && priv->key_id.size > 0) {
4138 			a[a_vals].type = CKA_ID;
4139 			a[a_vals].value = priv->key_id.data;
4140 			a[a_vals].value_len = priv->key_id.size;
4141 			a_vals++;
4142 		}
4143 
4144 		/* This doesn't do a proper comparison, see
4145 		 * _gnutls_x509_compare_raw_dn() */
4146 		if (priv->dn.size > 0) {
4147 			a[a_vals].type = CKA_SUBJECT;
4148 			a[a_vals].value = priv->dn.data;
4149 			a[a_vals].value_len = priv->dn.size;
4150 			a_vals++;
4151 		}
4152 
4153 		if (priv->serial.size > 0) {
4154 			a[a_vals].type = CKA_SERIAL_NUMBER;
4155 			a[a_vals].value = priv->serial.data;
4156 			a[a_vals].value_len = priv->serial.size;
4157 			a_vals++;
4158 		}
4159 
4160 		/* Same problem as for priv->dn */
4161 		if (priv->issuer_dn.size > 0) {
4162 			a[a_vals].type = CKA_ISSUER;
4163 			a[a_vals].value = priv->issuer_dn.data;
4164 			a[a_vals].value_len = priv->issuer_dn.size;
4165 			a_vals++;
4166 		}
4167 
4168 		finalized = 0;
4169 		rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
4170 					      a_vals);
4171 		if (rv != CKR_OK) {
4172 			gnutls_assert();
4173 			_gnutls_debug_log
4174 			    ("p11: FindObjectsInit failed.\n");
4175 			ret = pkcs11_rv_to_err(rv);
4176 			goto cleanup;
4177 		}
4178 
4179 		while (pkcs11_find_objects
4180 		       (sinfo->module, sinfo->pks, &ctx, 1,
4181 			&count) == CKR_OK && count == 1) {
4182 
4183 			if (priv->need_import == 0 && !(priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE)
4184 			    && !(priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY)) {
4185 				found = 1;
4186 				break;
4187 			}
4188 
4189 			ret = get_data_and_attrs(sinfo, ctx, &data,
4190 						 label_tmp, sizeof(label_tmp),
4191 						 id_tmp, sizeof(id_tmp),
4192 						 &label,
4193 						 &id);
4194 			if (ret < 0)
4195 				continue;
4196 
4197 			ret = check_found_cert(priv, ctx, &data, now, &cand_ctx);
4198 			if (ret < 0) {
4199 				_gnutls_free_datum(&data);
4200 				continue;
4201 			}
4202 
4203 			found = 1;
4204 			break;
4205 		}
4206 
4207 		if (!found && cand_ctx != CK_INVALID_HANDLE) {
4208 			/* there was a possible match; let's retrieve that one instead of
4209 			 * failing */
4210 			ret = get_data_and_attrs(sinfo, cand_ctx, &data,
4211 						 label_tmp, sizeof(label_tmp),
4212 						 id_tmp, sizeof(id_tmp),
4213 						 &label,
4214 						 &id);
4215 			if (ret >= 0)
4216 				found = 1;
4217 
4218 			/* we do not need to use check_found_cert() because
4219 			 * in case we have a candidate, we already have checked it
4220 			 */
4221 		}
4222 
4223 		pkcs11_find_objects_final(sinfo);
4224 		finalized = 1;
4225 
4226 		if (found != 0) {
4227 			if (!(priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) &&
4228 			    (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT) && data.size > 0) {
4229 				gnutls_datum_t spki;
4230 				rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, ctx, CKA_PUBLIC_KEY_INFO, &spki);
4231 				if (rv == CKR_OK) {
4232 					ret = pkcs11_override_cert_exts(sinfo, &spki, &data);
4233 					gnutls_free(spki.data);
4234 					if (ret < 0) {
4235 						gnutls_assert();
4236 						goto cleanup;
4237 					}
4238 				}
4239 			}
4240 
4241 			if (priv->need_import != 0) {
4242 				ret =
4243 				    pkcs11_obj_import(class, priv->obj,
4244 						      &data, &id, &label,
4245 						      tinfo,
4246 						      lib_info);
4247 				if (ret < 0) {
4248 					gnutls_assert();
4249 					goto cleanup;
4250 				}
4251 			}
4252 			break;
4253 		}
4254 	}
4255 
4256 	if (found == 0) {
4257 		gnutls_assert();
4258 		ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
4259 	} else {
4260 		ret = 0;
4261 	}
4262 
4263       cleanup:
4264 	gnutls_free(data.data);
4265 	if (finalized == 0)
4266 		pkcs11_find_objects_final(sinfo);
4267 
4268 	return ret;
4269 }
4270 
4271 /**
4272  * gnutls_pkcs11_get_raw_issuer:
4273  * @url: A PKCS 11 url identifying a token
4274  * @cert: is the certificate to find issuer for
4275  * @issuer: Will hold the issuer if any in an allocated buffer.
4276  * @fmt: The format of the exported issuer.
4277  * @flags: Use zero or flags from %GNUTLS_PKCS11_OBJ_FLAG.
4278  *
4279  * This function will return the issuer of a given certificate, if it
4280  * is stored in the token. By default only marked as trusted issuers
4281  * are returned. If any issuer should be returned specify
4282  * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY in @flags.
4283  *
4284  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
4285  *   negative error value.
4286  *
4287  * Since: 3.2.7
4288  **/
gnutls_pkcs11_get_raw_issuer(const char * url,gnutls_x509_crt_t cert,gnutls_datum_t * issuer,gnutls_x509_crt_fmt_t fmt,unsigned int flags)4289 int gnutls_pkcs11_get_raw_issuer(const char *url, gnutls_x509_crt_t cert,
4290 				 gnutls_datum_t * issuer,
4291 				 gnutls_x509_crt_fmt_t fmt,
4292 				 unsigned int flags)
4293 {
4294 	int ret;
4295 	struct find_cert_st priv;
4296 	uint8_t id[PKCS11_ID_SIZE];
4297 	size_t id_size;
4298 	struct p11_kit_uri *info = NULL;
4299 
4300 	PKCS11_CHECK_INIT_FLAGS(flags);
4301 
4302 	memset(&priv, 0, sizeof(priv));
4303 
4304 	if (url == NULL || url[0] == 0) {
4305 		url = "pkcs11:";
4306 	}
4307 
4308 	ret = pkcs11_url_to_info(url, &info, flags);
4309 	if (ret < 0) {
4310 		gnutls_assert();
4311 		return ret;
4312 	}
4313 
4314 	id_size = sizeof(id);
4315 	ret =
4316 	    gnutls_x509_crt_get_authority_key_id(cert, id, &id_size, NULL);
4317 	if (ret >= 0) {
4318 		priv.key_id.data = id;
4319 		priv.key_id.size = id_size;
4320 	}
4321 
4322 	priv.dn.data = cert->raw_issuer_dn.data;
4323 	priv.dn.size = cert->raw_issuer_dn.size;
4324 
4325 	if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY))
4326 		flags |= GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED;
4327 
4328 	priv.flags = flags;
4329 
4330 	ret = gnutls_pkcs11_obj_init(&priv.obj);
4331 	if (ret < 0) {
4332 		gnutls_assert();
4333 		goto cleanup;
4334 	}
4335 
4336 	gnutls_pkcs11_obj_set_pin_function(priv.obj, cert->pin.cb, cert->pin.data);
4337 
4338 	priv.need_import = 1;
4339 
4340 	ret =
4341 	    _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
4342 				    &cert->pin, pkcs11_obj_flags_to_int(flags));
4343 	if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
4344 		/* we have failed retrieving the right certificate; if there
4345 		 * was a close match return that one. */
4346 		priv.flags |= GNUTLS_PKCS11_OBJ_FLAG_FIRST_CLOSE_MATCH;
4347 		ret =
4348 		    _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
4349 					    &cert->pin, pkcs11_obj_flags_to_int(flags));
4350 	}
4351 
4352 	if (ret < 0) {
4353 		gnutls_assert();
4354 		goto cleanup;
4355 	}
4356 
4357 	ret = gnutls_pkcs11_obj_export3(priv.obj, fmt, issuer);
4358 	if (ret < 0) {
4359 		gnutls_assert();
4360 		goto cleanup;
4361 	}
4362 
4363 	ret = 0;
4364 
4365       cleanup:
4366 	if (priv.obj)
4367 		gnutls_pkcs11_obj_deinit(priv.obj);
4368 	if (info)
4369 		p11_kit_uri_free(info);
4370 
4371 	return ret;
4372 }
4373 
4374 /**
4375  * gnutls_pkcs11_get_raw_issuer_by_dn:
4376  * @url: A PKCS 11 url identifying a token
4377  * @dn: is the DN to search for
4378  * @issuer: Will hold the issuer if any in an allocated buffer.
4379  * @fmt: The format of the exported issuer.
4380  * @flags: Use zero or flags from %GNUTLS_PKCS11_OBJ_FLAG.
4381  *
4382  * This function will return the certificate with the given DN, if it
4383  * is stored in the token. By default only marked as trusted issuers
4384  * are returned. If any issuer should be returned specify
4385  * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY in @flags.
4386  *
4387  * The name of the function includes issuer because it can
4388  * be used to discover issuers of certificates.
4389  *
4390  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
4391  *   negative error value.
4392  *
4393  * Since: 3.4.0
4394  **/
gnutls_pkcs11_get_raw_issuer_by_dn(const char * url,const gnutls_datum_t * dn,gnutls_datum_t * issuer,gnutls_x509_crt_fmt_t fmt,unsigned int flags)4395 int gnutls_pkcs11_get_raw_issuer_by_dn (const char *url, const gnutls_datum_t *dn,
4396 					gnutls_datum_t *issuer,
4397 					gnutls_x509_crt_fmt_t fmt,
4398 					unsigned int flags)
4399 {
4400 	int ret;
4401 	struct find_cert_st priv;
4402 	struct p11_kit_uri *info = NULL;
4403 
4404 	PKCS11_CHECK_INIT_FLAGS(flags);
4405 
4406 	memset(&priv, 0, sizeof(priv));
4407 
4408 	if (url == NULL || url[0] == 0) {
4409 		url = "pkcs11:";
4410 	}
4411 
4412 	ret = pkcs11_url_to_info(url, &info, flags);
4413 	if (ret < 0) {
4414 		gnutls_assert();
4415 		return ret;
4416 	}
4417 
4418 	priv.dn.data = dn->data;
4419 	priv.dn.size = dn->size;
4420 
4421 	if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY))
4422 		flags |= GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED;
4423 
4424 	priv.flags = flags;
4425 
4426 	ret = gnutls_pkcs11_obj_init(&priv.obj);
4427 	if (ret < 0) {
4428 		gnutls_assert();
4429 		goto cleanup;
4430 	}
4431 	priv.need_import = 1;
4432 
4433 	ret =
4434 	    _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
4435 				    NULL, pkcs11_obj_flags_to_int(flags));
4436 	if (ret < 0) {
4437 		gnutls_assert();
4438 		goto cleanup;
4439 	}
4440 
4441 	ret = gnutls_pkcs11_obj_export3(priv.obj, fmt, issuer);
4442 	if (ret < 0) {
4443 		gnutls_assert();
4444 		goto cleanup;
4445 	}
4446 
4447 	ret = 0;
4448 
4449       cleanup:
4450 	if (priv.obj)
4451 		gnutls_pkcs11_obj_deinit(priv.obj);
4452 	if (info)
4453 		p11_kit_uri_free(info);
4454 
4455 	return ret;
4456 }
4457 
4458 /**
4459  * gnutls_pkcs11_get_raw_issuer_by_subject_key_id:
4460  * @url: A PKCS 11 url identifying a token
4461  * @dn: is the DN to search for (may be %NULL)
4462  * @spki: is the subject key ID to search for
4463  * @issuer: Will hold the issuer if any in an allocated buffer.
4464  * @fmt: The format of the exported issuer.
4465  * @flags: Use zero or flags from %GNUTLS_PKCS11_OBJ_FLAG.
4466  *
4467  * This function will return the certificate with the given DN and @spki, if it
4468  * is stored in the token. By default only marked as trusted issuers
4469  * are returned. If any issuer should be returned specify
4470  * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY in @flags.
4471  *
4472  * The name of the function includes issuer because it can
4473  * be used to discover issuers of certificates.
4474  *
4475  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
4476  *   negative error value.
4477  *
4478  * Since: 3.4.2
4479  **/
gnutls_pkcs11_get_raw_issuer_by_subject_key_id(const char * url,const gnutls_datum_t * dn,const gnutls_datum_t * spki,gnutls_datum_t * issuer,gnutls_x509_crt_fmt_t fmt,unsigned int flags)4480 int gnutls_pkcs11_get_raw_issuer_by_subject_key_id (const char *url,
4481 					const gnutls_datum_t *dn,
4482 					const gnutls_datum_t *spki,
4483 					gnutls_datum_t *issuer,
4484 					gnutls_x509_crt_fmt_t fmt,
4485 					unsigned int flags)
4486 {
4487 	int ret;
4488 	struct find_cert_st priv;
4489 	struct p11_kit_uri *info = NULL;
4490 
4491 	PKCS11_CHECK_INIT_FLAGS(flags);
4492 
4493 	memset(&priv, 0, sizeof(priv));
4494 
4495 	if (url == NULL || url[0] == 0) {
4496 		url = "pkcs11:";
4497 	}
4498 
4499 	ret = pkcs11_url_to_info(url, &info, flags);
4500 	if (ret < 0) {
4501 		gnutls_assert();
4502 		return ret;
4503 	}
4504 
4505 	if (dn) {
4506 		priv.dn.data = dn->data;
4507 		priv.dn.size = dn->size;
4508 	}
4509 
4510 	priv.key_id.data = spki->data;
4511 	priv.key_id.size = spki->size;
4512 
4513 	if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY))
4514 		flags |= GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED;
4515 
4516 	priv.flags = flags;
4517 
4518 	ret = gnutls_pkcs11_obj_init(&priv.obj);
4519 	if (ret < 0) {
4520 		gnutls_assert();
4521 		goto cleanup;
4522 	}
4523 	priv.need_import = 1;
4524 
4525 	ret =
4526 	    _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
4527 				    NULL, pkcs11_obj_flags_to_int(flags));
4528 	if (ret < 0) {
4529 		gnutls_assert();
4530 		goto cleanup;
4531 	}
4532 
4533 	ret = gnutls_pkcs11_obj_export3(priv.obj, fmt, issuer);
4534 	if (ret < 0) {
4535 		gnutls_assert();
4536 		goto cleanup;
4537 	}
4538 
4539 	ret = 0;
4540 
4541       cleanup:
4542 	if (priv.obj)
4543 		gnutls_pkcs11_obj_deinit(priv.obj);
4544 	if (info)
4545 		p11_kit_uri_free(info);
4546 
4547 	return ret;
4548 }
4549 
4550 unsigned
_gnutls_pkcs11_crt_is_known(const char * url,gnutls_x509_crt_t cert,unsigned int flags,gnutls_x509_crt_t * trusted_cert)4551 _gnutls_pkcs11_crt_is_known(const char *url, gnutls_x509_crt_t cert,
4552 			    unsigned int flags,
4553 			    gnutls_x509_crt_t *trusted_cert)
4554 {
4555 	int ret;
4556 	struct find_cert_st priv;
4557 	uint8_t serial[128];
4558 	size_t serial_size;
4559 	struct p11_kit_uri *info = NULL;
4560 
4561 	PKCS11_CHECK_INIT_FLAGS_RET(flags, 0);
4562 
4563 	memset(&priv, 0, sizeof(priv));
4564 
4565 	if (trusted_cert) {
4566 		ret = gnutls_pkcs11_obj_init(&priv.obj);
4567 		if (ret < 0) {
4568 			gnutls_assert();
4569 			goto cleanup;
4570 		}
4571 		priv.need_import = 1;
4572 	}
4573 
4574 	if (url == NULL || url[0] == 0) {
4575 		url = "pkcs11:";
4576 	}
4577 
4578 	ret = pkcs11_url_to_info(url, &info, 0);
4579 	if (ret < 0) {
4580 		gnutls_assert();
4581 		return 0;
4582 	}
4583 
4584 	/* Attempt searching using the issuer DN + serial number */
4585 	serial_size = sizeof(serial);
4586 	ret =
4587 	    gnutls_x509_crt_get_serial(cert, serial, &serial_size);
4588 	if (ret < 0) {
4589 		gnutls_assert();
4590 		ret = 0;
4591 		goto cleanup;
4592 	}
4593 
4594 	ret = _gnutls_x509_ext_gen_number(serial, serial_size, &priv.serial);
4595 	if (ret < 0) {
4596 		gnutls_assert();
4597 		ret = 0;
4598 		goto cleanup;
4599 	}
4600 
4601 	priv.crt = cert;
4602 
4603 	priv.issuer_dn.data = cert->raw_issuer_dn.data;
4604 	priv.issuer_dn.size = cert->raw_issuer_dn.size;
4605 
4606 	/* assume PKCS11_OBJ_FLAG_COMPARE everywhere but DISTRUST info */
4607 	if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) && !(flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY)) {
4608 		flags |= GNUTLS_PKCS11_OBJ_FLAG_COMPARE;
4609 	}
4610 
4611 	priv.flags = flags;
4612 
4613 	ret =
4614 	    _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
4615 				    NULL, pkcs11_obj_flags_to_int(flags));
4616 	if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
4617 		_gnutls_debug_log("crt_is_known: did not find cert, using issuer DN + serial, using DN only\n");
4618 		/* attempt searching with the subject DN only */
4619 		gnutls_assert();
4620 		if (priv.obj)
4621 			gnutls_pkcs11_obj_deinit(priv.obj);
4622 		gnutls_free(priv.serial.data);
4623 		memset(&priv, 0, sizeof(priv));
4624 		if (trusted_cert) {
4625 			ret = gnutls_pkcs11_obj_init(&priv.obj);
4626 			if (ret < 0) {
4627 				gnutls_assert();
4628 				goto cleanup;
4629 			}
4630 			priv.need_import = 1;
4631 		}
4632 		priv.crt = cert;
4633 		priv.flags = flags;
4634 
4635 		priv.dn.data = cert->raw_dn.data;
4636 		priv.dn.size = cert->raw_dn.size;
4637 		ret =
4638 		    _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
4639 				    NULL, pkcs11_obj_flags_to_int(flags));
4640 	}
4641 	if (ret < 0) {
4642 		gnutls_assert();
4643 		_gnutls_debug_log("crt_is_known: did not find any cert\n");
4644 		ret = 0;
4645 		goto cleanup;
4646 	}
4647 
4648 	if (trusted_cert) {
4649 		ret = gnutls_x509_crt_init(trusted_cert);
4650 		if (ret < 0) {
4651 			gnutls_assert();
4652 			ret = 0;
4653 			goto cleanup;
4654 		}
4655 		ret = gnutls_x509_crt_import_pkcs11(*trusted_cert, priv.obj);
4656 		if (ret < 0) {
4657 			gnutls_assert();
4658 			gnutls_x509_crt_deinit(*trusted_cert);
4659 			ret = 0;
4660 			goto cleanup;
4661 		}
4662 	}
4663 	ret = 1;
4664 
4665       cleanup:
4666 	if (priv.obj)
4667 		gnutls_pkcs11_obj_deinit(priv.obj);
4668 	if (info)
4669 		p11_kit_uri_free(info);
4670 	gnutls_free(priv.serial.data);
4671 
4672 	return ret;
4673 }
4674 
4675 /**
4676  * gnutls_pkcs11_crt_is_known:
4677  * @url: A PKCS 11 url identifying a token
4678  * @cert: is the certificate to find issuer for
4679  * @flags: Use zero or flags from %GNUTLS_PKCS11_OBJ_FLAG.
4680  *
4681  * This function will check whether the provided certificate is stored
4682  * in the specified token. This is useful in combination with
4683  * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED or
4684  * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED,
4685  * to check whether a CA is present or a certificate is blacklisted in
4686  * a trust PKCS #11 module.
4687  *
4688  * This function can be used with a @url of "pkcs11:", and in that case all modules
4689  * will be searched. To restrict the modules to the marked as trusted in p11-kit
4690  * use the %GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE flag.
4691  *
4692  * Note that the flag %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED is
4693  * specific to p11-kit trust modules.
4694  *
4695  * Returns: If the certificate exists non-zero is returned, otherwise zero.
4696  *
4697  * Since: 3.3.0
4698  **/
gnutls_pkcs11_crt_is_known(const char * url,gnutls_x509_crt_t cert,unsigned int flags)4699 unsigned gnutls_pkcs11_crt_is_known(const char *url, gnutls_x509_crt_t cert,
4700 				 unsigned int flags)
4701 {
4702 	return _gnutls_pkcs11_crt_is_known(url, cert, flags, NULL);
4703 }
4704 
4705 /**
4706  * gnutls_pkcs11_obj_get_flags:
4707  * @obj: The pkcs11 object
4708  * @oflags: Will hold the output flags
4709  *
4710  * This function will return the flags of the object.
4711  * The @oflags will be flags from %gnutls_pkcs11_obj_flags. That is,
4712  * the %GNUTLS_PKCS11_OBJ_FLAG_MARK_* flags.
4713  *
4714  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
4715  *   negative error value.
4716  *
4717  * Since: 3.3.7
4718  **/
4719 int
gnutls_pkcs11_obj_get_flags(gnutls_pkcs11_obj_t obj,unsigned int * oflags)4720 gnutls_pkcs11_obj_get_flags(gnutls_pkcs11_obj_t obj, unsigned int *oflags)
4721 {
4722 	*oflags = obj->flags;
4723 
4724 	return 0;
4725 }
4726 
4727 /**
4728  * gnutls_pkcs11_obj_flags_get_str:
4729  * @flags: holds the flags
4730  *
4731  * This function given an or-sequence of %GNUTLS_PKCS11_OBJ_FLAG_MARK,
4732  * will return an allocated string with its description. The string
4733  * needs to be deallocated using gnutls_free().
4734  *
4735  * Returns: If flags is zero %NULL is returned, otherwise an allocated string.
4736  *
4737  * Since: 3.3.7
4738  **/
gnutls_pkcs11_obj_flags_get_str(unsigned int flags)4739 char *gnutls_pkcs11_obj_flags_get_str(unsigned int flags)
4740 {
4741 	gnutls_buffer_st str;
4742 	gnutls_datum_t out;
4743 	int ret;
4744 
4745 	if (flags == 0)
4746 		return NULL;
4747 
4748 	_gnutls_buffer_init(&str);
4749 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP)
4750 		_gnutls_buffer_append_str(&str, "CKA_WRAP/UNWRAP; ");
4751 
4752 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA)
4753 		_gnutls_buffer_append_str(&str, "CKA_CERTIFICATE_CATEGORY=CA; ");
4754 
4755 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE)
4756 		_gnutls_buffer_append_str(&str, "CKA_PRIVATE; ");
4757 
4758 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH)
4759 		_gnutls_buffer_append_str(&str, "CKA_ALWAYS_AUTH; ");
4760 
4761 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED)
4762 		_gnutls_buffer_append_str(&str, "CKA_TRUSTED; ");
4763 
4764 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_DISTRUSTED)
4765 		_gnutls_buffer_append_str(&str, "CKA_X_DISTRUSTED; ");
4766 
4767 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_EXTRACTABLE)
4768 		_gnutls_buffer_append_str(&str, "CKA_EXTRACTABLE; ");
4769 
4770 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_NEVER_EXTRACTABLE)
4771 		_gnutls_buffer_append_str(&str, "CKA_NEVER_EXTRACTABLE; ");
4772 
4773 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
4774 		_gnutls_buffer_append_str(&str, "CKA_SENSITIVE; ");
4775 
4776 	ret = _gnutls_buffer_to_datum(&str, &out, 1);
4777 	if (ret < 0) {
4778 		gnutls_assert();
4779 		goto fail;
4780 	}
4781 
4782 	return (char*)out.data;
4783 fail:
4784 	return NULL;
4785 
4786 }
4787