gmp: Support of SHA-3 RSA signatures
[strongswan.git] / src / libstrongswan / plugins / pkcs11 / pkcs11_private_key.c
1 /*
2 * Copyright (C) 2011-2015 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2010 Martin Willi
6 * Copyright (C) 2010 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include "pkcs11_private_key.h"
20
21 #include "pkcs11_library.h"
22 #include "pkcs11_manager.h"
23 #include "pkcs11_public_key.h"
24
25 #include <utils/debug.h>
26 #include <asn1/asn1.h>
27
28 typedef struct private_pkcs11_private_key_t private_pkcs11_private_key_t;
29
30 /**
31 * Private data of an pkcs11_private_key_t object.
32 */
33 struct private_pkcs11_private_key_t {
34
35 /**
36 * Public pkcs11_private_key_t interface.
37 */
38 pkcs11_private_key_t public;
39
40 /**
41 * PKCS#11 module
42 */
43 pkcs11_library_t *lib;
44
45 /**
46 * Slot the token is in
47 */
48 CK_SLOT_ID slot;
49
50 /**
51 * Token session
52 */
53 CK_SESSION_HANDLE session;
54
55 /**
56 * Key object on the token
57 */
58 CK_OBJECT_HANDLE object;
59
60 /**
61 * Key requires reauthentication for each signature/decryption
62 */
63 CK_BBOOL reauth;
64
65 /**
66 * Keyid of the key we use
67 */
68 identification_t *keyid;
69
70 /**
71 * Associated public key
72 */
73 public_key_t *pubkey;
74
75 /**
76 * References to this key
77 */
78 refcount_t ref;
79
80 /**
81 * Type of this private key
82 */
83 key_type_t type;
84 };
85
86
87 METHOD(private_key_t, get_type, key_type_t,
88 private_pkcs11_private_key_t *this)
89 {
90 return this->type;
91 }
92
93 METHOD(private_key_t, get_keysize, int,
94 private_pkcs11_private_key_t *this)
95 {
96 return this->pubkey->get_keysize(this->pubkey);
97 }
98
99 /**
100 * See header.
101 */
102 CK_MECHANISM_PTR pkcs11_signature_scheme_to_mech(signature_scheme_t scheme,
103 key_type_t type, size_t keylen,
104 hash_algorithm_t *hash)
105 {
106 static struct {
107 signature_scheme_t scheme;
108 CK_MECHANISM mechanism;
109 key_type_t type;
110 size_t keylen;
111 hash_algorithm_t hash;
112 } mappings[] = {
113 {SIGN_RSA_EMSA_PKCS1_NULL, {CKM_RSA_PKCS, NULL, 0},
114 KEY_RSA, 0, HASH_UNKNOWN},
115 {SIGN_RSA_EMSA_PKCS1_SHA2_256, {CKM_SHA256_RSA_PKCS, NULL, 0},
116 KEY_RSA, 0, HASH_UNKNOWN},
117 {SIGN_RSA_EMSA_PKCS1_SHA2_384, {CKM_SHA384_RSA_PKCS, NULL, 0},
118 KEY_RSA, 0, HASH_UNKNOWN},
119 {SIGN_RSA_EMSA_PKCS1_SHA2_512, {CKM_SHA512_RSA_PKCS, NULL, 0},
120 KEY_RSA, 0, HASH_UNKNOWN},
121 {SIGN_RSA_EMSA_PKCS1_SHA1, {CKM_SHA1_RSA_PKCS, NULL, 0},
122 KEY_RSA, 0, HASH_UNKNOWN},
123 {SIGN_RSA_EMSA_PKCS1_MD5, {CKM_MD5_RSA_PKCS, NULL, 0},
124 KEY_RSA, 0, HASH_UNKNOWN},
125 {SIGN_ECDSA_WITH_NULL, {CKM_ECDSA, NULL, 0},
126 KEY_ECDSA, 0, HASH_UNKNOWN},
127 {SIGN_ECDSA_WITH_SHA1_DER, {CKM_ECDSA_SHA1, NULL, 0},
128 KEY_ECDSA, 0, HASH_UNKNOWN},
129 {SIGN_ECDSA_WITH_SHA256_DER, {CKM_ECDSA, NULL, 0},
130 KEY_ECDSA, 0, HASH_SHA256},
131 {SIGN_ECDSA_WITH_SHA384_DER, {CKM_ECDSA, NULL, 0},
132 KEY_ECDSA, 0, HASH_SHA384},
133 {SIGN_ECDSA_WITH_SHA512_DER, {CKM_ECDSA, NULL, 0},
134 KEY_ECDSA, 0, HASH_SHA512},
135 {SIGN_ECDSA_256, {CKM_ECDSA, NULL, 0},
136 KEY_ECDSA, 256, HASH_SHA256},
137 {SIGN_ECDSA_384, {CKM_ECDSA, NULL, 0},
138 KEY_ECDSA, 384, HASH_SHA384},
139 {SIGN_ECDSA_521, {CKM_ECDSA, NULL, 0},
140 KEY_ECDSA, 521, HASH_SHA512},
141 };
142 int i;
143
144 for (i = 0; i < countof(mappings); i++)
145 {
146 if (mappings[i].scheme == scheme)
147 {
148 size_t len = mappings[i].keylen;
149 if (mappings[i].type != type || (len && keylen != len))
150 {
151 return NULL;
152 }
153 if (hash)
154 {
155 *hash = mappings[i].hash;
156 }
157 return &mappings[i].mechanism;
158 }
159 }
160 return NULL;
161 }
162
163 /**
164 * See header.
165 */
166 CK_MECHANISM_PTR pkcs11_encryption_scheme_to_mech(encryption_scheme_t scheme)
167 {
168 static struct {
169 encryption_scheme_t scheme;
170 CK_MECHANISM mechanism;
171 } mappings[] = {
172 {ENCRYPT_RSA_PKCS1, {CKM_RSA_PKCS, NULL, 0}},
173 {ENCRYPT_RSA_OAEP_SHA1, {CKM_RSA_PKCS_OAEP, NULL, 0}},
174 };
175 int i;
176
177 for (i = 0; i < countof(mappings); i++)
178 {
179 if (mappings[i].scheme == scheme)
180 {
181 return &mappings[i].mechanism;
182 }
183 }
184 return NULL;
185 }
186
187 /**
188 * Reauthenticate to do a signature
189 */
190 static bool reauth(private_pkcs11_private_key_t *this,
191 CK_SESSION_HANDLE session)
192 {
193 enumerator_t *enumerator;
194 shared_key_t *shared;
195 chunk_t pin;
196 CK_RV rv;
197 bool found = FALSE, success = FALSE;
198
199 enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
200 SHARED_PIN, this->keyid, NULL);
201 while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
202 {
203 found = TRUE;
204 pin = shared->get_key(shared);
205 rv = this->lib->f->C_Login(session, CKU_CONTEXT_SPECIFIC,
206 pin.ptr, pin.len);
207 if (rv == CKR_OK)
208 {
209 success = TRUE;
210 break;
211 }
212 DBG1(DBG_CFG, "reauthentication login failed: %N", ck_rv_names, rv);
213 }
214 enumerator->destroy(enumerator);
215
216 if (!found)
217 {
218 DBG1(DBG_CFG, "private key requires reauthentication, but no PIN found");
219 return FALSE;
220 }
221 return success;
222 }
223
224 METHOD(private_key_t, sign, bool,
225 private_pkcs11_private_key_t *this, signature_scheme_t scheme,
226 chunk_t data, chunk_t *signature)
227 {
228 CK_MECHANISM_PTR mechanism;
229 CK_SESSION_HANDLE session;
230 CK_BYTE_PTR buf;
231 CK_ULONG len;
232 CK_RV rv;
233 hash_algorithm_t hash_alg;
234 chunk_t hash = chunk_empty;
235
236 mechanism = pkcs11_signature_scheme_to_mech(scheme, this->type,
237 get_keysize(this), &hash_alg);
238 if (!mechanism)
239 {
240 DBG1(DBG_LIB, "signature scheme %N not supported",
241 signature_scheme_names, scheme);
242 return FALSE;
243 }
244 rv = this->lib->f->C_OpenSession(this->slot, CKF_SERIAL_SESSION, NULL, NULL,
245 &session);
246 if (rv != CKR_OK)
247 {
248 DBG1(DBG_CFG, "opening PKCS#11 session failed: %N", ck_rv_names, rv);
249 return FALSE;
250 }
251 rv = this->lib->f->C_SignInit(session, mechanism, this->object);
252 if (this->reauth && !reauth(this, session))
253 {
254 this->lib->f->C_CloseSession(session);
255 return FALSE;
256 }
257 if (rv != CKR_OK)
258 {
259 this->lib->f->C_CloseSession(session);
260 DBG1(DBG_LIB, "C_SignInit() failed: %N", ck_rv_names, rv);
261 return FALSE;
262 }
263 if (hash_alg != HASH_UNKNOWN)
264 {
265 hasher_t *hasher;
266
267 hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
268 if (!hasher || !hasher->allocate_hash(hasher, data, &hash))
269 {
270 DESTROY_IF(hasher);
271 this->lib->f->C_CloseSession(session);
272 return FALSE;
273 }
274 hasher->destroy(hasher);
275 data = hash;
276 }
277 len = (get_keysize(this) + 7) / 8;
278 if (this->type == KEY_ECDSA)
279 { /* signature is twice the length of the base point order */
280 len *= 2;
281 }
282 buf = malloc(len);
283 rv = this->lib->f->C_Sign(session, data.ptr, data.len, buf, &len);
284 this->lib->f->C_CloseSession(session);
285 chunk_free(&hash);
286 if (rv != CKR_OK)
287 {
288 DBG1(DBG_LIB, "C_Sign() failed: %N", ck_rv_names, rv);
289 free(buf);
290 return FALSE;
291 }
292 switch (scheme)
293 {
294 case SIGN_ECDSA_WITH_SHA1_DER:
295 case SIGN_ECDSA_WITH_SHA256_DER:
296 case SIGN_ECDSA_WITH_SHA384_DER:
297 case SIGN_ECDSA_WITH_SHA512_DER:
298 {
299 chunk_t r, s;
300
301 /* return an ASN.1 encoded sequence of integers r and s, removing
302 * any zero-padding */
303 len /= 2;
304 r = chunk_skip_zero(chunk_create(buf, len));
305 s = chunk_skip_zero(chunk_create(buf+len, len));
306 *signature = asn1_wrap(ASN1_SEQUENCE, "mm",
307 asn1_integer("c", r), asn1_integer("c", s));
308 free(buf);
309 break;
310 }
311 default:
312 *signature = chunk_create(buf, len);
313 break;
314 }
315 return TRUE;
316 }
317
318 METHOD(private_key_t, decrypt, bool,
319 private_pkcs11_private_key_t *this, encryption_scheme_t scheme,
320 chunk_t crypt, chunk_t *plain)
321 {
322 CK_MECHANISM_PTR mechanism;
323 CK_SESSION_HANDLE session;
324 CK_BYTE_PTR buf;
325 CK_ULONG len;
326 CK_RV rv;
327
328 mechanism = pkcs11_encryption_scheme_to_mech(scheme);
329 if (!mechanism)
330 {
331 DBG1(DBG_LIB, "encryption scheme %N not supported",
332 encryption_scheme_names, scheme);
333 return FALSE;
334 }
335 rv = this->lib->f->C_OpenSession(this->slot, CKF_SERIAL_SESSION, NULL, NULL,
336 &session);
337 if (rv != CKR_OK)
338 {
339 DBG1(DBG_CFG, "opening PKCS#11 session failed: %N", ck_rv_names, rv);
340 return FALSE;
341 }
342 rv = this->lib->f->C_DecryptInit(session, mechanism, this->object);
343 if (this->reauth && !reauth(this, session))
344 {
345 this->lib->f->C_CloseSession(session);
346 return FALSE;
347 }
348 if (rv != CKR_OK)
349 {
350 this->lib->f->C_CloseSession(session);
351 DBG1(DBG_LIB, "C_DecryptInit() failed: %N", ck_rv_names, rv);
352 return FALSE;
353 }
354 len = (get_keysize(this) + 7) / 8;
355 buf = malloc(len);
356 rv = this->lib->f->C_Decrypt(session, crypt.ptr, crypt.len, buf, &len);
357 this->lib->f->C_CloseSession(session);
358 if (rv != CKR_OK)
359 {
360 DBG1(DBG_LIB, "C_Decrypt() failed: %N", ck_rv_names, rv);
361 free(buf);
362 return FALSE;
363 }
364 *plain = chunk_create(buf, len);
365 return TRUE;
366 }
367
368 METHOD(private_key_t, get_public_key, public_key_t*,
369 private_pkcs11_private_key_t *this)
370 {
371 return this->pubkey->get_ref(this->pubkey);
372 }
373
374 METHOD(private_key_t, get_fingerprint, bool,
375 private_pkcs11_private_key_t *this, cred_encoding_type_t type,
376 chunk_t *fingerprint)
377 {
378 return this->pubkey->get_fingerprint(this->pubkey, type, fingerprint);
379 }
380
381 METHOD(private_key_t, get_encoding, bool,
382 private_pkcs11_private_key_t *this, cred_encoding_type_t type,
383 chunk_t *encoding)
384 {
385 return FALSE;
386 }
387
388 METHOD(private_key_t, get_ref, private_key_t*,
389 private_pkcs11_private_key_t *this)
390 {
391 ref_get(&this->ref);
392 return &this->public.key;
393 }
394
395 METHOD(private_key_t, destroy, void,
396 private_pkcs11_private_key_t *this)
397 {
398 if (ref_put(&this->ref))
399 {
400 if (this->pubkey)
401 {
402 this->pubkey->destroy(this->pubkey);
403 }
404 this->keyid->destroy(this->keyid);
405 this->lib->f->C_CloseSession(this->session);
406 free(this);
407 }
408 }
409
410 /**
411 * Find the PKCS#11 library by its friendly name
412 */
413 static pkcs11_library_t* find_lib(char *module)
414 {
415 pkcs11_manager_t *manager;
416 enumerator_t *enumerator;
417 pkcs11_library_t *p11, *found = NULL;
418 CK_SLOT_ID slot;
419
420 manager = lib->get(lib, "pkcs11-manager");
421 if (!manager)
422 {
423 return NULL;
424 }
425 enumerator = manager->create_token_enumerator(manager);
426 while (enumerator->enumerate(enumerator, &p11, &slot))
427 {
428 if (streq(module, p11->get_name(p11)))
429 {
430 found = p11;
431 break;
432 }
433 }
434 enumerator->destroy(enumerator);
435 return found;
436 }
437
438 /**
439 * Find the PKCS#11 lib having a keyid, and optionally a slot
440 */
441 static pkcs11_library_t* find_lib_by_keyid(chunk_t keyid, int *slot,
442 CK_OBJECT_CLASS class)
443 {
444 pkcs11_manager_t *manager;
445 enumerator_t *enumerator;
446 pkcs11_library_t *p11, *found = NULL;
447 CK_SLOT_ID current;
448
449 manager = lib->get(lib, "pkcs11-manager");
450 if (!manager)
451 {
452 return NULL;
453 }
454 enumerator = manager->create_token_enumerator(manager);
455 while (enumerator->enumerate(enumerator, &p11, &current))
456 {
457 if (*slot == -1 || *slot == current)
458 {
459 /* look for a pubkey/cert, it is usually readable without login */
460 CK_ATTRIBUTE tmpl[] = {
461 {CKA_CLASS, &class, sizeof(class)},
462 {CKA_ID, keyid.ptr, keyid.len},
463 };
464 CK_OBJECT_HANDLE object;
465 CK_SESSION_HANDLE session;
466 CK_RV rv;
467 enumerator_t *keys;
468
469 rv = p11->f->C_OpenSession(current, CKF_SERIAL_SESSION, NULL, NULL,
470 &session);
471 if (rv != CKR_OK)
472 {
473 DBG1(DBG_CFG, "opening PKCS#11 session failed: %N",
474 ck_rv_names, rv);
475 continue;
476 }
477 keys = p11->create_object_enumerator(p11, session,
478 tmpl, countof(tmpl), NULL, 0);
479 if (keys->enumerate(keys, &object))
480 {
481 DBG1(DBG_CFG, "found key on PKCS#11 token '%s':%d",
482 p11->get_name(p11), current);
483 found = p11;
484 *slot = current;
485 }
486 keys->destroy(keys);
487 p11->f->C_CloseSession(session);
488 if (found)
489 {
490 break;
491 }
492 }
493 }
494 enumerator->destroy(enumerator);
495 return found;
496 }
497
498 /**
499 * Find the key on the token
500 */
501 static bool find_key(private_pkcs11_private_key_t *this, chunk_t keyid)
502 {
503 CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
504 CK_ATTRIBUTE tmpl[] = {
505 {CKA_CLASS, &class, sizeof(class)},
506 {CKA_ID, keyid.ptr, keyid.len},
507 };
508 CK_OBJECT_HANDLE object;
509 CK_KEY_TYPE type;
510 CK_BBOOL reauth = FALSE;
511 CK_ATTRIBUTE attr[] = {
512 {CKA_KEY_TYPE, &type, sizeof(type)},
513 {CKA_ALWAYS_AUTHENTICATE, &reauth, sizeof(reauth)},
514 };
515 enumerator_t *enumerator;
516 int count = countof(attr);
517 bool found = FALSE;
518
519 /* do not use CKA_ALWAYS_AUTHENTICATE if not supported */
520 if (!(this->lib->get_features(this->lib) & PKCS11_ALWAYS_AUTH_KEYS))
521 {
522 count--;
523 }
524 enumerator = this->lib->create_object_enumerator(this->lib,
525 this->session, tmpl, countof(tmpl), attr, count);
526 if (enumerator->enumerate(enumerator, &object))
527 {
528 this->type = KEY_RSA;
529 switch (type)
530 {
531 case CKK_ECDSA:
532 this->type = KEY_ECDSA;
533 /* fall-through */
534 case CKK_RSA:
535 this->reauth = reauth;
536 this->object = object;
537 found = TRUE;
538 break;
539 default:
540 DBG1(DBG_CFG, "PKCS#11 key type %d not supported", type);
541 break;
542 }
543 }
544 enumerator->destroy(enumerator);
545 return found;
546 }
547
548 /**
549 * Find a PIN and try to log in
550 */
551 static bool login(private_pkcs11_private_key_t *this, int slot)
552 {
553 enumerator_t *enumerator;
554 shared_key_t *shared;
555 chunk_t pin;
556 CK_RV rv;
557 CK_SESSION_INFO info;
558 bool found = FALSE, success = FALSE;
559
560 rv = this->lib->f->C_GetSessionInfo(this->session, &info);
561 if (rv != CKR_OK)
562 {
563 DBG1(DBG_CFG, "C_GetSessionInfo failed: %N", ck_rv_names, rv);
564 return FALSE;
565 }
566 if (info.state != CKS_RO_PUBLIC_SESSION &&
567 info.state != CKS_RW_PUBLIC_SESSION)
568 { /* already logged in with another session, skip */
569 return TRUE;
570 }
571
572 enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
573 SHARED_PIN, this->keyid, NULL);
574 while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
575 {
576 found = TRUE;
577 pin = shared->get_key(shared);
578 rv = this->lib->f->C_Login(this->session, CKU_USER, pin.ptr, pin.len);
579 if (rv == CKR_OK)
580 {
581 success = TRUE;
582 break;
583 }
584 DBG1(DBG_CFG, "login to '%s':%d failed: %N",
585 this->lib->get_name(this->lib), slot, ck_rv_names, rv);
586 }
587 enumerator->destroy(enumerator);
588
589 if (!found)
590 {
591 DBG1(DBG_CFG, "no PIN found for PKCS#11 key %Y", this->keyid);
592 return FALSE;
593 }
594 return success;
595 }
596
597 /**
598 * Get a public key from a certificate with a given key ID.
599 */
600 static public_key_t* find_pubkey_in_certs(private_pkcs11_private_key_t *this,
601 chunk_t keyid)
602 {
603 CK_OBJECT_CLASS class = CKO_CERTIFICATE;
604 CK_CERTIFICATE_TYPE type = CKC_X_509;
605 CK_ATTRIBUTE tmpl[] = {
606 {CKA_CLASS, &class, sizeof(class)},
607 {CKA_CERTIFICATE_TYPE, &type, sizeof(type)},
608 {CKA_ID, keyid.ptr, keyid.len},
609 };
610 CK_OBJECT_HANDLE object;
611 CK_ATTRIBUTE attr[] = {
612 {CKA_VALUE, NULL, 0},
613 };
614 enumerator_t *enumerator;
615 chunk_t data = chunk_empty;
616 public_key_t *key = NULL;
617 certificate_t *cert;
618
619 enumerator = this->lib->create_object_enumerator(this->lib, this->session,
620 tmpl, countof(tmpl), attr, countof(attr));
621 if (enumerator->enumerate(enumerator, &object))
622 {
623 data = chunk_clone(chunk_create(attr[0].pValue, attr[0].ulValueLen));
624 }
625 enumerator->destroy(enumerator);
626
627 if (data.ptr)
628 {
629 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
630 BUILD_BLOB_ASN1_DER, data, BUILD_END);
631 free(data.ptr);
632 if (cert)
633 {
634 key = cert->get_public_key(cert);
635 cert->destroy(cert);
636 }
637 }
638 return key;
639 }
640
641 /**
642 * See header.
643 */
644 pkcs11_private_key_t *pkcs11_private_key_connect(key_type_t type, va_list args)
645 {
646 private_pkcs11_private_key_t *this;
647 char *module = NULL;
648 chunk_t keyid = chunk_empty;
649 int slot = -1;
650 CK_RV rv;
651
652 while (TRUE)
653 {
654 switch (va_arg(args, builder_part_t))
655 {
656 case BUILD_PKCS11_KEYID:
657 keyid = va_arg(args, chunk_t);
658 continue;
659 case BUILD_PKCS11_SLOT:
660 slot = va_arg(args, int);
661 continue;
662 case BUILD_PKCS11_MODULE:
663 module = va_arg(args, char*);
664 continue;
665 case BUILD_END:
666 break;
667 default:
668 return NULL;
669 }
670 break;
671 }
672 if (!keyid.len)
673 {
674 return NULL;
675 }
676
677 INIT(this,
678 .public = {
679 .key = {
680 .get_type = _get_type,
681 .sign = _sign,
682 .decrypt = _decrypt,
683 .get_keysize = _get_keysize,
684 .get_public_key = _get_public_key,
685 .equals = private_key_equals,
686 .belongs_to = private_key_belongs_to,
687 .get_fingerprint = _get_fingerprint,
688 .has_fingerprint = private_key_has_fingerprint,
689 .get_encoding = _get_encoding,
690 .get_ref = _get_ref,
691 .destroy = _destroy,
692 },
693 },
694 .ref = 1,
695 );
696
697 if (module && slot != -1)
698 {
699 this->lib = find_lib(module);
700 if (!this->lib)
701 {
702 DBG1(DBG_CFG, "PKCS#11 module '%s' not found", module);
703 free(this);
704 return NULL;
705 }
706 }
707 else
708 {
709 this->lib = find_lib_by_keyid(keyid, &slot, CKO_PUBLIC_KEY);
710 if (!this->lib)
711 {
712 this->lib = find_lib_by_keyid(keyid, &slot, CKO_CERTIFICATE);
713 }
714 if (!this->lib)
715 {
716 DBG1(DBG_CFG, "no PKCS#11 module found having a keyid %#B", &keyid);
717 free(this);
718 return NULL;
719 }
720 }
721
722 rv = this->lib->f->C_OpenSession(slot, CKF_SERIAL_SESSION,
723 NULL, NULL, &this->session);
724 if (rv != CKR_OK)
725 {
726 DBG1(DBG_CFG, "opening private key session on '%s':%d failed: %N",
727 module, slot, ck_rv_names, rv);
728 free(this);
729 return NULL;
730 }
731
732 this->slot = slot;
733 this->keyid = identification_create_from_encoding(ID_KEY_ID, keyid);
734
735 if (!login(this, slot))
736 {
737 destroy(this);
738 return NULL;
739 }
740
741 if (!find_key(this, keyid))
742 {
743 destroy(this);
744 return NULL;
745 }
746
747 this->pubkey = pkcs11_public_key_connect(this->lib, slot, this->type, keyid);
748 if (!this->pubkey)
749 {
750 this->pubkey = find_pubkey_in_certs(this, keyid);
751 if (!this->pubkey)
752 {
753 DBG1(DBG_CFG, "no public key or certificate found for private key "
754 "on '%s':%d", module, slot);
755 destroy(this);
756 return NULL;
757 }
758 }
759
760 return &this->public;
761 }