1/* $OpenBSD: ssh-pkcs11.c,v 1.59 2023/07/27 22:26:49 djm Exp $ */
2/*
3 * Copyright (c) 2010 Markus Friedl.  All rights reserved.
4 * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
5 *
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.
9 *
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.
17 */
18
19#include "includes.h"
20
21#ifdef ENABLE_PKCS11
22
23#ifdef HAVE_SYS_TIME_H
24# include <sys/time.h>
25#endif
26
27#include <sys/types.h>
28#include <stdarg.h>
29#include <stdio.h>
30
31#include <ctype.h>
32#include <string.h>
33#include <dlfcn.h>
34
35#include "openbsd-compat/sys-queue.h"
36#include "openbsd-compat/openssl-compat.h"
37
38#include <openssl/ecdsa.h>
39#include <openssl/x509.h>
40#include <openssl/err.h>
41
42#define CRYPTOKI_COMPAT
43#include "pkcs11.h"
44
45#include "log.h"
46#include "misc.h"
47#include "sshkey.h"
48#include "ssh-pkcs11.h"
49#include "digest.h"
50#include "xmalloc.h"
51
52struct pkcs11_slotinfo {
53	CK_TOKEN_INFO		token;
54	CK_SESSION_HANDLE	session;
55	int			logged_in;
56};
57
58struct pkcs11_provider {
59	char			*name;
60	void			*handle;
61	CK_FUNCTION_LIST	*function_list;
62	CK_INFO			info;
63	CK_ULONG		nslots;
64	CK_SLOT_ID		*slotlist;
65	struct pkcs11_slotinfo	*slotinfo;
66	int			valid;
67	int			refcount;
68	TAILQ_ENTRY(pkcs11_provider) next;
69};
70
71TAILQ_HEAD(, pkcs11_provider) pkcs11_providers;
72
73struct pkcs11_key {
74	struct pkcs11_provider	*provider;
75	CK_ULONG		slotidx;
76	char			*keyid;
77	int			keyid_len;
78};
79
80int pkcs11_interactive = 0;
81
82#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
83static void
84ossl_error(const char *msg)
85{
86	unsigned long    e;
87
88	error_f("%s", msg);
89	while ((e = ERR_get_error()) != 0)
90		error_f("libcrypto error: %s", ERR_error_string(e, NULL));
91}
92#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
93
94int
95pkcs11_init(int interactive)
96{
97	pkcs11_interactive = interactive;
98	TAILQ_INIT(&pkcs11_providers);
99	return (0);
100}
101
102/*
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.
107 */
108static void
109pkcs11_provider_finalize(struct pkcs11_provider *p)
110{
111	CK_RV rv;
112	CK_ULONG i;
113
114	debug_f("provider \"%s\" refcount %d valid %d",
115	    p->name, p->refcount, p->valid);
116	if (!p->valid)
117		return;
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);
123	}
124	if ((rv = p->function_list->C_Finalize(NULL)) != CKR_OK)
125		error("C_Finalize failed: %lu", rv);
126	p->valid = 0;
127	p->function_list = NULL;
128	dlclose(p->handle);
129}
130
131/*
132 * remove a reference to the provider.
133 * called when a key gets destroyed or when the provider is unregistered.
134 */
135static void
136pkcs11_provider_unref(struct pkcs11_provider *p)
137{
138	debug_f("provider \"%s\" refcount %d", p->name, p->refcount);
139	if (--p->refcount <= 0) {
140		if (p->valid)
141			error_f("provider \"%s\" still valid", p->name);
142		free(p->name);
143		free(p->slotlist);
144		free(p->slotinfo);
145		free(p);
146	}
147}
148
149/* unregister all providers, keys might still point to the providers */
150void
151pkcs11_terminate(void)
152{
153	struct pkcs11_provider *p;
154
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);
159	}
160}
161
162/* lookup provider by name */
163static struct pkcs11_provider *
164pkcs11_provider_lookup(char *provider_id)
165{
166	struct pkcs11_provider *p;
167
168	TAILQ_FOREACH(p, &pkcs11_providers, next) {
169		debug("check provider \"%s\"", p->name);
170		if (!strcmp(provider_id, p->name))
171			return (p);
172	}
173	return (NULL);
174}
175
176/* unregister provider by name */
177int
178pkcs11_del_provider(char *provider_id)
179{
180	struct pkcs11_provider *p;
181
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);
186		return (0);
187	}
188	return (-1);
189}
190
191static RSA_METHOD *rsa_method;
192static int rsa_idx = 0;
193#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
194static EC_KEY_METHOD *ec_key_method;
195static int ec_key_idx = 0;
196#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
197
198/* release a wrapped object */
199static void
200pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
201    long argl, void *argp)
202{
203	struct pkcs11_key	*k11 = ptr;
204
205	debug_f("parent %p ptr %p idx %d", parent, ptr, idx);
206	if (k11 == NULL)
207		return;
208	if (k11->provider)
209		pkcs11_provider_unref(k11->provider);
210	free(k11->keyid);
211	free(k11);
212}
213
214/* find a single 'obj' for given attributes */
215static int
216pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr,
217    CK_ULONG nattr, CK_OBJECT_HANDLE *obj)
218{
219	CK_FUNCTION_LIST	*f;
220	CK_SESSION_HANDLE	session;
221	CK_ULONG		nfound = 0;
222	CK_RV			rv;
223	int			ret = -1;
224
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);
229		return (-1);
230	}
231	if ((rv = f->C_FindObjects(session, obj, 1, &nfound)) != CKR_OK ||
232	    nfound != 1) {
233		debug("C_FindObjects failed (nfound %lu nattr %lu): %lu",
234		    nfound, nattr, rv);
235	} else
236		ret = 0;
237	if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK)
238		error("C_FindObjectsFinal failed: %lu", rv);
239	return (ret);
240}
241
242static int
243pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si,
244    CK_USER_TYPE type)
245{
246	char			*pin = NULL, prompt[1024];
247	CK_RV			 rv;
248
249	if (provider == NULL || si == NULL || !provider->valid) {
250		error("no pkcs11 (valid) provider found");
251		return (-1);
252	}
253
254	if (!pkcs11_interactive) {
255		error("need pin entry%s",
256		    (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ?
257		    " on reader keypad" : "");
258		return (-1);
259	}
260	if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
261		verbose("Deferring PIN entry to reader keypad.");
262	else {
263		snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
264		    si->token.label);
265		if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) {
266			debug_f("no pin specified");
267			return (-1);	/* bail out */
268		}
269	}
270	rv = provider->function_list->C_Login(si->session, type, (u_char *)pin,
271	    (pin != NULL) ? strlen(pin) : 0);
272	if (pin != NULL)
273		freezero(pin, strlen(pin));
274
275	switch (rv) {
276	case CKR_OK:
277	case CKR_USER_ALREADY_LOGGED_IN:
278		/* success */
279		break;
280	case CKR_PIN_LEN_RANGE:
281		error("PKCS#11 login failed: PIN length out of range");
282		return -1;
283	case CKR_PIN_INCORRECT:
284		error("PKCS#11 login failed: PIN incorrect");
285		return -1;
286	case CKR_PIN_LOCKED:
287		error("PKCS#11 login failed: PIN locked");
288		return -1;
289	default:
290		error("PKCS#11 login failed: error %lu", rv);
291		return -1;
292	}
293	si->logged_in = 1;
294	return (0);
295}
296
297static int
298pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type)
299{
300	if (k11 == NULL || k11->provider == NULL || !k11->provider->valid) {
301		error("no pkcs11 (valid) provider found");
302		return (-1);
303	}
304
305	return pkcs11_login_slot(k11->provider,
306	    &k11->provider->slotinfo[k11->slotidx], type);
307}
308
309
310static int
311pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj,
312    CK_ATTRIBUTE_TYPE type, int *val)
313{
314	struct pkcs11_slotinfo	*si;
315	CK_FUNCTION_LIST	*f;
316	CK_BBOOL		flag = 0;
317	CK_ATTRIBUTE		attr;
318	CK_RV			 rv;
319
320	*val = 0;
321
322	if (!k11->provider || !k11->provider->valid) {
323		error("no pkcs11 (valid) provider found");
324		return (-1);
325	}
326
327	f = k11->provider->function_list;
328	si = &k11->provider->slotinfo[k11->slotidx];
329
330	attr.type = type;
331	attr.pValue = &flag;
332	attr.ulValueLen = sizeof(flag);
333
334	rv = f->C_GetAttributeValue(si->session, obj, &attr, 1);
335	if (rv != CKR_OK) {
336		error("C_GetAttributeValue failed: %lu", rv);
337		return (-1);
338	}
339	*val = flag != 0;
340	debug_f("provider \"%s\" slot %lu object %lu: attrib %lu = %d",
341	    k11->provider->name, k11->slotidx, obj, type, *val);
342	return (0);
343}
344
345static int
346pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
347{
348	struct pkcs11_slotinfo	*si;
349	CK_FUNCTION_LIST	*f;
350	CK_OBJECT_HANDLE	 obj;
351	CK_RV			 rv;
352	CK_OBJECT_CLASS		 private_key_class;
353	CK_BBOOL		 true_val;
354	CK_MECHANISM		 mech;
355	CK_ATTRIBUTE		 key_filter[3];
356	int			 always_auth = 0;
357	int			 did_login = 0;
358
359	if (!k11->provider || !k11->provider->valid) {
360		error("no pkcs11 (valid) provider found");
361		return (-1);
362	}
363
364	f = k11->provider->function_list;
365	si = &k11->provider->slotinfo[k11->slotidx];
366
367	if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
368		if (pkcs11_login(k11, CKU_USER) < 0) {
369			error("login failed");
370			return (-1);
371		}
372		did_login = 1;
373	}
374
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);
380
381	key_filter[1].type = CKA_ID;
382	key_filter[1].pValue = k11->keyid;
383	key_filter[1].ulValueLen = k11->keyid_len;
384
385	true_val = CK_TRUE;
386	key_filter[2].type = CKA_SIGN;
387	key_filter[2].pValue = &true_val;
388	key_filter[2].ulValueLen = sizeof(true_val);
389
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");
394		return (-1);
395	}
396
397	memset(&mech, 0, sizeof(mech));
398	mech.mechanism = mech_type;
399	mech.pParameter = NULL_PTR;
400	mech.ulParameterLen = 0;
401
402	if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
403		error("C_SignInit failed: %lu", rv);
404		return (-1);
405	}
406
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");
413			return (-1);
414		}
415	}
416
417	return (0);
418}
419
420/* openssl callback doing the actual signing operation */
421static int
422pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
423    int padding)
424{
425	struct pkcs11_key	*k11;
426	struct pkcs11_slotinfo	*si;
427	CK_FUNCTION_LIST	*f;
428	CK_ULONG		tlen = 0;
429	CK_RV			rv;
430	int			rval = -1;
431
432	if ((k11 = RSA_get_ex_data(rsa, rsa_idx)) == NULL) {
433		error("RSA_get_ex_data failed");
434		return (-1);
435	}
436
437	if (pkcs11_get_key(k11, CKM_RSA_PKCS) == -1) {
438		error("pkcs11_get_key failed");
439		return (-1);
440	}
441
442	f = k11->provider->function_list;
443	si = &k11->provider->slotinfo[k11->slotidx];
444	tlen = RSA_size(rsa);
445
446	/* XXX handle CKR_BUFFER_TOO_SMALL */
447	rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen);
448	if (rv == CKR_OK)
449		rval = tlen;
450	else
451		error("C_Sign failed: %lu", rv);
452
453	return (rval);
454}
455
456static int
457pkcs11_rsa_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
458    int padding)
459{
460	return (-1);
461}
462
463static int
464pkcs11_rsa_start_wrapper(void)
465{
466	if (rsa_method != NULL)
467		return (0);
468	rsa_method = RSA_meth_dup(RSA_get_default_method());
469	if (rsa_method == NULL)
470		return (-1);
471	rsa_idx = RSA_get_ex_new_index(0, "ssh-pkcs11-rsa",
472	    NULL, NULL, pkcs11_k11_free);
473	if (rsa_idx == -1)
474		return (-1);
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");
479		return (-1);
480	}
481	return (0);
482}
483
484/* redirect private key operations for rsa key to pkcs11 token */
485static int
486pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
487    CK_ATTRIBUTE *keyid_attrib, RSA *rsa)
488{
489	struct pkcs11_key	*k11;
490
491	if (pkcs11_rsa_start_wrapper() == -1)
492		return (-1);
493
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);
503	}
504
505	RSA_set_method(rsa, rsa_method);
506	RSA_set_ex_data(rsa, rsa_idx, k11);
507	return (0);
508}
509
510#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
511/* openssl callback doing the actual signing operation */
512static ECDSA_SIG *
513ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
514    const BIGNUM *rp, EC_KEY *ec)
515{
516	struct pkcs11_key	*k11;
517	struct pkcs11_slotinfo	*si;
518	CK_FUNCTION_LIST	*f;
519	CK_ULONG		siglen = 0, bnlen;
520	CK_RV			rv;
521	ECDSA_SIG		*ret = NULL;
522	u_char			*sig;
523	BIGNUM			*r = NULL, *s = NULL;
524
525	if ((k11 = EC_KEY_get_ex_data(ec, ec_key_idx)) == NULL) {
526		ossl_error("EC_KEY_get_ex_data failed for ec");
527		return (NULL);
528	}
529
530	if (pkcs11_get_key(k11, CKM_ECDSA) == -1) {
531		error("pkcs11_get_key failed");
532		return (NULL);
533	}
534
535	f = k11->provider->function_list;
536	si = &k11->provider->slotinfo[k11->slotidx];
537
538	siglen = ECDSA_size(ec);
539	sig = xmalloc(siglen);
540
541	/* XXX handle CKR_BUFFER_TOO_SMALL */
542	rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, &siglen);
543	if (rv != CKR_OK) {
544		error("C_Sign failed: %lu", rv);
545		goto done;
546	}
547	if (siglen < 64 || siglen > 132 || siglen % 2) {
548		error_f("bad signature length: %lu", (u_long)siglen);
549		goto done;
550	}
551	bnlen = siglen/2;
552	if ((ret = ECDSA_SIG_new()) == NULL) {
553		error("ECDSA_SIG_new failed");
554		goto done;
555	}
556	if ((r = BN_bin2bn(sig, bnlen, NULL)) == NULL ||
557	    (s = BN_bin2bn(sig+bnlen, bnlen, NULL)) == NULL) {
558		ossl_error("BN_bin2bn failed");
559		ECDSA_SIG_free(ret);
560		ret = NULL;
561		goto done;
562	}
563	if (!ECDSA_SIG_set0(ret, r, s)) {
564		error_f("ECDSA_SIG_set0 failed");
565		ECDSA_SIG_free(ret);
566		ret = NULL;
567		goto done;
568	}
569	r = s = NULL; /* now owned by ret */
570	/* success */
571 done:
572	BN_free(r);
573	BN_free(s);
574	free(sig);
575
576	return (ret);
577}
578
579static int
580pkcs11_ecdsa_start_wrapper(void)
581{
582	int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
583	    unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
584
585	if (ec_key_method != NULL)
586		return (0);
587	ec_key_idx = EC_KEY_get_ex_new_index(0, "ssh-pkcs11-ecdsa",
588	    NULL, NULL, pkcs11_k11_free);
589	if (ec_key_idx == -1)
590		return (-1);
591	ec_key_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
592	if (ec_key_method == NULL)
593		return (-1);
594	EC_KEY_METHOD_get_sign(ec_key_method, &orig_sign, NULL, NULL);
595	EC_KEY_METHOD_set_sign(ec_key_method, orig_sign, NULL, ecdsa_do_sign);
596	return (0);
597}
598
599static int
600pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
601    CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec)
602{
603	struct pkcs11_key	*k11;
604
605	if (pkcs11_ecdsa_start_wrapper() == -1)
606		return (-1);
607
608	k11 = xcalloc(1, sizeof(*k11));
609	k11->provider = provider;
610	provider->refcount++;	/* provider referenced by ECDSA key */
611	k11->slotidx = slotidx;
612	/* identify key object on smartcard */
613	k11->keyid_len = keyid_attrib->ulValueLen;
614	if (k11->keyid_len > 0) {
615		k11->keyid = xmalloc(k11->keyid_len);
616		memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
617	}
618	EC_KEY_set_method(ec, ec_key_method);
619	EC_KEY_set_ex_data(ec, ec_key_idx, k11);
620
621	return (0);
622}
623#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
624
625/* remove trailing spaces */
626static char *
627rmspace(u_char *buf, size_t len)
628{
629	size_t i;
630
631	if (len == 0)
632		return buf;
633	for (i = len - 1; i > 0; i--)
634		if (buf[i] == ' ')
635			buf[i] = '\0';
636		else
637			break;
638	return buf;
639}
640/* Used to printf fixed-width, space-padded, unterminated strings using %.*s */
641#define RMSPACE(s) (int)sizeof(s), rmspace(s, sizeof(s))
642
643/*
644 * open a pkcs11 session and login if required.
645 * if pin == NULL we delay login until key use
646 */
647static int
648pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin,
649    CK_ULONG user)
650{
651	struct pkcs11_slotinfo	*si;
652	CK_FUNCTION_LIST	*f;
653	CK_RV			rv;
654	CK_SESSION_HANDLE	session;
655	int			login_required, ret;
656
657	f = p->function_list;
658	si = &p->slotinfo[slotidx];
659
660	login_required = si->token.flags & CKF_LOGIN_REQUIRED;
661
662	/* fail early before opening session */
663	if (login_required && !pkcs11_interactive &&
664	    (pin == NULL || strlen(pin) == 0)) {
665		error("pin required");
666		return (-SSH_PKCS11_ERR_PIN_REQUIRED);
667	}
668	if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION|
669	    CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) {
670		error("C_OpenSession failed: %lu", rv);
671		return (-1);
672	}
673	if (login_required && pin != NULL && strlen(pin) != 0) {
674		rv = f->C_Login(session, user, (u_char *)pin, strlen(pin));
675		if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
676			error("C_Login failed: %lu", rv);
677			ret = (rv == CKR_PIN_LOCKED) ?
678			    -SSH_PKCS11_ERR_PIN_LOCKED :
679			    -SSH_PKCS11_ERR_LOGIN_FAIL;
680			if ((rv = f->C_CloseSession(session)) != CKR_OK)
681				error("C_CloseSession failed: %lu", rv);
682			return (ret);
683		}
684		si->logged_in = 1;
685	}
686	si->session = session;
687	return (0);
688}
689
690static int
691pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key)
692{
693	int i;
694
695	for (i = 0; i < *nkeys; i++)
696		if (sshkey_equal(key, (*keysp)[i]))
697			return (1);
698	return (0);
699}
700
701#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
702static struct sshkey *
703pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
704    CK_OBJECT_HANDLE *obj)
705{
706	CK_ATTRIBUTE		 key_attr[3];
707	CK_SESSION_HANDLE	 session;
708	CK_FUNCTION_LIST	*f = NULL;
709	CK_RV			 rv;
710	ASN1_OCTET_STRING	*octet = NULL;
711	EC_KEY			*ec = NULL;
712	EC_GROUP		*group = NULL;
713	struct sshkey		*key = NULL;
714	const unsigned char	*attrp = NULL;
715	int			 i;
716	int			 nid;
717
718	memset(&key_attr, 0, sizeof(key_attr));
719	key_attr[0].type = CKA_ID;
720	key_attr[1].type = CKA_EC_POINT;
721	key_attr[2].type = CKA_EC_PARAMS;
722
723	session = p->slotinfo[slotidx].session;
724	f = p->function_list;
725
726	/* figure out size of the attributes */
727	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
728	if (rv != CKR_OK) {
729		error("C_GetAttributeValue failed: %lu", rv);
730		return (NULL);
731	}
732
733	/*
734	 * Allow CKA_ID (always first attribute) to be empty, but
735	 * ensure that none of the others are zero length.
736	 * XXX assumes CKA_ID is always first.
737	 */
738	if (key_attr[1].ulValueLen == 0 ||
739	    key_attr[2].ulValueLen == 0) {
740		error("invalid attribute length");
741		return (NULL);
742	}
743
744	/* allocate buffers for attributes */
745	for (i = 0; i < 3; i++)
746		if (key_attr[i].ulValueLen > 0)
747			key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
748
749	/* retrieve ID, public point and curve parameters of EC key */
750	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
751	if (rv != CKR_OK) {
752		error("C_GetAttributeValue failed: %lu", rv);
753		goto fail;
754	}
755
756	ec = EC_KEY_new();
757	if (ec == NULL) {
758		error("EC_KEY_new failed");
759		goto fail;
760	}
761
762	attrp = key_attr[2].pValue;
763	group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen);
764	if (group == NULL) {
765		ossl_error("d2i_ECPKParameters failed");
766		goto fail;
767	}
768
769	if (EC_KEY_set_group(ec, group) == 0) {
770		ossl_error("EC_KEY_set_group failed");
771		goto fail;
772	}
773
774	if (key_attr[1].ulValueLen <= 2) {
775		error("CKA_EC_POINT too small");
776		goto fail;
777	}
778
779	attrp = key_attr[1].pValue;
780	octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen);
781	if (octet == NULL) {
782		ossl_error("d2i_ASN1_OCTET_STRING failed");
783		goto fail;
784	}
785	attrp = octet->data;
786	if (o2i_ECPublicKey(&ec, &attrp, octet->length) == NULL) {
787		ossl_error("o2i_ECPublicKey failed");
788		goto fail;
789	}
790
791	nid = sshkey_ecdsa_key_to_nid(ec);
792	if (nid < 0) {
793		error("couldn't get curve nid");
794		goto fail;
795	}
796
797	if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec))
798		goto fail;
799
800	key = sshkey_new(KEY_UNSPEC);
801	if (key == NULL) {
802		error("sshkey_new failed");
803		goto fail;
804	}
805
806	key->ecdsa = ec;
807	key->ecdsa_nid = nid;
808	key->type = KEY_ECDSA;
809	key->flags |= SSHKEY_FLAG_EXT;
810	ec = NULL;	/* now owned by key */
811
812fail:
813	for (i = 0; i < 3; i++)
814		free(key_attr[i].pValue);
815	if (ec)
816		EC_KEY_free(ec);
817	if (group)
818		EC_GROUP_free(group);
819	if (octet)
820		ASN1_OCTET_STRING_free(octet);
821
822	return (key);
823}
824#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
825
826static struct sshkey *
827pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
828    CK_OBJECT_HANDLE *obj)
829{
830	CK_ATTRIBUTE		 key_attr[3];
831	CK_SESSION_HANDLE	 session;
832	CK_FUNCTION_LIST	*f = NULL;
833	CK_RV			 rv;
834	RSA			*rsa = NULL;
835	BIGNUM			*rsa_n, *rsa_e;
836	struct sshkey		*key = NULL;
837	int			 i;
838
839	memset(&key_attr, 0, sizeof(key_attr));
840	key_attr[0].type = CKA_ID;
841	key_attr[1].type = CKA_MODULUS;
842	key_attr[2].type = CKA_PUBLIC_EXPONENT;
843
844	session = p->slotinfo[slotidx].session;
845	f = p->function_list;
846
847	/* figure out size of the attributes */
848	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
849	if (rv != CKR_OK) {
850		error("C_GetAttributeValue failed: %lu", rv);
851		return (NULL);
852	}
853
854	/*
855	 * Allow CKA_ID (always first attribute) to be empty, but
856	 * ensure that none of the others are zero length.
857	 * XXX assumes CKA_ID is always first.
858	 */
859	if (key_attr[1].ulValueLen == 0 ||
860	    key_attr[2].ulValueLen == 0) {
861		error("invalid attribute length");
862		return (NULL);
863	}
864
865	/* allocate buffers for attributes */
866	for (i = 0; i < 3; i++)
867		if (key_attr[i].ulValueLen > 0)
868			key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
869
870	/* retrieve ID, modulus and public exponent of RSA key */
871	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
872	if (rv != CKR_OK) {
873		error("C_GetAttributeValue failed: %lu", rv);
874		goto fail;
875	}
876
877	rsa = RSA_new();
878	if (rsa == NULL) {
879		error("RSA_new failed");
880		goto fail;
881	}
882
883	rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL);
884	rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL);
885	if (rsa_n == NULL || rsa_e == NULL) {
886		error("BN_bin2bn failed");
887		goto fail;
888	}
889	if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL))
890		fatal_f("set key");
891	rsa_n = rsa_e = NULL; /* transferred */
892
893	if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa))
894		goto fail;
895
896	key = sshkey_new(KEY_UNSPEC);
897	if (key == NULL) {
898		error("sshkey_new failed");
899		goto fail;
900	}
901
902	key->rsa = rsa;
903	key->type = KEY_RSA;
904	key->flags |= SSHKEY_FLAG_EXT;
905	rsa = NULL;	/* now owned by key */
906
907fail:
908	for (i = 0; i < 3; i++)
909		free(key_attr[i].pValue);
910	RSA_free(rsa);
911
912	return (key);
913}
914
915static int
916pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
917    CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp)
918{
919	CK_ATTRIBUTE		 cert_attr[3];
920	CK_SESSION_HANDLE	 session;
921	CK_FUNCTION_LIST	*f = NULL;
922	CK_RV			 rv;
923	X509			*x509 = NULL;
924	X509_NAME		*x509_name = NULL;
925	EVP_PKEY		*evp;
926	RSA			*rsa = NULL;
927#ifdef OPENSSL_HAS_ECC
928	EC_KEY			*ec = NULL;
929#endif
930	struct sshkey		*key = NULL;
931	int			 i;
932#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
933	int			 nid;
934#endif
935	const u_char		*cp;
936	char			*subject = NULL;
937
938	*keyp = NULL;
939	*labelp = NULL;
940
941	memset(&cert_attr, 0, sizeof(cert_attr));
942	cert_attr[0].type = CKA_ID;
943	cert_attr[1].type = CKA_SUBJECT;
944	cert_attr[2].type = CKA_VALUE;
945
946	session = p->slotinfo[slotidx].session;
947	f = p->function_list;
948
949	/* figure out size of the attributes */
950	rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
951	if (rv != CKR_OK) {
952		error("C_GetAttributeValue failed: %lu", rv);
953		return -1;
954	}
955
956	/*
957	 * Allow CKA_ID (always first attribute) to be empty, but
958	 * ensure that none of the others are zero length.
959	 * XXX assumes CKA_ID is always first.
960	 */
961	if (cert_attr[1].ulValueLen == 0 ||
962	    cert_attr[2].ulValueLen == 0) {
963		error("invalid attribute length");
964		return -1;
965	}
966
967	/* allocate buffers for attributes */
968	for (i = 0; i < 3; i++)
969		if (cert_attr[i].ulValueLen > 0)
970			cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen);
971
972	/* retrieve ID, subject and value of certificate */
973	rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
974	if (rv != CKR_OK) {
975		error("C_GetAttributeValue failed: %lu", rv);
976		goto out;
977	}
978
979	/* Decode DER-encoded cert subject */
980	cp = cert_attr[1].pValue;
981	if ((x509_name = d2i_X509_NAME(NULL, &cp,
982	    cert_attr[1].ulValueLen)) == NULL ||
983	    (subject = X509_NAME_oneline(x509_name, NULL, 0)) == NULL)
984		subject = xstrdup("invalid subject");
985	X509_NAME_free(x509_name);
986
987	cp = cert_attr[2].pValue;
988	if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) {
989		error("d2i_x509 failed");
990		goto out;
991	}
992
993	if ((evp = X509_get_pubkey(x509)) == NULL) {
994		error("X509_get_pubkey failed");
995		goto out;
996	}
997
998	if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) {
999		if (EVP_PKEY_get0_RSA(evp) == NULL) {
1000			error("invalid x509; no rsa key");
1001			goto out;
1002		}
1003		if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) {
1004			error("RSAPublicKey_dup failed");
1005			goto out;
1006		}
1007
1008		if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa))
1009			goto out;
1010
1011		key = sshkey_new(KEY_UNSPEC);
1012		if (key == NULL) {
1013			error("sshkey_new failed");
1014			goto out;
1015		}
1016
1017		key->rsa = rsa;
1018		key->type = KEY_RSA;
1019		key->flags |= SSHKEY_FLAG_EXT;
1020		rsa = NULL;	/* now owned by key */
1021#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
1022	} else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
1023		if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {
1024			error("invalid x509; no ec key");
1025			goto out;
1026		}
1027		if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) {
1028			error("EC_KEY_dup failed");
1029			goto out;
1030		}
1031
1032		nid = sshkey_ecdsa_key_to_nid(ec);
1033		if (nid < 0) {
1034			error("couldn't get curve nid");
1035			goto out;
1036		}
1037
1038		if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec))
1039			goto out;
1040
1041		key = sshkey_new(KEY_UNSPEC);
1042		if (key == NULL) {
1043			error("sshkey_new failed");
1044			goto out;
1045		}
1046
1047		key->ecdsa = ec;
1048		key->ecdsa_nid = nid;
1049		key->type = KEY_ECDSA;
1050		key->flags |= SSHKEY_FLAG_EXT;
1051		ec = NULL;	/* now owned by key */
1052#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
1053	} else {
1054		error("unknown certificate key type");
1055		goto out;
1056	}
1057 out:
1058	for (i = 0; i < 3; i++)
1059		free(cert_attr[i].pValue);
1060	X509_free(x509);
1061	RSA_free(rsa);
1062#ifdef OPENSSL_HAS_ECC
1063	EC_KEY_free(ec);
1064#endif
1065	if (key == NULL) {
1066		free(subject);
1067		return -1;
1068	}
1069	/* success */
1070	*keyp = key;
1071	*labelp = subject;
1072	return 0;
1073}
1074
1075#if 0
1076static int
1077have_rsa_key(const RSA *rsa)
1078{
1079	const BIGNUM *rsa_n, *rsa_e;
1080
1081	RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
1082	return rsa_n != NULL && rsa_e != NULL;
1083}
1084#endif
1085
1086static void
1087note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context,
1088    struct sshkey *key)
1089{
1090	char *fp;
1091
1092	if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
1093	    SSH_FP_DEFAULT)) == NULL) {
1094		error_f("sshkey_fingerprint failed");
1095		return;
1096	}
1097	debug2("%s: provider %s slot %lu: %s %s", context, p->name,
1098	    (u_long)slotidx, sshkey_type(key), fp);
1099	free(fp);
1100}
1101
1102/*
1103 * lookup certificates for token in slot identified by slotidx,
1104 * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
1105 * keysp points to an (possibly empty) array with *nkeys keys.
1106 */
1107static int
1108pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
1109    struct sshkey ***keysp, char ***labelsp, int *nkeys)
1110{
1111	struct sshkey		*key = NULL;
1112	CK_OBJECT_CLASS		 key_class;
1113	CK_ATTRIBUTE		 key_attr[1];
1114	CK_SESSION_HANDLE	 session;
1115	CK_FUNCTION_LIST	*f = NULL;
1116	CK_RV			 rv;
1117	CK_OBJECT_HANDLE	 obj;
1118	CK_ULONG		 n = 0;
1119	int			 ret = -1;
1120	char			*label;
1121
1122	memset(&key_attr, 0, sizeof(key_attr));
1123	memset(&obj, 0, sizeof(obj));
1124
1125	key_class = CKO_CERTIFICATE;
1126	key_attr[0].type = CKA_CLASS;
1127	key_attr[0].pValue = &key_class;
1128	key_attr[0].ulValueLen = sizeof(key_class);
1129
1130	session = p->slotinfo[slotidx].session;
1131	f = p->function_list;
1132
1133	rv = f->C_FindObjectsInit(session, key_attr, 1);
1134	if (rv != CKR_OK) {
1135		error("C_FindObjectsInit failed: %lu", rv);
1136		goto fail;
1137	}
1138
1139	while (1) {
1140		CK_CERTIFICATE_TYPE	ck_cert_type;
1141
1142		rv = f->C_FindObjects(session, &obj, 1, &n);
1143		if (rv != CKR_OK) {
1144			error("C_FindObjects failed: %lu", rv);
1145			goto fail;
1146		}
1147		if (n == 0)
1148			break;
1149
1150		memset(&ck_cert_type, 0, sizeof(ck_cert_type));
1151		memset(&key_attr, 0, sizeof(key_attr));
1152		key_attr[0].type = CKA_CERTIFICATE_TYPE;
1153		key_attr[0].pValue = &ck_cert_type;
1154		key_attr[0].ulValueLen = sizeof(ck_cert_type);
1155
1156		rv = f->C_GetAttributeValue(session, obj, key_attr, 1);
1157		if (rv != CKR_OK) {
1158			error("C_GetAttributeValue failed: %lu", rv);
1159			goto fail;
1160		}
1161
1162		key = NULL;
1163		label = NULL;
1164		switch (ck_cert_type) {
1165		case CKC_X_509:
1166			if (pkcs11_fetch_x509_pubkey(p, slotidx, &obj,
1167			    &key, &label) != 0) {
1168				error("failed to fetch key");
1169				continue;
1170			}
1171			break;
1172		default:
1173			error("skipping unsupported certificate type %lu",
1174			    ck_cert_type);
1175			continue;
1176		}
1177		note_key(p, slotidx, __func__, key);
1178		if (pkcs11_key_included(keysp, nkeys, key)) {
1179			debug2_f("key already included");;
1180			sshkey_free(key);
1181		} else {
1182			/* expand key array and add key */
1183			*keysp = xrecallocarray(*keysp, *nkeys,
1184			    *nkeys + 1, sizeof(struct sshkey *));
1185			(*keysp)[*nkeys] = key;
1186			if (labelsp != NULL) {
1187				*labelsp = xrecallocarray(*labelsp, *nkeys,
1188				    *nkeys + 1, sizeof(char *));
1189				(*labelsp)[*nkeys] = xstrdup((char *)label);
1190			}
1191			*nkeys = *nkeys + 1;
1192			debug("have %d keys", *nkeys);
1193		}
1194	}
1195
1196	ret = 0;
1197fail:
1198	rv = f->C_FindObjectsFinal(session);
1199	if (rv != CKR_OK) {
1200		error("C_FindObjectsFinal failed: %lu", rv);
1201		ret = -1;
1202	}
1203
1204	return (ret);
1205}
1206
1207/*
1208 * lookup public keys for token in slot identified by slotidx,
1209 * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
1210 * keysp points to an (possibly empty) array with *nkeys keys.
1211 */
1212static int
1213pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1214    struct sshkey ***keysp, char ***labelsp, int *nkeys)
1215{
1216	struct sshkey		*key = NULL;
1217	CK_OBJECT_CLASS		 key_class;
1218	CK_ATTRIBUTE		 key_attr[2];
1219	CK_SESSION_HANDLE	 session;
1220	CK_FUNCTION_LIST	*f = NULL;
1221	CK_RV			 rv;
1222	CK_OBJECT_HANDLE	 obj;
1223	CK_ULONG		 n = 0;
1224	int			 ret = -1;
1225
1226	memset(&key_attr, 0, sizeof(key_attr));
1227	memset(&obj, 0, sizeof(obj));
1228
1229	key_class = CKO_PUBLIC_KEY;
1230	key_attr[0].type = CKA_CLASS;
1231	key_attr[0].pValue = &key_class;
1232	key_attr[0].ulValueLen = sizeof(key_class);
1233
1234	session = p->slotinfo[slotidx].session;
1235	f = p->function_list;
1236
1237	rv = f->C_FindObjectsInit(session, key_attr, 1);
1238	if (rv != CKR_OK) {
1239		error("C_FindObjectsInit failed: %lu", rv);
1240		goto fail;
1241	}
1242
1243	while (1) {
1244		CK_KEY_TYPE	ck_key_type;
1245		CK_UTF8CHAR	label[256];
1246
1247		rv = f->C_FindObjects(session, &obj, 1, &n);
1248		if (rv != CKR_OK) {
1249			error("C_FindObjects failed: %lu", rv);
1250			goto fail;
1251		}
1252		if (n == 0)
1253			break;
1254
1255		memset(&ck_key_type, 0, sizeof(ck_key_type));
1256		memset(&key_attr, 0, sizeof(key_attr));
1257		key_attr[0].type = CKA_KEY_TYPE;
1258		key_attr[0].pValue = &ck_key_type;
1259		key_attr[0].ulValueLen = sizeof(ck_key_type);
1260		key_attr[1].type = CKA_LABEL;
1261		key_attr[1].pValue = &label;
1262		key_attr[1].ulValueLen = sizeof(label) - 1;
1263
1264		rv = f->C_GetAttributeValue(session, obj, key_attr, 2);
1265		if (rv != CKR_OK) {
1266			error("C_GetAttributeValue failed: %lu", rv);
1267			goto fail;
1268		}
1269
1270		label[key_attr[1].ulValueLen] = '\0';
1271
1272		switch (ck_key_type) {
1273		case CKK_RSA:
1274			key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
1275			break;
1276#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
1277		case CKK_ECDSA:
1278			key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
1279			break;
1280#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
1281		default:
1282			/* XXX print key type? */
1283			key = NULL;
1284			error("skipping unsupported key type");
1285		}
1286
1287		if (key == NULL) {
1288			error("failed to fetch key");
1289			continue;
1290		}
1291		note_key(p, slotidx, __func__, key);
1292		if (pkcs11_key_included(keysp, nkeys, key)) {
1293			debug2_f("key already included");;
1294			sshkey_free(key);
1295		} else {
1296			/* expand key array and add key */
1297			*keysp = xrecallocarray(*keysp, *nkeys,
1298			    *nkeys + 1, sizeof(struct sshkey *));
1299			(*keysp)[*nkeys] = key;
1300			if (labelsp != NULL) {
1301				*labelsp = xrecallocarray(*labelsp, *nkeys,
1302				    *nkeys + 1, sizeof(char *));
1303				(*labelsp)[*nkeys] = xstrdup((char *)label);
1304			}
1305			*nkeys = *nkeys + 1;
1306			debug("have %d keys", *nkeys);
1307		}
1308	}
1309
1310	ret = 0;
1311fail:
1312	rv = f->C_FindObjectsFinal(session);
1313	if (rv != CKR_OK) {
1314		error("C_FindObjectsFinal failed: %lu", rv);
1315		ret = -1;
1316	}
1317
1318	return (ret);
1319}
1320
1321#ifdef WITH_PKCS11_KEYGEN
1322#define FILL_ATTR(attr, idx, typ, val, len) \
1323	{ (attr[idx]).type=(typ); (attr[idx]).pValue=(val); (attr[idx]).ulValueLen=len; idx++; }
1324
1325static struct sshkey *
1326pkcs11_rsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
1327    char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err)
1328{
1329	struct pkcs11_slotinfo	*si;
1330	char			*plabel = label ? label : "";
1331	int			 npub = 0, npriv = 0;
1332	CK_RV			 rv;
1333	CK_FUNCTION_LIST	*f;
1334	CK_SESSION_HANDLE	 session;
1335	CK_BBOOL		 true_val = CK_TRUE, false_val = CK_FALSE;
1336	CK_OBJECT_HANDLE	 pubKey, privKey;
1337	CK_ATTRIBUTE		 tpub[16], tpriv[16];
1338	CK_MECHANISM		 mech = {
1339	    CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0
1340	};
1341	CK_BYTE			 pubExponent[] = {
1342	    0x01, 0x00, 0x01 /* RSA_F4 in bytes */
1343	};
1344	pubkey_filter[0].pValue = &pubkey_class;
1345	cert_filter[0].pValue = &cert_class;
1346
1347	*err = 0;
1348
1349	FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val));
1350	FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel));
1351	FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val));
1352	FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val));
1353	FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val,
1354	    sizeof(false_val));
1355	FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val));
1356	FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val));
1357	FILL_ATTR(tpub, npub, CKA_MODULUS_BITS, &bits, sizeof(bits));
1358	FILL_ATTR(tpub, npub, CKA_PUBLIC_EXPONENT, pubExponent,
1359	    sizeof(pubExponent));
1360	FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid));
1361
1362	FILL_ATTR(tpriv, npriv, CKA_TOKEN,  &true_val, sizeof(true_val));
1363	FILL_ATTR(tpriv, npriv, CKA_LABEL,  plabel, strlen(plabel));
1364	FILL_ATTR(tpriv, npriv, CKA_PRIVATE,  &true_val, sizeof(true_val));
1365	FILL_ATTR(tpriv, npriv, CKA_SENSITIVE,  &true_val, sizeof(true_val));
1366	FILL_ATTR(tpriv, npriv, CKA_DECRYPT,  &false_val, sizeof(false_val));
1367	FILL_ATTR(tpriv, npriv, CKA_SIGN,  &true_val, sizeof(true_val));
1368	FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER,  &false_val,
1369	    sizeof(false_val));
1370	FILL_ATTR(tpriv, npriv, CKA_UNWRAP,  &false_val, sizeof(false_val));
1371	FILL_ATTR(tpriv, npriv, CKA_DERIVE,  &false_val, sizeof(false_val));
1372	FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid));
1373
1374	f = p->function_list;
1375	si = &p->slotinfo[slotidx];
1376	session = si->session;
1377
1378	if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
1379	    &pubKey, &privKey)) != CKR_OK) {
1380		error_f("key generation failed: error 0x%lx", rv);
1381		*err = rv;
1382		return NULL;
1383	}
1384
1385	return pkcs11_fetch_rsa_pubkey(p, slotidx, &pubKey);
1386}
1387
1388static int
1389pkcs11_decode_hex(const char *hex, unsigned char **dest, size_t *rlen)
1390{
1391	size_t	i, len;
1392	char	ptr[3];
1393
1394	if (dest)
1395		*dest = NULL;
1396	if (rlen)
1397		*rlen = 0;
1398
1399	if ((len = strlen(hex)) % 2)
1400		return -1;
1401	len /= 2;
1402
1403	*dest = xmalloc(len);
1404
1405	ptr[2] = '\0';
1406	for (i = 0; i < len; i++) {
1407		ptr[0] = hex[2 * i];
1408		ptr[1] = hex[(2 * i) + 1];
1409		if (!isxdigit(ptr[0]) || !isxdigit(ptr[1]))
1410			return -1;
1411		(*dest)[i] = (unsigned char)strtoul(ptr, NULL, 16);
1412	}
1413
1414	if (rlen)
1415		*rlen = len;
1416
1417	return 0;
1418}
1419
1420static struct ec_curve_info {
1421	const char	*name;
1422	const char	*oid;
1423	const char	*oid_encoded;
1424	size_t		 size;
1425} ec_curve_infos[] = {
1426	{"prime256v1",	"1.2.840.10045.3.1.7",	"06082A8648CE3D030107", 256},
1427	{"secp384r1",	"1.3.132.0.34",		"06052B81040022",	384},
1428	{"secp521r1",	"1.3.132.0.35",		"06052B81040023",	521},
1429	{NULL,		NULL,			NULL,			0},
1430};
1431
1432static struct sshkey *
1433pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
1434    char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err)
1435{
1436	struct pkcs11_slotinfo	*si;
1437	char			*plabel = label ? label : "";
1438	int			 i;
1439	size_t			 ecparams_size;
1440	unsigned char		*ecparams = NULL;
1441	int			 npub = 0, npriv = 0;
1442	CK_RV			 rv;
1443	CK_FUNCTION_LIST	*f;
1444	CK_SESSION_HANDLE	 session;
1445	CK_BBOOL		 true_val = CK_TRUE, false_val = CK_FALSE;
1446	CK_OBJECT_HANDLE	 pubKey, privKey;
1447	CK_MECHANISM		 mech = {
1448	    CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0
1449	};
1450	CK_ATTRIBUTE		 tpub[16], tpriv[16];
1451
1452	*err = 0;
1453
1454	for (i = 0; ec_curve_infos[i].name; i++) {
1455		if (ec_curve_infos[i].size == bits)
1456			break;
1457	}
1458	if (!ec_curve_infos[i].name) {
1459		error_f("invalid key size %lu", bits);
1460		return NULL;
1461	}
1462	if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams,
1463	    &ecparams_size) == -1) {
1464		error_f("invalid oid");
1465		return NULL;
1466	}
1467
1468	FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val));
1469	FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel));
1470	FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val));
1471	FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val));
1472	FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val,
1473	    sizeof(false_val));
1474	FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val));
1475	FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val));
1476	FILL_ATTR(tpub, npub, CKA_EC_PARAMS, ecparams, ecparams_size);
1477	FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid));
1478
1479	FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val));
1480	FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel));
1481	FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val));
1482	FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val));
1483	FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val));
1484	FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val));
1485	FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val,
1486	    sizeof(false_val));
1487	FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val));
1488	FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val));
1489	FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid));
1490
1491	f = p->function_list;
1492	si = &p->slotinfo[slotidx];
1493	session = si->session;
1494
1495	if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
1496	    &pubKey, &privKey)) != CKR_OK) {
1497		error_f("key generation failed: error 0x%lx", rv);
1498		*err = rv;
1499		return NULL;
1500	}
1501
1502	return pkcs11_fetch_ecdsa_pubkey(p, slotidx, &pubKey);
1503}
1504#endif /* WITH_PKCS11_KEYGEN */
1505
1506/*
1507 * register a new provider, fails if provider already exists. if
1508 * keyp is provided, fetch keys.
1509 */
1510static int
1511pkcs11_register_provider(char *provider_id, char *pin,
1512    struct sshkey ***keyp, char ***labelsp,
1513    struct pkcs11_provider **providerp, CK_ULONG user)
1514{
1515	int nkeys, need_finalize = 0;
1516	int ret = -1;
1517	struct pkcs11_provider *p = NULL;
1518	void *handle = NULL;
1519	CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **);
1520	CK_RV rv;
1521	CK_FUNCTION_LIST *f = NULL;
1522	CK_TOKEN_INFO *token;
1523	CK_ULONG i;
1524
1525	if (providerp == NULL)
1526		goto fail;
1527	*providerp = NULL;
1528
1529	if (keyp != NULL)
1530		*keyp = NULL;
1531	if (labelsp != NULL)
1532		*labelsp = NULL;
1533
1534	if (pkcs11_provider_lookup(provider_id) != NULL) {
1535		debug_f("provider already registered: %s", provider_id);
1536		goto fail;
1537	}
1538	if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) {
1539		error("provider %s is not a PKCS11 library", provider_id);
1540		goto fail;
1541	}
1542	/* open shared pkcs11-library */
1543	if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {
1544		error("dlopen %s failed: %s", provider_id, dlerror());
1545		goto fail;
1546	}
1547	if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL)
1548		fatal("dlsym(C_GetFunctionList) failed: %s", dlerror());
1549	p = xcalloc(1, sizeof(*p));
1550	p->name = xstrdup(provider_id);
1551	p->handle = handle;
1552	/* setup the pkcs11 callbacks */
1553	if ((rv = (*getfunctionlist)(&f)) != CKR_OK) {
1554		error("C_GetFunctionList for provider %s failed: %lu",
1555		    provider_id, rv);
1556		goto fail;
1557	}
1558	p->function_list = f;
1559	if ((rv = f->C_Initialize(NULL)) != CKR_OK) {
1560		error("C_Initialize for provider %s failed: %lu",
1561		    provider_id, rv);
1562		goto fail;
1563	}
1564	need_finalize = 1;
1565	if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) {
1566		error("C_GetInfo for provider %s failed: %lu",
1567		    provider_id, rv);
1568		goto fail;
1569	}
1570	debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d"
1571	    " libraryDescription <%.*s> libraryVersion %d.%d",
1572	    provider_id,
1573	    RMSPACE(p->info.manufacturerID),
1574	    p->info.cryptokiVersion.major,
1575	    p->info.cryptokiVersion.minor,
1576	    RMSPACE(p->info.libraryDescription),
1577	    p->info.libraryVersion.major,
1578	    p->info.libraryVersion.minor);
1579	if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) {
1580		error("C_GetSlotList failed: %lu", rv);
1581		goto fail;
1582	}
1583	if (p->nslots == 0) {
1584		debug_f("provider %s returned no slots", provider_id);
1585		ret = -SSH_PKCS11_ERR_NO_SLOTS;
1586		goto fail;
1587	}
1588	p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID));
1589	if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots))
1590	    != CKR_OK) {
1591		error("C_GetSlotList for provider %s failed: %lu",
1592		    provider_id, rv);
1593		goto fail;
1594	}
1595	p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo));
1596	p->valid = 1;
1597	nkeys = 0;
1598	for (i = 0; i < p->nslots; i++) {
1599		token = &p->slotinfo[i].token;
1600		if ((rv = f->C_GetTokenInfo(p->slotlist[i], token))
1601		    != CKR_OK) {
1602			error("C_GetTokenInfo for provider %s slot %lu "
1603			    "failed: %lu", provider_id, (u_long)i, rv);
1604			continue;
1605		}
1606		if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) {
1607			debug2_f("ignoring uninitialised token in "
1608			    "provider %s slot %lu", provider_id, (u_long)i);
1609			continue;
1610		}
1611		debug("provider %s slot %lu: label <%.*s> "
1612		    "manufacturerID <%.*s> model <%.*s> serial <%.*s> "
1613		    "flags 0x%lx",
1614		    provider_id, (unsigned long)i,
1615		    RMSPACE(token->label), RMSPACE(token->manufacturerID),
1616		    RMSPACE(token->model), RMSPACE(token->serialNumber),
1617		    token->flags);
1618		/*
1619		 * open session, login with pin and retrieve public
1620		 * keys (if keyp is provided)
1621		 */
1622		if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 ||
1623		    keyp == NULL)
1624			continue;
1625		pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
1626		pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
1627		if (nkeys == 0 && !p->slotinfo[i].logged_in &&
1628		    pkcs11_interactive) {
1629			/*
1630			 * Some tokens require login before they will
1631			 * expose keys.
1632			 */
1633			if (pkcs11_login_slot(p, &p->slotinfo[i],
1634			    CKU_USER) < 0) {
1635				error("login failed");
1636				continue;
1637			}
1638			pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
1639			pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
1640		}
1641	}
1642
1643	/* now owned by caller */
1644	*providerp = p;
1645
1646	TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
1647	p->refcount++;	/* add to provider list */
1648
1649	return (nkeys);
1650fail:
1651	if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK)
1652		error("C_Finalize for provider %s failed: %lu",
1653		    provider_id, rv);
1654	if (p) {
1655		free(p->name);
1656		free(p->slotlist);
1657		free(p->slotinfo);
1658		free(p);
1659	}
1660	if (handle)
1661		dlclose(handle);
1662	if (ret > 0)
1663		ret = -1;
1664	return (ret);
1665}
1666
1667/*
1668 * register a new provider and get number of keys hold by the token,
1669 * fails if provider already exists
1670 */
1671int
1672pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1673    char ***labelsp)
1674{
1675	struct pkcs11_provider *p = NULL;
1676	int nkeys;
1677
1678	nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp,
1679	    &p, CKU_USER);
1680
1681	/* no keys found or some other error, de-register provider */
1682	if (nkeys <= 0 && p != NULL) {
1683		TAILQ_REMOVE(&pkcs11_providers, p, next);
1684		pkcs11_provider_finalize(p);
1685		pkcs11_provider_unref(p);
1686	}
1687	if (nkeys == 0)
1688		debug_f("provider %s returned no keys", provider_id);
1689
1690	return (nkeys);
1691}
1692
1693#ifdef WITH_PKCS11_KEYGEN
1694struct sshkey *
1695pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label,
1696    unsigned int type, unsigned int bits, unsigned char keyid, u_int32_t *err)
1697{
1698	struct pkcs11_provider	*p = NULL;
1699	struct pkcs11_slotinfo	*si;
1700	CK_FUNCTION_LIST	*f;
1701	CK_SESSION_HANDLE	 session;
1702	struct sshkey		*k = NULL;
1703	int			 ret = -1, reset_pin = 0, reset_provider = 0;
1704	CK_RV			 rv;
1705
1706	*err = 0;
1707
1708	if ((p = pkcs11_provider_lookup(provider_id)) != NULL)
1709		debug_f("provider \"%s\" available", provider_id);
1710	else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL,
1711	    &p, CKU_SO)) < 0) {
1712		debug_f("could not register provider %s", provider_id);
1713		goto out;
1714	} else
1715		reset_provider = 1;
1716
1717	f = p->function_list;
1718	si = &p->slotinfo[slotidx];
1719	session = si->session;
1720
1721	if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
1722	    CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
1723		debug_f("could not supply SO pin: %lu", rv);
1724		reset_pin = 0;
1725	} else
1726		reset_pin = 1;
1727
1728	switch (type) {
1729	case KEY_RSA:
1730		if ((k = pkcs11_rsa_generate_private_key(p, slotidx, label,
1731		    bits, keyid, err)) == NULL) {
1732			debug_f("failed to generate RSA key");
1733			goto out;
1734		}
1735		break;
1736	case KEY_ECDSA:
1737		if ((k = pkcs11_ecdsa_generate_private_key(p, slotidx, label,
1738		    bits, keyid, err)) == NULL) {
1739			debug_f("failed to generate ECDSA key");
1740			goto out;
1741		}
1742		break;
1743	default:
1744		*err = SSH_PKCS11_ERR_GENERIC;
1745		debug_f("unknown type %d", type);
1746		goto out;
1747	}
1748
1749out:
1750	if (reset_pin)
1751		f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
1752		    CK_INVALID_HANDLE);
1753
1754	if (reset_provider)
1755		pkcs11_del_provider(provider_id);
1756
1757	return (k);
1758}
1759
1760struct sshkey *
1761pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
1762    unsigned char keyid, u_int32_t *err)
1763{
1764	struct pkcs11_provider	*p = NULL;
1765	struct pkcs11_slotinfo	*si;
1766	struct sshkey		*k = NULL;
1767	int			 reset_pin = 0, reset_provider = 0;
1768	CK_ULONG		 nattrs;
1769	CK_FUNCTION_LIST	*f;
1770	CK_SESSION_HANDLE	 session;
1771	CK_ATTRIBUTE		 attrs[16];
1772	CK_OBJECT_CLASS		 key_class;
1773	CK_KEY_TYPE		 key_type;
1774	CK_OBJECT_HANDLE	 obj = CK_INVALID_HANDLE;
1775	CK_RV			 rv;
1776
1777	*err = 0;
1778
1779	if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
1780		debug_f("using provider \"%s\"", provider_id);
1781	} else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p,
1782	    CKU_SO) < 0) {
1783		debug_f("could not register provider %s",
1784		    provider_id);
1785		goto out;
1786	} else
1787		reset_provider = 1;
1788
1789	f = p->function_list;
1790	si = &p->slotinfo[slotidx];
1791	session = si->session;
1792
1793	if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
1794	    CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
1795		debug_f("could not supply SO pin: %lu", rv);
1796		reset_pin = 0;
1797	} else
1798		reset_pin = 1;
1799
1800	/* private key */
1801	nattrs = 0;
1802	key_class = CKO_PRIVATE_KEY;
1803	FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class));
1804	FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid));
1805
1806	if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
1807	    obj != CK_INVALID_HANDLE) {
1808		if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
1809			debug_f("could not destroy private key 0x%hhx",
1810			    keyid);
1811			*err = rv;
1812			goto out;
1813		}
1814	}
1815
1816	/* public key */
1817	nattrs = 0;
1818	key_class = CKO_PUBLIC_KEY;
1819	FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class));
1820	FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid));
1821
1822	if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
1823	    obj != CK_INVALID_HANDLE) {
1824
1825		/* get key type */
1826		nattrs = 0;
1827		FILL_ATTR(attrs, nattrs, CKA_KEY_TYPE, &key_type,
1828		    sizeof(key_type));
1829		rv = f->C_GetAttributeValue(session, obj, attrs, nattrs);
1830		if (rv != CKR_OK) {
1831			debug_f("could not get key type of public key 0x%hhx",
1832			    keyid);
1833			*err = rv;
1834			key_type = -1;
1835		}
1836		if (key_type == CKK_RSA)
1837			k = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
1838		else if (key_type == CKK_ECDSA)
1839			k = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
1840
1841		if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
1842			debug_f("could not destroy public key 0x%hhx", keyid);
1843			*err = rv;
1844			goto out;
1845		}
1846	}
1847
1848out:
1849	if (reset_pin)
1850		f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
1851		    CK_INVALID_HANDLE);
1852
1853	if (reset_provider)
1854		pkcs11_del_provider(provider_id);
1855
1856	return (k);
1857}
1858#endif /* WITH_PKCS11_KEYGEN */
1859#else /* ENABLE_PKCS11 */
1860
1861#include <sys/types.h>
1862#include <stdarg.h>
1863#include <stdio.h>
1864
1865#include "log.h"
1866#include "sshkey.h"
1867
1868int
1869pkcs11_init(int interactive)
1870{
1871	error("%s: dlopen() not supported", __func__);
1872	return (-1);
1873}
1874
1875int
1876pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1877    char ***labelsp)
1878{
1879	error("%s: dlopen() not supported", __func__);
1880	return (-1);
1881}
1882
1883void
1884pkcs11_terminate(void)
1885{
1886	error("%s: dlopen() not supported", __func__);
1887}
1888#endif /* ENABLE_PKCS11 */
1889