2 * Copyright (C) 2011-2016 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
5 * Copyright (C) 2010 Martin Willi
6 * Copyright (C) 2010 revosec AG
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>.
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
19 * Copyright (C) 2016 EDF S.A.
21 * Permission is hereby granted, free of charge, to any person obtaining a copy
22 * of this software and associated documentation files (the "Software"), to deal
23 * in the Software without restriction, including without limitation the rights
24 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 * copies of the Software, and to permit persons to whom the Software is
26 * furnished to do so, subject to the following conditions:
28 * The above copyright notice and this permission notice shall be included in
29 * all copies or substantial portions of the Software.
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
40 #include "pkcs11_private_key.h"
42 #include "pkcs11_library.h"
43 #include "pkcs11_manager.h"
44 #include "pkcs11_public_key.h"
46 #include <utils/debug.h>
47 #include <asn1/asn1.h>
49 typedef struct private_pkcs11_private_key_t private_pkcs11_private_key_t
;
52 * Private data of an pkcs11_private_key_t object.
54 struct private_pkcs11_private_key_t
{
57 * Public pkcs11_private_key_t interface.
59 pkcs11_private_key_t
public;
64 pkcs11_library_t
*lib
;
67 * Slot the token is in
74 CK_SESSION_HANDLE session
;
77 * Key object on the token
79 CK_OBJECT_HANDLE object
;
82 * Key requires reauthentication for each signature/decryption
87 * Keyid of the key we use
89 identification_t
*keyid
;
92 * Associated public key
97 * References to this key
102 * Type of this private key
108 METHOD(private_key_t
, get_type
, key_type_t
,
109 private_pkcs11_private_key_t
*this)
114 METHOD(private_key_t
, get_keysize
, int,
115 private_pkcs11_private_key_t
*this)
117 return this->pubkey
->get_keysize(this->pubkey
);
121 * Check if a token supports the given mechanism.
123 static bool is_mechanism_supported(pkcs11_library_t
*p11
, CK_SLOT_ID slot
,
124 const CK_MECHANISM_PTR mech
)
127 CK_MECHANISM_TYPE type
;
129 mechs
= p11
->create_mechanism_enumerator(p11
, slot
);
130 while (mechs
->enumerate(mechs
, &type
, NULL
))
132 if (type
== mech
->mechanism
)
134 mechs
->destroy(mechs
);
138 mechs
->destroy(mechs
);
143 * Described in header
145 CK_MECHANISM_PTR
pkcs11_signature_scheme_to_mech(pkcs11_library_t
*p11
,
147 signature_scheme_t scheme
,
148 key_type_t type
, size_t keylen
,
149 hash_algorithm_t
*hash
)
152 signature_scheme_t scheme
;
153 CK_MECHANISM mechanism
;
156 hash_algorithm_t hash
;
158 {SIGN_RSA_EMSA_PKCS1_NULL
, {CKM_RSA_PKCS
, NULL
, 0},
159 KEY_RSA
, 0, HASH_UNKNOWN
},
160 {SIGN_RSA_EMSA_PKCS1_SHA2_256
, {CKM_SHA256_RSA_PKCS
, NULL
, 0},
161 KEY_RSA
, 0, HASH_UNKNOWN
},
162 {SIGN_RSA_EMSA_PKCS1_SHA2_256
, {CKM_RSA_PKCS
, NULL
, 0},
163 KEY_RSA
, 0, HASH_SHA256
},
164 {SIGN_RSA_EMSA_PKCS1_SHA2_384
, {CKM_SHA384_RSA_PKCS
, NULL
, 0},
165 KEY_RSA
, 0, HASH_UNKNOWN
},
166 {SIGN_RSA_EMSA_PKCS1_SHA2_384
, {CKM_RSA_PKCS
, NULL
, 0},
167 KEY_RSA
, 0, HASH_SHA384
},
168 {SIGN_RSA_EMSA_PKCS1_SHA2_512
, {CKM_SHA512_RSA_PKCS
, NULL
, 0},
169 KEY_RSA
, 0, HASH_UNKNOWN
},
170 {SIGN_RSA_EMSA_PKCS1_SHA2_512
, {CKM_RSA_PKCS
, NULL
, 0},
171 KEY_RSA
, 0, HASH_SHA512
},
172 {SIGN_RSA_EMSA_PKCS1_SHA1
, {CKM_SHA1_RSA_PKCS
, NULL
, 0},
173 KEY_RSA
, 0, HASH_UNKNOWN
},
174 {SIGN_RSA_EMSA_PKCS1_SHA1
, {CKM_RSA_PKCS
, NULL
, 0},
175 KEY_RSA
, 0, HASH_SHA1
},
176 {SIGN_RSA_EMSA_PKCS1_MD5
, {CKM_MD5_RSA_PKCS
, NULL
, 0},
177 KEY_RSA
, 0, HASH_UNKNOWN
},
178 {SIGN_ECDSA_WITH_NULL
, {CKM_ECDSA
, NULL
, 0},
179 KEY_ECDSA
, 0, HASH_UNKNOWN
},
180 {SIGN_ECDSA_WITH_SHA1_DER
, {CKM_ECDSA_SHA1
, NULL
, 0},
181 KEY_ECDSA
, 0, HASH_UNKNOWN
},
182 {SIGN_ECDSA_WITH_SHA256_DER
, {CKM_ECDSA
, NULL
, 0},
183 KEY_ECDSA
, 0, HASH_SHA256
},
184 {SIGN_ECDSA_WITH_SHA384_DER
, {CKM_ECDSA
, NULL
, 0},
185 KEY_ECDSA
, 0, HASH_SHA384
},
186 {SIGN_ECDSA_WITH_SHA512_DER
, {CKM_ECDSA
, NULL
, 0},
187 KEY_ECDSA
, 0, HASH_SHA512
},
188 {SIGN_ECDSA_256
, {CKM_ECDSA
, NULL
, 0},
189 KEY_ECDSA
, 256, HASH_SHA256
},
190 {SIGN_ECDSA_384
, {CKM_ECDSA
, NULL
, 0},
191 KEY_ECDSA
, 384, HASH_SHA384
},
192 {SIGN_ECDSA_521
, {CKM_ECDSA
, NULL
, 0},
193 KEY_ECDSA
, 521, HASH_SHA512
},
197 for (i
= 0; i
< countof(mappings
); i
++)
199 if (mappings
[i
].scheme
== scheme
)
201 size_t len
= mappings
[i
].keylen
;
203 if (mappings
[i
].type
!= type
|| (len
&& keylen
!= len
) ||
204 !is_mechanism_supported(p11
, slot
, &mappings
[i
].mechanism
))
210 *hash
= mappings
[i
].hash
;
212 return &mappings
[i
].mechanism
;
221 CK_MECHANISM_PTR
pkcs11_encryption_scheme_to_mech(encryption_scheme_t scheme
)
224 encryption_scheme_t scheme
;
225 CK_MECHANISM mechanism
;
227 {ENCRYPT_RSA_PKCS1
, {CKM_RSA_PKCS
, NULL
, 0}},
228 {ENCRYPT_RSA_OAEP_SHA1
, {CKM_RSA_PKCS_OAEP
, NULL
, 0}},
232 for (i
= 0; i
< countof(mappings
); i
++)
234 if (mappings
[i
].scheme
== scheme
)
236 return &mappings
[i
].mechanism
;
243 * Reauthenticate to do a signature
245 static bool reauth(private_pkcs11_private_key_t
*this,
246 CK_SESSION_HANDLE session
)
248 enumerator_t
*enumerator
;
249 shared_key_t
*shared
;
252 bool found
= FALSE
, success
= FALSE
;
254 enumerator
= lib
->credmgr
->create_shared_enumerator(lib
->credmgr
,
255 SHARED_PIN
, this->keyid
, NULL
);
256 while (enumerator
->enumerate(enumerator
, &shared
, NULL
, NULL
))
259 pin
= shared
->get_key(shared
);
260 rv
= this->lib
->f
->C_Login(session
, CKU_CONTEXT_SPECIFIC
,
267 DBG1(DBG_CFG
, "reauthentication login failed: %N", ck_rv_names
, rv
);
269 enumerator
->destroy(enumerator
);
273 DBG1(DBG_CFG
, "private key requires reauthentication, but no PIN found");
279 METHOD(private_key_t
, sign
, bool,
280 private_pkcs11_private_key_t
*this, signature_scheme_t scheme
, void *params
,
281 chunk_t data
, chunk_t
*signature
)
283 CK_MECHANISM_PTR mechanism
;
284 CK_SESSION_HANDLE session
;
288 hash_algorithm_t hash_alg
;
289 chunk_t hash
= chunk_empty
;
291 mechanism
= pkcs11_signature_scheme_to_mech(this->lib
, this->slot
, scheme
,
292 this->type
, get_keysize(this),
296 DBG1(DBG_LIB
, "signature scheme %N not supported",
297 signature_scheme_names
, scheme
);
300 rv
= this->lib
->f
->C_OpenSession(this->slot
, CKF_SERIAL_SESSION
, NULL
, NULL
,
304 DBG1(DBG_CFG
, "opening PKCS#11 session failed: %N", ck_rv_names
, rv
);
307 rv
= this->lib
->f
->C_SignInit(session
, mechanism
, this->object
);
308 if (this->reauth
&& !reauth(this, session
))
310 this->lib
->f
->C_CloseSession(session
);
315 this->lib
->f
->C_CloseSession(session
);
316 DBG1(DBG_LIB
, "C_SignInit() failed: %N", ck_rv_names
, rv
);
319 if (hash_alg
!= HASH_UNKNOWN
)
323 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, hash_alg
);
324 if (!hasher
|| !hasher
->allocate_hash(hasher
, data
, &hash
))
327 this->lib
->f
->C_CloseSession(session
);
330 hasher
->destroy(hasher
);
333 case SIGN_RSA_EMSA_PKCS1_SHA1
:
334 case SIGN_RSA_EMSA_PKCS1_SHA2_256
:
335 case SIGN_RSA_EMSA_PKCS1_SHA2_384
:
336 case SIGN_RSA_EMSA_PKCS1_SHA2_512
:
337 /* encode PKCS#1 digestInfo if the token does not support it */
338 hash
= asn1_wrap(ASN1_SEQUENCE
, "mm",
339 asn1_algorithmIdentifier(
340 hasher_algorithm_to_oid(hash_alg
)),
341 asn1_wrap(ASN1_OCTET_STRING
, "m", hash
));
348 len
= (get_keysize(this) + 7) / 8;
349 if (this->type
== KEY_ECDSA
)
350 { /* signature is twice the length of the base point order */
354 rv
= this->lib
->f
->C_Sign(session
, data
.ptr
, data
.len
, buf
, &len
);
355 this->lib
->f
->C_CloseSession(session
);
359 DBG1(DBG_LIB
, "C_Sign() failed: %N", ck_rv_names
, rv
);
365 case SIGN_ECDSA_WITH_SHA1_DER
:
366 case SIGN_ECDSA_WITH_SHA256_DER
:
367 case SIGN_ECDSA_WITH_SHA384_DER
:
368 case SIGN_ECDSA_WITH_SHA512_DER
:
372 /* return an ASN.1 encoded sequence of integers r and s, removing
373 * any zero-padding */
375 r
= chunk_skip_zero(chunk_create(buf
, len
));
376 s
= chunk_skip_zero(chunk_create(buf
+len
, len
));
377 *signature
= asn1_wrap(ASN1_SEQUENCE
, "mm",
378 asn1_integer("c", r
), asn1_integer("c", s
));
383 *signature
= chunk_create(buf
, len
);
389 METHOD(private_key_t
, decrypt
, bool,
390 private_pkcs11_private_key_t
*this, encryption_scheme_t scheme
,
391 chunk_t crypt
, chunk_t
*plain
)
393 CK_MECHANISM_PTR mechanism
;
394 CK_SESSION_HANDLE session
;
399 mechanism
= pkcs11_encryption_scheme_to_mech(scheme
);
402 DBG1(DBG_LIB
, "encryption scheme %N not supported",
403 encryption_scheme_names
, scheme
);
406 rv
= this->lib
->f
->C_OpenSession(this->slot
, CKF_SERIAL_SESSION
, NULL
, NULL
,
410 DBG1(DBG_CFG
, "opening PKCS#11 session failed: %N", ck_rv_names
, rv
);
413 rv
= this->lib
->f
->C_DecryptInit(session
, mechanism
, this->object
);
414 if (this->reauth
&& !reauth(this, session
))
416 this->lib
->f
->C_CloseSession(session
);
421 this->lib
->f
->C_CloseSession(session
);
422 DBG1(DBG_LIB
, "C_DecryptInit() failed: %N", ck_rv_names
, rv
);
425 len
= (get_keysize(this) + 7) / 8;
427 rv
= this->lib
->f
->C_Decrypt(session
, crypt
.ptr
, crypt
.len
, buf
, &len
);
428 this->lib
->f
->C_CloseSession(session
);
431 DBG1(DBG_LIB
, "C_Decrypt() failed: %N", ck_rv_names
, rv
);
435 *plain
= chunk_create(buf
, len
);
439 METHOD(private_key_t
, get_public_key
, public_key_t
*,
440 private_pkcs11_private_key_t
*this)
442 return this->pubkey
->get_ref(this->pubkey
);
445 METHOD(private_key_t
, get_fingerprint
, bool,
446 private_pkcs11_private_key_t
*this, cred_encoding_type_t type
,
447 chunk_t
*fingerprint
)
449 return this->pubkey
->get_fingerprint(this->pubkey
, type
, fingerprint
);
452 METHOD(private_key_t
, get_encoding
, bool,
453 private_pkcs11_private_key_t
*this, cred_encoding_type_t type
,
459 METHOD(private_key_t
, get_ref
, private_key_t
*,
460 private_pkcs11_private_key_t
*this)
463 return &this->public.key
;
466 METHOD(private_key_t
, destroy
, void,
467 private_pkcs11_private_key_t
*this)
469 if (ref_put(&this->ref
))
473 this->pubkey
->destroy(this->pubkey
);
475 this->keyid
->destroy(this->keyid
);
476 this->lib
->f
->C_CloseSession(this->session
);
482 * Find the PKCS#11 library by its friendly name
484 static pkcs11_library_t
* find_lib(char *module
)
486 pkcs11_manager_t
*manager
;
487 enumerator_t
*enumerator
;
488 pkcs11_library_t
*p11
, *found
= NULL
;
491 manager
= lib
->get(lib
, "pkcs11-manager");
496 enumerator
= manager
->create_token_enumerator(manager
);
497 while (enumerator
->enumerate(enumerator
, &p11
, &slot
))
499 if (streq(module
, p11
->get_name(p11
)))
505 enumerator
->destroy(enumerator
);
510 * Find the PKCS#11 lib having a keyid, and optionally a slot
512 static pkcs11_library_t
* find_lib_by_keyid(chunk_t keyid
, int *slot
,
513 CK_OBJECT_CLASS
class)
515 pkcs11_manager_t
*manager
;
516 enumerator_t
*enumerator
;
517 pkcs11_library_t
*p11
, *found
= NULL
;
520 manager
= lib
->get(lib
, "pkcs11-manager");
525 enumerator
= manager
->create_token_enumerator(manager
);
526 while (enumerator
->enumerate(enumerator
, &p11
, ¤t
))
528 if (*slot
== -1 || *slot
== current
)
530 /* look for a pubkey/cert, it is usually readable without login */
531 CK_ATTRIBUTE tmpl
[] = {
532 {CKA_CLASS
, &class, sizeof(class)},
533 {CKA_ID
, keyid
.ptr
, keyid
.len
},
535 CK_OBJECT_HANDLE object
;
536 CK_SESSION_HANDLE session
;
540 rv
= p11
->f
->C_OpenSession(current
, CKF_SERIAL_SESSION
, NULL
, NULL
,
544 DBG1(DBG_CFG
, "opening PKCS#11 session failed: %N",
548 keys
= p11
->create_object_enumerator(p11
, session
,
549 tmpl
, countof(tmpl
), NULL
, 0);
550 if (keys
->enumerate(keys
, &object
))
552 DBG1(DBG_CFG
, "found key on PKCS#11 token '%s':%d",
553 p11
->get_name(p11
), current
);
558 p11
->f
->C_CloseSession(session
);
565 enumerator
->destroy(enumerator
);
570 * Find the PKCS#11 lib and CKA_ID of the certificate object of a given
571 * subjectKeyIdentifier and optional slot
573 static pkcs11_library_t
* find_lib_and_keyid_by_skid(chunk_t keyid_chunk
,
574 chunk_t
*ckaid
, int *slot
)
576 CK_OBJECT_CLASS
class = CKO_CERTIFICATE
;
577 CK_CERTIFICATE_TYPE type
= CKC_X_509
;
578 CK_ATTRIBUTE tmpl
[] = {
579 {CKA_CLASS
, &class, sizeof(class)},
580 {CKA_CERTIFICATE_TYPE
, &type
, sizeof(type
)},
582 CK_ATTRIBUTE attr
[] = {
583 {CKA_VALUE
, NULL
, 0},
586 CK_OBJECT_HANDLE object
;
587 CK_SESSION_HANDLE session
;
589 pkcs11_manager_t
*manager
;
590 enumerator_t
*enumerator
, *certs
;
591 identification_t
*keyid
;
592 pkcs11_library_t
*p11
, *found
= NULL
;
601 manager
= lib
->get(lib
, "pkcs11-manager");
607 keyid
= identification_create_from_encoding(ID_KEY_ID
, keyid_chunk
);
608 /* store result in a temporary list, avoid recursive operation */
609 raw
= linked_list_create();
611 enumerator
= manager
->create_token_enumerator(manager
);
612 while (enumerator
->enumerate(enumerator
, &p11
, ¤t
))
614 if (*slot
!= -1 && *slot
!= current
)
618 rv
= p11
->f
->C_OpenSession(current
, CKF_SERIAL_SESSION
, NULL
, NULL
,
622 DBG1(DBG_CFG
, "opening PKCS#11 session failed: %N",
626 certs
= p11
->create_object_enumerator(p11
, session
, tmpl
, countof(tmpl
),
627 attr
, countof(attr
));
628 while (certs
->enumerate(certs
, &object
))
630 if (attr
[0].ulValueLen
!= CK_UNAVAILABLE_INFORMATION
&&
631 attr
[1].ulValueLen
!= CK_UNAVAILABLE_INFORMATION
)
634 .value
= chunk_clone(
635 chunk_create(attr
[0].pValue
, attr
[0].ulValueLen
)),
636 .ckaid
= chunk_clone(
637 chunk_create(attr
[1].pValue
, attr
[1].ulValueLen
)),
639 raw
->insert_last(raw
, entry
);
642 certs
->destroy(certs
);
644 while (raw
->remove_first(raw
, (void**)&entry
) == SUCCESS
)
648 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
,
649 CERT_X509
, BUILD_BLOB_ASN1_DER
,
650 entry
->value
, BUILD_END
);
653 if (cert
->has_subject(cert
, keyid
))
655 DBG1(DBG_CFG
, "found cert with keyid '%#B' on PKCS#11 "
656 "token '%s':%d", &keyid_chunk
, p11
->get_name(p11
),
659 *ckaid
= chunk_clone(entry
->ckaid
);
666 DBG1(DBG_CFG
, "parsing cert with CKA_ID '%#B' on PKCS#11 "
667 "token '%s':%d failed", &entry
->ckaid
,
668 p11
->get_name(p11
), current
);
671 chunk_free(&entry
->value
);
672 chunk_free(&entry
->ckaid
);
675 p11
->f
->C_CloseSession(session
);
681 enumerator
->destroy(enumerator
);
682 keyid
->destroy(keyid
);
688 * Find the key on the token
690 static bool find_key(private_pkcs11_private_key_t
*this, chunk_t keyid
)
692 CK_OBJECT_CLASS
class = CKO_PRIVATE_KEY
;
693 CK_ATTRIBUTE tmpl
[] = {
694 {CKA_CLASS
, &class, sizeof(class)},
695 {CKA_ID
, keyid
.ptr
, keyid
.len
},
697 CK_OBJECT_HANDLE object
;
699 CK_BBOOL reauth
= FALSE
;
700 CK_ATTRIBUTE attr
[] = {
701 {CKA_KEY_TYPE
, &type
, sizeof(type
)},
702 {CKA_ALWAYS_AUTHENTICATE
, &reauth
, sizeof(reauth
)},
704 enumerator_t
*enumerator
;
705 int count
= countof(attr
);
708 /* do not use CKA_ALWAYS_AUTHENTICATE if not supported */
709 if (!(this->lib
->get_features(this->lib
) & PKCS11_ALWAYS_AUTH_KEYS
))
713 enumerator
= this->lib
->create_object_enumerator(this->lib
,
714 this->session
, tmpl
, countof(tmpl
), attr
, count
);
715 if (enumerator
->enumerate(enumerator
, &object
) &&
716 attr
[0].ulValueLen
!= CK_UNAVAILABLE_INFORMATION
)
718 this->type
= KEY_RSA
;
722 this->type
= KEY_ECDSA
;
725 if (attr
[1].ulValueLen
!= CK_UNAVAILABLE_INFORMATION
)
727 this->reauth
= reauth
;
729 this->object
= object
;
733 DBG1(DBG_CFG
, "PKCS#11 key type %d not supported", type
);
737 enumerator
->destroy(enumerator
);
742 * Find a PIN and try to log in
744 static bool login(private_pkcs11_private_key_t
*this, int slot
)
746 enumerator_t
*enumerator
;
747 shared_key_t
*shared
;
750 CK_SESSION_INFO info
;
751 bool found
= FALSE
, success
= FALSE
;
753 rv
= this->lib
->f
->C_GetSessionInfo(this->session
, &info
);
756 DBG1(DBG_CFG
, "C_GetSessionInfo failed: %N", ck_rv_names
, rv
);
759 if (info
.state
!= CKS_RO_PUBLIC_SESSION
&&
760 info
.state
!= CKS_RW_PUBLIC_SESSION
)
761 { /* already logged in with another session, skip */
765 enumerator
= lib
->credmgr
->create_shared_enumerator(lib
->credmgr
,
766 SHARED_PIN
, this->keyid
, NULL
);
767 while (enumerator
->enumerate(enumerator
, &shared
, NULL
, NULL
))
770 pin
= shared
->get_key(shared
);
771 rv
= this->lib
->f
->C_Login(this->session
, CKU_USER
, pin
.ptr
, pin
.len
);
777 DBG1(DBG_CFG
, "login to '%s':%d failed: %N",
778 this->lib
->get_name(this->lib
), slot
, ck_rv_names
, rv
);
780 enumerator
->destroy(enumerator
);
784 DBG1(DBG_CFG
, "no PIN found for PKCS#11 key %Y", this->keyid
);
791 * Get a public key from a certificate with a given key ID.
793 static public_key_t
* find_pubkey_in_certs(private_pkcs11_private_key_t
*this,
796 CK_OBJECT_CLASS
class = CKO_CERTIFICATE
;
797 CK_CERTIFICATE_TYPE type
= CKC_X_509
;
798 CK_ATTRIBUTE tmpl
[] = {
799 {CKA_CLASS
, &class, sizeof(class)},
800 {CKA_CERTIFICATE_TYPE
, &type
, sizeof(type
)},
801 {CKA_ID
, keyid
.ptr
, keyid
.len
},
803 CK_OBJECT_HANDLE object
;
804 CK_ATTRIBUTE attr
[] = {
805 {CKA_VALUE
, NULL
, 0},
807 enumerator_t
*enumerator
;
808 chunk_t data
= chunk_empty
;
809 public_key_t
*key
= NULL
;
812 enumerator
= this->lib
->create_object_enumerator(this->lib
, this->session
,
813 tmpl
, countof(tmpl
), attr
, countof(attr
));
814 if (enumerator
->enumerate(enumerator
, &object
) &&
815 attr
[0].ulValueLen
!= CK_UNAVAILABLE_INFORMATION
)
817 data
= chunk_clone(chunk_create(attr
[0].pValue
, attr
[0].ulValueLen
));
819 enumerator
->destroy(enumerator
);
823 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
824 BUILD_BLOB_ASN1_DER
, data
, BUILD_END
);
828 key
= cert
->get_public_key(cert
);
838 pkcs11_private_key_t
*pkcs11_private_key_connect(key_type_t type
, va_list args
)
840 private_pkcs11_private_key_t
*this;
842 chunk_t keyid
= chunk_empty
, ckaid
= chunk_empty
;
848 switch (va_arg(args
, builder_part_t
))
850 case BUILD_PKCS11_KEYID
:
851 keyid
= va_arg(args
, chunk_t
);
853 case BUILD_PKCS11_SLOT
:
854 slot
= va_arg(args
, int);
856 case BUILD_PKCS11_MODULE
:
857 module
= va_arg(args
, char*);
874 .get_type
= _get_type
,
877 .get_keysize
= _get_keysize
,
878 .get_public_key
= _get_public_key
,
879 .equals
= private_key_equals
,
880 .belongs_to
= private_key_belongs_to
,
881 .get_fingerprint
= _get_fingerprint
,
882 .has_fingerprint
= private_key_has_fingerprint
,
883 .get_encoding
= _get_encoding
,
891 if (module
&& slot
!= -1)
893 this->lib
= find_lib(module
);
896 DBG1(DBG_CFG
, "PKCS#11 module '%s' not found", module
);
903 this->lib
= find_lib_by_keyid(keyid
, &slot
, CKO_PUBLIC_KEY
);
906 this->lib
= find_lib_by_keyid(keyid
, &slot
, CKO_CERTIFICATE
);
910 this->lib
= find_lib_and_keyid_by_skid(keyid
, &ckaid
, &slot
);
914 DBG1(DBG_CFG
, "no PKCS#11 module found having a keyid %#B", &keyid
);
920 rv
= this->lib
->f
->C_OpenSession(slot
, CKF_SERIAL_SESSION
,
921 NULL
, NULL
, &this->session
);
924 DBG1(DBG_CFG
, "opening private key session on '%s':%d failed: %N",
925 module
, slot
, ck_rv_names
, rv
);
931 this->keyid
= identification_create_from_encoding(ID_KEY_ID
, keyid
);
933 if (!login(this, slot
))
941 DBG1(DBG_CFG
, "using CKA_ID '%#B' for key with keyid '%#B'",
946 if (!find_key(this, keyid
))
948 DBG1(DBG_CFG
, "did not find the key with %s '%#B'",
949 ckaid
.ptr
? "CKA_ID" : "keyid", &keyid
);
954 this->pubkey
= pkcs11_public_key_connect(this->lib
, slot
, this->type
, keyid
);
957 this->pubkey
= find_pubkey_in_certs(this, keyid
);
960 DBG1(DBG_CFG
, "no public key or certificate found for private key "
961 "(%s '%#B') on '%s':%d", ckaid
.ptr
? "CKA_ID" : "keyid",
962 &keyid
, module
, slot
);
967 return &this->public;