Line data Source code
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 :
131 3 : int pkcs11_rv_to_err(ck_rv_t rv)
132 : {
133 3 : switch (rv) {
134 : case CKR_OK:
135 : return 0;
136 0 : case CKR_HOST_MEMORY:
137 0 : return GNUTLS_E_MEMORY_ERROR;
138 0 : case CKR_SLOT_ID_INVALID:
139 0 : return GNUTLS_E_PKCS11_SLOT_ERROR;
140 0 : case CKR_ARGUMENTS_BAD:
141 : case CKR_MECHANISM_PARAM_INVALID:
142 0 : return GNUTLS_E_INVALID_REQUEST;
143 0 : 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 0 : return GNUTLS_E_LOCKING_ERROR;
149 1 : case CKR_ATTRIBUTE_READ_ONLY:
150 : case CKR_ATTRIBUTE_SENSITIVE:
151 : case CKR_ATTRIBUTE_TYPE_INVALID:
152 : case CKR_ATTRIBUTE_VALUE_INVALID:
153 1 : return GNUTLS_E_PKCS11_ATTRIBUTE_ERROR;
154 0 : case CKR_DEVICE_ERROR:
155 : case CKR_DEVICE_MEMORY:
156 : case CKR_DEVICE_REMOVED:
157 0 : return GNUTLS_E_PKCS11_DEVICE_ERROR;
158 0 : 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 0 : return GNUTLS_E_PKCS11_DATA_ERROR;
164 0 : case CKR_FUNCTION_NOT_SUPPORTED:
165 : case CKR_MECHANISM_INVALID:
166 0 : return GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR;
167 2 : 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 2 : return GNUTLS_E_PKCS11_KEY_ERROR;
178 0 : case CKR_PIN_INCORRECT:
179 : case CKR_PIN_INVALID:
180 : case CKR_PIN_LEN_RANGE:
181 0 : return GNUTLS_E_PKCS11_PIN_ERROR;
182 0 : case CKR_PIN_EXPIRED:
183 0 : return GNUTLS_E_PKCS11_PIN_EXPIRED;
184 0 : case CKR_PIN_LOCKED:
185 0 : return GNUTLS_E_PKCS11_PIN_LOCKED;
186 0 : 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 0 : return GNUTLS_E_PKCS11_SESSION_ERROR;
195 0 : case CKR_SIGNATURE_INVALID:
196 : case CKR_SIGNATURE_LEN_RANGE:
197 0 : return GNUTLS_E_PKCS11_SIGNATURE_ERROR;
198 0 : case CKR_TOKEN_NOT_PRESENT:
199 : case CKR_TOKEN_NOT_RECOGNIZED:
200 : case CKR_TOKEN_WRITE_PROTECTED:
201 0 : return GNUTLS_E_PKCS11_TOKEN_ERROR;
202 0 : 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 0 : return GNUTLS_E_PKCS11_USER_ERROR;
209 0 : case CKR_BUFFER_TOO_SMALL:
210 0 : return GNUTLS_E_SHORT_MEMORY_BUFFER;
211 0 : default:
212 0 : return GNUTLS_E_PKCS11_ERROR;
213 : }
214 : }
215 :
216 :
217 3040 : static int scan_slots(struct gnutls_pkcs11_provider_st *p,
218 : ck_slot_id_t * slots, unsigned long *nslots)
219 : {
220 3040 : ck_rv_t rv;
221 :
222 3040 : rv = pkcs11_get_slot_list(p->module, 1, slots, nslots);
223 3040 : if (rv != CKR_OK) {
224 0 : gnutls_assert();
225 0 : return pkcs11_rv_to_err(rv);
226 : }
227 : return 0;
228 : }
229 :
230 : static int
231 137 : pkcs11_add_module(const char* name, struct ck_function_list *module, unsigned custom_init, const char *params)
232 : {
233 137 : unsigned int i;
234 137 : struct ck_info info;
235 :
236 137 : if (active_providers >= MAX_PROVIDERS) {
237 0 : gnutls_assert();
238 0 : return GNUTLS_E_CONSTRAINT_ERROR;
239 : }
240 :
241 137 : memset(&info, 0, sizeof(info));
242 137 : pkcs11_get_module_info(module, &info);
243 :
244 : /* initially check if this module is a duplicate */
245 278 : for (i = 0; i < active_providers; i++) {
246 : /* already loaded, skip the rest */
247 4 : if (module == providers[i].module ||
248 4 : memcmp(&info, &providers[i].info, sizeof(info)) == 0) {
249 0 : _gnutls_debug_log("p11: module %s is already loaded.\n", name);
250 0 : return GNUTLS_E_INT_RET_0;
251 : }
252 : }
253 :
254 137 : active_providers++;
255 137 : providers[active_providers - 1].module = module;
256 137 : providers[active_providers - 1].active = 1;
257 137 : providers[active_providers - 1].trusted = 0;
258 137 : providers[active_providers - 1].custom_init = custom_init;
259 :
260 137 : if (p11_kit_module_get_flags(module) & P11_KIT_MODULE_TRUSTED ||
261 15 : (params != NULL && strstr(params, "trusted") != 0))
262 19 : providers[active_providers - 1].trusted = 1;
263 :
264 137 : memcpy(&providers[active_providers - 1].info, &info, sizeof(info));
265 :
266 137 : 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 : */
277 1986 : int _gnutls_pkcs11_check_init(init_level_t req_level, void *priv, pkcs11_reinit_function cb)
278 : {
279 1986 : int ret, sret = 0;
280 :
281 1986 : ret = gnutls_mutex_lock(&_gnutls_pkcs11_mutex);
282 1986 : if (ret != 0)
283 0 : return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
284 :
285 1986 : if (providers_initialized > PROV_UNINITIALIZED) {
286 1986 : ret = 0;
287 :
288 1986 : if (_gnutls_detect_fork(pkcs11_forkid)) {
289 : /* if we are initialized but a fork is detected */
290 2 : ret = _gnutls_pkcs11_reinit();
291 2 : if (ret == 0) {
292 2 : sret = 1;
293 2 : if (cb) {
294 2 : int ret2 = cb(priv);
295 2 : if (ret2 < 0)
296 0 : ret = ret2;
297 : }
298 2 : pkcs11_forkid = _gnutls_get_forkid();
299 : }
300 : }
301 :
302 2 : if (ret < 0) {
303 0 : gnutls_assert();
304 0 : 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 1986 : switch(req_level) {
315 : case PROV_UNINITIALIZED:
316 : case PROV_INIT_MANUAL:
317 : break;
318 646 : case PROV_INIT_TRUSTED:
319 : case PROV_INIT_MANUAL_TRUSTED:
320 646 : if (providers_initialized < PROV_INIT_MANUAL_TRUSTED) {
321 4 : _gnutls_debug_log("Initializing needed PKCS #11 modules\n");
322 4 : ret = auto_load(1);
323 4 : if (ret < 0) {
324 0 : gnutls_assert();
325 : }
326 :
327 4 : if (providers_initialized == PROV_INIT_MANUAL)
328 4 : providers_initialized = PROV_INIT_MANUAL_TRUSTED;
329 : else
330 0 : providers_initialized = PROV_INIT_TRUSTED;
331 :
332 4 : goto cleanup;
333 : }
334 : break;
335 1340 : case PROV_INIT_ALL:
336 1340 : if (providers_initialized == PROV_INIT_TRUSTED ||
337 : providers_initialized == PROV_UNINITIALIZED) {
338 0 : _gnutls_debug_log("Initializing all PKCS #11 modules\n");
339 0 : ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO, NULL);
340 0 : if (ret < 0) {
341 0 : gnutls_assert();
342 : }
343 :
344 0 : providers_initialized = PROV_INIT_ALL;
345 0 : goto cleanup;
346 : }
347 : break;
348 : }
349 :
350 : ret = sret;
351 :
352 1986 : cleanup:
353 1986 : gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
354 :
355 1986 : 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 : **/
378 133 : int gnutls_pkcs11_add_provider(const char *name, const char *params)
379 : {
380 133 : struct ck_function_list *module;
381 133 : unsigned custom_init = 0, flags = 0;
382 133 : struct ck_c_initialize_args args;
383 133 : const char *p;
384 133 : int ret;
385 :
386 133 : if (params && (p = strstr(params, "p11-kit:")) != 0) {
387 3 : memset (&args, 0, sizeof (args));
388 3 : args.reserved = (char*)(p + sizeof("p11-kit:")-1);
389 3 : args.flags = CKF_OS_LOCKING_OK;
390 :
391 3 : custom_init = 1;
392 3 : flags = P11_KIT_MODULE_UNMANAGED;
393 : }
394 :
395 133 : module = p11_kit_module_load(name, P11_KIT_MODULE_CRITICAL|flags);
396 133 : if (module == NULL) {
397 0 : gnutls_assert();
398 0 : _gnutls_debug_log("p11: Cannot load provider %s\n", name);
399 0 : return GNUTLS_E_PKCS11_LOAD_ERROR;
400 : }
401 :
402 133 : _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 133 : if (custom_init) {
407 3 : ret = module->C_Initialize(&args);
408 : } else {
409 130 : ret = p11_kit_module_initialize(module);
410 : }
411 :
412 133 : if (ret != CKR_OK) {
413 0 : p11_kit_module_release(module);
414 0 : gnutls_assert();
415 0 : return pkcs11_rv_to_err(ret);
416 : }
417 :
418 133 : ret = pkcs11_add_module(name, module, custom_init, params);
419 133 : if (ret != 0) {
420 0 : if (ret == GNUTLS_E_INT_RET_0)
421 0 : ret = 0;
422 0 : if (!custom_init)
423 0 : p11_kit_module_finalize(module);
424 : else
425 0 : module->C_Finalize(NULL);
426 0 : p11_kit_module_release(module);
427 0 : gnutls_assert();
428 : }
429 :
430 : return ret;
431 : }
432 :
433 : static
434 68 : 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 68 : struct ck_attribute *attr;
437 :
438 68 : *type = -1;
439 68 : *class = CKO_CERTIFICATE;
440 :
441 : /* find the object that matches the URL */
442 68 : *a_vals = 0;
443 68 : attr = p11_kit_uri_get_attribute(info, CKA_ID);
444 68 : if (attr) {
445 25 : memcpy(a + (*a_vals), attr, sizeof(struct ck_attribute));
446 25 : (*a_vals)++;
447 : }
448 :
449 68 : attr = p11_kit_uri_get_attribute(info, CKA_LABEL);
450 68 : if (attr) {
451 66 : memcpy(a + (*a_vals), attr, sizeof(struct ck_attribute));
452 66 : (*a_vals)++;
453 : }
454 :
455 68 : if (!(*a_vals)) {
456 0 : gnutls_assert();
457 0 : return GNUTLS_E_INVALID_REQUEST;
458 : }
459 :
460 : /* Find objects with given class and type */
461 68 : attr = p11_kit_uri_get_attribute(info, CKA_CLASS);
462 68 : if (attr) {
463 65 : if (attr->value
464 65 : && attr->value_len == sizeof(ck_object_class_t))
465 65 : memcpy(class, attr->value, sizeof(ck_object_class_t));
466 65 : if (*class == CKO_CERTIFICATE)
467 31 : *type = CKC_X_509;
468 65 : memcpy(a + (*a_vals), attr, sizeof(struct ck_attribute));
469 65 : (*a_vals)++;
470 : }
471 :
472 68 : if (*type != (ck_certificate_type_t) - 1) {
473 31 : a[(*a_vals)].type = CKA_CERTIFICATE_TYPE;
474 31 : a[(*a_vals)].value = type;
475 31 : a[(*a_vals)].value_len = sizeof *type;
476 31 : (*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
499 3 : 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 3 : struct p11_kit_uri *info = obj->info;
505 3 : struct pkcs11_session_info sinfo;
506 3 : struct ck_attribute a[4];
507 3 : ck_object_handle_t ctx[2];
508 3 : ck_certificate_type_t type;
509 3 : ck_object_class_t class;
510 3 : unsigned long count;
511 3 : size_t size;
512 3 : unsigned a_vals;
513 3 : char tmp[128];
514 3 : ck_rv_t rv;
515 3 : int ret;
516 :
517 3 : PKCS11_CHECK_INIT;
518 :
519 3 : ret =
520 3 : pkcs11_open_session(&sinfo, NULL, info,
521 : SESSION_WRITE |
522 3 : pkcs11_obj_flags_to_int(flags));
523 3 : if (ret < 0) {
524 0 : gnutls_assert();
525 0 : return ret;
526 : }
527 :
528 3 : ret = add_obj_attrs(info, a, &a_vals, &class, &type);
529 3 : if (ret < 0) {
530 0 : gnutls_assert();
531 0 : goto cleanup;
532 : }
533 :
534 3 : rv = pkcs11_find_objects_init(sinfo.module, sinfo.pks, a,
535 : a_vals);
536 3 : if (rv != CKR_OK) {
537 0 : gnutls_assert();
538 0 : _gnutls_debug_log("p11: FindObjectsInit failed.\n");
539 0 : ret = pkcs11_rv_to_err(rv);
540 0 : goto cleanup;
541 : }
542 :
543 3 : rv = pkcs11_find_objects(sinfo.module, sinfo.pks, ctx, 2, &count);
544 3 : if (rv != CKR_OK) {
545 0 : gnutls_assert();
546 0 : _gnutls_debug_log("p11: FindObjects failed.\n");
547 0 : ret = pkcs11_rv_to_err(rv);
548 0 : goto cleanup;
549 : }
550 :
551 3 : if (count > 1 || count == 0) {
552 0 : gnutls_assert();
553 0 : if (count > 1)
554 0 : _gnutls_debug_log("p11: More than one objects match (%d)\n", (int)count);
555 0 : ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
556 0 : goto cleanup;
557 : }
558 :
559 3 : switch (itype) {
560 1 : case GNUTLS_PKCS11_OBJ_ID_HEX:
561 1 : size = sizeof(tmp);
562 1 : ret = _gnutls_hex2bin(data, data_size, (uint8_t*)tmp, &size);
563 1 : if (ret < 0) {
564 0 : gnutls_assert();
565 0 : goto cleanup;
566 : }
567 1 : data = tmp;
568 1 : data_size = size;
569 :
570 1 : FALLTHROUGH;
571 1 : case GNUTLS_PKCS11_OBJ_ID:
572 1 : a[0].type = CKA_ID;
573 1 : a[0].value = (void*)data;
574 1 : a[0].value_len = data_size;
575 :
576 1 : rv = pkcs11_set_attribute_value(sinfo.module, sinfo.pks, ctx[0], a, 1);
577 1 : if (rv != CKR_OK) {
578 0 : gnutls_assert();
579 0 : _gnutls_debug_log("p11: set_attribute_value failed.\n");
580 0 : ret = pkcs11_rv_to_err(rv);
581 0 : goto cleanup;
582 : }
583 :
584 : break;
585 2 : case GNUTLS_PKCS11_OBJ_LABEL:
586 2 : a[0].type = CKA_LABEL;
587 2 : a[0].value = (void*)data;
588 2 : a[0].value_len = data_size;
589 :
590 2 : rv = pkcs11_set_attribute_value(sinfo.module, sinfo.pks, ctx[0], a, 1);
591 2 : if (rv != CKR_OK) {
592 0 : gnutls_assert();
593 0 : _gnutls_debug_log("p11: set_attribute_value failed.\n");
594 0 : ret = pkcs11_rv_to_err(rv);
595 0 : goto cleanup;
596 : }
597 :
598 : break;
599 0 : default:
600 0 : gnutls_assert();
601 : return GNUTLS_E_INVALID_REQUEST;
602 : }
603 :
604 : ret = 0;
605 3 : cleanup:
606 3 : pkcs11_close_session(&sinfo);
607 3 : 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
635 61 : 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 61 : return pkcs11_get_info(obj->info, itype, output, output_size);
640 : }
641 :
642 : static int
643 1 : 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 1 : struct find_obj_session_st *find_data = input;
648 1 : struct ck_attribute a[4];
649 1 : ck_rv_t rv;
650 1 : ck_object_handle_t ctx = CK_INVALID_HANDLE;
651 1 : unsigned long count;
652 1 : unsigned a_vals;
653 1 : ck_certificate_type_t type;
654 1 : ck_object_class_t class;
655 1 : int found = 0, ret;
656 :
657 1 : if (tinfo == NULL) { /* we don't support multiple calls */
658 0 : gnutls_assert();
659 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
660 : }
661 :
662 : /* do not bother reading the token if basic fields do not match
663 : */
664 2 : if (!p11_kit_uri_match_token_info(find_data->obj->info, tinfo) ||
665 1 : !p11_kit_uri_match_module_info(find_data->obj->info,
666 : lib_info)) {
667 0 : gnutls_assert();
668 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
669 : }
670 :
671 1 : ret = add_obj_attrs(find_data->obj->info, a, &a_vals, &class, &type);
672 1 : if (ret < 0)
673 0 : return gnutls_assert_val(ret);
674 :
675 1 : rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
676 : a_vals);
677 1 : if (rv != CKR_OK) {
678 0 : gnutls_assert();
679 0 : _gnutls_debug_log("p11: FindObjectsInit failed.\n");
680 0 : ret = pkcs11_rv_to_err(rv);
681 0 : goto cleanup;
682 : }
683 :
684 1 : if (pkcs11_find_objects(sinfo->module, sinfo->pks, &ctx, 1, &count) == CKR_OK &&
685 1 : count == 1) {
686 1 : find_data->ptr = sinfo->module;
687 1 : find_data->pks = sinfo->pks;
688 1 : find_data->slot_id = sinfo->sid;
689 1 : find_data->ohandle = ctx;
690 1 : found = 1;
691 : }
692 :
693 1 : if (found == 0) {
694 0 : gnutls_assert();
695 0 : if (count > 1)
696 : ret = GNUTLS_E_TOO_MANY_MATCHES;
697 : else
698 0 : ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
699 :
700 : } else {
701 : ret = 0;
702 : }
703 :
704 1 : cleanup:
705 1 : pkcs11_find_objects_final(sinfo);
706 :
707 1 : 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
730 1 : 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 1 : int ret;
736 1 : struct find_obj_session_st find_data;
737 :
738 1 : PKCS11_CHECK_INIT;
739 1 : memset(&find_data, 0, sizeof(find_data));
740 :
741 1 : find_data.obj = obj;
742 :
743 1 : ret =
744 1 : _pkcs11_traverse_tokens(find_obj_session_cb, &find_data, obj->info,
745 : &obj->pin,
746 1 : SESSION_NO_CLOSE|pkcs11_obj_flags_to_int(flags));
747 1 : if (ret < 0) {
748 0 : gnutls_assert();
749 0 : return ret;
750 : }
751 :
752 1 : if (ptr)
753 1 : *ptr = find_data.ptr;
754 :
755 1 : *ohandle = (void*)find_data.ohandle;
756 1 : *session = (void*)find_data.pks;
757 :
758 1 : if (slot_id)
759 1 : *slot_id = find_data.slot_id;
760 :
761 : return 0;
762 : }
763 :
764 : int
765 61 : pkcs11_get_info(struct p11_kit_uri *info,
766 : gnutls_pkcs11_obj_info_t itype, void *output,
767 : size_t * output_size)
768 : {
769 61 : struct ck_attribute *attr = NULL;
770 61 : struct ck_version *version = NULL;
771 61 : const uint8_t *str = NULL;
772 61 : size_t str_max = 0;
773 61 : int terminate = 0;
774 61 : int hexify = 0;
775 61 : size_t length = 0;
776 61 : const char *data = NULL;
777 61 : char buf[32];
778 :
779 : /*
780 : * Either attr, str or version is valid by the time switch
781 : * finishes
782 : */
783 :
784 61 : switch (itype) {
785 4 : case GNUTLS_PKCS11_OBJ_ID:
786 4 : attr = p11_kit_uri_get_attribute(info, CKA_ID);
787 4 : break;
788 25 : case GNUTLS_PKCS11_OBJ_ID_HEX:
789 25 : attr = p11_kit_uri_get_attribute(info, CKA_ID);
790 25 : hexify = 1;
791 25 : terminate = 1;
792 25 : break;
793 25 : case GNUTLS_PKCS11_OBJ_LABEL:
794 25 : attr = p11_kit_uri_get_attribute(info, CKA_LABEL);
795 25 : terminate = 1;
796 25 : break;
797 1 : case GNUTLS_PKCS11_OBJ_TOKEN_LABEL:
798 1 : str = p11_kit_uri_get_token_info(info)->label;
799 1 : str_max = 32;
800 1 : break;
801 1 : case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL:
802 1 : str = p11_kit_uri_get_token_info(info)->serial_number;
803 1 : str_max = 16;
804 1 : break;
805 1 : case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER:
806 1 : str = p11_kit_uri_get_token_info(info)->manufacturer_id;
807 1 : str_max = 32;
808 1 : break;
809 1 : case GNUTLS_PKCS11_OBJ_TOKEN_MODEL:
810 1 : str = p11_kit_uri_get_token_info(info)->model;
811 1 : str_max = 16;
812 1 : break;
813 1 : case GNUTLS_PKCS11_OBJ_LIBRARY_DESCRIPTION:
814 2 : str =
815 1 : p11_kit_uri_get_module_info(info)->library_description;
816 1 : str_max = 32;
817 1 : break;
818 1 : case GNUTLS_PKCS11_OBJ_LIBRARY_VERSION:
819 2 : version =
820 1 : &p11_kit_uri_get_module_info(info)->library_version;
821 1 : break;
822 1 : case GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER:
823 1 : str = p11_kit_uri_get_module_info(info)->manufacturer_id;
824 1 : str_max = 32;
825 1 : break;
826 0 : default:
827 0 : gnutls_assert();
828 : return GNUTLS_E_INVALID_REQUEST;
829 : }
830 :
831 61 : if (attr != NULL) {
832 54 : data = attr->value;
833 54 : length = attr->value_len;
834 7 : } else if (str != NULL) {
835 6 : data = (void *) str;
836 6 : length = p11_kit_space_strlen(str, str_max);
837 6 : terminate = 1;
838 1 : } else if (version != NULL) {
839 1 : data = buf;
840 1 : length =
841 1 : snprintf(buf, sizeof(buf), "%d.%d",
842 1 : (int) version->major, (int) version->minor);
843 1 : terminate = 1;
844 : } else {
845 0 : *output_size = 0;
846 0 : if (output)
847 0 : ((uint8_t *) output)[0] = 0;
848 0 : return 0;
849 : }
850 :
851 61 : if (hexify) {
852 : /* terminate is assumed with hexify */
853 25 : if (*output_size < length * 3) {
854 0 : *output_size = length * 3;
855 0 : return GNUTLS_E_SHORT_MEMORY_BUFFER;
856 : }
857 25 : if (output && length > 0)
858 25 : _gnutls_bin2hex(data, length, output, *output_size,
859 : ":");
860 25 : *output_size = length * 3;
861 25 : return 0;
862 : } else {
863 36 : if (*output_size < length + terminate) {
864 0 : *output_size = length + terminate;
865 0 : return GNUTLS_E_SHORT_MEMORY_BUFFER;
866 : }
867 36 : if (output) {
868 36 : memcpy(output, data, length);
869 36 : if (terminate)
870 32 : ((unsigned char *) output)[length] = '\0';
871 : }
872 36 : *output_size = length;
873 : }
874 :
875 36 : return 0;
876 : }
877 :
878 : static int init = 0;
879 :
880 : /* tries to load modules from /etc/gnutls/pkcs11.conf if it exists
881 : */
882 0 : static void compat_load(const char *configfile)
883 : {
884 0 : FILE *fp;
885 0 : int ret;
886 0 : char line[512];
887 0 : const char *library;
888 :
889 0 : if (configfile == NULL)
890 0 : configfile = "/etc/gnutls/pkcs11.conf";
891 :
892 0 : fp = fopen(configfile, "re");
893 0 : if (fp == NULL) {
894 0 : gnutls_assert();
895 0 : return;
896 : }
897 :
898 0 : _gnutls_debug_log("Loading PKCS #11 libraries from %s\n",
899 : configfile);
900 0 : while (fgets(line, sizeof(line), fp) != NULL) {
901 0 : if (strncmp(line, "load", sizeof("load") - 1) == 0) {
902 0 : char *p;
903 0 : p = strchr(line, '=');
904 0 : if (p == NULL)
905 0 : continue;
906 :
907 0 : library = ++p;
908 0 : p = strchr(line, '\n');
909 0 : if (p != NULL)
910 0 : *p = 0;
911 :
912 0 : ret = gnutls_pkcs11_add_provider(library, NULL);
913 0 : if (ret < 0) {
914 0 : gnutls_assert();
915 0 : _gnutls_debug_log
916 : ("Cannot load provider: %s\n",
917 : library);
918 0 : continue;
919 : }
920 : }
921 : }
922 0 : fclose(fp);
923 :
924 0 : return;
925 : }
926 :
927 4 : static int auto_load(unsigned trusted)
928 : {
929 4 : struct ck_function_list **modules;
930 4 : int i, ret;
931 4 : char* name;
932 :
933 4 : modules = p11_kit_modules_load_and_initialize(trusted?P11_KIT_MODULE_TRUSTED:0);
934 4 : if (modules == NULL) {
935 0 : gnutls_assert();
936 0 : _gnutls_debug_log
937 : ("Cannot initialize registered modules: %s\n",
938 : p11_kit_message());
939 0 : return GNUTLS_E_PKCS11_LOAD_ERROR;
940 : }
941 :
942 8 : for (i = 0; modules[i] != NULL; i++) {
943 4 : name = p11_kit_module_get_name(modules[i]);
944 4 : _gnutls_debug_log
945 : ("p11: Initializing module: %s\n", name);
946 :
947 4 : ret = pkcs11_add_module(name, modules[i], 0, NULL);
948 4 : if (ret < 0) {
949 0 : gnutls_assert();
950 0 : _gnutls_debug_log
951 : ("Cannot load PKCS #11 module: %s\n", name);
952 : }
953 4 : free(name);
954 : }
955 :
956 : /* Shallow free */
957 4 : free(modules);
958 4 : 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
983 5283 : gnutls_pkcs11_init(unsigned int flags, const char *deprecated_config_file)
984 : {
985 5283 : int ret = 0;
986 :
987 5283 : if (init != 0) {
988 4371 : init++;
989 4371 : return 0;
990 : }
991 912 : init++;
992 :
993 912 : pkcs11_forkid = _gnutls_get_forkid();
994 :
995 912 : p11_kit_pin_register_callback(P11_KIT_PIN_FALLBACK,
996 : p11_kit_pin_file_callback, NULL,
997 : NULL);
998 :
999 912 : if (flags == GNUTLS_PKCS11_FLAG_MANUAL) {
1000 : /* if manual configuration is requested then don't
1001 : * bother loading any other providers */
1002 912 : providers_initialized = PROV_INIT_MANUAL;
1003 912 : return 0;
1004 0 : } else if (flags & GNUTLS_PKCS11_FLAG_AUTO) {
1005 0 : if (deprecated_config_file == NULL)
1006 0 : ret = auto_load(0);
1007 :
1008 0 : compat_load(deprecated_config_file);
1009 :
1010 0 : providers_initialized = PROV_INIT_ALL;
1011 :
1012 0 : return ret;
1013 0 : } else if (flags & GNUTLS_PKCS11_FLAG_AUTO_TRUSTED) {
1014 0 : ret = auto_load(1);
1015 :
1016 0 : providers_initialized = PROV_INIT_TRUSTED;
1017 :
1018 0 : return ret;
1019 : }
1020 :
1021 : return 0;
1022 : }
1023 :
1024 3 : static int _gnutls_pkcs11_reinit(void)
1025 : {
1026 3 : unsigned i;
1027 3 : ck_rv_t rv;
1028 :
1029 6 : for (i = 0; i < active_providers; i++) {
1030 3 : if (providers[i].module != NULL) {
1031 3 : rv = p11_kit_module_initialize(providers
1032 : [i].module);
1033 3 : if (rv == CKR_OK || rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) {
1034 3 : providers[i].active = 1;
1035 : } else {
1036 0 : providers[i].active = 0;
1037 3 : _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 3 : 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 : **/
1063 1 : int gnutls_pkcs11_reinit(void)
1064 : {
1065 1 : int ret;
1066 :
1067 : /* make sure that we don't call more than once after a fork */
1068 1 : if (_gnutls_detect_fork(pkcs11_forkid) == 0)
1069 : return 0;
1070 :
1071 1 : ret = _gnutls_pkcs11_reinit();
1072 :
1073 1 : pkcs11_forkid = _gnutls_get_forkid();
1074 :
1075 1 : 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 : **/
1087 941 : void gnutls_pkcs11_deinit(void)
1088 : {
1089 941 : unsigned int i;
1090 :
1091 941 : if (init == 0)
1092 : return;
1093 :
1094 95 : init--;
1095 95 : if (init > 0)
1096 : return;
1097 :
1098 166 : for (i = 0; i < active_providers; i++) {
1099 82 : if (providers[i].active) {
1100 :
1101 82 : if (!providers[i].custom_init)
1102 79 : p11_kit_module_finalize(providers[i].module);
1103 : else
1104 3 : providers[i].module->C_Finalize(NULL);
1105 : }
1106 82 : p11_kit_module_release(providers[i].module);
1107 : }
1108 84 : active_providers = 0;
1109 84 : providers_initialized = PROV_UNINITIALIZED;
1110 :
1111 84 : gnutls_pkcs11_set_pin_function(NULL, NULL);
1112 84 : gnutls_pkcs11_set_token_function(NULL, NULL);
1113 84 : 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
1128 2064 : gnutls_pkcs11_set_token_function(gnutls_pkcs11_token_callback_t fn,
1129 : void *userdata)
1130 : {
1131 2064 : _gnutls_token_func = fn;
1132 2064 : _gnutls_token_data = userdata;
1133 2064 : }
1134 :
1135 1699 : int pkcs11_url_to_info(const char *url, struct p11_kit_uri **info, unsigned flags)
1136 : {
1137 1699 : int allocated = 0;
1138 1699 : int ret;
1139 1699 : struct ck_attribute at;
1140 1699 : ck_object_class_t klass;
1141 :
1142 1699 : if (*info == NULL) {
1143 1634 : *info = p11_kit_uri_new();
1144 1634 : if (*info == NULL) {
1145 0 : gnutls_assert();
1146 0 : return GNUTLS_E_MEMORY_ERROR;
1147 : }
1148 : allocated = 1;
1149 : }
1150 :
1151 1699 : ret = p11_kit_uri_parse(url, P11_KIT_URI_FOR_ANY, *info);
1152 1699 : if (ret < 0) {
1153 0 : if (allocated) {
1154 0 : p11_kit_uri_free(*info);
1155 0 : *info = NULL;
1156 : }
1157 0 : gnutls_assert();
1158 0 : return ret == P11_KIT_URI_NO_MEMORY ?
1159 0 : GNUTLS_E_MEMORY_ERROR : GNUTLS_E_PARSING_ERROR;
1160 : }
1161 :
1162 : /* check for incomplete/invalid URIs */
1163 1699 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_EXPECT_CERT) {
1164 28 : klass = CKO_CERTIFICATE;
1165 28 : at.type = CKA_CLASS;
1166 28 : at.value = &klass;
1167 28 : at.value_len = sizeof (klass);
1168 28 : p11_kit_uri_set_attribute (*info, &at);
1169 1671 : } else if (flags & GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY) {
1170 72 : klass = CKO_PRIVATE_KEY;
1171 72 : at.type = CKA_CLASS;
1172 72 : at.value = &klass;
1173 72 : at.value_len = sizeof (klass);
1174 72 : p11_kit_uri_set_attribute (*info, &at);
1175 1599 : } else if (flags & GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PUBKEY) {
1176 23 : klass = CKO_PUBLIC_KEY;
1177 23 : at.type = CKA_CLASS;
1178 23 : at.value = &klass;
1179 23 : at.value_len = sizeof (klass);
1180 23 : p11_kit_uri_set_attribute (*info, &at);
1181 : }
1182 :
1183 : return 0;
1184 : }
1185 :
1186 : int
1187 422 : pkcs11_info_to_url(struct p11_kit_uri *info,
1188 : gnutls_pkcs11_url_type_t detailed, char **url)
1189 : {
1190 422 : p11_kit_uri_type_t type = 0;
1191 422 : int ret;
1192 :
1193 422 : switch (detailed) {
1194 86 : case GNUTLS_PKCS11_URL_GENERIC:
1195 86 : type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN;
1196 86 : break;
1197 336 : case GNUTLS_PKCS11_URL_LIB:
1198 336 : type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE;
1199 336 : break;
1200 0 : case GNUTLS_PKCS11_URL_LIB_VERSION:
1201 0 : type =
1202 : P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE |
1203 : P11_KIT_URI_FOR_MODULE_WITH_VERSION;
1204 0 : break;
1205 : }
1206 :
1207 422 : ret = p11_kit_uri_format(info, type, url);
1208 422 : if (ret < 0) {
1209 0 : gnutls_assert();
1210 0 : return ret == P11_KIT_URI_NO_MEMORY ?
1211 0 : 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 : **/
1228 789 : int gnutls_pkcs11_obj_init(gnutls_pkcs11_obj_t * obj)
1229 : {
1230 789 : *obj = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_obj_st));
1231 789 : if (*obj == NULL) {
1232 0 : gnutls_assert();
1233 0 : return GNUTLS_E_MEMORY_ERROR;
1234 : }
1235 :
1236 789 : (*obj)->info = p11_kit_uri_new();
1237 789 : if ((*obj)->info == NULL) {
1238 0 : gnutls_free(*obj);
1239 0 : gnutls_assert();
1240 0 : 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
1259 120 : gnutls_pkcs11_obj_set_pin_function(gnutls_pkcs11_obj_t obj,
1260 : gnutls_pin_callback_t fn,
1261 : void *userdata)
1262 : {
1263 120 : obj->pin.cb = fn;
1264 120 : obj->pin.data = userdata;
1265 120 : }
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 : **/
1275 779 : void gnutls_pkcs11_obj_deinit(gnutls_pkcs11_obj_t obj)
1276 : {
1277 779 : unsigned i;
1278 1005 : for (i=0;i<obj->pubkey_size;i++)
1279 452 : _gnutls_free_datum(&obj->pubkey[i]);
1280 779 : _gnutls_free_datum(&obj->raw);
1281 779 : p11_kit_uri_free(obj->info);
1282 779 : free(obj);
1283 779 : }
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
1306 2 : gnutls_pkcs11_obj_export(gnutls_pkcs11_obj_t obj,
1307 : void *output_data, size_t * output_data_size)
1308 : {
1309 2 : if (obj == NULL || obj->raw.data == NULL) {
1310 0 : gnutls_assert();
1311 0 : return GNUTLS_E_INVALID_REQUEST;
1312 : }
1313 :
1314 2 : if (output_data == NULL || *output_data_size < obj->raw.size) {
1315 1 : *output_data_size = obj->raw.size;
1316 1 : gnutls_assert();
1317 1 : return GNUTLS_E_SHORT_MEMORY_BUFFER;
1318 : }
1319 1 : *output_data_size = obj->raw.size;
1320 :
1321 1 : memcpy(output_data, obj->raw.data, obj->raw.size);
1322 1 : 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
1342 46 : gnutls_pkcs11_obj_export2(gnutls_pkcs11_obj_t obj, gnutls_datum_t * out)
1343 : {
1344 46 : 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
1365 153 : gnutls_pkcs11_obj_export3(gnutls_pkcs11_obj_t obj,
1366 : gnutls_x509_crt_fmt_t fmt, gnutls_datum_t * out)
1367 : {
1368 153 : int ret;
1369 :
1370 153 : if (obj == NULL) {
1371 0 : gnutls_assert();
1372 0 : return GNUTLS_E_INVALID_REQUEST;
1373 : }
1374 :
1375 153 : switch (obj->type) {
1376 107 : case GNUTLS_PKCS11_OBJ_X509_CRT:
1377 107 : if (obj->raw.data == NULL)
1378 0 : return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1379 :
1380 107 : if (fmt == GNUTLS_X509_FMT_PEM) {
1381 3 : return
1382 3 : gnutls_pem_base64_encode2(PEM_X509_CERT2,
1383 3 : &obj->raw, out);
1384 : } else {
1385 104 : return _gnutls_set_datum(out, obj->raw.data,
1386 104 : obj->raw.size);
1387 : }
1388 46 : case GNUTLS_PKCS11_OBJ_PUBKEY:{
1389 : /* that approach allows to return a public key even if
1390 : * CKA_VALUE is not set */
1391 46 : gnutls_pubkey_t pubkey;
1392 :
1393 46 : ret = gnutls_pubkey_init(&pubkey);
1394 46 : if (ret < 0)
1395 0 : return gnutls_assert_val(ret);
1396 :
1397 46 : ret =
1398 46 : gnutls_pubkey_import_pkcs11(pubkey,
1399 : obj, 0);
1400 46 : if (ret < 0) {
1401 0 : gnutls_assert();
1402 0 : goto pcleanup;
1403 : }
1404 :
1405 46 : ret =
1406 46 : gnutls_pubkey_export2(pubkey, fmt,
1407 : out);
1408 :
1409 46 : pcleanup:
1410 46 : gnutls_pubkey_deinit(pubkey);
1411 46 : return ret;
1412 : }
1413 0 : default:
1414 0 : if (obj->raw.data == NULL)
1415 0 : return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1416 :
1417 0 : if (fmt == GNUTLS_X509_FMT_PEM) {
1418 0 : return gnutls_pem_base64_encode2("DATA",
1419 0 : &obj->raw,
1420 : out);
1421 : } else {
1422 0 : return _gnutls_set_datum(out, obj->raw.data,
1423 0 : obj->raw.size);
1424 : }
1425 : }
1426 : }
1427 :
1428 :
1429 : int
1430 859 : 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 859 : unsigned int x, z;
1437 859 : int ret;
1438 859 : unsigned long nslots;
1439 859 : ck_slot_id_t slots[MAX_SLOTS];
1440 :
1441 859 : for (x = 0; x < active_providers; x++) {
1442 859 : if (providers[x].active == 0)
1443 0 : continue;
1444 :
1445 859 : if (!p11_kit_uri_match_module_info(info,
1446 859 : &providers[x].info)) {
1447 0 : continue;
1448 : }
1449 :
1450 859 : nslots = sizeof(slots) / sizeof(slots[0]);
1451 859 : ret = scan_slots(&providers[x], slots, &nslots);
1452 859 : if (ret < 0) {
1453 0 : gnutls_assert();
1454 0 : continue;
1455 : }
1456 :
1457 859 : for (z = 0; z < nslots; z++) {
1458 859 : struct ck_token_info tinfo;
1459 859 : struct ck_slot_info sinfo;
1460 :
1461 859 : if (pkcs11_get_token_info
1462 : (providers[x].module, slots[z],
1463 : &tinfo) != CKR_OK) {
1464 0 : continue;
1465 : }
1466 :
1467 859 : if (!p11_kit_uri_match_token_info(info, &tinfo)) {
1468 0 : continue;
1469 : }
1470 :
1471 859 : if (pkcs11_get_slot_info
1472 : (providers[x].module, slots[z], &sinfo) != CKR_OK) {
1473 0 : continue;
1474 : }
1475 :
1476 : /* ok found */
1477 859 : *module = providers[x].module;
1478 859 : *slot = slots[z];
1479 :
1480 859 : if (trusted)
1481 260 : *trusted = providers[x].trusted;
1482 :
1483 859 : if (_tinfo != NULL)
1484 759 : memcpy(_tinfo, &tinfo, sizeof(tinfo));
1485 :
1486 859 : if (_slot_info != NULL)
1487 260 : memcpy(_slot_info, &sinfo, sizeof(sinfo));
1488 :
1489 859 : return 0;
1490 : }
1491 : }
1492 :
1493 0 : gnutls_assert();
1494 : return GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE;
1495 : }
1496 :
1497 : int
1498 260 : 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 260 : ck_rv_t rv;
1503 260 : int ret;
1504 260 : ck_session_handle_t pks = 0;
1505 260 : struct ck_function_list *module;
1506 260 : ck_slot_id_t slot;
1507 260 : struct ck_token_info tinfo;
1508 :
1509 260 : memset(sinfo, 0, sizeof(*sinfo));
1510 :
1511 260 : ret = pkcs11_find_slot(&module, &slot, info, &tinfo,
1512 : &sinfo->slot_info,
1513 : &sinfo->trusted);
1514 260 : if (ret < 0) {
1515 0 : gnutls_assert();
1516 0 : return ret;
1517 : }
1518 :
1519 520 : rv = (module)->C_OpenSession(slot, ((flags & SESSION_WRITE)
1520 260 : ? CKF_RW_SESSION : 0) |
1521 : CKF_SERIAL_SESSION, NULL, NULL, &pks);
1522 260 : if (rv != CKR_OK) {
1523 0 : gnutls_assert();
1524 0 : return pkcs11_rv_to_err(rv);
1525 : }
1526 :
1527 : /* ok found */
1528 260 : sinfo->pks = pks;
1529 260 : sinfo->module = module;
1530 260 : sinfo->sid = slot;
1531 260 : sinfo->init = 1;
1532 260 : memcpy(&sinfo->tinfo, &tinfo, sizeof(sinfo->tinfo));
1533 :
1534 260 : ret =
1535 260 : pkcs11_login(sinfo, pin_info, info,
1536 : flags);
1537 260 : if (ret < 0) {
1538 2 : gnutls_assert();
1539 2 : pkcs11_close_session(sinfo);
1540 2 : return ret;
1541 : }
1542 :
1543 : return 0;
1544 : }
1545 :
1546 :
1547 : int
1548 1232 : _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 1232 : ck_rv_t rv;
1553 1232 : unsigned int found = 0, x, z;
1554 1232 : int ret;
1555 1232 : ck_session_handle_t pks = 0;
1556 1232 : struct pkcs11_session_info sinfo;
1557 1232 : struct ck_function_list *module = NULL;
1558 1232 : unsigned long nslots;
1559 1232 : ck_slot_id_t slots[MAX_SLOTS];
1560 :
1561 3186 : for (x = 0; x < active_providers; x++) {
1562 2181 : if (providers[x].active == 0)
1563 0 : continue;
1564 :
1565 2181 : if (flags & SESSION_TRUSTED && providers[x].trusted == 0)
1566 0 : continue;
1567 :
1568 2181 : if (info && !p11_kit_uri_match_module_info(info, &providers[x].info)) {
1569 0 : continue;
1570 : }
1571 :
1572 2181 : nslots = sizeof(slots) / sizeof(slots[0]);
1573 2181 : ret = scan_slots(&providers[x], slots, &nslots);
1574 2181 : if (ret < 0) {
1575 0 : gnutls_assert();
1576 0 : continue;
1577 : }
1578 :
1579 2181 : module = providers[x].module;
1580 6080 : for (z = 0; z < nslots; z++) {
1581 4126 : struct ck_token_info l_tinfo;
1582 4126 : struct ck_slot_info l_sinfo;
1583 :
1584 4126 : if (pkcs11_get_token_info(module, slots[z],
1585 : &l_tinfo) != CKR_OK) {
1586 2895 : continue;
1587 : }
1588 :
1589 4126 : if (info && !p11_kit_uri_match_token_info(info, &l_tinfo)) {
1590 2893 : continue;
1591 : }
1592 :
1593 1233 : if (pkcs11_get_slot_info(module, slots[z],
1594 : &l_sinfo) != CKR_OK) {
1595 0 : continue;
1596 : }
1597 :
1598 2466 : rv = (module)->C_OpenSession(slots[z],
1599 1233 : ((flags & SESSION_WRITE) ? CKF_RW_SESSION : 0)
1600 : | CKF_SERIAL_SESSION,
1601 : NULL, NULL, &pks);
1602 1233 : if (rv != CKR_OK) {
1603 2 : continue;
1604 : }
1605 :
1606 1231 : memset(&sinfo, 0, sizeof(sinfo));
1607 1231 : sinfo.module = module;
1608 1231 : sinfo.pks = pks;
1609 1231 : sinfo.sid = slots[z];
1610 1231 : sinfo.trusted = providers[x].trusted;
1611 :
1612 1231 : memcpy(&sinfo.tinfo, &l_tinfo, sizeof(sinfo.tinfo));
1613 1231 : memcpy(&sinfo.slot_info, &l_sinfo, sizeof(sinfo.slot_info));
1614 :
1615 1231 : ret =
1616 1231 : pkcs11_login(&sinfo, pin_info,
1617 : info, flags);
1618 1231 : if (ret < 0) {
1619 0 : gnutls_assert();
1620 0 : pkcs11_close_session(&sinfo);
1621 :
1622 : /* treat the error as fatal only if
1623 : * the token requires login */
1624 0 : if (l_tinfo.flags & CKF_LOGIN_REQUIRED)
1625 0 : return ret;
1626 0 : continue;
1627 : }
1628 :
1629 1231 : ret =
1630 1231 : find_func(providers[x].module, &sinfo, &l_tinfo, &providers[x].info, input);
1631 :
1632 1231 : if (ret == 0) {
1633 227 : found = 1;
1634 227 : goto finish;
1635 : } else {
1636 1004 : pkcs11_close_session(&sinfo);
1637 1004 : pks = 0;
1638 : }
1639 : }
1640 : }
1641 :
1642 1005 : finish:
1643 : /* final call */
1644 :
1645 227 : if (found == 0) {
1646 1005 : if (module) {
1647 1005 : sinfo.module = module;
1648 1005 : sinfo.pks = pks;
1649 1005 : ret = find_func(providers[x].module, &sinfo, NULL, NULL, input);
1650 : } else
1651 0 : ret =
1652 1232 : gnutls_assert_val
1653 : (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1654 : } else {
1655 : ret = 0;
1656 : }
1657 :
1658 1232 : if (pks != 0 && module != NULL) {
1659 227 : if (ret != 0 || !(flags & SESSION_NO_CLOSE))
1660 226 : pkcs11_close_session(&sinfo);
1661 : }
1662 :
1663 : return ret;
1664 : }
1665 :
1666 0 : ck_object_class_t pkcs11_type_to_class(gnutls_pkcs11_obj_type_t type)
1667 : {
1668 0 : switch (type) {
1669 : case GNUTLS_PKCS11_OBJ_X509_CRT:
1670 : return CKO_CERTIFICATE;
1671 0 : case GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION:
1672 0 : return CKO_X_CERTIFICATE_EXTENSION;
1673 0 : case GNUTLS_PKCS11_OBJ_PUBKEY:
1674 0 : return CKO_PUBLIC_KEY;
1675 0 : case GNUTLS_PKCS11_OBJ_PRIVKEY:
1676 0 : return CKO_PRIVATE_KEY;
1677 0 : case GNUTLS_PKCS11_OBJ_SECRET_KEY:
1678 0 : return CKO_SECRET_KEY;
1679 0 : case GNUTLS_PKCS11_OBJ_DATA:
1680 0 : return CKO_DATA;
1681 0 : default:
1682 0 : return -1;
1683 : }
1684 : }
1685 :
1686 441 : static gnutls_pkcs11_obj_type_t pkcs11_class_to_type(ck_object_class_t class)
1687 : {
1688 441 : switch (class) {
1689 : case CKO_CERTIFICATE:
1690 : return GNUTLS_PKCS11_OBJ_X509_CRT;
1691 0 : case CKO_X_CERTIFICATE_EXTENSION:
1692 0 : return GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION;
1693 79 : case CKO_PUBLIC_KEY:
1694 79 : return GNUTLS_PKCS11_OBJ_PUBKEY;
1695 33 : case CKO_PRIVATE_KEY:
1696 33 : return GNUTLS_PKCS11_OBJ_PRIVKEY;
1697 0 : case CKO_SECRET_KEY:
1698 0 : return GNUTLS_PKCS11_OBJ_SECRET_KEY;
1699 0 : case CKO_DATA:
1700 0 : return GNUTLS_PKCS11_OBJ_DATA;
1701 0 : default:
1702 0 : _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
1710 441 : 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 441 : struct ck_attribute attr;
1717 441 : int ret;
1718 :
1719 441 : obj->type = pkcs11_class_to_type(class);
1720 :
1721 441 : attr.type = CKA_CLASS;
1722 441 : attr.value = &class;
1723 441 : attr.value_len = sizeof(class);
1724 441 : ret = p11_kit_uri_set_attribute(obj->info, &attr);
1725 441 : if (ret < 0) {
1726 0 : gnutls_assert();
1727 0 : return GNUTLS_E_MEMORY_ERROR;
1728 : }
1729 :
1730 441 : if (data && data->data && data->size) {
1731 339 : ret = _gnutls_set_datum(&obj->raw, data->data, data->size);
1732 339 : if (ret < 0) {
1733 0 : gnutls_assert();
1734 0 : return ret;
1735 : }
1736 : }
1737 :
1738 : /* copy the token and library info into the uri */
1739 441 : memcpy(p11_kit_uri_get_token_info(obj->info), tinfo,
1740 : sizeof(struct ck_token_info));
1741 441 : memcpy(p11_kit_uri_get_module_info(obj->info), lib_info,
1742 : sizeof(struct ck_info));
1743 :
1744 441 : if (label && label->data && label->size) {
1745 441 : attr.type = CKA_LABEL;
1746 441 : attr.value = label->data;
1747 441 : attr.value_len = label->size;
1748 441 : ret = p11_kit_uri_set_attribute(obj->info, &attr);
1749 441 : if (ret < 0) {
1750 0 : gnutls_assert();
1751 0 : return GNUTLS_E_MEMORY_ERROR;
1752 : }
1753 : }
1754 :
1755 441 : if (id && id->data && id->size) {
1756 441 : attr.type = CKA_ID;
1757 441 : attr.value = id->data;
1758 441 : attr.value_len = id->size;
1759 441 : ret = p11_kit_uri_set_attribute(obj->info, &attr);
1760 441 : if (ret < 0) {
1761 0 : gnutls_assert();
1762 0 : return GNUTLS_E_MEMORY_ERROR;
1763 : }
1764 : }
1765 :
1766 : return 0;
1767 : }
1768 :
1769 111 : 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 111 : struct ck_attribute a[4];
1774 111 : uint8_t *tmp1;
1775 111 : uint8_t *tmp2 = NULL;
1776 111 : size_t tmp1_size, tmp2_size;
1777 111 : int ret;
1778 111 : ck_rv_t rv;
1779 :
1780 111 : tmp1_size = tmp2_size = MAX_PK_PARAM_SIZE;
1781 111 : tmp1 = gnutls_calloc(1, tmp1_size);
1782 111 : if (tmp1 == NULL)
1783 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1784 :
1785 111 : tmp2 = gnutls_calloc(1, tmp2_size);
1786 111 : if (tmp2 == NULL) {
1787 0 : ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1788 0 : goto cleanup;
1789 : }
1790 :
1791 111 : switch (key_type) {
1792 65 : case CKK_RSA:
1793 65 : a[0].type = CKA_MODULUS;
1794 65 : a[0].value = tmp1;
1795 65 : a[0].value_len = tmp1_size;
1796 65 : a[1].type = CKA_PUBLIC_EXPONENT;
1797 65 : a[1].value = tmp2;
1798 65 : a[1].value_len = tmp2_size;
1799 :
1800 65 : if (pkcs11_get_attribute_value(module, pks, ctx, a, 2) ==
1801 : CKR_OK) {
1802 :
1803 65 : pobj->pubkey[0].data = a[0].value;
1804 65 : pobj->pubkey[0].size = a[0].value_len;
1805 :
1806 65 : pobj->pubkey[1].data = a[1].value;
1807 65 : pobj->pubkey[1].size = a[1].value_len;
1808 :
1809 65 : pobj->pubkey_size = 2;
1810 : } else {
1811 0 : gnutls_assert();
1812 0 : ret = GNUTLS_E_PKCS11_ERROR;
1813 0 : goto cleanup;
1814 : }
1815 65 : break;
1816 10 : case CKK_DSA:
1817 10 : a[0].type = CKA_PRIME;
1818 10 : a[0].value = tmp1;
1819 10 : a[0].value_len = tmp1_size;
1820 10 : a[1].type = CKA_SUBPRIME;
1821 10 : a[1].value = tmp2;
1822 10 : a[1].value_len = tmp2_size;
1823 :
1824 10 : if ((rv = pkcs11_get_attribute_value(module, pks, ctx, a, 2)) ==
1825 : CKR_OK) {
1826 10 : ret =
1827 10 : _gnutls_set_datum(&pobj->pubkey[0], a[0].value,
1828 : a[0].value_len);
1829 :
1830 10 : if (ret >= 0)
1831 10 : ret =
1832 10 : _gnutls_set_datum(&pobj->pubkey
1833 10 : [1], a[1].value,
1834 : a[1].value_len);
1835 :
1836 10 : if (ret < 0) {
1837 0 : gnutls_assert();
1838 0 : _gnutls_free_datum(&pobj->pubkey[1]);
1839 0 : _gnutls_free_datum(&pobj->pubkey[0]);
1840 0 : ret = GNUTLS_E_MEMORY_ERROR;
1841 0 : goto cleanup;
1842 : }
1843 :
1844 10 : pobj->pubkey_size = 2;
1845 : } else {
1846 0 : gnutls_assert();
1847 0 : ret = pkcs11_rv_to_err(rv);
1848 0 : goto cleanup;
1849 : }
1850 :
1851 10 : a[0].type = CKA_BASE;
1852 10 : a[0].value = tmp1;
1853 10 : a[0].value_len = tmp1_size;
1854 10 : a[1].type = CKA_VALUE;
1855 10 : a[1].value = tmp2;
1856 10 : a[1].value_len = tmp2_size;
1857 :
1858 10 : if ((rv = pkcs11_get_attribute_value(module, pks, ctx, a, 2)) ==
1859 : CKR_OK) {
1860 10 : pobj->pubkey[2].data = a[0].value;
1861 10 : pobj->pubkey[2].size = a[0].value_len;
1862 :
1863 10 : pobj->pubkey[3].data = a[1].value;
1864 10 : pobj->pubkey[3].size = a[1].value_len;
1865 :
1866 10 : pobj->pubkey_size = 4;
1867 : } else {
1868 0 : gnutls_assert();
1869 0 : ret = pkcs11_rv_to_err(rv);
1870 0 : goto cleanup;
1871 : }
1872 10 : break;
1873 33 : case CKK_ECDSA:
1874 33 : a[0].type = CKA_EC_PARAMS;
1875 33 : a[0].value = tmp1;
1876 33 : a[0].value_len = tmp1_size;
1877 :
1878 33 : a[1].type = CKA_EC_POINT;
1879 33 : a[1].value = tmp2;
1880 33 : a[1].value_len = tmp2_size;
1881 :
1882 33 : if ((rv = pkcs11_get_attribute_value(module, pks, ctx, a, 2)) ==
1883 : CKR_OK) {
1884 :
1885 33 : pobj->pubkey[0].data = a[0].value;
1886 33 : pobj->pubkey[0].size = a[0].value_len;
1887 :
1888 33 : pobj->pubkey[1].data = a[1].value;
1889 33 : pobj->pubkey[1].size = a[1].value_len;
1890 :
1891 33 : pobj->pubkey_size = 2;
1892 : } else {
1893 0 : gnutls_assert();
1894 :
1895 0 : ret = pkcs11_rv_to_err(rv);
1896 0 : goto cleanup;
1897 : }
1898 :
1899 33 : break;
1900 : #ifdef HAVE_CKM_EDDSA
1901 3 : case CKK_EC_EDWARDS:
1902 3 : a[0].type = CKA_EC_PARAMS;
1903 3 : a[0].value = tmp1;
1904 3 : a[0].value_len = tmp1_size;
1905 :
1906 3 : a[1].type = CKA_EC_POINT;
1907 3 : a[1].value = tmp2;
1908 3 : a[1].value_len = tmp2_size;
1909 :
1910 3 : if ((rv = pkcs11_get_attribute_value(module, pks, ctx, a, 2)) ==
1911 : CKR_OK) {
1912 :
1913 3 : pobj->pubkey[0].data = a[0].value;
1914 3 : pobj->pubkey[0].size = a[0].value_len;
1915 :
1916 3 : pobj->pubkey[1].data = a[1].value;
1917 3 : pobj->pubkey[1].size = a[1].value_len;
1918 :
1919 3 : pobj->pubkey_size = 2;
1920 : } else {
1921 0 : gnutls_assert();
1922 :
1923 0 : ret = pkcs11_rv_to_err(rv);
1924 0 : goto cleanup;
1925 : }
1926 :
1927 3 : break;
1928 : #endif
1929 0 : default:
1930 0 : _gnutls_debug_log("requested reading public key of unsupported type %u\n", (unsigned)key_type);
1931 0 : ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1932 0 : goto cleanup;
1933 : }
1934 :
1935 : return 0;
1936 :
1937 0 : cleanup:
1938 0 : gnutls_free(tmp1);
1939 0 : gnutls_free(tmp2);
1940 :
1941 0 : return ret;
1942 : }
1943 :
1944 : static int
1945 79 : 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 79 : struct ck_attribute a[4];
1956 79 : ck_key_type_t key_type;
1957 79 : int ret;
1958 79 : ck_bool_t tval;
1959 :
1960 79 : a[0].type = CKA_KEY_TYPE;
1961 79 : a[0].value = &key_type;
1962 79 : a[0].value_len = sizeof(key_type);
1963 :
1964 79 : if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1965 79 : pobj->pk_algorithm = key_type_to_pk(key_type);
1966 :
1967 79 : ret =
1968 79 : pkcs11_read_pubkey(module, pks, ctx, key_type,
1969 : pobj);
1970 79 : if (ret < 0)
1971 0 : return gnutls_assert_val(ret);
1972 : }
1973 :
1974 : /* read key usage flags */
1975 79 : a[0].type = CKA_ENCRYPT;
1976 79 : a[0].value = &tval;
1977 79 : a[0].value_len = sizeof(tval);
1978 :
1979 79 : if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1980 78 : if (tval != 0) {
1981 78 : pobj->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
1982 : }
1983 : }
1984 :
1985 79 : a[0].type = CKA_VERIFY;
1986 79 : a[0].value = &tval;
1987 79 : a[0].value_len = sizeof(tval);
1988 :
1989 79 : if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
1990 78 : if (tval != 0) {
1991 78 : 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 79 : a[0].type = CKA_VERIFY_RECOVER;
1998 79 : a[0].value = &tval;
1999 79 : a[0].value_len = sizeof(tval);
2000 :
2001 79 : if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
2002 78 : if (tval != 0) {
2003 78 : 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 79 : a[0].type = CKA_DERIVE;
2010 79 : a[0].value = &tval;
2011 79 : a[0].value_len = sizeof(tval);
2012 :
2013 79 : if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
2014 78 : if (tval != 0) {
2015 0 : pobj->key_usage |= GNUTLS_KEY_KEY_AGREEMENT;
2016 : }
2017 : }
2018 :
2019 79 : a[0].type = CKA_WRAP;
2020 79 : a[0].value = &tval;
2021 79 : a[0].value_len = sizeof(tval);
2022 :
2023 79 : if (pkcs11_get_attribute_value(module, pks, ctx, a, 1) == CKR_OK) {
2024 78 : if (tval != 0) {
2025 78 : pobj->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
2026 : }
2027 : }
2028 :
2029 79 : ret = pkcs11_obj_import(CKO_PUBLIC_KEY, pobj, data, id, label,
2030 : tinfo, lib_info);
2031 79 : return ret;
2032 : }
2033 :
2034 : static int
2035 329 : 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 329 : ck_bool_t b;
2041 329 : int rv, ret;
2042 329 : struct ck_attribute a[4];
2043 329 : unsigned long category = 0;
2044 329 : char label_tmp[PKCS11_LABEL_SIZE];
2045 329 : char id_tmp[PKCS11_ID_SIZE];
2046 329 : gnutls_datum_t id, label, data = {NULL, 0};
2047 :
2048 : /* now figure out flags */
2049 329 : pobj->flags = 0;
2050 329 : a[0].type = CKA_WRAP;
2051 329 : a[0].value = &b;
2052 329 : a[0].value_len = sizeof(b);
2053 :
2054 329 : rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2055 329 : if (rv == CKR_OK && b != 0)
2056 78 : pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP;
2057 :
2058 329 : a[0].type = CKA_UNWRAP;
2059 329 : a[0].value = &b;
2060 329 : a[0].value_len = sizeof(b);
2061 :
2062 329 : rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2063 329 : if (rv == CKR_OK && b != 0)
2064 27 : pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP;
2065 :
2066 329 : a[0].type = CKA_PRIVATE;
2067 329 : a[0].value = &b;
2068 329 : a[0].value_len = sizeof(b);
2069 :
2070 329 : rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2071 329 : if (rv == CKR_OK && b != 0)
2072 33 : pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE;
2073 :
2074 329 : a[0].type = CKA_TRUSTED;
2075 329 : a[0].value = &b;
2076 329 : a[0].value_len = sizeof(b);
2077 :
2078 329 : rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2079 329 : if (rv == CKR_OK && b != 0)
2080 183 : pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED;
2081 :
2082 329 : if (sinfo->trusted) { /* only p11-kit "trusted" modules support this flag */
2083 190 : a[0].type = CKA_X_DISTRUSTED;
2084 190 : a[0].value = &b;
2085 190 : a[0].value_len = sizeof(b);
2086 :
2087 190 : rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2088 190 : if (rv == CKR_OK && b != 0)
2089 0 : pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_DISTRUSTED;
2090 : }
2091 :
2092 329 : a[0].type = CKA_SENSITIVE;
2093 329 : a[0].value = &b;
2094 329 : a[0].value_len = sizeof(b);
2095 :
2096 329 : rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2097 329 : if (rv == CKR_OK) {
2098 27 : if (b != 0)
2099 26 : pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE;
2100 : else
2101 1 : pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE;
2102 : }
2103 :
2104 329 : a[0].type = CKA_EXTRACTABLE;
2105 329 : a[0].value = &b;
2106 329 : a[0].value_len = sizeof(b);
2107 :
2108 329 : rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2109 329 : if (rv == CKR_OK && b != 0)
2110 0 : pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_EXTRACTABLE;
2111 :
2112 329 : a[0].type = CKA_NEVER_EXTRACTABLE;
2113 329 : a[0].value = &b;
2114 329 : a[0].value_len = sizeof(b);
2115 :
2116 329 : rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2117 329 : if (rv == CKR_OK && b != 0)
2118 14 : pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_NEVER_EXTRACTABLE;
2119 :
2120 329 : a[0].type = CKA_CERTIFICATE_CATEGORY;
2121 329 : a[0].value = &category;
2122 329 : a[0].value_len = sizeof(category);
2123 :
2124 329 : rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2125 329 : if (rv == CKR_OK && category == 2)
2126 200 : pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_CA;
2127 :
2128 329 : a[0].type = CKA_ALWAYS_AUTHENTICATE;
2129 329 : a[0].value = &b;
2130 329 : a[0].value_len = sizeof(b);
2131 :
2132 329 : rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1);
2133 329 : if (rv == CKR_OK && b != 0)
2134 1 : pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH;
2135 :
2136 : /* now recover the object label/id */
2137 329 : a[0].type = CKA_LABEL;
2138 329 : a[0].value = label_tmp;
2139 329 : a[0].value_len = sizeof(label_tmp);
2140 329 : rv = pkcs11_get_attribute_value
2141 : (sinfo->module, sinfo->pks, ctx, a, 1);
2142 329 : if (rv != CKR_OK) {
2143 0 : gnutls_assert();
2144 0 : label.data = NULL;
2145 0 : label.size = 0;
2146 : } else {
2147 329 : label.data = a[0].value;
2148 329 : label.size = a[0].value_len;
2149 : }
2150 :
2151 329 : a[0].type = CKA_ID;
2152 329 : a[0].value = id_tmp;
2153 329 : a[0].value_len = sizeof(id_tmp);
2154 329 : rv = pkcs11_get_attribute_value
2155 : (sinfo->module, sinfo->pks, ctx, a, 1);
2156 329 : if (rv != CKR_OK) {
2157 0 : gnutls_assert();
2158 0 : id.data = NULL;
2159 0 : id.size = 0;
2160 : } else {
2161 329 : id.data = a[0].value;
2162 329 : id.size = a[0].value_len;
2163 : }
2164 :
2165 329 : if (label.data == NULL && id.data == NULL)
2166 0 : return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
2167 :
2168 329 : rv = pkcs11_get_attribute_avalue
2169 : (sinfo->module, sinfo->pks, ctx, CKA_VALUE, &data);
2170 329 : if (rv != CKR_OK) {
2171 102 : gnutls_assert();
2172 : /* data will be null */
2173 : }
2174 :
2175 329 : if (class == CKO_PUBLIC_KEY) {
2176 79 : ret =
2177 79 : 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 250 : ret =
2187 250 : pkcs11_obj_import(class,
2188 : pobj,
2189 : &data, &id, &label,
2190 : tinfo,
2191 : lib_info);
2192 : }
2193 329 : if (ret < 0) {
2194 0 : gnutls_assert();
2195 0 : goto cleanup;
2196 : }
2197 :
2198 : ret = 0;
2199 329 : cleanup:
2200 329 : gnutls_free(data.data);
2201 329 : return ret;
2202 : }
2203 :
2204 : static int
2205 74 : 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 74 : struct find_single_obj_st *find_data = input;
2210 74 : struct ck_attribute a[4];
2211 74 : ck_certificate_type_t type;
2212 74 : ck_object_class_t class;
2213 74 : ck_rv_t rv;
2214 74 : ck_object_handle_t ctx = CK_INVALID_HANDLE;
2215 74 : unsigned long count;
2216 74 : unsigned a_vals;
2217 74 : int found = 0, ret;
2218 :
2219 74 : if (tinfo == NULL) { /* we don't support multiple calls */
2220 10 : gnutls_assert();
2221 10 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2222 : }
2223 :
2224 : /* do not bother reading the token if basic fields do not match
2225 : */
2226 64 : if (!p11_kit_uri_match_token_info
2227 64 : (find_data->obj->info, tinfo)
2228 64 : || !p11_kit_uri_match_module_info(find_data->obj->info,
2229 : lib_info)) {
2230 0 : gnutls_assert();
2231 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2232 : }
2233 :
2234 64 : ret = add_obj_attrs(find_data->obj->info, a, &a_vals, &class, &type);
2235 64 : if (ret < 0)
2236 0 : return gnutls_assert_val(ret);
2237 :
2238 64 : rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
2239 : a_vals);
2240 64 : if (rv != CKR_OK) {
2241 0 : gnutls_assert();
2242 0 : _gnutls_debug_log("p11: FindObjectsInit failed.\n");
2243 0 : ret = pkcs11_rv_to_err(rv);
2244 0 : goto cleanup;
2245 : }
2246 :
2247 64 : if (pkcs11_find_objects(sinfo->module, sinfo->pks, &ctx, 1, &count) == CKR_OK &&
2248 64 : count == 1) {
2249 55 : ret = pkcs11_import_object(ctx, class, sinfo, tinfo, lib_info, find_data->obj);
2250 55 : if (ret >= 0) {
2251 : found = 1;
2252 : }
2253 : } else {
2254 9 : _gnutls_debug_log
2255 : ("p11: Skipped object, missing attrs.\n");
2256 : }
2257 :
2258 0 : if (found == 0) {
2259 9 : gnutls_assert();
2260 : ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2261 : } else {
2262 : ret = 0;
2263 : }
2264 :
2265 64 : cleanup:
2266 64 : pkcs11_find_objects_final(sinfo);
2267 :
2268 64 : if (ret == 0 && find_data->overwrite_exts && find_data->obj->raw.size > 0 && ctx != CK_INVALID_HANDLE) {
2269 2 : gnutls_datum_t spki;
2270 2 : rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, ctx, CKA_PUBLIC_KEY_INFO, &spki);
2271 2 : if (rv == CKR_OK) {
2272 2 : ret = pkcs11_override_cert_exts(sinfo, &spki, &find_data->obj->raw);
2273 2 : gnutls_free(spki.data);
2274 2 : if (ret < 0) {
2275 0 : gnutls_assert();
2276 0 : return ret;
2277 : }
2278 : }
2279 : }
2280 :
2281 : return ret;
2282 : }
2283 :
2284 1367 : unsigned int pkcs11_obj_flags_to_int(unsigned int flags)
2285 : {
2286 1367 : unsigned int ret_flags = 0;
2287 :
2288 1367 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN)
2289 156 : ret_flags |= SESSION_LOGIN | SESSION_FORCE_LOGIN;
2290 :
2291 1367 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO)
2292 102 : ret_flags |= SESSION_LOGIN | SESSION_SO | SESSION_FORCE_LOGIN | SESSION_WRITE;
2293 :
2294 1367 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE)
2295 1027 : ret_flags |= SESSION_TRUSTED;
2296 :
2297 1367 : 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
2321 65 : gnutls_pkcs11_obj_import_url(gnutls_pkcs11_obj_t obj, const char *url,
2322 : unsigned int flags)
2323 : {
2324 65 : int ret;
2325 65 : struct find_single_obj_st find_data;
2326 :
2327 65 : PKCS11_CHECK_INIT;
2328 65 : memset(&find_data, 0, sizeof(find_data));
2329 :
2330 : /* fill in the find data structure */
2331 65 : find_data.obj = obj;
2332 :
2333 65 : ret = pkcs11_url_to_info(url, &obj->info, flags);
2334 65 : if (ret < 0) {
2335 0 : gnutls_assert();
2336 0 : return ret;
2337 : }
2338 :
2339 65 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT) {
2340 2 : find_data.overwrite_exts = 1;
2341 : }
2342 :
2343 65 : ret =
2344 65 : _pkcs11_traverse_tokens(find_single_obj_cb, &find_data, obj->info,
2345 : &obj->pin,
2346 : pkcs11_obj_flags_to_int(flags));
2347 65 : if (ret < 0) {
2348 10 : gnutls_assert();
2349 10 : return ret;
2350 : }
2351 :
2352 : return 0;
2353 : }
2354 :
2355 : static int
2356 6 : 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 6 : struct find_token_num *find_data = input;
2361 :
2362 6 : if (tinfo == NULL) { /* we don't support multiple calls */
2363 2 : gnutls_assert();
2364 2 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2365 : }
2366 :
2367 4 : if (find_data->current == find_data->seq) {
2368 2 : memcpy(p11_kit_uri_get_token_info(find_data->info),
2369 : tinfo, sizeof(struct ck_token_info));
2370 2 : memcpy(p11_kit_uri_get_module_info(find_data->info),
2371 : lib_info, sizeof(struct ck_info));
2372 2 : return 0;
2373 : }
2374 :
2375 2 : find_data->current++;
2376 : /* search the token for the id */
2377 :
2378 :
2379 2 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* non zero is enough */
2380 : }
2381 :
2382 : static int
2383 5 : 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 5 : struct find_token_modname *find_data = input;
2388 :
2389 5 : if (tinfo == NULL) { /* we don't support multiple calls */
2390 1 : gnutls_assert();
2391 1 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2392 : }
2393 :
2394 4 : if (!p11_kit_uri_match_token_info(find_data->info, tinfo)
2395 3 : || !p11_kit_uri_match_module_info(find_data->info,
2396 : lib_info)) {
2397 1 : gnutls_assert();
2398 1 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2399 : }
2400 :
2401 3 : find_data->modname = p11_kit_config_option(module, "module");
2402 3 : find_data->ptr = module;
2403 3 : find_data->slot_id = sinfo->sid;
2404 3 : 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
2429 4 : _gnutls_pkcs11_token_get_url(unsigned int seq,
2430 : gnutls_pkcs11_url_type_t detailed, char **url,
2431 : unsigned flags)
2432 : {
2433 4 : int ret;
2434 4 : struct find_token_num tn;
2435 :
2436 4 : if (!(flags & 1)) {
2437 4 : PKCS11_CHECK_INIT;
2438 : }
2439 :
2440 4 : memset(&tn, 0, sizeof(tn));
2441 4 : tn.seq = seq;
2442 4 : tn.info = p11_kit_uri_new();
2443 :
2444 4 : ret = _pkcs11_traverse_tokens(find_token_num_cb, &tn, NULL, NULL, 0);
2445 4 : if (ret < 0) {
2446 2 : p11_kit_uri_free(tn.info);
2447 2 : gnutls_assert();
2448 2 : return ret;
2449 : }
2450 :
2451 2 : ret = pkcs11_info_to_url(tn.info, detailed, url);
2452 2 : p11_kit_uri_free(tn.info);
2453 :
2454 2 : if (ret < 0) {
2455 0 : gnutls_assert();
2456 0 : 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
2478 4 : gnutls_pkcs11_token_get_url(unsigned int seq,
2479 : gnutls_pkcs11_url_type_t detailed, char **url)
2480 : {
2481 4 : 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
2506 13 : gnutls_pkcs11_token_get_info(const char *url,
2507 : gnutls_pkcs11_token_info_t ttype,
2508 : void *output, size_t * output_size)
2509 : {
2510 13 : struct p11_kit_uri *info = NULL;
2511 13 : const uint8_t *str;
2512 13 : char *temp_str = NULL;
2513 13 : size_t len;
2514 13 : int ret;
2515 :
2516 13 : PKCS11_CHECK_INIT;
2517 :
2518 13 : ret = pkcs11_url_to_info(url, &info, 0);
2519 13 : if (ret < 0) {
2520 0 : gnutls_assert();
2521 0 : return ret;
2522 : }
2523 :
2524 13 : switch (ttype) {
2525 5 : case GNUTLS_PKCS11_TOKEN_LABEL:
2526 5 : str = p11_kit_uri_get_token_info(info)->label;
2527 5 : len = p11_kit_space_strlen(str, 32);
2528 5 : break;
2529 2 : case GNUTLS_PKCS11_TOKEN_SERIAL:
2530 2 : str = p11_kit_uri_get_token_info(info)->serial_number;
2531 2 : len = p11_kit_space_strlen(str, 16);
2532 2 : break;
2533 2 : case GNUTLS_PKCS11_TOKEN_MANUFACTURER:
2534 2 : str = p11_kit_uri_get_token_info(info)->manufacturer_id;
2535 2 : len = p11_kit_space_strlen(str, 32);
2536 2 : break;
2537 2 : case GNUTLS_PKCS11_TOKEN_MODEL:
2538 2 : str = p11_kit_uri_get_token_info(info)->model;
2539 2 : len = p11_kit_space_strlen(str, 16);
2540 2 : break;
2541 2 : case GNUTLS_PKCS11_TOKEN_MODNAME: {
2542 2 : struct find_token_modname tn;
2543 :
2544 2 : memset(&tn, 0, sizeof(tn));
2545 2 : tn.info = info;
2546 :
2547 2 : ret = _pkcs11_traverse_tokens(find_token_modname_cb, &tn, NULL, NULL, 0);
2548 2 : if (ret < 0) {
2549 0 : gnutls_assert();
2550 0 : goto cleanup;
2551 : }
2552 :
2553 2 : temp_str = tn.modname;
2554 2 : if (temp_str) {
2555 0 : str = (uint8_t *)temp_str;
2556 0 : len = strlen(temp_str);
2557 : } else {
2558 2 : gnutls_assert();
2559 : len = 0;
2560 : }
2561 2 : break;
2562 : }
2563 0 : default:
2564 0 : gnutls_assert();
2565 0 : ret = GNUTLS_E_INVALID_REQUEST;
2566 0 : goto cleanup;
2567 : }
2568 :
2569 13 : if (len < *output_size) {
2570 11 : if (len)
2571 9 : memcpy(output, str, len);
2572 11 : ((char *) output)[len] = '\0';
2573 11 : *output_size = len;
2574 11 : ret = 0;
2575 : } else {
2576 2 : *output_size = len + 1;
2577 2 : ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
2578 : }
2579 :
2580 13 : cleanup:
2581 13 : free(temp_str);
2582 13 : p11_kit_uri_free(info);
2583 13 : 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
2603 2 : gnutls_pkcs11_token_get_ptr(const char *url, void **ptr, unsigned long *slot_id,
2604 : unsigned int flags)
2605 : {
2606 2 : struct p11_kit_uri *info = NULL;
2607 2 : int ret;
2608 2 : struct find_token_modname tn;
2609 :
2610 2 : PKCS11_CHECK_INIT;
2611 :
2612 2 : ret = pkcs11_url_to_info(url, &info, 0);
2613 2 : if (ret < 0) {
2614 0 : gnutls_assert();
2615 0 : return ret;
2616 : }
2617 :
2618 2 : memset(&tn, 0, sizeof(tn));
2619 2 : tn.info = info;
2620 :
2621 2 : ret = _pkcs11_traverse_tokens(find_token_modname_cb, &tn, NULL, NULL, 0);
2622 2 : if (ret < 0) {
2623 1 : gnutls_assert();
2624 1 : goto cleanup;
2625 : }
2626 :
2627 1 : if (ptr)
2628 1 : *ptr = tn.ptr;
2629 1 : if (slot_id)
2630 1 : *slot_id = tn.slot_id;
2631 :
2632 : ret = 0;
2633 :
2634 2 : cleanup:
2635 2 : free(tn.modname);
2636 2 : p11_kit_uri_free(info);
2637 2 : 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
2654 84 : gnutls_pkcs11_obj_export_url(gnutls_pkcs11_obj_t obj,
2655 : gnutls_pkcs11_url_type_t detailed, char **url)
2656 : {
2657 84 : int ret;
2658 :
2659 84 : ret = pkcs11_info_to_url(obj->info, detailed, url);
2660 84 : if (ret < 0) {
2661 0 : gnutls_assert();
2662 0 : 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
2680 179 : gnutls_pkcs11_obj_get_type(gnutls_pkcs11_obj_t obj)
2681 : {
2682 179 : return obj->type;
2683 : }
2684 :
2685 : static int
2686 2 : 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 2 : unsigned int flags = 0;
2692 2 : struct p11_kit_uri *token_uri;
2693 2 : struct p11_kit_pin *result;
2694 2 : char *label;
2695 :
2696 2 : label =
2697 2 : p11_kit_space_strdup(token_info->label,
2698 : sizeof(token_info->label));
2699 2 : if (label == NULL) {
2700 0 : gnutls_assert();
2701 0 : return GNUTLS_E_MEMORY_ERROR;
2702 : }
2703 :
2704 2 : token_uri = p11_kit_uri_new();
2705 2 : if (token_uri == NULL) {
2706 0 : free(label);
2707 0 : gnutls_assert();
2708 0 : return GNUTLS_E_MEMORY_ERROR;
2709 : }
2710 :
2711 2 : memcpy(p11_kit_uri_get_token_info(token_uri), token_info,
2712 : sizeof(struct ck_token_info));
2713 :
2714 2 : if (attempts)
2715 0 : flags |= P11_KIT_PIN_FLAGS_RETRY;
2716 2 : if (user_type == CKU_USER) {
2717 2 : flags |= P11_KIT_PIN_FLAGS_USER_LOGIN;
2718 2 : if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
2719 1 : flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
2720 2 : if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
2721 0 : flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
2722 0 : } else if (user_type == CKU_SO) {
2723 0 : flags |= P11_KIT_PIN_FLAGS_SO_LOGIN;
2724 0 : if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
2725 0 : flags |= P11_KIT_PIN_FLAGS_MANY_TRIES;
2726 0 : if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
2727 0 : flags |= P11_KIT_PIN_FLAGS_FINAL_TRY;
2728 0 : } else if (user_type == CKU_CONTEXT_SPECIFIC) {
2729 0 : flags |= P11_KIT_PIN_FLAGS_CONTEXT_LOGIN;
2730 : }
2731 :
2732 2 : result = p11_kit_pin_request(pinfile, token_uri, label, flags);
2733 2 : p11_kit_uri_free(token_uri);
2734 2 : free(label);
2735 :
2736 2 : if (result == NULL) {
2737 0 : gnutls_assert();
2738 0 : return GNUTLS_E_PKCS11_PIN_ERROR;
2739 : }
2740 :
2741 2 : *pin = result;
2742 2 : return 0;
2743 : }
2744 :
2745 : static int
2746 336 : 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 336 : char pin_value[GNUTLS_PKCS11_MAX_PIN_LEN];
2752 336 : unsigned int flags = 0;
2753 336 : char *token_str;
2754 336 : char *label;
2755 336 : struct p11_kit_uri *token_uri;
2756 336 : int ret = 0;
2757 :
2758 336 : label =
2759 336 : p11_kit_space_strdup(token_info->label,
2760 : sizeof(token_info->label));
2761 336 : if (label == NULL) {
2762 0 : gnutls_assert();
2763 0 : return GNUTLS_E_MEMORY_ERROR;
2764 : }
2765 :
2766 336 : token_uri = p11_kit_uri_new();
2767 336 : if (token_uri == NULL) {
2768 0 : free(label);
2769 0 : gnutls_assert();
2770 0 : return GNUTLS_E_MEMORY_ERROR;
2771 : }
2772 :
2773 336 : memcpy(p11_kit_uri_get_token_info(token_uri), token_info,
2774 : sizeof(struct ck_token_info));
2775 336 : ret = pkcs11_info_to_url(token_uri, 1, &token_str);
2776 336 : p11_kit_uri_free(token_uri);
2777 :
2778 336 : if (ret < 0) {
2779 0 : free(label);
2780 0 : gnutls_assert();
2781 0 : return GNUTLS_E_MEMORY_ERROR;
2782 : }
2783 :
2784 336 : if (user_type == CKU_USER || user_type == CKU_CONTEXT_SPECIFIC) {
2785 211 : flags |= GNUTLS_PIN_USER;
2786 :
2787 211 : if (user_type == CKU_CONTEXT_SPECIFIC)
2788 2 : flags |= GNUTLS_PIN_CONTEXT_SPECIFIC;
2789 211 : if (token_info->flags & CKF_USER_PIN_COUNT_LOW)
2790 0 : flags |= GNUTLS_PIN_COUNT_LOW;
2791 211 : if (token_info->flags & CKF_USER_PIN_FINAL_TRY)
2792 0 : flags |= GNUTLS_PIN_FINAL_TRY;
2793 125 : } else if (user_type == CKU_SO) {
2794 125 : flags |= GNUTLS_PIN_SO;
2795 125 : if (token_info->flags & CKF_SO_PIN_COUNT_LOW)
2796 0 : flags |= GNUTLS_PIN_COUNT_LOW;
2797 125 : if (token_info->flags & CKF_SO_PIN_FINAL_TRY)
2798 0 : flags |= GNUTLS_PIN_FINAL_TRY;
2799 : }
2800 :
2801 336 : if (attempts > 0)
2802 0 : flags |= GNUTLS_PIN_WRONG;
2803 :
2804 336 : if (pin_info && pin_info->cb)
2805 40 : ret =
2806 40 : pin_info->cb(pin_info->data, attempts,
2807 : (char *) token_str, label, flags,
2808 : pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2809 296 : else if (_gnutls_pin_func)
2810 296 : ret =
2811 296 : _gnutls_pin_func(_gnutls_pin_data, attempts,
2812 : (char *) token_str, label, flags,
2813 : pin_value, GNUTLS_PKCS11_MAX_PIN_LEN);
2814 : else
2815 0 : ret = gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2816 :
2817 336 : free(token_str);
2818 336 : free(label);
2819 :
2820 336 : if (ret < 0)
2821 0 : return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2822 :
2823 336 : *pin = p11_kit_pin_new_for_string(pin_value);
2824 :
2825 336 : if (*pin == NULL)
2826 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2827 :
2828 : return 0;
2829 : }
2830 :
2831 : int
2832 351 : 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 351 : const char *pinfile;
2837 351 : int ret = GNUTLS_E_PKCS11_PIN_ERROR;
2838 :
2839 351 : *pin = NULL;
2840 :
2841 : /* First check for pin-value field */
2842 351 : pinfile = p11_kit_uri_get_pin_value(info);
2843 351 : if (pinfile != NULL) {
2844 12 : if (attempts > 0) {
2845 1 : _gnutls_debug_log("p11: refusing more than a single attempts with pin-value\n");
2846 1 : return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2847 : }
2848 :
2849 11 : _gnutls_debug_log("p11: Using pin-value to retrieve PIN\n");
2850 11 : *pin = p11_kit_pin_new_for_string(pinfile);
2851 11 : if (*pin != NULL)
2852 : ret = 0;
2853 : } else { /* try pin-source */
2854 : /* Check if a pinfile is specified, and use that if possible */
2855 339 : pinfile = p11_kit_uri_get_pin_source(info);
2856 339 : if (pinfile != NULL) {
2857 3 : if (attempts > 0) {
2858 1 : _gnutls_debug_log("p11: refusing more than a single attempts with pin-source\n");
2859 1 : return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR);
2860 : }
2861 :
2862 2 : _gnutls_debug_log("p11: Using pin-source to retrieve PIN\n");
2863 2 : ret =
2864 2 : retrieve_pin_from_source(pinfile, token_info, attempts,
2865 : user_type, pin);
2866 : }
2867 : }
2868 :
2869 : /* The global gnutls pin callback */
2870 2 : if (ret < 0)
2871 336 : ret =
2872 336 : 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 349 : if (ret < 0) {
2879 0 : gnutls_assert();
2880 0 : _gnutls_debug_log
2881 : ("p11: No suitable pin callback but login required.\n");
2882 : }
2883 :
2884 : return ret;
2885 : }
2886 :
2887 : int
2888 1495 : 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 1495 : struct ck_session_info session_info;
2894 1495 : int attempt = 0, ret;
2895 1495 : ck_user_type_t user_type;
2896 1495 : ck_rv_t rv;
2897 :
2898 1495 : if (!(flags & SESSION_LOGIN)) {
2899 1140 : _gnutls_debug_log("p11: No login requested.\n");
2900 1140 : return 0;
2901 : }
2902 :
2903 355 : if (flags & SESSION_SO) {
2904 : user_type = CKU_SO;
2905 234 : } else if (flags & SESSION_CONTEXT_SPECIFIC) {
2906 : user_type = CKU_CONTEXT_SPECIFIC;
2907 : } else {
2908 232 : user_type = CKU_USER;
2909 : }
2910 :
2911 355 : if (!(flags & (SESSION_FORCE_LOGIN|SESSION_SO)) &&
2912 77 : !(sinfo->tinfo.flags & CKF_LOGIN_REQUIRED)) {
2913 1 : gnutls_assert();
2914 1 : _gnutls_debug_log("p11: No login required in token.\n");
2915 1 : 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 354 : if (sinfo->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
2922 0 : rv = (sinfo->module)->C_Login(sinfo->pks,
2923 : user_type,
2924 : NULL, 0);
2925 0 : if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) {
2926 : return 0;
2927 : } else {
2928 0 : gnutls_assert();
2929 0 : _gnutls_debug_log
2930 : ("p11: Protected login failed.\n");
2931 0 : ret = pkcs11_rv_to_err(rv);
2932 0 : goto cleanup;
2933 : }
2934 : }
2935 :
2936 356 : do {
2937 356 : struct p11_kit_pin *pin;
2938 356 : struct ck_token_info tinfo;
2939 :
2940 356 : memcpy(&tinfo, &sinfo->tinfo, sizeof(tinfo));
2941 :
2942 356 : if (!(flags & SESSION_CONTEXT_SPECIFIC)) {
2943 : /* Check whether the session is already logged in, and if so, just skip */
2944 354 : rv = (sinfo->module)->C_GetSessionInfo(sinfo->pks,
2945 : &session_info);
2946 354 : if (rv == CKR_OK) {
2947 354 : if (flags & SESSION_SO) {
2948 121 : if (session_info.state == CKS_RW_SO_FUNCTIONS) {
2949 0 : ret = 0;
2950 0 : _gnutls_debug_log
2951 : ("p11: Already logged in as SO\n");
2952 11 : goto cleanup;
2953 : }
2954 233 : } else if (session_info.state == CKS_RO_USER_FUNCTIONS
2955 233 : || session_info.state == CKS_RW_USER_FUNCTIONS) {
2956 9 : ret = 0;
2957 9 : _gnutls_debug_log
2958 : ("p11: Already logged in as user\n");
2959 9 : 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 347 : if (attempt) {
2967 2 : rv = pkcs11_get_token_info(sinfo->module, sinfo->sid,
2968 : &tinfo);
2969 2 : if (rv != CKR_OK) {
2970 0 : gnutls_assert();
2971 0 : _gnutls_debug_log
2972 : ("p11: GetTokenInfo failed\n");
2973 :
2974 0 : ret = pkcs11_rv_to_err(rv);
2975 0 : goto cleanup;
2976 : }
2977 : }
2978 :
2979 347 : ret =
2980 347 : pkcs11_retrieve_pin(pin_info, info, &tinfo, attempt++,
2981 : user_type, &pin);
2982 347 : if (ret < 0) {
2983 2 : gnutls_assert();
2984 2 : goto cleanup;
2985 : }
2986 :
2987 690 : rv = (sinfo->module)->C_Login(sinfo->pks, user_type,
2988 : (unsigned char *)
2989 345 : p11_kit_pin_get_value(pin,
2990 : NULL),
2991 : p11_kit_pin_get_length(pin));
2992 :
2993 345 : p11_kit_pin_unref(pin);
2994 : }
2995 345 : while (rv == CKR_PIN_INCORRECT);
2996 :
2997 343 : _gnutls_debug_log("p11: Login result = %s (%lu)\n", (rv==0)?"ok":p11_kit_strerror(rv), rv);
2998 :
2999 343 : ret = (rv == CKR_OK || rv ==
3000 343 : CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err(rv);
3001 :
3002 : cleanup:
3003 : return ret;
3004 : }
3005 :
3006 0 : int pkcs11_call_token_func(struct p11_kit_uri *info, const unsigned retry)
3007 : {
3008 0 : struct ck_token_info *tinfo;
3009 0 : char *label;
3010 0 : int ret = 0;
3011 :
3012 0 : tinfo = p11_kit_uri_get_token_info(info);
3013 0 : label = p11_kit_space_strdup(tinfo->label, sizeof(tinfo->label));
3014 0 : ret = (_gnutls_token_func) (_gnutls_token_data, label, retry);
3015 0 : free(label);
3016 :
3017 0 : return ret;
3018 : }
3019 :
3020 :
3021 : static int
3022 4 : find_privkeys(struct pkcs11_session_info *sinfo,
3023 : struct ck_token_info *tinfo, struct find_pkey_list_st *list)
3024 : {
3025 4 : struct ck_attribute a[3];
3026 4 : ck_object_class_t class;
3027 4 : ck_rv_t rv;
3028 4 : ck_object_handle_t ctx;
3029 4 : unsigned long count, current;
3030 4 : char certid_tmp[PKCS11_ID_SIZE];
3031 4 : int ret;
3032 :
3033 4 : class = CKO_PRIVATE_KEY;
3034 :
3035 : /* Find an object with private key class and a certificate ID
3036 : * which matches the certificate. */
3037 4 : a[0].type = CKA_CLASS;
3038 4 : a[0].value = &class;
3039 4 : a[0].value_len = sizeof class;
3040 :
3041 4 : rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 1);
3042 4 : if (rv != CKR_OK) {
3043 0 : gnutls_assert();
3044 0 : return pkcs11_rv_to_err(rv);
3045 : }
3046 :
3047 4 : list->key_ids_size = 0;
3048 21 : while (pkcs11_find_objects
3049 : (sinfo->module, sinfo->pks, &ctx, 1, &count) == CKR_OK
3050 21 : && count == 1) {
3051 17 : list->key_ids_size++;
3052 : }
3053 :
3054 4 : pkcs11_find_objects_final(sinfo);
3055 :
3056 4 : if (list->key_ids_size == 0) {
3057 0 : gnutls_assert();
3058 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3059 : }
3060 :
3061 8 : list->key_ids =
3062 4 : gnutls_malloc(sizeof(gnutls_buffer_st) * list->key_ids_size);
3063 4 : if (list->key_ids == NULL) {
3064 0 : gnutls_assert();
3065 0 : return GNUTLS_E_MEMORY_ERROR;
3066 : }
3067 :
3068 : /* actual search */
3069 4 : a[0].type = CKA_CLASS;
3070 4 : a[0].value = &class;
3071 4 : a[0].value_len = sizeof class;
3072 :
3073 4 : rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 1);
3074 4 : if (rv != CKR_OK) {
3075 0 : gnutls_assert();
3076 0 : return pkcs11_rv_to_err(rv);
3077 : }
3078 :
3079 : current = 0;
3080 21 : while (pkcs11_find_objects
3081 : (sinfo->module, sinfo->pks, &ctx, 1, &count) == CKR_OK
3082 21 : && count == 1) {
3083 :
3084 17 : a[0].type = CKA_ID;
3085 17 : a[0].value = certid_tmp;
3086 17 : a[0].value_len = sizeof(certid_tmp);
3087 :
3088 17 : _gnutls_buffer_init(&list->key_ids[current]);
3089 :
3090 17 : if (pkcs11_get_attribute_value
3091 : (sinfo->module, sinfo->pks, ctx, a, 1) == CKR_OK) {
3092 34 : ret = _gnutls_buffer_append_data(&list->key_ids[current],
3093 17 : a[0].value,
3094 : a[0].value_len);
3095 17 : if (ret < 0)
3096 0 : return gnutls_assert_val(ret);
3097 17 : current++;
3098 : }
3099 :
3100 17 : if (current > list->key_ids_size)
3101 : break;
3102 : }
3103 :
3104 4 : pkcs11_find_objects_final(sinfo);
3105 :
3106 4 : list->key_ids_size = current - 1;
3107 :
3108 4 : return 0;
3109 : }
3110 :
3111 : /* Recover certificate list from tokens */
3112 :
3113 : #define OBJECTS_A_TIME 8*1024
3114 :
3115 : static int
3116 428 : 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 428 : struct find_multi_obj_st *find_data = input;
3120 428 : struct ck_attribute a[16];
3121 428 : struct ck_attribute *attr;
3122 428 : ck_object_class_t class = (ck_object_class_t) -1;
3123 428 : ck_certificate_type_t type = (ck_certificate_type_t) -1;
3124 428 : ck_bool_t trusted;
3125 428 : unsigned long category;
3126 428 : ck_rv_t rv;
3127 428 : ck_object_handle_t *ctx = NULL;
3128 428 : unsigned long count;
3129 428 : char certid_tmp[PKCS11_ID_SIZE];
3130 428 : int ret;
3131 428 : struct find_pkey_list_st plist; /* private key holder */
3132 428 : unsigned int i, tot_values = 0, class_set = 0;
3133 428 : unsigned start_elem;
3134 :
3135 428 : if (tinfo == NULL) {
3136 214 : gnutls_assert();
3137 214 : return 0;
3138 : }
3139 :
3140 : /* do not bother reading the token if basic fields do not match
3141 : */
3142 428 : if (!p11_kit_uri_match_token_info(find_data->info, tinfo) ||
3143 214 : !p11_kit_uri_match_module_info(find_data->info, lib_info)) {
3144 0 : gnutls_assert();
3145 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3146 : }
3147 :
3148 214 : memset(&plist, 0, sizeof(plist));
3149 :
3150 214 : if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_WITH_PRIVKEY) {
3151 4 : ret = find_privkeys(sinfo, tinfo, &plist);
3152 4 : if (ret < 0) {
3153 0 : gnutls_assert();
3154 0 : return ret;
3155 : }
3156 :
3157 4 : if (plist.key_ids_size == 0) {
3158 0 : gnutls_assert();
3159 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3160 : }
3161 : }
3162 :
3163 : /* Find objects with given class and type */
3164 214 : attr = p11_kit_uri_get_attribute(find_data->info, CKA_CLASS);
3165 214 : if (attr) {
3166 17 : if (attr->value
3167 17 : && attr->value_len == sizeof(ck_object_class_t))
3168 17 : class = *((ck_object_class_t *) attr->value);
3169 17 : if (class == CKO_CERTIFICATE)
3170 9 : type = CKC_X_509;
3171 : }
3172 :
3173 214 : if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_CRT) {
3174 185 : class = CKO_CERTIFICATE;
3175 :
3176 185 : a[tot_values].type = CKA_CLASS;
3177 185 : a[tot_values].value = &class;
3178 185 : a[tot_values].value_len = sizeof class;
3179 185 : tot_values++;
3180 185 : class_set = 1;
3181 :
3182 185 : type = CKC_X_509;
3183 185 : a[tot_values].type = CKA_CERTIFICATE_TYPE;
3184 185 : a[tot_values].value = &type;
3185 185 : a[tot_values].value_len = sizeof type;
3186 185 : tot_values++;
3187 185 : _gnutls_assert_log("p11 attrs: CKA_CLASS (CERT), CKA_CERTIFICATE_TYPE\n");
3188 : }
3189 :
3190 214 : if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_PUBKEY) {
3191 7 : class = CKO_PUBLIC_KEY;
3192 :
3193 7 : a[tot_values].type = CKA_CLASS;
3194 7 : a[tot_values].value = &class;
3195 7 : a[tot_values].value_len = sizeof class;
3196 7 : tot_values++;
3197 7 : class_set = 1;
3198 7 : _gnutls_assert_log("p11 attrs: CKA_CLASS (PUBLIC KEY)\n");
3199 : }
3200 :
3201 214 : if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY) {
3202 14 : class = CKO_PRIVATE_KEY;
3203 :
3204 14 : a[tot_values].type = CKA_CLASS;
3205 14 : a[tot_values].value = &class;
3206 14 : a[tot_values].value_len = sizeof class;
3207 14 : tot_values++;
3208 14 : class_set = 1;
3209 14 : _gnutls_assert_log("p11 attrs: CKA_CLASS (PRIVATE KEY)\n");
3210 : }
3211 :
3212 214 : if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
3213 178 : trusted = 1;
3214 178 : a[tot_values].type = CKA_TRUSTED;
3215 178 : a[tot_values].value = &trusted;
3216 178 : a[tot_values].value_len = sizeof trusted;
3217 178 : tot_values++;
3218 178 : _gnutls_assert_log("p11 attrs: CKA_TRUSTED\n");
3219 : }
3220 :
3221 214 : if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_DISTRUSTED) {
3222 0 : if (!sinfo->trusted) { /* only p11-kit trust modules support this */
3223 0 : gnutls_assert();
3224 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3225 : }
3226 :
3227 0 : trusted = 1;
3228 0 : a[tot_values].type = CKA_X_DISTRUSTED;
3229 0 : a[tot_values].value = &trusted;
3230 0 : a[tot_values].value_len = sizeof trusted;
3231 0 : tot_values++;
3232 0 : _gnutls_assert_log("p11 attrs: CKA_X_DISTRUSTED\n");
3233 : }
3234 :
3235 214 : if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA) {
3236 175 : category = 2;
3237 175 : a[tot_values].type = CKA_CERTIFICATE_CATEGORY;
3238 175 : a[tot_values].value = &category;
3239 175 : a[tot_values].value_len = sizeof category;
3240 175 : tot_values++;
3241 175 : _gnutls_assert_log("p11 attrs: CKA_CERTIFICATE_CATEGORY=CA\n");
3242 : }
3243 :
3244 214 : if (class_set == 0 && class != (ck_object_class_t)-1) {
3245 7 : a[tot_values].type = CKA_CLASS;
3246 7 : a[tot_values].value = &class;
3247 7 : a[tot_values].value_len = sizeof class;
3248 7 : tot_values++;
3249 7 : class_set = 1;
3250 7 : _gnutls_assert_log("p11 attrs: CKA_CLASS\n");
3251 : }
3252 :
3253 214 : attr = p11_kit_uri_get_attribute(find_data->info, CKA_ID);
3254 214 : if (attr) {
3255 3 : a[tot_values].type = CKA_ID;
3256 3 : a[tot_values].value = attr->value;
3257 3 : a[tot_values].value_len = attr->value_len;
3258 3 : tot_values++;
3259 3 : _gnutls_assert_log("p11 attrs: CKA_ID\n");
3260 : }
3261 :
3262 214 : attr = p11_kit_uri_get_attribute(find_data->info, CKA_LABEL);
3263 214 : if (attr) {
3264 22 : a[tot_values].type = CKA_LABEL;
3265 22 : a[tot_values].value = attr->value;
3266 22 : a[tot_values].value_len = attr->value_len;
3267 22 : tot_values++;
3268 22 : _gnutls_assert_log("p11 attrs: CKA_LABEL\n");
3269 : }
3270 :
3271 214 : rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
3272 : tot_values);
3273 214 : if (rv != CKR_OK) {
3274 0 : gnutls_assert();
3275 0 : _gnutls_debug_log("p11: FindObjectsInit failed.\n");
3276 0 : return pkcs11_rv_to_err(rv);
3277 : }
3278 :
3279 214 : ctx = gnutls_malloc(OBJECTS_A_TIME*sizeof(ctx[0]));
3280 214 : if (ctx == NULL) {
3281 0 : ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
3282 0 : goto fail;
3283 : }
3284 :
3285 214 : start_elem = find_data->current;
3286 :
3287 424 : while (pkcs11_find_objects
3288 : (sinfo->module, sinfo->pks, ctx, OBJECTS_A_TIME, &count) == CKR_OK
3289 424 : && count > 0) {
3290 210 : unsigned j;
3291 210 : gnutls_datum_t id;
3292 :
3293 210 : find_data->p_list = gnutls_realloc_fast(find_data->p_list, (find_data->current+count)*sizeof(find_data->p_list[0]));
3294 210 : if (find_data->p_list == NULL) {
3295 0 : ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
3296 0 : goto fail;
3297 : }
3298 :
3299 484 : for (j=0;j<count;j++) {
3300 274 : a[0].type = CKA_ID;
3301 274 : a[0].value = certid_tmp;
3302 274 : a[0].value_len = sizeof certid_tmp;
3303 :
3304 274 : if (pkcs11_get_attribute_value
3305 274 : (sinfo->module, sinfo->pks, ctx[j], a, 1) == CKR_OK) {
3306 274 : id.data = a[0].value;
3307 274 : id.size = a[0].value_len;
3308 : } else {
3309 0 : id.data = NULL;
3310 0 : id.size = 0;
3311 : }
3312 :
3313 274 : if (class_set == 0) {
3314 6 : a[0].type = CKA_CLASS;
3315 6 : a[0].value = &class;
3316 6 : a[0].value_len = sizeof class;
3317 :
3318 6 : rv = pkcs11_get_attribute_value(sinfo->module,
3319 : sinfo->pks, ctx[j], a, 1);
3320 6 : if (rv != CKR_OK) {
3321 0 : class = -1;
3322 : }
3323 : }
3324 :
3325 274 : if (find_data->flags & GNUTLS_PKCS11_OBJ_FLAG_WITH_PRIVKEY) {
3326 17 : for (i = 0; i < plist.key_ids_size; i++) {
3327 13 : if (plist.key_ids[i].length !=
3328 13 : id.size
3329 10 : || memcmp(plist.key_ids[i].data,
3330 10 : id.data,
3331 : id.size) != 0) {
3332 : /* not found */
3333 11 : continue;
3334 : }
3335 : }
3336 : }
3337 :
3338 274 : ret =
3339 548 : gnutls_pkcs11_obj_init(&find_data->p_list
3340 274 : [find_data->current]);
3341 274 : if (ret < 0) {
3342 0 : gnutls_assert();
3343 0 : goto fail;
3344 : }
3345 :
3346 548 : ret = pkcs11_import_object(ctx[j], class, sinfo,
3347 : tinfo, lib_info,
3348 274 : find_data->p_list[find_data->current]);
3349 274 : if (ret < 0) {
3350 0 : gnutls_assert();
3351 : /* skip the failed object */
3352 0 : continue;
3353 : }
3354 :
3355 274 : find_data->current++;
3356 : }
3357 : }
3358 :
3359 214 : 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 214 : if (find_data->overwrite_exts) {
3364 2 : for (i=start_elem;i<find_data->current;i++) {
3365 1 : if (find_data->p_list[i]->raw.size > 0) {
3366 1 : gnutls_datum_t spki;
3367 1 : rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, ctx[i], CKA_PUBLIC_KEY_INFO, &spki);
3368 1 : if (rv == CKR_OK) {
3369 1 : ret = pkcs11_override_cert_exts(sinfo, &spki, &find_data->p_list[i]->raw);
3370 1 : gnutls_free(spki.data);
3371 1 : if (ret < 0) {
3372 0 : gnutls_assert();
3373 0 : goto fail;
3374 : }
3375 : }
3376 : }
3377 : }
3378 : }
3379 214 : gnutls_free(ctx);
3380 :
3381 214 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* continue until all tokens have been checked */
3382 :
3383 0 : fail:
3384 0 : gnutls_free(ctx);
3385 0 : pkcs11_find_objects_final(sinfo);
3386 0 : if (plist.key_ids != NULL) {
3387 0 : for (i = 0; i < plist.key_ids_size; i++) {
3388 0 : _gnutls_buffer_clear(&plist.key_ids[i]);
3389 : }
3390 0 : gnutls_free(plist.key_ids);
3391 : }
3392 0 : if (find_data->p_list != NULL) {
3393 0 : for (i = 0; i < find_data->current; i++) {
3394 0 : gnutls_pkcs11_obj_deinit(find_data->p_list[i]);
3395 : }
3396 0 : gnutls_free(find_data->p_list);
3397 : }
3398 0 : find_data->p_list = NULL;
3399 0 : find_data->current = 0;
3400 :
3401 0 : 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
3438 89 : 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 89 : gnutls_pkcs11_obj_t *list1 = NULL;
3444 89 : unsigned int n_list1, i;
3445 89 : int ret;
3446 :
3447 89 : ret = gnutls_pkcs11_obj_list_import_url4(&list1, &n_list1, url, flags);
3448 89 : if (ret < 0)
3449 0 : return gnutls_assert_val(ret);
3450 :
3451 89 : if (n_list1 > *n_list) {
3452 87 : *n_list = n_list1;
3453 176 : for (i=0;i<n_list1;i++) {
3454 89 : gnutls_pkcs11_obj_deinit(list1[i]);
3455 : }
3456 87 : gnutls_free(list1);
3457 87 : return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
3458 : }
3459 :
3460 2 : *n_list = n_list1;
3461 2 : if (p_list && list1)
3462 0 : memcpy(p_list, list1, n_list1*sizeof(p_list[0]));
3463 2 : gnutls_free(list1);
3464 :
3465 2 : 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
3498 214 : 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 214 : int ret;
3504 214 : struct find_multi_obj_st priv;
3505 :
3506 253 : PKCS11_CHECK_INIT_FLAGS(flags);
3507 :
3508 214 : memset(&priv, 0, sizeof(priv));
3509 :
3510 : /* fill in the find data structure */
3511 214 : priv.flags = flags;
3512 :
3513 214 : if (url == NULL || url[0] == 0) {
3514 0 : url = "pkcs11:";
3515 : }
3516 :
3517 214 : ret = pkcs11_url_to_info(url, &priv.info, flags);
3518 214 : if (ret < 0) {
3519 0 : gnutls_assert();
3520 0 : return ret;
3521 : }
3522 :
3523 214 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT) {
3524 1 : priv.overwrite_exts = 1;
3525 : }
3526 :
3527 214 : ret =
3528 214 : _pkcs11_traverse_tokens(find_multi_objs_cb, &priv, priv.info,
3529 : NULL, pkcs11_obj_flags_to_int(flags));
3530 214 : p11_kit_uri_free(priv.info);
3531 :
3532 214 : if (ret < 0) {
3533 0 : gnutls_assert();
3534 0 : if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
3535 0 : *p_list = NULL;
3536 0 : *n_list = 0;
3537 0 : ret = 0;
3538 : }
3539 0 : return ret;
3540 : }
3541 :
3542 214 : *n_list = priv.current;
3543 214 : *p_list = priv.p_list;
3544 :
3545 214 : 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
3562 102 : gnutls_x509_crt_import_pkcs11(gnutls_x509_crt_t crt,
3563 : gnutls_pkcs11_obj_t pkcs11_crt)
3564 : {
3565 102 : 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
3585 28 : _gnutls_x509_crt_import_pkcs11_url(gnutls_x509_crt_t crt,
3586 : const char *url, unsigned int flags)
3587 : {
3588 28 : gnutls_pkcs11_obj_t pcrt;
3589 28 : int ret;
3590 :
3591 28 : ret = gnutls_pkcs11_obj_init(&pcrt);
3592 28 : if (ret < 0) {
3593 0 : gnutls_assert();
3594 0 : return ret;
3595 : }
3596 :
3597 28 : if (crt->pin.cb)
3598 11 : gnutls_pkcs11_obj_set_pin_function(pcrt, crt->pin.cb,
3599 : crt->pin.data);
3600 :
3601 28 : ret = gnutls_pkcs11_obj_import_url(pcrt, url, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_CERT);
3602 28 : if (ret < 0) {
3603 4 : gnutls_assert();
3604 4 : goto cleanup;
3605 : }
3606 :
3607 24 : ret = gnutls_x509_crt_import(crt, &pcrt->raw, GNUTLS_X509_FMT_DER);
3608 24 : if (ret < 0) {
3609 0 : gnutls_assert();
3610 0 : goto cleanup;
3611 : }
3612 :
3613 :
3614 : ret = 0;
3615 28 : cleanup:
3616 :
3617 28 : gnutls_pkcs11_obj_deinit(pcrt);
3618 28 : 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
3637 3 : 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 3 : unsigned int i, j;
3643 3 : int ret;
3644 :
3645 6 : for (i = 0; i < cert_max; i++) {
3646 3 : ret = gnutls_x509_crt_init(&certs[i]);
3647 3 : if (ret < 0) {
3648 0 : gnutls_assert();
3649 0 : goto cleanup;
3650 : }
3651 :
3652 3 : ret = gnutls_x509_crt_import_pkcs11(certs[i], objs[i]);
3653 3 : if (ret < 0) {
3654 0 : gnutls_assert();
3655 0 : goto cleanup;
3656 : }
3657 : }
3658 :
3659 : return 0;
3660 :
3661 0 : cleanup:
3662 0 : for (j = 0; j < i; j++) {
3663 0 : gnutls_x509_crt_deinit(certs[j]);
3664 : }
3665 :
3666 : return ret;
3667 : }
3668 :
3669 : static int
3670 23 : 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 23 : struct find_flags_data_st *find_data = input;
3674 :
3675 23 : if (tinfo == NULL) { /* we don't support multiple calls */
3676 0 : gnutls_assert();
3677 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3678 : }
3679 :
3680 : /* do not bother reading the token if basic fields do not match
3681 : */
3682 46 : if (!p11_kit_uri_match_token_info(find_data->info, tinfo) ||
3683 23 : !p11_kit_uri_match_module_info(find_data->info, lib_info)) {
3684 0 : gnutls_assert();
3685 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3686 : }
3687 :
3688 : /* found token! */
3689 23 : if (p11_kit_module_get_flags(sinfo->module) & P11_KIT_MODULE_TRUSTED)
3690 0 : find_data->trusted = 1;
3691 : else
3692 23 : find_data->trusted = 0;
3693 23 : find_data->slot_flags = sinfo->slot_info.flags;
3694 23 : find_data->token_flags = sinfo->tinfo.flags;
3695 :
3696 23 : 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 : **/
3712 23 : int gnutls_pkcs11_token_get_flags(const char *url, unsigned int *flags)
3713 : {
3714 23 : struct find_flags_data_st find_data;
3715 23 : int ret;
3716 :
3717 23 : PKCS11_CHECK_INIT;
3718 :
3719 23 : memset(&find_data, 0, sizeof(find_data));
3720 23 : ret = pkcs11_url_to_info(url, &find_data.info, 0);
3721 23 : if (ret < 0) {
3722 0 : gnutls_assert();
3723 0 : return ret;
3724 : }
3725 :
3726 23 : ret =
3727 23 : _pkcs11_traverse_tokens(find_flags_cb, &find_data, find_data.info,
3728 : NULL, 0);
3729 23 : p11_kit_uri_free(find_data.info);
3730 :
3731 23 : if (ret < 0) {
3732 0 : gnutls_assert();
3733 0 : return ret;
3734 : }
3735 :
3736 23 : *flags = 0;
3737 :
3738 : /* read slot flags */
3739 23 : if (find_data.slot_flags & CKF_HW_SLOT)
3740 0 : *flags |= GNUTLS_PKCS11_TOKEN_HW;
3741 :
3742 : /* read token flags */
3743 23 : if (find_data.token_flags & CKF_RNG)
3744 22 : *flags |= GNUTLS_PKCS11_TOKEN_RNG;
3745 :
3746 23 : if (find_data.token_flags & CKF_LOGIN_REQUIRED)
3747 22 : *flags |= GNUTLS_PKCS11_TOKEN_LOGIN_REQUIRED;
3748 :
3749 23 : if (find_data.token_flags & CKF_PROTECTED_AUTHENTICATION_PATH)
3750 0 : *flags |= GNUTLS_PKCS11_TOKEN_PROTECTED_AUTHENTICATION_PATH;
3751 :
3752 23 : if (find_data.token_flags & CKF_TOKEN_INITIALIZED)
3753 23 : *flags |= GNUTLS_PKCS11_TOKEN_INITIALIZED;
3754 :
3755 23 : if (find_data.token_flags & CKF_USER_PIN_COUNT_LOW)
3756 0 : *flags |= GNUTLS_PKCS11_TOKEN_USER_PIN_COUNT_LOW;
3757 :
3758 23 : if (find_data.token_flags & CKF_USER_PIN_FINAL_TRY)
3759 0 : *flags |= GNUTLS_PKCS11_TOKEN_USER_PIN_FINAL_TRY;
3760 :
3761 23 : if (find_data.token_flags & CKF_USER_PIN_LOCKED)
3762 0 : *flags |= GNUTLS_PKCS11_TOKEN_USER_PIN_LOCKED;
3763 :
3764 23 : if (find_data.token_flags & CKF_SO_PIN_COUNT_LOW)
3765 0 : *flags |= GNUTLS_PKCS11_TOKEN_SO_PIN_COUNT_LOW;
3766 :
3767 23 : if (find_data.token_flags & CKF_SO_PIN_FINAL_TRY)
3768 0 : *flags |= GNUTLS_PKCS11_TOKEN_SO_PIN_FINAL_TRY;
3769 :
3770 23 : if (find_data.token_flags & CKF_SO_PIN_LOCKED)
3771 0 : *flags |= GNUTLS_PKCS11_TOKEN_SO_PIN_LOCKED;
3772 :
3773 23 : if (find_data.token_flags & CKF_USER_PIN_INITIALIZED)
3774 22 : *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 23 : if (find_data.trusted != 0)
3783 0 : *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
3804 283 : gnutls_pkcs11_token_get_mechanism(const char *url, unsigned int idx,
3805 : unsigned long *mechanism)
3806 : {
3807 283 : int ret;
3808 283 : ck_rv_t rv;
3809 283 : struct ck_function_list *module;
3810 283 : ck_slot_id_t slot;
3811 283 : struct ck_token_info tinfo;
3812 283 : struct p11_kit_uri *info = NULL;
3813 283 : unsigned long count;
3814 283 : ck_mechanism_type_t mlist[400];
3815 :
3816 283 : PKCS11_CHECK_INIT;
3817 :
3818 283 : ret = pkcs11_url_to_info(url, &info, 0);
3819 283 : if (ret < 0) {
3820 0 : gnutls_assert();
3821 0 : return ret;
3822 : }
3823 :
3824 283 : ret = pkcs11_find_slot(&module, &slot, info, &tinfo, NULL, NULL);
3825 283 : p11_kit_uri_free(info);
3826 :
3827 283 : if (ret < 0) {
3828 0 : gnutls_assert();
3829 0 : return ret;
3830 : }
3831 :
3832 283 : count = sizeof(mlist) / sizeof(mlist[0]);
3833 283 : rv = pkcs11_get_mechanism_list(module, slot, mlist, &count);
3834 283 : if (rv != CKR_OK) {
3835 0 : gnutls_assert();
3836 0 : return pkcs11_rv_to_err(rv);
3837 : }
3838 :
3839 283 : if (idx >= count) {
3840 3 : gnutls_assert();
3841 3 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3842 : }
3843 :
3844 280 : *mechanism = mlist[idx];
3845 :
3846 280 : 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
3866 216 : gnutls_pkcs11_token_check_mechanism(const char *url,
3867 : unsigned long mechanism,
3868 : void *ptr, unsigned psize, unsigned flags)
3869 : {
3870 216 : int ret;
3871 216 : ck_rv_t rv;
3872 216 : struct ck_function_list *module;
3873 216 : ck_slot_id_t slot;
3874 216 : struct ck_token_info tinfo;
3875 216 : struct p11_kit_uri *info = NULL;
3876 216 : struct ck_mechanism_info minfo;
3877 :
3878 216 : PKCS11_CHECK_INIT;
3879 :
3880 216 : ret = pkcs11_url_to_info(url, &info, 0);
3881 216 : if (ret < 0) {
3882 0 : gnutls_assert();
3883 0 : return ret;
3884 : }
3885 :
3886 216 : ret = pkcs11_find_slot(&module, &slot, info, &tinfo, NULL, NULL);
3887 216 : p11_kit_uri_free(info);
3888 :
3889 216 : if (ret < 0) {
3890 0 : gnutls_assert();
3891 0 : return ret;
3892 : }
3893 :
3894 216 : rv = pkcs11_get_mechanism_info(module, slot, mechanism, &minfo);
3895 216 : if (rv != CKR_OK) {
3896 12 : gnutls_assert();
3897 12 : return 0;
3898 : }
3899 :
3900 204 : if (ptr) {
3901 140 : if (sizeof(minfo) > psize)
3902 0 : return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
3903 140 : else if (sizeof(minfo) < psize)
3904 0 : memset(ptr, 0, psize);
3905 140 : 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 : **/
3924 24 : const char *gnutls_pkcs11_type_get_name(gnutls_pkcs11_obj_type_t type)
3925 : {
3926 24 : switch (type) {
3927 : case GNUTLS_PKCS11_OBJ_X509_CRT:
3928 : return "X.509 Certificate";
3929 9 : case GNUTLS_PKCS11_OBJ_PUBKEY:
3930 9 : return "Public key";
3931 8 : case GNUTLS_PKCS11_OBJ_PRIVKEY:
3932 8 : return "Private key";
3933 0 : case GNUTLS_PKCS11_OBJ_SECRET_KEY:
3934 0 : return "Secret key";
3935 0 : case GNUTLS_PKCS11_OBJ_DATA:
3936 0 : return "Data";
3937 0 : case GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION:
3938 0 : return "X.509 certificate extension";
3939 0 : case GNUTLS_PKCS11_OBJ_UNKNOWN:
3940 : default:
3941 0 : return "Unknown";
3942 : }
3943 : }
3944 :
3945 : static
3946 139 : 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 139 : gnutls_x509_crt_t tcrt = NULL;
3953 139 : unsigned has_ski;
3954 139 : int ret;
3955 :
3956 139 : ret = gnutls_x509_crt_init(&tcrt);
3957 139 : if (ret < 0) {
3958 0 : gnutls_assert();
3959 0 : return ret;
3960 : }
3961 :
3962 139 : ret = gnutls_x509_crt_import(tcrt, data, GNUTLS_X509_FMT_DER);
3963 139 : if (ret < 0) {
3964 0 : gnutls_assert();
3965 0 : goto cleanup;
3966 : }
3967 :
3968 139 : if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE) {
3969 29 : if (priv->crt == NULL) {
3970 0 : gnutls_assert();
3971 0 : ret = -1;
3972 0 : goto cleanup;
3973 : }
3974 :
3975 29 : if (gnutls_x509_crt_equals(priv->crt, tcrt) == 0) {
3976 : /* doesn't match */
3977 21 : _gnutls_debug_log("check_found_cert: cert doesn't match the expected\n");
3978 21 : ret = -1;
3979 21 : goto cleanup;
3980 : }
3981 : }
3982 :
3983 118 : if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY) {
3984 8 : if (priv->crt == NULL) {
3985 0 : gnutls_assert();
3986 0 : ret = -1;
3987 0 : goto cleanup;
3988 : }
3989 :
3990 8 : if (_gnutls_check_if_same_key(priv->crt, tcrt, 1) == 0) {
3991 : /* doesn't match */
3992 1 : _gnutls_debug_log("check_found_cert: cert key doesn't match the expected key\n");
3993 1 : ret = -1;
3994 1 : goto cleanup;
3995 : }
3996 : }
3997 :
3998 181 : if (priv->key_id.size > 0 &&
3999 64 : !_gnutls_check_valid_key_id(&priv->key_id, tcrt, now, &has_ski)) {
4000 1 : gnutls_assert();
4001 1 : if (has_ski) {
4002 0 : _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 1 : *cand_ctx = ctx;
4008 : }
4009 1 : goto cleanup;
4010 : }
4011 :
4012 : ret = 0;
4013 139 : cleanup:
4014 139 : if (tcrt != NULL)
4015 139 : gnutls_x509_crt_deinit(tcrt);
4016 : return ret;
4017 : }
4018 :
4019 139 : 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 139 : ck_rv_t rv;
4026 139 : struct ck_attribute a[2];
4027 :
4028 : /* data will contain the certificate */
4029 139 : rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, object, CKA_VALUE, data);
4030 139 : if (rv == CKR_OK) {
4031 139 : a[0].type = CKA_LABEL;
4032 139 : a[0].value = label;
4033 139 : a[0].value_len = label_size;
4034 :
4035 139 : a[1].type = CKA_ID;
4036 139 : a[1].value = id;
4037 139 : a[1].value_len = id_size;
4038 :
4039 139 : if (pkcs11_get_attribute_value(sinfo->module, sinfo->pks, object, a,
4040 : 2) == CKR_OK) {
4041 139 : o_label->data = a[0].value;
4042 139 : o_label->size = a[0].value_len;
4043 139 : o_id->data = a[1].value;
4044 139 : o_id->size = a[1].value_len;
4045 :
4046 139 : return 0;
4047 : } else {
4048 0 : _gnutls_free_datum(data);
4049 0 : _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
4058 1673 : 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 1673 : struct ck_attribute a[10];
4062 1673 : ck_object_class_t class = -1;
4063 1673 : ck_certificate_type_t type = (ck_certificate_type_t) - 1;
4064 1673 : ck_rv_t rv;
4065 1673 : ck_object_handle_t ctx, cand_ctx = CK_INVALID_HANDLE;
4066 1673 : unsigned long count, a_vals;
4067 1673 : int found = 0, ret;
4068 1673 : struct find_cert_st *priv = input;
4069 1673 : char label_tmp[PKCS11_LABEL_SIZE];
4070 1673 : uint8_t id_tmp[PKCS11_ID_SIZE];
4071 1673 : gnutls_datum_t data = {NULL, 0};
4072 1673 : unsigned finalized;
4073 1673 : int i, tries;
4074 1673 : ck_bool_t trusted = 1;
4075 1673 : time_t now;
4076 1673 : gnutls_datum_t label = {NULL,0}, id = {NULL,0};
4077 :
4078 1673 : if (tinfo == NULL) {
4079 778 : gnutls_assert();
4080 778 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
4081 : }
4082 :
4083 : /* the DISTRUSTED flag is p11-kit module specific */
4084 895 : if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) {
4085 456 : if (memcmp(lib_info->manufacturer_id, "PKCS#11 Kit", 11) != 0) {
4086 456 : gnutls_assert();
4087 456 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
4088 : }
4089 : }
4090 :
4091 439 : if (priv->dn.size == 0 && priv->key_id.size == 0 && priv->issuer_dn.size == 0 &&
4092 0 : priv->serial.size == 0)
4093 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
4094 :
4095 : /* Find objects with given class and type */
4096 :
4097 439 : if (priv->key_id.size > 0 && priv->dn.size > 0)
4098 : tries = 2;
4099 : else
4100 371 : tries = 1;
4101 :
4102 439 : now = gnutls_time(0);
4103 1205 : for (i = 0; i < tries; i++) {
4104 :
4105 444 : a_vals = 0;
4106 444 : class = CKO_CERTIFICATE;
4107 444 : a[a_vals].type = CKA_CLASS;
4108 444 : a[a_vals].value = &class;
4109 444 : a[a_vals].value_len = sizeof class;
4110 444 : a_vals++;
4111 :
4112 444 : if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED) {
4113 425 : a[a_vals].type = CKA_TRUSTED;
4114 425 : a[a_vals].value = &trusted;
4115 425 : a[a_vals].value_len = sizeof trusted;
4116 425 : a_vals++;
4117 : }
4118 :
4119 444 : if (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) {
4120 0 : if (!sinfo->trusted) /* only p11-kit "trusted" modules support this flag */
4121 0 : return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
4122 :
4123 0 : a[a_vals].type = CKA_X_DISTRUSTED;
4124 0 : a[a_vals].value = &trusted;
4125 0 : a[a_vals].value_len = sizeof trusted;
4126 0 : a_vals++;
4127 : }
4128 :
4129 444 : if (priv->need_import != 0) {
4130 424 : type = CKC_X_509;
4131 424 : a[a_vals].type = CKA_CERTIFICATE_TYPE;
4132 424 : a[a_vals].value = &type;
4133 424 : a[a_vals].value_len = sizeof type;
4134 424 : a_vals++;
4135 : }
4136 :
4137 444 : if (i == 0 && priv->key_id.size > 0) {
4138 68 : a[a_vals].type = CKA_ID;
4139 68 : a[a_vals].value = priv->key_id.data;
4140 68 : a[a_vals].value_len = priv->key_id.size;
4141 68 : a_vals++;
4142 : }
4143 :
4144 : /* This doesn't do a proper comparison, see
4145 : * _gnutls_x509_compare_raw_dn() */
4146 444 : if (priv->dn.size > 0) {
4147 274 : a[a_vals].type = CKA_SUBJECT;
4148 274 : a[a_vals].value = priv->dn.data;
4149 274 : a[a_vals].value_len = priv->dn.size;
4150 274 : a_vals++;
4151 : }
4152 :
4153 444 : if (priv->serial.size > 0) {
4154 170 : a[a_vals].type = CKA_SERIAL_NUMBER;
4155 170 : a[a_vals].value = priv->serial.data;
4156 170 : a[a_vals].value_len = priv->serial.size;
4157 170 : a_vals++;
4158 : }
4159 :
4160 : /* Same problem as for priv->dn */
4161 444 : if (priv->issuer_dn.size > 0) {
4162 170 : a[a_vals].type = CKA_ISSUER;
4163 170 : a[a_vals].value = priv->issuer_dn.data;
4164 170 : a[a_vals].value_len = priv->issuer_dn.size;
4165 170 : a_vals++;
4166 : }
4167 :
4168 444 : finalized = 0;
4169 444 : rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
4170 : a_vals);
4171 444 : if (rv != CKR_OK) {
4172 0 : gnutls_assert();
4173 0 : _gnutls_debug_log
4174 : ("p11: FindObjectsInit failed.\n");
4175 0 : ret = pkcs11_rv_to_err(rv);
4176 0 : goto cleanup;
4177 : }
4178 :
4179 466 : while (pkcs11_find_objects
4180 : (sinfo->module, sinfo->pks, &ctx, 1,
4181 466 : &count) == CKR_OK && count == 1) {
4182 :
4183 139 : if (priv->need_import == 0 && !(priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE)
4184 26 : && !(priv->flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY)) {
4185 : found = 1;
4186 : break;
4187 : }
4188 :
4189 139 : 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 139 : if (ret < 0)
4195 0 : continue;
4196 :
4197 139 : ret = check_found_cert(priv, ctx, &data, now, &cand_ctx);
4198 139 : if (ret < 0) {
4199 22 : _gnutls_free_datum(&data);
4200 22 : continue;
4201 : }
4202 :
4203 : found = 1;
4204 : break;
4205 : }
4206 :
4207 444 : if (!found && cand_ctx != CK_INVALID_HANDLE) {
4208 : /* there was a possible match; let's retrieve that one instead of
4209 : * failing */
4210 0 : 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 0 : if (ret >= 0)
4216 0 : 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 444 : pkcs11_find_objects_final(sinfo);
4224 444 : finalized = 1;
4225 :
4226 444 : if (found != 0) {
4227 117 : if (!(priv->flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) &&
4228 79 : (priv->flags & GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT) && data.size > 0) {
4229 79 : gnutls_datum_t spki;
4230 79 : rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, ctx, CKA_PUBLIC_KEY_INFO, &spki);
4231 79 : if (rv == CKR_OK) {
4232 79 : ret = pkcs11_override_cert_exts(sinfo, &spki, &data);
4233 79 : gnutls_free(spki.data);
4234 79 : if (ret < 0) {
4235 0 : gnutls_assert();
4236 0 : goto cleanup;
4237 : }
4238 : }
4239 : }
4240 :
4241 117 : if (priv->need_import != 0) {
4242 112 : ret =
4243 112 : pkcs11_obj_import(class, priv->obj,
4244 : &data, &id, &label,
4245 : tinfo,
4246 : lib_info);
4247 112 : if (ret < 0) {
4248 0 : gnutls_assert();
4249 0 : goto cleanup;
4250 : }
4251 : }
4252 : break;
4253 : }
4254 : }
4255 :
4256 439 : if (found == 0) {
4257 322 : gnutls_assert();
4258 : ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
4259 : } else {
4260 : ret = 0;
4261 : }
4262 :
4263 439 : cleanup:
4264 439 : gnutls_free(data.data);
4265 439 : if (finalized == 0)
4266 0 : 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 : **/
4289 105 : 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 105 : int ret;
4295 105 : struct find_cert_st priv;
4296 105 : uint8_t id[PKCS11_ID_SIZE];
4297 105 : size_t id_size;
4298 105 : struct p11_kit_uri *info = NULL;
4299 :
4300 126 : PKCS11_CHECK_INIT_FLAGS(flags);
4301 :
4302 105 : memset(&priv, 0, sizeof(priv));
4303 :
4304 105 : if (url == NULL || url[0] == 0) {
4305 0 : url = "pkcs11:";
4306 : }
4307 :
4308 105 : ret = pkcs11_url_to_info(url, &info, flags);
4309 105 : if (ret < 0) {
4310 0 : gnutls_assert();
4311 0 : return ret;
4312 : }
4313 :
4314 105 : id_size = sizeof(id);
4315 105 : ret =
4316 105 : gnutls_x509_crt_get_authority_key_id(cert, id, &id_size, NULL);
4317 105 : if (ret >= 0) {
4318 66 : priv.key_id.data = id;
4319 66 : priv.key_id.size = id_size;
4320 : }
4321 :
4322 105 : priv.dn.data = cert->raw_issuer_dn.data;
4323 105 : priv.dn.size = cert->raw_issuer_dn.size;
4324 :
4325 105 : if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY))
4326 90 : flags |= GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED;
4327 :
4328 105 : priv.flags = flags;
4329 :
4330 105 : ret = gnutls_pkcs11_obj_init(&priv.obj);
4331 105 : if (ret < 0) {
4332 0 : gnutls_assert();
4333 0 : goto cleanup;
4334 : }
4335 :
4336 105 : gnutls_pkcs11_obj_set_pin_function(priv.obj, cert->pin.cb, cert->pin.data);
4337 :
4338 105 : priv.need_import = 1;
4339 :
4340 105 : ret =
4341 105 : _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
4342 : &cert->pin, pkcs11_obj_flags_to_int(flags));
4343 105 : 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 4 : priv.flags |= GNUTLS_PKCS11_OBJ_FLAG_FIRST_CLOSE_MATCH;
4347 4 : ret =
4348 4 : _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
4349 : &cert->pin, pkcs11_obj_flags_to_int(flags));
4350 : }
4351 :
4352 105 : if (ret < 0) {
4353 4 : gnutls_assert();
4354 4 : goto cleanup;
4355 : }
4356 :
4357 101 : ret = gnutls_pkcs11_obj_export3(priv.obj, fmt, issuer);
4358 101 : if (ret < 0) {
4359 0 : gnutls_assert();
4360 0 : goto cleanup;
4361 : }
4362 :
4363 : ret = 0;
4364 :
4365 105 : cleanup:
4366 105 : if (priv.obj)
4367 105 : gnutls_pkcs11_obj_deinit(priv.obj);
4368 105 : if (info)
4369 105 : 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 : **/
4395 1 : 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 1 : int ret;
4401 1 : struct find_cert_st priv;
4402 1 : struct p11_kit_uri *info = NULL;
4403 :
4404 1 : PKCS11_CHECK_INIT_FLAGS(flags);
4405 :
4406 1 : memset(&priv, 0, sizeof(priv));
4407 :
4408 1 : if (url == NULL || url[0] == 0) {
4409 0 : url = "pkcs11:";
4410 : }
4411 :
4412 1 : ret = pkcs11_url_to_info(url, &info, flags);
4413 1 : if (ret < 0) {
4414 0 : gnutls_assert();
4415 0 : return ret;
4416 : }
4417 :
4418 1 : priv.dn.data = dn->data;
4419 1 : priv.dn.size = dn->size;
4420 :
4421 1 : if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY))
4422 1 : flags |= GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED;
4423 :
4424 1 : priv.flags = flags;
4425 :
4426 1 : ret = gnutls_pkcs11_obj_init(&priv.obj);
4427 1 : if (ret < 0) {
4428 0 : gnutls_assert();
4429 0 : goto cleanup;
4430 : }
4431 1 : priv.need_import = 1;
4432 :
4433 1 : ret =
4434 1 : _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
4435 : NULL, pkcs11_obj_flags_to_int(flags));
4436 1 : if (ret < 0) {
4437 0 : gnutls_assert();
4438 0 : goto cleanup;
4439 : }
4440 :
4441 1 : ret = gnutls_pkcs11_obj_export3(priv.obj, fmt, issuer);
4442 1 : if (ret < 0) {
4443 0 : gnutls_assert();
4444 0 : goto cleanup;
4445 : }
4446 :
4447 : ret = 0;
4448 :
4449 1 : cleanup:
4450 1 : if (priv.obj)
4451 1 : gnutls_pkcs11_obj_deinit(priv.obj);
4452 1 : if (info)
4453 1 : 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 : **/
4480 0 : 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 0 : int ret;
4488 0 : struct find_cert_st priv;
4489 0 : struct p11_kit_uri *info = NULL;
4490 :
4491 0 : PKCS11_CHECK_INIT_FLAGS(flags);
4492 :
4493 0 : memset(&priv, 0, sizeof(priv));
4494 :
4495 0 : if (url == NULL || url[0] == 0) {
4496 0 : url = "pkcs11:";
4497 : }
4498 :
4499 0 : ret = pkcs11_url_to_info(url, &info, flags);
4500 0 : if (ret < 0) {
4501 0 : gnutls_assert();
4502 0 : return ret;
4503 : }
4504 :
4505 0 : if (dn) {
4506 0 : priv.dn.data = dn->data;
4507 0 : priv.dn.size = dn->size;
4508 : }
4509 :
4510 0 : priv.key_id.data = spki->data;
4511 0 : priv.key_id.size = spki->size;
4512 :
4513 0 : if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY))
4514 0 : flags |= GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED;
4515 :
4516 0 : priv.flags = flags;
4517 :
4518 0 : ret = gnutls_pkcs11_obj_init(&priv.obj);
4519 0 : if (ret < 0) {
4520 0 : gnutls_assert();
4521 0 : goto cleanup;
4522 : }
4523 0 : priv.need_import = 1;
4524 :
4525 0 : ret =
4526 0 : _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
4527 : NULL, pkcs11_obj_flags_to_int(flags));
4528 0 : if (ret < 0) {
4529 0 : gnutls_assert();
4530 0 : goto cleanup;
4531 : }
4532 :
4533 0 : ret = gnutls_pkcs11_obj_export3(priv.obj, fmt, issuer);
4534 0 : if (ret < 0) {
4535 0 : gnutls_assert();
4536 0 : goto cleanup;
4537 : }
4538 :
4539 : ret = 0;
4540 :
4541 0 : cleanup:
4542 0 : if (priv.obj)
4543 0 : gnutls_pkcs11_obj_deinit(priv.obj);
4544 0 : if (info)
4545 0 : p11_kit_uri_free(info);
4546 :
4547 : return ret;
4548 : }
4549 :
4550 : unsigned
4551 398 : _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 398 : int ret;
4556 398 : struct find_cert_st priv;
4557 398 : uint8_t serial[128];
4558 398 : size_t serial_size;
4559 398 : struct p11_kit_uri *info = NULL;
4560 :
4561 410 : PKCS11_CHECK_INIT_FLAGS_RET(flags, 0);
4562 :
4563 398 : memset(&priv, 0, sizeof(priv));
4564 :
4565 398 : if (trusted_cert) {
4566 158 : ret = gnutls_pkcs11_obj_init(&priv.obj);
4567 158 : if (ret < 0) {
4568 0 : gnutls_assert();
4569 0 : goto cleanup;
4570 : }
4571 158 : priv.need_import = 1;
4572 : }
4573 :
4574 398 : if (url == NULL || url[0] == 0) {
4575 0 : url = "pkcs11:";
4576 : }
4577 :
4578 398 : ret = pkcs11_url_to_info(url, &info, 0);
4579 398 : if (ret < 0) {
4580 0 : gnutls_assert();
4581 0 : return 0;
4582 : }
4583 :
4584 : /* Attempt searching using the issuer DN + serial number */
4585 398 : serial_size = sizeof(serial);
4586 398 : ret =
4587 398 : gnutls_x509_crt_get_serial(cert, serial, &serial_size);
4588 398 : if (ret < 0) {
4589 0 : gnutls_assert();
4590 0 : ret = 0;
4591 0 : goto cleanup;
4592 : }
4593 :
4594 398 : ret = _gnutls_x509_ext_gen_number(serial, serial_size, &priv.serial);
4595 398 : if (ret < 0) {
4596 0 : gnutls_assert();
4597 0 : ret = 0;
4598 0 : goto cleanup;
4599 : }
4600 :
4601 398 : priv.crt = cert;
4602 :
4603 398 : priv.issuer_dn.data = cert->raw_issuer_dn.data;
4604 398 : priv.issuer_dn.size = cert->raw_issuer_dn.size;
4605 :
4606 : /* assume PKCS11_OBJ_FLAG_COMPARE everywhere but DISTRUST info */
4607 398 : if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) && !(flags & GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY)) {
4608 92 : flags |= GNUTLS_PKCS11_OBJ_FLAG_COMPARE;
4609 : }
4610 :
4611 398 : priv.flags = flags;
4612 :
4613 398 : ret =
4614 398 : _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
4615 : NULL, pkcs11_obj_flags_to_int(flags));
4616 398 : if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
4617 387 : _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 387 : gnutls_assert();
4620 387 : if (priv.obj)
4621 151 : gnutls_pkcs11_obj_deinit(priv.obj);
4622 387 : gnutls_free(priv.serial.data);
4623 387 : memset(&priv, 0, sizeof(priv));
4624 387 : if (trusted_cert) {
4625 151 : ret = gnutls_pkcs11_obj_init(&priv.obj);
4626 151 : if (ret < 0) {
4627 0 : gnutls_assert();
4628 0 : goto cleanup;
4629 : }
4630 151 : priv.need_import = 1;
4631 : }
4632 387 : priv.crt = cert;
4633 387 : priv.flags = flags;
4634 :
4635 387 : priv.dn.data = cert->raw_dn.data;
4636 387 : priv.dn.size = cert->raw_dn.size;
4637 387 : ret =
4638 387 : _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
4639 : NULL, pkcs11_obj_flags_to_int(flags));
4640 : }
4641 398 : if (ret < 0) {
4642 383 : gnutls_assert();
4643 383 : _gnutls_debug_log("crt_is_known: did not find any cert\n");
4644 383 : ret = 0;
4645 383 : goto cleanup;
4646 : }
4647 :
4648 15 : if (trusted_cert) {
4649 10 : ret = gnutls_x509_crt_init(trusted_cert);
4650 10 : if (ret < 0) {
4651 0 : gnutls_assert();
4652 0 : ret = 0;
4653 0 : goto cleanup;
4654 : }
4655 10 : ret = gnutls_x509_crt_import_pkcs11(*trusted_cert, priv.obj);
4656 10 : if (ret < 0) {
4657 0 : gnutls_assert();
4658 0 : gnutls_x509_crt_deinit(*trusted_cert);
4659 0 : ret = 0;
4660 0 : goto cleanup;
4661 : }
4662 : }
4663 : ret = 1;
4664 :
4665 398 : cleanup:
4666 398 : if (priv.obj)
4667 158 : gnutls_pkcs11_obj_deinit(priv.obj);
4668 398 : if (info)
4669 398 : p11_kit_uri_free(info);
4670 398 : gnutls_free(priv.serial.data);
4671 :
4672 398 : 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 : **/
4699 240 : unsigned gnutls_pkcs11_crt_is_known(const char *url, gnutls_x509_crt_t cert,
4700 : unsigned int flags)
4701 : {
4702 240 : 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
4720 27 : gnutls_pkcs11_obj_get_flags(gnutls_pkcs11_obj_t obj, unsigned int *oflags)
4721 : {
4722 27 : *oflags = obj->flags;
4723 :
4724 27 : 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 : **/
4739 24 : char *gnutls_pkcs11_obj_flags_get_str(unsigned int flags)
4740 : {
4741 24 : gnutls_buffer_st str;
4742 24 : gnutls_datum_t out;
4743 24 : int ret;
4744 :
4745 24 : if (flags == 0)
4746 : return NULL;
4747 :
4748 19 : _gnutls_buffer_init(&str);
4749 19 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP)
4750 17 : _gnutls_buffer_append_str(&str, "CKA_WRAP/UNWRAP; ");
4751 :
4752 19 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA)
4753 2 : _gnutls_buffer_append_str(&str, "CKA_CERTIFICATE_CATEGORY=CA; ");
4754 :
4755 19 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE)
4756 8 : _gnutls_buffer_append_str(&str, "CKA_PRIVATE; ");
4757 :
4758 19 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH)
4759 0 : _gnutls_buffer_append_str(&str, "CKA_ALWAYS_AUTH; ");
4760 :
4761 19 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED)
4762 1 : _gnutls_buffer_append_str(&str, "CKA_TRUSTED; ");
4763 :
4764 19 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_DISTRUSTED)
4765 0 : _gnutls_buffer_append_str(&str, "CKA_X_DISTRUSTED; ");
4766 :
4767 19 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_EXTRACTABLE)
4768 0 : _gnutls_buffer_append_str(&str, "CKA_EXTRACTABLE; ");
4769 :
4770 19 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_NEVER_EXTRACTABLE)
4771 4 : _gnutls_buffer_append_str(&str, "CKA_NEVER_EXTRACTABLE; ");
4772 :
4773 19 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
4774 8 : _gnutls_buffer_append_str(&str, "CKA_SENSITIVE; ");
4775 :
4776 19 : ret = _gnutls_buffer_to_datum(&str, &out, 1);
4777 19 : if (ret < 0) {
4778 0 : gnutls_assert();
4779 0 : goto fail;
4780 : }
4781 :
4782 19 : return (char*)out.data;
4783 0 : fail:
4784 0 : return NULL;
4785 :
4786 : }
|