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