1 /* $OpenBSD: ssh-pkcs11.c,v 1.64 2024/09/20 02:00:46 jsg Exp $ */
3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 #ifdef HAVE_SYS_TIME_H
24 # include <sys/time.h>
27 #include <sys/types.h>
35 #include "openbsd-compat/sys-queue.h"
36 #include "openbsd-compat/openssl-compat.h"
38 #include <openssl/ecdsa.h>
39 #include <openssl/x509.h>
40 #include <openssl/err.h>
42 #define CRYPTOKI_COMPAT
48 #include "ssh-pkcs11.h"
52 struct pkcs11_slotinfo
{
54 CK_SESSION_HANDLE session
;
58 struct pkcs11_provider
{
61 CK_FUNCTION_LIST
*function_list
;
65 struct pkcs11_slotinfo
*slotinfo
;
68 TAILQ_ENTRY(pkcs11_provider
) next
;
71 TAILQ_HEAD(, pkcs11_provider
) pkcs11_providers
;
74 struct pkcs11_provider
*provider
;
80 int pkcs11_interactive
= 0;
82 #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
84 ossl_error(const char *msg
)
89 while ((e
= ERR_get_error()) != 0)
90 error_f("libcrypto error: %s", ERR_error_string(e
, NULL
));
92 #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
95 pkcs11_init(int interactive
)
97 pkcs11_interactive
= interactive
;
98 TAILQ_INIT(&pkcs11_providers
);
103 * finalize a provider shared library, it's no longer usable.
104 * however, there might still be keys referencing this provider,
105 * so the actual freeing of memory is handled by pkcs11_provider_unref().
106 * this is called when a provider gets unregistered.
109 pkcs11_provider_finalize(struct pkcs11_provider
*p
)
114 debug_f("provider \"%s\" refcount %d valid %d",
115 p
->name
, p
->refcount
, p
->valid
);
118 for (i
= 0; i
< p
->nslots
; i
++) {
119 if (p
->slotinfo
[i
].session
&&
120 (rv
= p
->function_list
->C_CloseSession(
121 p
->slotinfo
[i
].session
)) != CKR_OK
)
122 error("C_CloseSession failed: %lu", rv
);
124 if ((rv
= p
->function_list
->C_Finalize(NULL
)) != CKR_OK
)
125 error("C_Finalize failed: %lu", rv
);
127 p
->function_list
= NULL
;
132 * remove a reference to the provider.
133 * called when a key gets destroyed or when the provider is unregistered.
136 pkcs11_provider_unref(struct pkcs11_provider
*p
)
138 debug_f("provider \"%s\" refcount %d", p
->name
, p
->refcount
);
139 if (--p
->refcount
<= 0) {
141 error_f("provider \"%s\" still valid", p
->name
);
149 /* unregister all providers, keys might still point to the providers */
151 pkcs11_terminate(void)
153 struct pkcs11_provider
*p
;
155 while ((p
= TAILQ_FIRST(&pkcs11_providers
)) != NULL
) {
156 TAILQ_REMOVE(&pkcs11_providers
, p
, next
);
157 pkcs11_provider_finalize(p
);
158 pkcs11_provider_unref(p
);
162 /* lookup provider by name */
163 static struct pkcs11_provider
*
164 pkcs11_provider_lookup(char *provider_id
)
166 struct pkcs11_provider
*p
;
168 TAILQ_FOREACH(p
, &pkcs11_providers
, next
) {
169 debug("check provider \"%s\"", p
->name
);
170 if (!strcmp(provider_id
, p
->name
))
176 /* unregister provider by name */
178 pkcs11_del_provider(char *provider_id
)
180 struct pkcs11_provider
*p
;
182 if ((p
= pkcs11_provider_lookup(provider_id
)) != NULL
) {
183 TAILQ_REMOVE(&pkcs11_providers
, p
, next
);
184 pkcs11_provider_finalize(p
);
185 pkcs11_provider_unref(p
);
191 static RSA_METHOD
*rsa_method
;
192 static int rsa_idx
= 0;
193 #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
194 static EC_KEY_METHOD
*ec_key_method
;
195 static int ec_key_idx
= 0;
196 #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
198 /* release a wrapped object */
200 pkcs11_k11_free(void *parent
, void *ptr
, CRYPTO_EX_DATA
*ad
, int idx
,
201 long argl
, void *argp
)
203 struct pkcs11_key
*k11
= ptr
;
205 debug_f("parent %p ptr %p idx %d", parent
, ptr
, idx
);
209 pkcs11_provider_unref(k11
->provider
);
214 /* find a single 'obj' for given attributes */
216 pkcs11_find(struct pkcs11_provider
*p
, CK_ULONG slotidx
, CK_ATTRIBUTE
*attr
,
217 CK_ULONG nattr
, CK_OBJECT_HANDLE
*obj
)
220 CK_SESSION_HANDLE session
;
225 f
= p
->function_list
;
226 session
= p
->slotinfo
[slotidx
].session
;
227 if ((rv
= f
->C_FindObjectsInit(session
, attr
, nattr
)) != CKR_OK
) {
228 error("C_FindObjectsInit failed (nattr %lu): %lu", nattr
, rv
);
231 if ((rv
= f
->C_FindObjects(session
, obj
, 1, &nfound
)) != CKR_OK
||
233 debug("C_FindObjects failed (nfound %lu nattr %lu): %lu",
237 if ((rv
= f
->C_FindObjectsFinal(session
)) != CKR_OK
)
238 error("C_FindObjectsFinal failed: %lu", rv
);
243 pkcs11_login_slot(struct pkcs11_provider
*provider
, struct pkcs11_slotinfo
*si
,
246 char *pin
= NULL
, prompt
[1024];
249 if (provider
== NULL
|| si
== NULL
|| !provider
->valid
) {
250 error("no pkcs11 (valid) provider found");
254 if (!pkcs11_interactive
) {
255 error("need pin entry%s",
256 (si
->token
.flags
& CKF_PROTECTED_AUTHENTICATION_PATH
) ?
257 " on reader keypad" : "");
260 if (si
->token
.flags
& CKF_PROTECTED_AUTHENTICATION_PATH
)
261 verbose("Deferring PIN entry to reader keypad.");
263 snprintf(prompt
, sizeof(prompt
), "Enter PIN for '%s': ",
265 if ((pin
= read_passphrase(prompt
, RP_ALLOW_EOF
)) == NULL
) {
266 debug_f("no pin specified");
267 return (-1); /* bail out */
270 rv
= provider
->function_list
->C_Login(si
->session
, type
, (u_char
*)pin
,
271 (pin
!= NULL
) ? strlen(pin
) : 0);
273 freezero(pin
, strlen(pin
));
277 case CKR_USER_ALREADY_LOGGED_IN
:
280 case CKR_PIN_LEN_RANGE
:
281 error("PKCS#11 login failed: PIN length out of range");
283 case CKR_PIN_INCORRECT
:
284 error("PKCS#11 login failed: PIN incorrect");
287 error("PKCS#11 login failed: PIN locked");
290 error("PKCS#11 login failed: error %lu", rv
);
298 pkcs11_login(struct pkcs11_key
*k11
, CK_USER_TYPE type
)
300 if (k11
== NULL
|| k11
->provider
== NULL
|| !k11
->provider
->valid
) {
301 error("no pkcs11 (valid) provider found");
305 return pkcs11_login_slot(k11
->provider
,
306 &k11
->provider
->slotinfo
[k11
->slotidx
], type
);
311 pkcs11_check_obj_bool_attrib(struct pkcs11_key
*k11
, CK_OBJECT_HANDLE obj
,
312 CK_ATTRIBUTE_TYPE type
, int *val
)
314 struct pkcs11_slotinfo
*si
;
322 if (!k11
->provider
|| !k11
->provider
->valid
) {
323 error("no pkcs11 (valid) provider found");
327 f
= k11
->provider
->function_list
;
328 si
= &k11
->provider
->slotinfo
[k11
->slotidx
];
332 attr
.ulValueLen
= sizeof(flag
);
334 rv
= f
->C_GetAttributeValue(si
->session
, obj
, &attr
, 1);
336 error("C_GetAttributeValue failed: %lu", rv
);
340 debug_f("provider \"%s\" slot %lu object %lu: attrib %lu = %d",
341 k11
->provider
->name
, k11
->slotidx
, obj
, type
, *val
);
346 pkcs11_get_key(struct pkcs11_key
*k11
, CK_MECHANISM_TYPE mech_type
)
348 struct pkcs11_slotinfo
*si
;
350 CK_OBJECT_HANDLE obj
;
352 CK_OBJECT_CLASS private_key_class
;
355 CK_ATTRIBUTE key_filter
[3];
359 if (!k11
->provider
|| !k11
->provider
->valid
) {
360 error("no pkcs11 (valid) provider found");
364 f
= k11
->provider
->function_list
;
365 si
= &k11
->provider
->slotinfo
[k11
->slotidx
];
367 if ((si
->token
.flags
& CKF_LOGIN_REQUIRED
) && !si
->logged_in
) {
368 if (pkcs11_login(k11
, CKU_USER
) < 0) {
369 error("login failed");
375 memset(&key_filter
, 0, sizeof(key_filter
));
376 private_key_class
= CKO_PRIVATE_KEY
;
377 key_filter
[0].type
= CKA_CLASS
;
378 key_filter
[0].pValue
= &private_key_class
;
379 key_filter
[0].ulValueLen
= sizeof(private_key_class
);
381 key_filter
[1].type
= CKA_ID
;
382 key_filter
[1].pValue
= k11
->keyid
;
383 key_filter
[1].ulValueLen
= k11
->keyid_len
;
386 key_filter
[2].type
= CKA_SIGN
;
387 key_filter
[2].pValue
= &true_val
;
388 key_filter
[2].ulValueLen
= sizeof(true_val
);
390 /* try to find object w/CKA_SIGN first, retry w/o */
391 if (pkcs11_find(k11
->provider
, k11
->slotidx
, key_filter
, 3, &obj
) < 0 &&
392 pkcs11_find(k11
->provider
, k11
->slotidx
, key_filter
, 2, &obj
) < 0) {
393 error("cannot find private key");
397 memset(&mech
, 0, sizeof(mech
));
398 mech
.mechanism
= mech_type
;
399 mech
.pParameter
= NULL_PTR
;
400 mech
.ulParameterLen
= 0;
402 if ((rv
= f
->C_SignInit(si
->session
, &mech
, obj
)) != CKR_OK
) {
403 error("C_SignInit failed: %lu", rv
);
407 pkcs11_check_obj_bool_attrib(k11
, obj
, CKA_ALWAYS_AUTHENTICATE
,
408 &always_auth
); /* ignore errors here */
409 if (always_auth
&& !did_login
) {
410 debug_f("always-auth key");
411 if (pkcs11_login(k11
, CKU_CONTEXT_SPECIFIC
) < 0) {
412 error("login failed for always-auth key");
420 /* openssl callback doing the actual signing operation */
422 pkcs11_rsa_private_encrypt(int flen
, const u_char
*from
, u_char
*to
, RSA
*rsa
,
425 struct pkcs11_key
*k11
;
426 struct pkcs11_slotinfo
*si
;
432 if ((k11
= RSA_get_ex_data(rsa
, rsa_idx
)) == NULL
) {
433 error("RSA_get_ex_data failed");
437 if (pkcs11_get_key(k11
, CKM_RSA_PKCS
) == -1) {
438 error("pkcs11_get_key failed");
442 f
= k11
->provider
->function_list
;
443 si
= &k11
->provider
->slotinfo
[k11
->slotidx
];
444 tlen
= RSA_size(rsa
);
446 /* XXX handle CKR_BUFFER_TOO_SMALL */
447 rv
= f
->C_Sign(si
->session
, (CK_BYTE
*)from
, flen
, to
, &tlen
);
451 error("C_Sign failed: %lu", rv
);
457 pkcs11_rsa_private_decrypt(int flen
, const u_char
*from
, u_char
*to
, RSA
*rsa
,
464 pkcs11_rsa_start_wrapper(void)
466 if (rsa_method
!= NULL
)
468 rsa_method
= RSA_meth_dup(RSA_get_default_method());
469 if (rsa_method
== NULL
)
471 rsa_idx
= RSA_get_ex_new_index(0, "ssh-pkcs11-rsa",
472 NULL
, NULL
, pkcs11_k11_free
);
475 if (!RSA_meth_set1_name(rsa_method
, "pkcs11") ||
476 !RSA_meth_set_priv_enc(rsa_method
, pkcs11_rsa_private_encrypt
) ||
477 !RSA_meth_set_priv_dec(rsa_method
, pkcs11_rsa_private_decrypt
)) {
478 error_f("setup pkcs11 method failed");
484 /* redirect private key operations for rsa key to pkcs11 token */
486 pkcs11_rsa_wrap(struct pkcs11_provider
*provider
, CK_ULONG slotidx
,
487 CK_ATTRIBUTE
*keyid_attrib
, RSA
*rsa
)
489 struct pkcs11_key
*k11
;
491 if (pkcs11_rsa_start_wrapper() == -1)
494 k11
= xcalloc(1, sizeof(*k11
));
495 k11
->provider
= provider
;
496 provider
->refcount
++; /* provider referenced by RSA key */
497 k11
->slotidx
= slotidx
;
498 /* identify key object on smartcard */
499 k11
->keyid_len
= keyid_attrib
->ulValueLen
;
500 if (k11
->keyid_len
> 0) {
501 k11
->keyid
= xmalloc(k11
->keyid_len
);
502 memcpy(k11
->keyid
, keyid_attrib
->pValue
, k11
->keyid_len
);
505 if (RSA_set_method(rsa
, rsa_method
) != 1)
506 fatal_f("RSA_set_method failed");
507 if (RSA_set_ex_data(rsa
, rsa_idx
, k11
) != 1)
508 fatal_f("RSA_set_ex_data failed");
512 #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
513 /* openssl callback doing the actual signing operation */
515 ecdsa_do_sign(const unsigned char *dgst
, int dgst_len
, const BIGNUM
*inv
,
516 const BIGNUM
*rp
, EC_KEY
*ec
)
518 struct pkcs11_key
*k11
;
519 struct pkcs11_slotinfo
*si
;
521 CK_ULONG siglen
= 0, bnlen
;
523 ECDSA_SIG
*ret
= NULL
;
525 BIGNUM
*r
= NULL
, *s
= NULL
;
527 if ((k11
= EC_KEY_get_ex_data(ec
, ec_key_idx
)) == NULL
) {
528 ossl_error("EC_KEY_get_ex_data failed for ec");
532 if (pkcs11_get_key(k11
, CKM_ECDSA
) == -1) {
533 error("pkcs11_get_key failed");
537 f
= k11
->provider
->function_list
;
538 si
= &k11
->provider
->slotinfo
[k11
->slotidx
];
540 siglen
= ECDSA_size(ec
);
541 sig
= xmalloc(siglen
);
543 /* XXX handle CKR_BUFFER_TOO_SMALL */
544 rv
= f
->C_Sign(si
->session
, (CK_BYTE
*)dgst
, dgst_len
, sig
, &siglen
);
546 error("C_Sign failed: %lu", rv
);
549 if (siglen
< 64 || siglen
> 132 || siglen
% 2) {
550 error_f("bad signature length: %lu", (u_long
)siglen
);
554 if ((ret
= ECDSA_SIG_new()) == NULL
) {
555 error("ECDSA_SIG_new failed");
558 if ((r
= BN_bin2bn(sig
, bnlen
, NULL
)) == NULL
||
559 (s
= BN_bin2bn(sig
+bnlen
, bnlen
, NULL
)) == NULL
) {
560 ossl_error("BN_bin2bn failed");
565 if (!ECDSA_SIG_set0(ret
, r
, s
)) {
566 error_f("ECDSA_SIG_set0 failed");
571 r
= s
= NULL
; /* now owned by ret */
582 pkcs11_ecdsa_start_wrapper(void)
584 int (*orig_sign
)(int, const unsigned char *, int, unsigned char *,
585 unsigned int *, const BIGNUM
*, const BIGNUM
*, EC_KEY
*) = NULL
;
587 if (ec_key_method
!= NULL
)
589 ec_key_idx
= EC_KEY_get_ex_new_index(0, "ssh-pkcs11-ecdsa",
590 NULL
, NULL
, pkcs11_k11_free
);
591 if (ec_key_idx
== -1)
593 ec_key_method
= EC_KEY_METHOD_new(EC_KEY_OpenSSL());
594 if (ec_key_method
== NULL
)
596 EC_KEY_METHOD_get_sign(ec_key_method
, &orig_sign
, NULL
, NULL
);
597 EC_KEY_METHOD_set_sign(ec_key_method
, orig_sign
, NULL
, ecdsa_do_sign
);
602 pkcs11_ecdsa_wrap(struct pkcs11_provider
*provider
, CK_ULONG slotidx
,
603 CK_ATTRIBUTE
*keyid_attrib
, EC_KEY
*ec
)
605 struct pkcs11_key
*k11
;
607 if (pkcs11_ecdsa_start_wrapper() == -1)
610 k11
= xcalloc(1, sizeof(*k11
));
611 k11
->provider
= provider
;
612 provider
->refcount
++; /* provider referenced by ECDSA key */
613 k11
->slotidx
= slotidx
;
614 /* identify key object on smartcard */
615 k11
->keyid_len
= keyid_attrib
->ulValueLen
;
616 if (k11
->keyid_len
> 0) {
617 k11
->keyid
= xmalloc(k11
->keyid_len
);
618 memcpy(k11
->keyid
, keyid_attrib
->pValue
, k11
->keyid_len
);
620 if (EC_KEY_set_method(ec
, ec_key_method
) != 1)
621 fatal_f("EC_KEY_set_method failed");
622 if (EC_KEY_set_ex_data(ec
, ec_key_idx
, k11
) != 1)
623 fatal_f("EC_KEY_set_ex_data failed");
627 #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
629 /* remove trailing spaces */
631 rmspace(u_char
*buf
, size_t len
)
637 for (i
= len
- 1; i
> 0; i
--)
644 /* Used to printf fixed-width, space-padded, unterminated strings using %.*s */
645 #define RMSPACE(s) (int)sizeof(s), rmspace(s, sizeof(s))
648 * open a pkcs11 session and login if required.
649 * if pin == NULL we delay login until key use
652 pkcs11_open_session(struct pkcs11_provider
*p
, CK_ULONG slotidx
, char *pin
,
655 struct pkcs11_slotinfo
*si
;
658 CK_SESSION_HANDLE session
;
659 int login_required
, ret
;
661 f
= p
->function_list
;
662 si
= &p
->slotinfo
[slotidx
];
664 login_required
= si
->token
.flags
& CKF_LOGIN_REQUIRED
;
666 /* fail early before opening session */
667 if (login_required
&& !pkcs11_interactive
&&
668 (pin
== NULL
|| strlen(pin
) == 0)) {
669 error("pin required");
670 return (-SSH_PKCS11_ERR_PIN_REQUIRED
);
672 if ((rv
= f
->C_OpenSession(p
->slotlist
[slotidx
], CKF_RW_SESSION
|
673 CKF_SERIAL_SESSION
, NULL
, NULL
, &session
)) != CKR_OK
) {
674 error("C_OpenSession failed: %lu", rv
);
677 if (login_required
&& pin
!= NULL
&& strlen(pin
) != 0) {
678 rv
= f
->C_Login(session
, user
, (u_char
*)pin
, strlen(pin
));
679 if (rv
!= CKR_OK
&& rv
!= CKR_USER_ALREADY_LOGGED_IN
) {
680 error("C_Login failed: %lu", rv
);
681 ret
= (rv
== CKR_PIN_LOCKED
) ?
682 -SSH_PKCS11_ERR_PIN_LOCKED
:
683 -SSH_PKCS11_ERR_LOGIN_FAIL
;
684 if ((rv
= f
->C_CloseSession(session
)) != CKR_OK
)
685 error("C_CloseSession failed: %lu", rv
);
690 si
->session
= session
;
695 pkcs11_key_included(struct sshkey
***keysp
, int *nkeys
, struct sshkey
*key
)
699 for (i
= 0; i
< *nkeys
; i
++)
700 if (sshkey_equal(key
, (*keysp
)[i
]))
705 #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
706 static struct sshkey
*
707 pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider
*p
, CK_ULONG slotidx
,
708 CK_OBJECT_HANDLE
*obj
)
710 CK_ATTRIBUTE key_attr
[3];
711 CK_SESSION_HANDLE session
;
712 CK_FUNCTION_LIST
*f
= NULL
;
714 ASN1_OCTET_STRING
*octet
= NULL
;
716 EC_GROUP
*group
= NULL
;
717 struct sshkey
*key
= NULL
;
718 const unsigned char *attrp
= NULL
;
722 memset(&key_attr
, 0, sizeof(key_attr
));
723 key_attr
[0].type
= CKA_ID
;
724 key_attr
[1].type
= CKA_EC_POINT
;
725 key_attr
[2].type
= CKA_EC_PARAMS
;
727 session
= p
->slotinfo
[slotidx
].session
;
728 f
= p
->function_list
;
730 /* figure out size of the attributes */
731 rv
= f
->C_GetAttributeValue(session
, *obj
, key_attr
, 3);
733 error("C_GetAttributeValue failed: %lu", rv
);
738 * Allow CKA_ID (always first attribute) to be empty, but
739 * ensure that none of the others are zero length.
740 * XXX assumes CKA_ID is always first.
742 if (key_attr
[1].ulValueLen
== 0 ||
743 key_attr
[2].ulValueLen
== 0) {
744 error("invalid attribute length");
748 /* allocate buffers for attributes */
749 for (i
= 0; i
< 3; i
++)
750 if (key_attr
[i
].ulValueLen
> 0)
751 key_attr
[i
].pValue
= xcalloc(1, key_attr
[i
].ulValueLen
);
753 /* retrieve ID, public point and curve parameters of EC key */
754 rv
= f
->C_GetAttributeValue(session
, *obj
, key_attr
, 3);
756 error("C_GetAttributeValue failed: %lu", rv
);
762 error("EC_KEY_new failed");
766 attrp
= key_attr
[2].pValue
;
767 group
= d2i_ECPKParameters(NULL
, &attrp
, key_attr
[2].ulValueLen
);
769 ossl_error("d2i_ECPKParameters failed");
773 if (EC_KEY_set_group(ec
, group
) == 0) {
774 ossl_error("EC_KEY_set_group failed");
778 if (key_attr
[1].ulValueLen
<= 2) {
779 error("CKA_EC_POINT too small");
783 attrp
= key_attr
[1].pValue
;
784 octet
= d2i_ASN1_OCTET_STRING(NULL
, &attrp
, key_attr
[1].ulValueLen
);
786 ossl_error("d2i_ASN1_OCTET_STRING failed");
790 if (o2i_ECPublicKey(&ec
, &attrp
, octet
->length
) == NULL
) {
791 ossl_error("o2i_ECPublicKey failed");
795 nid
= sshkey_ecdsa_key_to_nid(ec
);
797 error("couldn't get curve nid");
801 if (pkcs11_ecdsa_wrap(p
, slotidx
, &key_attr
[0], ec
))
804 key
= sshkey_new(KEY_UNSPEC
);
806 error("sshkey_new failed");
810 EVP_PKEY_free(key
->pkey
);
811 if ((key
->pkey
= EVP_PKEY_new()) == NULL
)
812 fatal("EVP_PKEY_new failed");
813 if (EVP_PKEY_set1_EC_KEY(key
->pkey
, ec
) != 1)
814 fatal("EVP_PKEY_set1_EC_KEY failed");
815 key
->ecdsa_nid
= nid
;
816 key
->type
= KEY_ECDSA
;
817 key
->flags
|= SSHKEY_FLAG_EXT
;
820 for (i
= 0; i
< 3; i
++)
821 free(key_attr
[i
].pValue
);
825 EC_GROUP_free(group
);
827 ASN1_OCTET_STRING_free(octet
);
831 #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
833 static struct sshkey
*
834 pkcs11_fetch_rsa_pubkey(struct pkcs11_provider
*p
, CK_ULONG slotidx
,
835 CK_OBJECT_HANDLE
*obj
)
837 CK_ATTRIBUTE key_attr
[3];
838 CK_SESSION_HANDLE session
;
839 CK_FUNCTION_LIST
*f
= NULL
;
842 BIGNUM
*rsa_n
, *rsa_e
;
843 struct sshkey
*key
= NULL
;
846 memset(&key_attr
, 0, sizeof(key_attr
));
847 key_attr
[0].type
= CKA_ID
;
848 key_attr
[1].type
= CKA_MODULUS
;
849 key_attr
[2].type
= CKA_PUBLIC_EXPONENT
;
851 session
= p
->slotinfo
[slotidx
].session
;
852 f
= p
->function_list
;
854 /* figure out size of the attributes */
855 rv
= f
->C_GetAttributeValue(session
, *obj
, key_attr
, 3);
857 error("C_GetAttributeValue failed: %lu", rv
);
862 * Allow CKA_ID (always first attribute) to be empty, but
863 * ensure that none of the others are zero length.
864 * XXX assumes CKA_ID is always first.
866 if (key_attr
[1].ulValueLen
== 0 ||
867 key_attr
[2].ulValueLen
== 0) {
868 error("invalid attribute length");
872 /* allocate buffers for attributes */
873 for (i
= 0; i
< 3; i
++)
874 if (key_attr
[i
].ulValueLen
> 0)
875 key_attr
[i
].pValue
= xcalloc(1, key_attr
[i
].ulValueLen
);
877 /* retrieve ID, modulus and public exponent of RSA key */
878 rv
= f
->C_GetAttributeValue(session
, *obj
, key_attr
, 3);
880 error("C_GetAttributeValue failed: %lu", rv
);
886 error("RSA_new failed");
890 rsa_n
= BN_bin2bn(key_attr
[1].pValue
, key_attr
[1].ulValueLen
, NULL
);
891 rsa_e
= BN_bin2bn(key_attr
[2].pValue
, key_attr
[2].ulValueLen
, NULL
);
892 if (rsa_n
== NULL
|| rsa_e
== NULL
) {
893 error("BN_bin2bn failed");
896 if (!RSA_set0_key(rsa
, rsa_n
, rsa_e
, NULL
))
898 rsa_n
= rsa_e
= NULL
; /* transferred */
900 if (pkcs11_rsa_wrap(p
, slotidx
, &key_attr
[0], rsa
))
903 key
= sshkey_new(KEY_UNSPEC
);
905 error("sshkey_new failed");
909 EVP_PKEY_free(key
->pkey
);
910 if ((key
->pkey
= EVP_PKEY_new()) == NULL
)
911 fatal("EVP_PKEY_new failed");
912 if (EVP_PKEY_set1_RSA(key
->pkey
, rsa
) != 1)
913 fatal("EVP_PKEY_set1_RSA failed");
915 key
->flags
|= SSHKEY_FLAG_EXT
;
918 for (i
= 0; i
< 3; i
++)
919 free(key_attr
[i
].pValue
);
926 pkcs11_fetch_x509_pubkey(struct pkcs11_provider
*p
, CK_ULONG slotidx
,
927 CK_OBJECT_HANDLE
*obj
, struct sshkey
**keyp
, char **labelp
)
929 CK_ATTRIBUTE cert_attr
[3];
930 CK_SESSION_HANDLE session
;
931 CK_FUNCTION_LIST
*f
= NULL
;
934 X509_NAME
*x509_name
= NULL
;
937 #ifdef OPENSSL_HAS_ECC
940 struct sshkey
*key
= NULL
;
942 #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
946 char *subject
= NULL
;
951 memset(&cert_attr
, 0, sizeof(cert_attr
));
952 cert_attr
[0].type
= CKA_ID
;
953 cert_attr
[1].type
= CKA_SUBJECT
;
954 cert_attr
[2].type
= CKA_VALUE
;
956 session
= p
->slotinfo
[slotidx
].session
;
957 f
= p
->function_list
;
959 /* figure out size of the attributes */
960 rv
= f
->C_GetAttributeValue(session
, *obj
, cert_attr
, 3);
962 error("C_GetAttributeValue failed: %lu", rv
);
967 * Allow CKA_ID (always first attribute) to be empty, but
968 * ensure that none of the others are zero length.
969 * XXX assumes CKA_ID is always first.
971 if (cert_attr
[1].ulValueLen
== 0 ||
972 cert_attr
[2].ulValueLen
== 0) {
973 error("invalid attribute length");
977 /* allocate buffers for attributes */
978 for (i
= 0; i
< 3; i
++)
979 if (cert_attr
[i
].ulValueLen
> 0)
980 cert_attr
[i
].pValue
= xcalloc(1, cert_attr
[i
].ulValueLen
);
982 /* retrieve ID, subject and value of certificate */
983 rv
= f
->C_GetAttributeValue(session
, *obj
, cert_attr
, 3);
985 error("C_GetAttributeValue failed: %lu", rv
);
989 /* Decode DER-encoded cert subject */
990 cp
= cert_attr
[1].pValue
;
991 if ((x509_name
= d2i_X509_NAME(NULL
, &cp
,
992 cert_attr
[1].ulValueLen
)) == NULL
||
993 (subject
= X509_NAME_oneline(x509_name
, NULL
, 0)) == NULL
)
994 subject
= xstrdup("invalid subject");
995 X509_NAME_free(x509_name
);
997 cp
= cert_attr
[2].pValue
;
998 if ((x509
= d2i_X509(NULL
, &cp
, cert_attr
[2].ulValueLen
)) == NULL
) {
999 error("d2i_x509 failed");
1003 if ((evp
= X509_get_pubkey(x509
)) == NULL
) {
1004 error("X509_get_pubkey failed");
1008 if (EVP_PKEY_base_id(evp
) == EVP_PKEY_RSA
) {
1009 if (EVP_PKEY_get0_RSA(evp
) == NULL
) {
1010 error("invalid x509; no rsa key");
1013 if ((rsa
= RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp
))) == NULL
) {
1014 error("RSAPublicKey_dup failed");
1018 if (pkcs11_rsa_wrap(p
, slotidx
, &cert_attr
[0], rsa
))
1021 key
= sshkey_new(KEY_UNSPEC
);
1023 error("sshkey_new failed");
1027 EVP_PKEY_free(key
->pkey
);
1028 if ((key
->pkey
= EVP_PKEY_new()) == NULL
)
1029 fatal("EVP_PKEY_new failed");
1030 if (EVP_PKEY_set1_RSA(key
->pkey
, rsa
) != 1)
1031 fatal("EVP_PKEY_set1_RSA failed");
1032 key
->type
= KEY_RSA
;
1033 key
->flags
|= SSHKEY_FLAG_EXT
;
1034 #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
1035 } else if (EVP_PKEY_base_id(evp
) == EVP_PKEY_EC
) {
1036 if (EVP_PKEY_get0_EC_KEY(evp
) == NULL
) {
1037 error("invalid x509; no ec key");
1040 if ((ec
= EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp
))) == NULL
) {
1041 error("EC_KEY_dup failed");
1045 nid
= sshkey_ecdsa_key_to_nid(ec
);
1047 error("couldn't get curve nid");
1051 if (pkcs11_ecdsa_wrap(p
, slotidx
, &cert_attr
[0], ec
))
1054 key
= sshkey_new(KEY_UNSPEC
);
1056 error("sshkey_new failed");
1060 EVP_PKEY_free(key
->pkey
);
1061 if ((key
->pkey
= EVP_PKEY_new()) == NULL
)
1062 fatal("EVP_PKEY_new failed");
1063 if (EVP_PKEY_set1_EC_KEY(key
->pkey
, ec
) != 1)
1064 fatal("EVP_PKEY_set1_EC_KEY failed");
1065 key
->ecdsa_nid
= nid
;
1066 key
->type
= KEY_ECDSA
;
1067 key
->flags
|= SSHKEY_FLAG_EXT
;
1068 #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
1070 error("unknown certificate key type");
1074 for (i
= 0; i
< 3; i
++)
1075 free(cert_attr
[i
].pValue
);
1078 #ifdef OPENSSL_HAS_ECC
1093 have_rsa_key(const RSA
*rsa
)
1095 const BIGNUM
*rsa_n
, *rsa_e
;
1097 RSA_get0_key(rsa
, &rsa_n
, &rsa_e
, NULL
);
1098 return rsa_n
!= NULL
&& rsa_e
!= NULL
;
1103 note_key(struct pkcs11_provider
*p
, CK_ULONG slotidx
, const char *context
,
1108 if ((fp
= sshkey_fingerprint(key
, SSH_FP_HASH_DEFAULT
,
1109 SSH_FP_DEFAULT
)) == NULL
) {
1110 error_f("sshkey_fingerprint failed");
1113 debug2("%s: provider %s slot %lu: %s %s", context
, p
->name
,
1114 (u_long
)slotidx
, sshkey_type(key
), fp
);
1119 * lookup certificates for token in slot identified by slotidx,
1120 * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
1121 * keysp points to an (possibly empty) array with *nkeys keys.
1124 pkcs11_fetch_certs(struct pkcs11_provider
*p
, CK_ULONG slotidx
,
1125 struct sshkey
***keysp
, char ***labelsp
, int *nkeys
)
1127 struct sshkey
*key
= NULL
;
1128 CK_OBJECT_CLASS key_class
;
1129 CK_ATTRIBUTE key_attr
[1];
1130 CK_SESSION_HANDLE session
;
1131 CK_FUNCTION_LIST
*f
= NULL
;
1133 CK_OBJECT_HANDLE obj
;
1138 memset(&key_attr
, 0, sizeof(key_attr
));
1139 memset(&obj
, 0, sizeof(obj
));
1141 key_class
= CKO_CERTIFICATE
;
1142 key_attr
[0].type
= CKA_CLASS
;
1143 key_attr
[0].pValue
= &key_class
;
1144 key_attr
[0].ulValueLen
= sizeof(key_class
);
1146 session
= p
->slotinfo
[slotidx
].session
;
1147 f
= p
->function_list
;
1149 rv
= f
->C_FindObjectsInit(session
, key_attr
, 1);
1151 error("C_FindObjectsInit failed: %lu", rv
);
1156 CK_CERTIFICATE_TYPE ck_cert_type
;
1158 rv
= f
->C_FindObjects(session
, &obj
, 1, &n
);
1160 error("C_FindObjects failed: %lu", rv
);
1166 memset(&ck_cert_type
, 0, sizeof(ck_cert_type
));
1167 memset(&key_attr
, 0, sizeof(key_attr
));
1168 key_attr
[0].type
= CKA_CERTIFICATE_TYPE
;
1169 key_attr
[0].pValue
= &ck_cert_type
;
1170 key_attr
[0].ulValueLen
= sizeof(ck_cert_type
);
1172 rv
= f
->C_GetAttributeValue(session
, obj
, key_attr
, 1);
1174 error("C_GetAttributeValue failed: %lu", rv
);
1180 switch (ck_cert_type
) {
1182 if (pkcs11_fetch_x509_pubkey(p
, slotidx
, &obj
,
1183 &key
, &label
) != 0) {
1184 error("failed to fetch key");
1189 error("skipping unsupported certificate type %lu",
1193 note_key(p
, slotidx
, __func__
, key
);
1194 if (pkcs11_key_included(keysp
, nkeys
, key
)) {
1195 debug2_f("key already included");
1198 /* expand key array and add key */
1199 *keysp
= xrecallocarray(*keysp
, *nkeys
,
1200 *nkeys
+ 1, sizeof(struct sshkey
*));
1201 (*keysp
)[*nkeys
] = key
;
1202 if (labelsp
!= NULL
) {
1203 *labelsp
= xrecallocarray(*labelsp
, *nkeys
,
1204 *nkeys
+ 1, sizeof(char *));
1205 (*labelsp
)[*nkeys
] = xstrdup((char *)label
);
1207 *nkeys
= *nkeys
+ 1;
1208 debug("have %d keys", *nkeys
);
1214 rv
= f
->C_FindObjectsFinal(session
);
1216 error("C_FindObjectsFinal failed: %lu", rv
);
1224 * lookup public keys for token in slot identified by slotidx,
1225 * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
1226 * keysp points to an (possibly empty) array with *nkeys keys.
1229 pkcs11_fetch_keys(struct pkcs11_provider
*p
, CK_ULONG slotidx
,
1230 struct sshkey
***keysp
, char ***labelsp
, int *nkeys
)
1232 struct sshkey
*key
= NULL
;
1233 CK_OBJECT_CLASS key_class
;
1234 CK_ATTRIBUTE key_attr
[2];
1235 CK_SESSION_HANDLE session
;
1236 CK_FUNCTION_LIST
*f
= NULL
;
1238 CK_OBJECT_HANDLE obj
;
1242 memset(&key_attr
, 0, sizeof(key_attr
));
1243 memset(&obj
, 0, sizeof(obj
));
1245 key_class
= CKO_PUBLIC_KEY
;
1246 key_attr
[0].type
= CKA_CLASS
;
1247 key_attr
[0].pValue
= &key_class
;
1248 key_attr
[0].ulValueLen
= sizeof(key_class
);
1250 session
= p
->slotinfo
[slotidx
].session
;
1251 f
= p
->function_list
;
1253 rv
= f
->C_FindObjectsInit(session
, key_attr
, 1);
1255 error("C_FindObjectsInit failed: %lu", rv
);
1260 CK_KEY_TYPE ck_key_type
;
1261 CK_UTF8CHAR label
[256];
1263 rv
= f
->C_FindObjects(session
, &obj
, 1, &n
);
1265 error("C_FindObjects failed: %lu", rv
);
1271 memset(&ck_key_type
, 0, sizeof(ck_key_type
));
1272 memset(&key_attr
, 0, sizeof(key_attr
));
1273 key_attr
[0].type
= CKA_KEY_TYPE
;
1274 key_attr
[0].pValue
= &ck_key_type
;
1275 key_attr
[0].ulValueLen
= sizeof(ck_key_type
);
1276 key_attr
[1].type
= CKA_LABEL
;
1277 key_attr
[1].pValue
= &label
;
1278 key_attr
[1].ulValueLen
= sizeof(label
) - 1;
1280 rv
= f
->C_GetAttributeValue(session
, obj
, key_attr
, 2);
1282 error("C_GetAttributeValue failed: %lu", rv
);
1286 label
[key_attr
[1].ulValueLen
] = '\0';
1288 switch (ck_key_type
) {
1290 key
= pkcs11_fetch_rsa_pubkey(p
, slotidx
, &obj
);
1292 #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
1294 key
= pkcs11_fetch_ecdsa_pubkey(p
, slotidx
, &obj
);
1296 #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
1298 /* XXX print key type? */
1300 error("skipping unsupported key type");
1304 error("failed to fetch key");
1307 note_key(p
, slotidx
, __func__
, key
);
1308 if (pkcs11_key_included(keysp
, nkeys
, key
)) {
1309 debug2_f("key already included");
1312 /* expand key array and add key */
1313 *keysp
= xrecallocarray(*keysp
, *nkeys
,
1314 *nkeys
+ 1, sizeof(struct sshkey
*));
1315 (*keysp
)[*nkeys
] = key
;
1316 if (labelsp
!= NULL
) {
1317 *labelsp
= xrecallocarray(*labelsp
, *nkeys
,
1318 *nkeys
+ 1, sizeof(char *));
1319 (*labelsp
)[*nkeys
] = xstrdup((char *)label
);
1321 *nkeys
= *nkeys
+ 1;
1322 debug("have %d keys", *nkeys
);
1328 rv
= f
->C_FindObjectsFinal(session
);
1330 error("C_FindObjectsFinal failed: %lu", rv
);
1337 #ifdef WITH_PKCS11_KEYGEN
1338 #define FILL_ATTR(attr, idx, typ, val, len) \
1339 { (attr[idx]).type=(typ); (attr[idx]).pValue=(val); (attr[idx]).ulValueLen=len; idx++; }
1341 static struct sshkey
*
1342 pkcs11_rsa_generate_private_key(struct pkcs11_provider
*p
, CK_ULONG slotidx
,
1343 char *label
, CK_ULONG bits
, CK_BYTE keyid
, u_int32_t
*err
)
1345 struct pkcs11_slotinfo
*si
;
1346 char *plabel
= label
? label
: "";
1347 int npub
= 0, npriv
= 0;
1349 CK_FUNCTION_LIST
*f
;
1350 CK_SESSION_HANDLE session
;
1351 CK_BBOOL true_val
= CK_TRUE
, false_val
= CK_FALSE
;
1352 CK_OBJECT_HANDLE pubKey
, privKey
;
1353 CK_ATTRIBUTE tpub
[16], tpriv
[16];
1354 CK_MECHANISM mech
= {
1355 CKM_RSA_PKCS_KEY_PAIR_GEN
, NULL_PTR
, 0
1357 CK_BYTE pubExponent
[] = {
1358 0x01, 0x00, 0x01 /* RSA_F4 in bytes */
1360 pubkey_filter
[0].pValue
= &pubkey_class
;
1361 cert_filter
[0].pValue
= &cert_class
;
1365 FILL_ATTR(tpub
, npub
, CKA_TOKEN
, &true_val
, sizeof(true_val
));
1366 FILL_ATTR(tpub
, npub
, CKA_LABEL
, plabel
, strlen(plabel
));
1367 FILL_ATTR(tpub
, npub
, CKA_ENCRYPT
, &false_val
, sizeof(false_val
));
1368 FILL_ATTR(tpub
, npub
, CKA_VERIFY
, &true_val
, sizeof(true_val
));
1369 FILL_ATTR(tpub
, npub
, CKA_VERIFY_RECOVER
, &false_val
,
1371 FILL_ATTR(tpub
, npub
, CKA_WRAP
, &false_val
, sizeof(false_val
));
1372 FILL_ATTR(tpub
, npub
, CKA_DERIVE
, &false_val
, sizeof(false_val
));
1373 FILL_ATTR(tpub
, npub
, CKA_MODULUS_BITS
, &bits
, sizeof(bits
));
1374 FILL_ATTR(tpub
, npub
, CKA_PUBLIC_EXPONENT
, pubExponent
,
1375 sizeof(pubExponent
));
1376 FILL_ATTR(tpub
, npub
, CKA_ID
, &keyid
, sizeof(keyid
));
1378 FILL_ATTR(tpriv
, npriv
, CKA_TOKEN
, &true_val
, sizeof(true_val
));
1379 FILL_ATTR(tpriv
, npriv
, CKA_LABEL
, plabel
, strlen(plabel
));
1380 FILL_ATTR(tpriv
, npriv
, CKA_PRIVATE
, &true_val
, sizeof(true_val
));
1381 FILL_ATTR(tpriv
, npriv
, CKA_SENSITIVE
, &true_val
, sizeof(true_val
));
1382 FILL_ATTR(tpriv
, npriv
, CKA_DECRYPT
, &false_val
, sizeof(false_val
));
1383 FILL_ATTR(tpriv
, npriv
, CKA_SIGN
, &true_val
, sizeof(true_val
));
1384 FILL_ATTR(tpriv
, npriv
, CKA_SIGN_RECOVER
, &false_val
,
1386 FILL_ATTR(tpriv
, npriv
, CKA_UNWRAP
, &false_val
, sizeof(false_val
));
1387 FILL_ATTR(tpriv
, npriv
, CKA_DERIVE
, &false_val
, sizeof(false_val
));
1388 FILL_ATTR(tpriv
, npriv
, CKA_ID
, &keyid
, sizeof(keyid
));
1390 f
= p
->function_list
;
1391 si
= &p
->slotinfo
[slotidx
];
1392 session
= si
->session
;
1394 if ((rv
= f
->C_GenerateKeyPair(session
, &mech
, tpub
, npub
, tpriv
, npriv
,
1395 &pubKey
, &privKey
)) != CKR_OK
) {
1396 error_f("key generation failed: error 0x%lx", rv
);
1401 return pkcs11_fetch_rsa_pubkey(p
, slotidx
, &pubKey
);
1407 if (c
>= '0' && c
<= '9')
1409 else if (c
>= 'a' && c
<= 'f')
1410 return c
- 'a' + 10;
1411 else if (c
>= 'A' && c
<= 'F')
1412 return c
- 'A' + 10;
1418 pkcs11_decode_hex(const char *hex
, unsigned char **dest
, size_t *rlen
)
1427 if ((len
= strlen(hex
)) % 2)
1431 *dest
= xmalloc(len
);
1433 for (i
= 0; i
< len
; i
++) {
1436 hi
= h2i(hex
[2 * i
]);
1437 lo
= h2i(hex
[(2 * i
) + 1]);
1438 if (hi
== -1 || lo
== -1)
1440 (*dest
)[i
] = (hi
<< 4) | lo
;
1449 static struct ec_curve_info
{
1452 const char *oid_encoded
;
1454 } ec_curve_infos
[] = {
1455 {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256},
1456 {"secp384r1", "1.3.132.0.34", "06052B81040022", 384},
1457 {"secp521r1", "1.3.132.0.35", "06052B81040023", 521},
1458 {NULL
, NULL
, NULL
, 0},
1461 static struct sshkey
*
1462 pkcs11_ecdsa_generate_private_key(struct pkcs11_provider
*p
, CK_ULONG slotidx
,
1463 char *label
, CK_ULONG bits
, CK_BYTE keyid
, u_int32_t
*err
)
1465 struct pkcs11_slotinfo
*si
;
1466 char *plabel
= label
? label
: "";
1468 size_t ecparams_size
;
1469 unsigned char *ecparams
= NULL
;
1470 int npub
= 0, npriv
= 0;
1472 CK_FUNCTION_LIST
*f
;
1473 CK_SESSION_HANDLE session
;
1474 CK_BBOOL true_val
= CK_TRUE
, false_val
= CK_FALSE
;
1475 CK_OBJECT_HANDLE pubKey
, privKey
;
1476 CK_MECHANISM mech
= {
1477 CKM_EC_KEY_PAIR_GEN
, NULL_PTR
, 0
1479 CK_ATTRIBUTE tpub
[16], tpriv
[16];
1483 for (i
= 0; ec_curve_infos
[i
].name
; i
++) {
1484 if (ec_curve_infos
[i
].size
== bits
)
1487 if (!ec_curve_infos
[i
].name
) {
1488 error_f("invalid key size %lu", bits
);
1491 if (pkcs11_decode_hex(ec_curve_infos
[i
].oid_encoded
, &ecparams
,
1492 &ecparams_size
) == -1) {
1493 error_f("invalid oid");
1497 FILL_ATTR(tpub
, npub
, CKA_TOKEN
, &true_val
, sizeof(true_val
));
1498 FILL_ATTR(tpub
, npub
, CKA_LABEL
, plabel
, strlen(plabel
));
1499 FILL_ATTR(tpub
, npub
, CKA_ENCRYPT
, &false_val
, sizeof(false_val
));
1500 FILL_ATTR(tpub
, npub
, CKA_VERIFY
, &true_val
, sizeof(true_val
));
1501 FILL_ATTR(tpub
, npub
, CKA_VERIFY_RECOVER
, &false_val
,
1503 FILL_ATTR(tpub
, npub
, CKA_WRAP
, &false_val
, sizeof(false_val
));
1504 FILL_ATTR(tpub
, npub
, CKA_DERIVE
, &false_val
, sizeof(false_val
));
1505 FILL_ATTR(tpub
, npub
, CKA_EC_PARAMS
, ecparams
, ecparams_size
);
1506 FILL_ATTR(tpub
, npub
, CKA_ID
, &keyid
, sizeof(keyid
));
1508 FILL_ATTR(tpriv
, npriv
, CKA_TOKEN
, &true_val
, sizeof(true_val
));
1509 FILL_ATTR(tpriv
, npriv
, CKA_LABEL
, plabel
, strlen(plabel
));
1510 FILL_ATTR(tpriv
, npriv
, CKA_PRIVATE
, &true_val
, sizeof(true_val
));
1511 FILL_ATTR(tpriv
, npriv
, CKA_SENSITIVE
, &true_val
, sizeof(true_val
));
1512 FILL_ATTR(tpriv
, npriv
, CKA_DECRYPT
, &false_val
, sizeof(false_val
));
1513 FILL_ATTR(tpriv
, npriv
, CKA_SIGN
, &true_val
, sizeof(true_val
));
1514 FILL_ATTR(tpriv
, npriv
, CKA_SIGN_RECOVER
, &false_val
,
1516 FILL_ATTR(tpriv
, npriv
, CKA_UNWRAP
, &false_val
, sizeof(false_val
));
1517 FILL_ATTR(tpriv
, npriv
, CKA_DERIVE
, &false_val
, sizeof(false_val
));
1518 FILL_ATTR(tpriv
, npriv
, CKA_ID
, &keyid
, sizeof(keyid
));
1520 f
= p
->function_list
;
1521 si
= &p
->slotinfo
[slotidx
];
1522 session
= si
->session
;
1524 if ((rv
= f
->C_GenerateKeyPair(session
, &mech
, tpub
, npub
, tpriv
, npriv
,
1525 &pubKey
, &privKey
)) != CKR_OK
) {
1526 error_f("key generation failed: error 0x%lx", rv
);
1531 return pkcs11_fetch_ecdsa_pubkey(p
, slotidx
, &pubKey
);
1533 #endif /* WITH_PKCS11_KEYGEN */
1536 * register a new provider, fails if provider already exists. if
1537 * keyp is provided, fetch keys.
1540 pkcs11_register_provider(char *provider_id
, char *pin
,
1541 struct sshkey
***keyp
, char ***labelsp
,
1542 struct pkcs11_provider
**providerp
, CK_ULONG user
)
1544 int nkeys
, need_finalize
= 0;
1546 struct pkcs11_provider
*p
= NULL
;
1547 void *handle
= NULL
;
1548 CK_RV (*getfunctionlist
)(CK_FUNCTION_LIST
**);
1550 CK_FUNCTION_LIST
*f
= NULL
;
1551 CK_TOKEN_INFO
*token
;
1554 if (providerp
== NULL
)
1560 if (labelsp
!= NULL
)
1563 if (pkcs11_provider_lookup(provider_id
) != NULL
) {
1564 debug_f("provider already registered: %s", provider_id
);
1567 if (lib_contains_symbol(provider_id
, "C_GetFunctionList") != 0) {
1568 error("provider %s is not a PKCS11 library", provider_id
);
1571 /* open shared pkcs11-library */
1572 if ((handle
= dlopen(provider_id
, RTLD_NOW
)) == NULL
) {
1573 error("dlopen %s failed: %s", provider_id
, dlerror());
1576 if ((getfunctionlist
= dlsym(handle
, "C_GetFunctionList")) == NULL
)
1577 fatal("dlsym(C_GetFunctionList) failed: %s", dlerror());
1578 p
= xcalloc(1, sizeof(*p
));
1579 p
->name
= xstrdup(provider_id
);
1581 /* setup the pkcs11 callbacks */
1582 if ((rv
= (*getfunctionlist
)(&f
)) != CKR_OK
) {
1583 error("C_GetFunctionList for provider %s failed: %lu",
1587 p
->function_list
= f
;
1588 if ((rv
= f
->C_Initialize(NULL
)) != CKR_OK
) {
1589 error("C_Initialize for provider %s failed: %lu",
1594 if ((rv
= f
->C_GetInfo(&p
->info
)) != CKR_OK
) {
1595 error("C_GetInfo for provider %s failed: %lu",
1599 debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d"
1600 " libraryDescription <%.*s> libraryVersion %d.%d",
1602 RMSPACE(p
->info
.manufacturerID
),
1603 p
->info
.cryptokiVersion
.major
,
1604 p
->info
.cryptokiVersion
.minor
,
1605 RMSPACE(p
->info
.libraryDescription
),
1606 p
->info
.libraryVersion
.major
,
1607 p
->info
.libraryVersion
.minor
);
1608 if ((rv
= f
->C_GetSlotList(CK_TRUE
, NULL
, &p
->nslots
)) != CKR_OK
) {
1609 error("C_GetSlotList failed: %lu", rv
);
1612 if (p
->nslots
== 0) {
1613 debug_f("provider %s returned no slots", provider_id
);
1614 ret
= -SSH_PKCS11_ERR_NO_SLOTS
;
1617 p
->slotlist
= xcalloc(p
->nslots
, sizeof(CK_SLOT_ID
));
1618 if ((rv
= f
->C_GetSlotList(CK_TRUE
, p
->slotlist
, &p
->nslots
))
1620 error("C_GetSlotList for provider %s failed: %lu",
1624 p
->slotinfo
= xcalloc(p
->nslots
, sizeof(struct pkcs11_slotinfo
));
1627 for (i
= 0; i
< p
->nslots
; i
++) {
1628 token
= &p
->slotinfo
[i
].token
;
1629 if ((rv
= f
->C_GetTokenInfo(p
->slotlist
[i
], token
))
1631 error("C_GetTokenInfo for provider %s slot %lu "
1632 "failed: %lu", provider_id
, (u_long
)i
, rv
);
1635 if ((token
->flags
& CKF_TOKEN_INITIALIZED
) == 0) {
1636 debug2_f("ignoring uninitialised token in "
1637 "provider %s slot %lu", provider_id
, (u_long
)i
);
1640 debug("provider %s slot %lu: label <%.*s> "
1641 "manufacturerID <%.*s> model <%.*s> serial <%.*s> "
1643 provider_id
, (unsigned long)i
,
1644 RMSPACE(token
->label
), RMSPACE(token
->manufacturerID
),
1645 RMSPACE(token
->model
), RMSPACE(token
->serialNumber
),
1648 * open session, login with pin and retrieve public
1649 * keys (if keyp is provided)
1651 if ((ret
= pkcs11_open_session(p
, i
, pin
, user
)) != 0 ||
1654 pkcs11_fetch_keys(p
, i
, keyp
, labelsp
, &nkeys
);
1655 pkcs11_fetch_certs(p
, i
, keyp
, labelsp
, &nkeys
);
1656 if (nkeys
== 0 && !p
->slotinfo
[i
].logged_in
&&
1657 pkcs11_interactive
) {
1659 * Some tokens require login before they will
1662 if (pkcs11_login_slot(p
, &p
->slotinfo
[i
],
1664 error("login failed");
1667 pkcs11_fetch_keys(p
, i
, keyp
, labelsp
, &nkeys
);
1668 pkcs11_fetch_certs(p
, i
, keyp
, labelsp
, &nkeys
);
1672 /* now owned by caller */
1675 TAILQ_INSERT_TAIL(&pkcs11_providers
, p
, next
);
1676 p
->refcount
++; /* add to provider list */
1680 if (need_finalize
&& (rv
= f
->C_Finalize(NULL
)) != CKR_OK
)
1681 error("C_Finalize for provider %s failed: %lu",
1697 * register a new provider and get number of keys hold by the token,
1698 * fails if provider already exists
1701 pkcs11_add_provider(char *provider_id
, char *pin
, struct sshkey
***keyp
,
1704 struct pkcs11_provider
*p
= NULL
;
1707 nkeys
= pkcs11_register_provider(provider_id
, pin
, keyp
, labelsp
,
1710 /* no keys found or some other error, de-register provider */
1711 if (nkeys
<= 0 && p
!= NULL
) {
1712 TAILQ_REMOVE(&pkcs11_providers
, p
, next
);
1713 pkcs11_provider_finalize(p
);
1714 pkcs11_provider_unref(p
);
1717 debug_f("provider %s returned no keys", provider_id
);
1722 #ifdef WITH_PKCS11_KEYGEN
1724 pkcs11_gakp(char *provider_id
, char *pin
, unsigned int slotidx
, char *label
,
1725 unsigned int type
, unsigned int bits
, unsigned char keyid
, u_int32_t
*err
)
1727 struct pkcs11_provider
*p
= NULL
;
1728 struct pkcs11_slotinfo
*si
;
1729 CK_FUNCTION_LIST
*f
;
1730 CK_SESSION_HANDLE session
;
1731 struct sshkey
*k
= NULL
;
1732 int ret
= -1, reset_pin
= 0, reset_provider
= 0;
1737 if ((p
= pkcs11_provider_lookup(provider_id
)) != NULL
)
1738 debug_f("provider \"%s\" available", provider_id
);
1739 else if ((ret
= pkcs11_register_provider(provider_id
, pin
, NULL
, NULL
,
1741 debug_f("could not register provider %s", provider_id
);
1746 f
= p
->function_list
;
1747 si
= &p
->slotinfo
[slotidx
];
1748 session
= si
->session
;
1750 if ((rv
= f
->C_SetOperationState(session
, pin
, strlen(pin
),
1751 CK_INVALID_HANDLE
, CK_INVALID_HANDLE
)) != CKR_OK
) {
1752 debug_f("could not supply SO pin: %lu", rv
);
1759 if ((k
= pkcs11_rsa_generate_private_key(p
, slotidx
, label
,
1760 bits
, keyid
, err
)) == NULL
) {
1761 debug_f("failed to generate RSA key");
1766 if ((k
= pkcs11_ecdsa_generate_private_key(p
, slotidx
, label
,
1767 bits
, keyid
, err
)) == NULL
) {
1768 debug_f("failed to generate ECDSA key");
1773 *err
= SSH_PKCS11_ERR_GENERIC
;
1774 debug_f("unknown type %d", type
);
1780 f
->C_SetOperationState(session
, NULL
, 0, CK_INVALID_HANDLE
,
1784 pkcs11_del_provider(provider_id
);
1790 pkcs11_destroy_keypair(char *provider_id
, char *pin
, unsigned long slotidx
,
1791 unsigned char keyid
, u_int32_t
*err
)
1793 struct pkcs11_provider
*p
= NULL
;
1794 struct pkcs11_slotinfo
*si
;
1795 struct sshkey
*k
= NULL
;
1796 int reset_pin
= 0, reset_provider
= 0;
1798 CK_FUNCTION_LIST
*f
;
1799 CK_SESSION_HANDLE session
;
1800 CK_ATTRIBUTE attrs
[16];
1801 CK_OBJECT_CLASS key_class
;
1802 CK_KEY_TYPE key_type
;
1803 CK_OBJECT_HANDLE obj
= CK_INVALID_HANDLE
;
1808 if ((p
= pkcs11_provider_lookup(provider_id
)) != NULL
) {
1809 debug_f("using provider \"%s\"", provider_id
);
1810 } else if (pkcs11_register_provider(provider_id
, pin
, NULL
, NULL
, &p
,
1812 debug_f("could not register provider %s",
1818 f
= p
->function_list
;
1819 si
= &p
->slotinfo
[slotidx
];
1820 session
= si
->session
;
1822 if ((rv
= f
->C_SetOperationState(session
, pin
, strlen(pin
),
1823 CK_INVALID_HANDLE
, CK_INVALID_HANDLE
)) != CKR_OK
) {
1824 debug_f("could not supply SO pin: %lu", rv
);
1831 key_class
= CKO_PRIVATE_KEY
;
1832 FILL_ATTR(attrs
, nattrs
, CKA_CLASS
, &key_class
, sizeof(key_class
));
1833 FILL_ATTR(attrs
, nattrs
, CKA_ID
, &keyid
, sizeof(keyid
));
1835 if (pkcs11_find(p
, slotidx
, attrs
, nattrs
, &obj
) == 0 &&
1836 obj
!= CK_INVALID_HANDLE
) {
1837 if ((rv
= f
->C_DestroyObject(session
, obj
)) != CKR_OK
) {
1838 debug_f("could not destroy private key 0x%hhx",
1847 key_class
= CKO_PUBLIC_KEY
;
1848 FILL_ATTR(attrs
, nattrs
, CKA_CLASS
, &key_class
, sizeof(key_class
));
1849 FILL_ATTR(attrs
, nattrs
, CKA_ID
, &keyid
, sizeof(keyid
));
1851 if (pkcs11_find(p
, slotidx
, attrs
, nattrs
, &obj
) == 0 &&
1852 obj
!= CK_INVALID_HANDLE
) {
1856 FILL_ATTR(attrs
, nattrs
, CKA_KEY_TYPE
, &key_type
,
1858 rv
= f
->C_GetAttributeValue(session
, obj
, attrs
, nattrs
);
1860 debug_f("could not get key type of public key 0x%hhx",
1865 if (key_type
== CKK_RSA
)
1866 k
= pkcs11_fetch_rsa_pubkey(p
, slotidx
, &obj
);
1867 else if (key_type
== CKK_ECDSA
)
1868 k
= pkcs11_fetch_ecdsa_pubkey(p
, slotidx
, &obj
);
1870 if ((rv
= f
->C_DestroyObject(session
, obj
)) != CKR_OK
) {
1871 debug_f("could not destroy public key 0x%hhx", keyid
);
1879 f
->C_SetOperationState(session
, NULL
, 0, CK_INVALID_HANDLE
,
1883 pkcs11_del_provider(provider_id
);
1887 #endif /* WITH_PKCS11_KEYGEN */
1888 #else /* ENABLE_PKCS11 */
1890 #include <sys/types.h>
1898 pkcs11_init(int interactive
)
1900 error("%s: dlopen() not supported", __func__
);
1905 pkcs11_add_provider(char *provider_id
, char *pin
, struct sshkey
***keyp
,
1908 error("%s: dlopen() not supported", __func__
);
1913 pkcs11_terminate(void)
1915 error("%s: dlopen() not supported", __func__
);
1917 #endif /* ENABLE_PKCS11 */