xref: /freebsd/crypto/openssh/ssh-pkcs11.c (revision 3d9fd9fcb432750f3716b28f6ccb0104cd9d351a)
1 /* $OpenBSD: ssh-pkcs11.c,v 1.63 2024/08/15 00:51:51 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 
52 struct pkcs11_slotinfo {
53 	CK_TOKEN_INFO		token;
54 	CK_SESSION_HANDLE	session;
55 	int			logged_in;
56 };
57 
58 struct 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 
71 TAILQ_HEAD(, pkcs11_provider) pkcs11_providers;
72 
73 struct pkcs11_key {
74 	struct pkcs11_provider	*provider;
75 	CK_ULONG		slotidx;
76 	char			*keyid;
77 	int			keyid_len;
78 };
79 
80 int pkcs11_interactive = 0;
81 
82 #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
83 static void
ossl_error(const char * msg)84 ossl_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 
94 int
pkcs11_init(int interactive)95 pkcs11_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  */
108 static void
pkcs11_provider_finalize(struct pkcs11_provider * p)109 pkcs11_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  */
135 static void
pkcs11_provider_unref(struct pkcs11_provider * p)136 pkcs11_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 */
150 void
pkcs11_terminate(void)151 pkcs11_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 */
163 static struct pkcs11_provider *
pkcs11_provider_lookup(char * provider_id)164 pkcs11_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 */
177 int
pkcs11_del_provider(char * provider_id)178 pkcs11_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 
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 */
197 
198 /* release a wrapped object */
199 static void
pkcs11_k11_free(void * parent,void * ptr,CRYPTO_EX_DATA * ad,int idx,long argl,void * argp)200 pkcs11_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 */
215 static int
pkcs11_find(struct pkcs11_provider * p,CK_ULONG slotidx,CK_ATTRIBUTE * attr,CK_ULONG nattr,CK_OBJECT_HANDLE * obj)216 pkcs11_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 
242 static int
pkcs11_login_slot(struct pkcs11_provider * provider,struct pkcs11_slotinfo * si,CK_USER_TYPE type)243 pkcs11_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 
297 static int
pkcs11_login(struct pkcs11_key * k11,CK_USER_TYPE type)298 pkcs11_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 
310 static int
pkcs11_check_obj_bool_attrib(struct pkcs11_key * k11,CK_OBJECT_HANDLE obj,CK_ATTRIBUTE_TYPE type,int * val)311 pkcs11_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 
345 static int
pkcs11_get_key(struct pkcs11_key * k11,CK_MECHANISM_TYPE mech_type)346 pkcs11_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 */
421 static int
pkcs11_rsa_private_encrypt(int flen,const u_char * from,u_char * to,RSA * rsa,int padding)422 pkcs11_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 
456 static int
pkcs11_rsa_private_decrypt(int flen,const u_char * from,u_char * to,RSA * rsa,int padding)457 pkcs11_rsa_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
458     int padding)
459 {
460 	return (-1);
461 }
462 
463 static int
pkcs11_rsa_start_wrapper(void)464 pkcs11_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 */
485 static int
pkcs11_rsa_wrap(struct pkcs11_provider * provider,CK_ULONG slotidx,CK_ATTRIBUTE * keyid_attrib,RSA * rsa)486 pkcs11_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 	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");
509 	return (0);
510 }
511 
512 #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
513 /* openssl callback doing the actual signing operation */
514 static ECDSA_SIG *
ecdsa_do_sign(const unsigned char * dgst,int dgst_len,const BIGNUM * inv,const BIGNUM * rp,EC_KEY * ec)515 ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
516     const BIGNUM *rp, EC_KEY *ec)
517 {
518 	struct pkcs11_key	*k11;
519 	struct pkcs11_slotinfo	*si;
520 	CK_FUNCTION_LIST	*f;
521 	CK_ULONG		siglen = 0, bnlen;
522 	CK_RV			rv;
523 	ECDSA_SIG		*ret = NULL;
524 	u_char			*sig;
525 	BIGNUM			*r = NULL, *s = NULL;
526 
527 	if ((k11 = EC_KEY_get_ex_data(ec, ec_key_idx)) == NULL) {
528 		ossl_error("EC_KEY_get_ex_data failed for ec");
529 		return (NULL);
530 	}
531 
532 	if (pkcs11_get_key(k11, CKM_ECDSA) == -1) {
533 		error("pkcs11_get_key failed");
534 		return (NULL);
535 	}
536 
537 	f = k11->provider->function_list;
538 	si = &k11->provider->slotinfo[k11->slotidx];
539 
540 	siglen = ECDSA_size(ec);
541 	sig = xmalloc(siglen);
542 
543 	/* XXX handle CKR_BUFFER_TOO_SMALL */
544 	rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, &siglen);
545 	if (rv != CKR_OK) {
546 		error("C_Sign failed: %lu", rv);
547 		goto done;
548 	}
549 	if (siglen < 64 || siglen > 132 || siglen % 2) {
550 		error_f("bad signature length: %lu", (u_long)siglen);
551 		goto done;
552 	}
553 	bnlen = siglen/2;
554 	if ((ret = ECDSA_SIG_new()) == NULL) {
555 		error("ECDSA_SIG_new failed");
556 		goto done;
557 	}
558 	if ((r = BN_bin2bn(sig, bnlen, NULL)) == NULL ||
559 	    (s = BN_bin2bn(sig+bnlen, bnlen, NULL)) == NULL) {
560 		ossl_error("BN_bin2bn failed");
561 		ECDSA_SIG_free(ret);
562 		ret = NULL;
563 		goto done;
564 	}
565 	if (!ECDSA_SIG_set0(ret, r, s)) {
566 		error_f("ECDSA_SIG_set0 failed");
567 		ECDSA_SIG_free(ret);
568 		ret = NULL;
569 		goto done;
570 	}
571 	r = s = NULL; /* now owned by ret */
572 	/* success */
573  done:
574 	BN_free(r);
575 	BN_free(s);
576 	free(sig);
577 
578 	return (ret);
579 }
580 
581 static int
pkcs11_ecdsa_start_wrapper(void)582 pkcs11_ecdsa_start_wrapper(void)
583 {
584 	int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
585 	    unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
586 
587 	if (ec_key_method != NULL)
588 		return (0);
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)
592 		return (-1);
593 	ec_key_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
594 	if (ec_key_method == NULL)
595 		return (-1);
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);
598 	return (0);
599 }
600 
601 static int
pkcs11_ecdsa_wrap(struct pkcs11_provider * provider,CK_ULONG slotidx,CK_ATTRIBUTE * keyid_attrib,EC_KEY * ec)602 pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
603     CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec)
604 {
605 	struct pkcs11_key	*k11;
606 
607 	if (pkcs11_ecdsa_start_wrapper() == -1)
608 		return (-1);
609 
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);
619 	}
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");
624 
625 	return (0);
626 }
627 #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
628 
629 /* remove trailing spaces */
630 static char *
rmspace(u_char * buf,size_t len)631 rmspace(u_char *buf, size_t len)
632 {
633 	size_t i;
634 
635 	if (len == 0)
636 		return buf;
637 	for (i = len - 1; i > 0; i--)
638 		if (buf[i] == ' ')
639 			buf[i] = '\0';
640 		else
641 			break;
642 	return buf;
643 }
644 /* Used to printf fixed-width, space-padded, unterminated strings using %.*s */
645 #define RMSPACE(s) (int)sizeof(s), rmspace(s, sizeof(s))
646 
647 /*
648  * open a pkcs11 session and login if required.
649  * if pin == NULL we delay login until key use
650  */
651 static int
pkcs11_open_session(struct pkcs11_provider * p,CK_ULONG slotidx,char * pin,CK_ULONG user)652 pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin,
653     CK_ULONG user)
654 {
655 	struct pkcs11_slotinfo	*si;
656 	CK_FUNCTION_LIST	*f;
657 	CK_RV			rv;
658 	CK_SESSION_HANDLE	session;
659 	int			login_required, ret;
660 
661 	f = p->function_list;
662 	si = &p->slotinfo[slotidx];
663 
664 	login_required = si->token.flags & CKF_LOGIN_REQUIRED;
665 
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);
671 	}
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);
675 		return (-1);
676 	}
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);
686 			return (ret);
687 		}
688 		si->logged_in = 1;
689 	}
690 	si->session = session;
691 	return (0);
692 }
693 
694 static int
pkcs11_key_included(struct sshkey *** keysp,int * nkeys,struct sshkey * key)695 pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key)
696 {
697 	int i;
698 
699 	for (i = 0; i < *nkeys; i++)
700 		if (sshkey_equal(key, (*keysp)[i]))
701 			return (1);
702 	return (0);
703 }
704 
705 #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
706 static struct sshkey *
pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider * p,CK_ULONG slotidx,CK_OBJECT_HANDLE * obj)707 pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
708     CK_OBJECT_HANDLE *obj)
709 {
710 	CK_ATTRIBUTE		 key_attr[3];
711 	CK_SESSION_HANDLE	 session;
712 	CK_FUNCTION_LIST	*f = NULL;
713 	CK_RV			 rv;
714 	ASN1_OCTET_STRING	*octet = NULL;
715 	EC_KEY			*ec = NULL;
716 	EC_GROUP		*group = NULL;
717 	struct sshkey		*key = NULL;
718 	const unsigned char	*attrp = NULL;
719 	int			 i;
720 	int			 nid;
721 
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;
726 
727 	session = p->slotinfo[slotidx].session;
728 	f = p->function_list;
729 
730 	/* figure out size of the attributes */
731 	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
732 	if (rv != CKR_OK) {
733 		error("C_GetAttributeValue failed: %lu", rv);
734 		return (NULL);
735 	}
736 
737 	/*
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.
741 	 */
742 	if (key_attr[1].ulValueLen == 0 ||
743 	    key_attr[2].ulValueLen == 0) {
744 		error("invalid attribute length");
745 		return (NULL);
746 	}
747 
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);
752 
753 	/* retrieve ID, public point and curve parameters of EC key */
754 	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
755 	if (rv != CKR_OK) {
756 		error("C_GetAttributeValue failed: %lu", rv);
757 		goto fail;
758 	}
759 
760 	ec = EC_KEY_new();
761 	if (ec == NULL) {
762 		error("EC_KEY_new failed");
763 		goto fail;
764 	}
765 
766 	attrp = key_attr[2].pValue;
767 	group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen);
768 	if (group == NULL) {
769 		ossl_error("d2i_ECPKParameters failed");
770 		goto fail;
771 	}
772 
773 	if (EC_KEY_set_group(ec, group) == 0) {
774 		ossl_error("EC_KEY_set_group failed");
775 		goto fail;
776 	}
777 
778 	if (key_attr[1].ulValueLen <= 2) {
779 		error("CKA_EC_POINT too small");
780 		goto fail;
781 	}
782 
783 	attrp = key_attr[1].pValue;
784 	octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen);
785 	if (octet == NULL) {
786 		ossl_error("d2i_ASN1_OCTET_STRING failed");
787 		goto fail;
788 	}
789 	attrp = octet->data;
790 	if (o2i_ECPublicKey(&ec, &attrp, octet->length) == NULL) {
791 		ossl_error("o2i_ECPublicKey failed");
792 		goto fail;
793 	}
794 
795 	nid = sshkey_ecdsa_key_to_nid(ec);
796 	if (nid < 0) {
797 		error("couldn't get curve nid");
798 		goto fail;
799 	}
800 
801 	if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec))
802 		goto fail;
803 
804 	key = sshkey_new(KEY_UNSPEC);
805 	if (key == NULL) {
806 		error("sshkey_new failed");
807 		goto fail;
808 	}
809 
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;
818 
819 fail:
820 	for (i = 0; i < 3; i++)
821 		free(key_attr[i].pValue);
822 	if (ec)
823 		EC_KEY_free(ec);
824 	if (group)
825 		EC_GROUP_free(group);
826 	if (octet)
827 		ASN1_OCTET_STRING_free(octet);
828 
829 	return (key);
830 }
831 #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
832 
833 static struct sshkey *
pkcs11_fetch_rsa_pubkey(struct pkcs11_provider * p,CK_ULONG slotidx,CK_OBJECT_HANDLE * obj)834 pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
835     CK_OBJECT_HANDLE *obj)
836 {
837 	CK_ATTRIBUTE		 key_attr[3];
838 	CK_SESSION_HANDLE	 session;
839 	CK_FUNCTION_LIST	*f = NULL;
840 	CK_RV			 rv;
841 	RSA			*rsa = NULL;
842 	BIGNUM			*rsa_n, *rsa_e;
843 	struct sshkey		*key = NULL;
844 	int			 i;
845 
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;
850 
851 	session = p->slotinfo[slotidx].session;
852 	f = p->function_list;
853 
854 	/* figure out size of the attributes */
855 	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
856 	if (rv != CKR_OK) {
857 		error("C_GetAttributeValue failed: %lu", rv);
858 		return (NULL);
859 	}
860 
861 	/*
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.
865 	 */
866 	if (key_attr[1].ulValueLen == 0 ||
867 	    key_attr[2].ulValueLen == 0) {
868 		error("invalid attribute length");
869 		return (NULL);
870 	}
871 
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);
876 
877 	/* retrieve ID, modulus and public exponent of RSA key */
878 	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
879 	if (rv != CKR_OK) {
880 		error("C_GetAttributeValue failed: %lu", rv);
881 		goto fail;
882 	}
883 
884 	rsa = RSA_new();
885 	if (rsa == NULL) {
886 		error("RSA_new failed");
887 		goto fail;
888 	}
889 
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");
894 		goto fail;
895 	}
896 	if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL))
897 		fatal_f("set key");
898 	rsa_n = rsa_e = NULL; /* transferred */
899 
900 	if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa))
901 		goto fail;
902 
903 	key = sshkey_new(KEY_UNSPEC);
904 	if (key == NULL) {
905 		error("sshkey_new failed");
906 		goto fail;
907 	}
908 
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");
914 	key->type = KEY_RSA;
915 	key->flags |= SSHKEY_FLAG_EXT;
916 
917 fail:
918 	for (i = 0; i < 3; i++)
919 		free(key_attr[i].pValue);
920 	RSA_free(rsa);
921 
922 	return (key);
923 }
924 
925 static int
pkcs11_fetch_x509_pubkey(struct pkcs11_provider * p,CK_ULONG slotidx,CK_OBJECT_HANDLE * obj,struct sshkey ** keyp,char ** labelp)926 pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
927     CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp)
928 {
929 	CK_ATTRIBUTE		 cert_attr[3];
930 	CK_SESSION_HANDLE	 session;
931 	CK_FUNCTION_LIST	*f = NULL;
932 	CK_RV			 rv;
933 	X509			*x509 = NULL;
934 	X509_NAME		*x509_name = NULL;
935 	EVP_PKEY		*evp;
936 	RSA			*rsa = NULL;
937 #ifdef OPENSSL_HAS_ECC
938 	EC_KEY			*ec = NULL;
939 #endif
940 	struct sshkey		*key = NULL;
941 	int			 i;
942 #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
943 	int			 nid;
944 #endif
945 	const u_char		*cp;
946 	char			*subject = NULL;
947 
948 	*keyp = NULL;
949 	*labelp = NULL;
950 
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;
955 
956 	session = p->slotinfo[slotidx].session;
957 	f = p->function_list;
958 
959 	/* figure out size of the attributes */
960 	rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
961 	if (rv != CKR_OK) {
962 		error("C_GetAttributeValue failed: %lu", rv);
963 		return -1;
964 	}
965 
966 	/*
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.
970 	 */
971 	if (cert_attr[1].ulValueLen == 0 ||
972 	    cert_attr[2].ulValueLen == 0) {
973 		error("invalid attribute length");
974 		return -1;
975 	}
976 
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);
981 
982 	/* retrieve ID, subject and value of certificate */
983 	rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
984 	if (rv != CKR_OK) {
985 		error("C_GetAttributeValue failed: %lu", rv);
986 		goto out;
987 	}
988 
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);
996 
997 	cp = cert_attr[2].pValue;
998 	if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) {
999 		error("d2i_x509 failed");
1000 		goto out;
1001 	}
1002 
1003 	if ((evp = X509_get_pubkey(x509)) == NULL) {
1004 		error("X509_get_pubkey failed");
1005 		goto out;
1006 	}
1007 
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");
1011 			goto out;
1012 		}
1013 		if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) {
1014 			error("RSAPublicKey_dup failed");
1015 			goto out;
1016 		}
1017 
1018 		if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa))
1019 			goto out;
1020 
1021 		key = sshkey_new(KEY_UNSPEC);
1022 		if (key == NULL) {
1023 			error("sshkey_new failed");
1024 			goto out;
1025 		}
1026 
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");
1038 			goto out;
1039 		}
1040 		if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) {
1041 			error("EC_KEY_dup failed");
1042 			goto out;
1043 		}
1044 
1045 		nid = sshkey_ecdsa_key_to_nid(ec);
1046 		if (nid < 0) {
1047 			error("couldn't get curve nid");
1048 			goto out;
1049 		}
1050 
1051 		if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec))
1052 			goto out;
1053 
1054 		key = sshkey_new(KEY_UNSPEC);
1055 		if (key == NULL) {
1056 			error("sshkey_new failed");
1057 			goto out;
1058 		}
1059 
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 */
1069 	} else {
1070 		error("unknown certificate key type");
1071 		goto out;
1072 	}
1073  out:
1074 	for (i = 0; i < 3; i++)
1075 		free(cert_attr[i].pValue);
1076 	X509_free(x509);
1077 	RSA_free(rsa);
1078 #ifdef OPENSSL_HAS_ECC
1079 	EC_KEY_free(ec);
1080 #endif
1081 	if (key == NULL) {
1082 		free(subject);
1083 		return -1;
1084 	}
1085 	/* success */
1086 	*keyp = key;
1087 	*labelp = subject;
1088 	return 0;
1089 }
1090 
1091 #if 0
1092 static int
1093 have_rsa_key(const RSA *rsa)
1094 {
1095 	const BIGNUM *rsa_n, *rsa_e;
1096 
1097 	RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
1098 	return rsa_n != NULL && rsa_e != NULL;
1099 }
1100 #endif
1101 
1102 static void
note_key(struct pkcs11_provider * p,CK_ULONG slotidx,const char * context,struct sshkey * key)1103 note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context,
1104     struct sshkey *key)
1105 {
1106 	char *fp;
1107 
1108 	if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
1109 	    SSH_FP_DEFAULT)) == NULL) {
1110 		error_f("sshkey_fingerprint failed");
1111 		return;
1112 	}
1113 	debug2("%s: provider %s slot %lu: %s %s", context, p->name,
1114 	    (u_long)slotidx, sshkey_type(key), fp);
1115 	free(fp);
1116 }
1117 
1118 /*
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.
1122  */
1123 static int
pkcs11_fetch_certs(struct pkcs11_provider * p,CK_ULONG slotidx,struct sshkey *** keysp,char *** labelsp,int * nkeys)1124 pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
1125     struct sshkey ***keysp, char ***labelsp, int *nkeys)
1126 {
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;
1132 	CK_RV			 rv;
1133 	CK_OBJECT_HANDLE	 obj;
1134 	CK_ULONG		 n = 0;
1135 	int			 ret = -1;
1136 	char			*label;
1137 
1138 	memset(&key_attr, 0, sizeof(key_attr));
1139 	memset(&obj, 0, sizeof(obj));
1140 
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);
1145 
1146 	session = p->slotinfo[slotidx].session;
1147 	f = p->function_list;
1148 
1149 	rv = f->C_FindObjectsInit(session, key_attr, 1);
1150 	if (rv != CKR_OK) {
1151 		error("C_FindObjectsInit failed: %lu", rv);
1152 		goto fail;
1153 	}
1154 
1155 	while (1) {
1156 		CK_CERTIFICATE_TYPE	ck_cert_type;
1157 
1158 		rv = f->C_FindObjects(session, &obj, 1, &n);
1159 		if (rv != CKR_OK) {
1160 			error("C_FindObjects failed: %lu", rv);
1161 			goto fail;
1162 		}
1163 		if (n == 0)
1164 			break;
1165 
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);
1171 
1172 		rv = f->C_GetAttributeValue(session, obj, key_attr, 1);
1173 		if (rv != CKR_OK) {
1174 			error("C_GetAttributeValue failed: %lu", rv);
1175 			goto fail;
1176 		}
1177 
1178 		key = NULL;
1179 		label = NULL;
1180 		switch (ck_cert_type) {
1181 		case CKC_X_509:
1182 			if (pkcs11_fetch_x509_pubkey(p, slotidx, &obj,
1183 			    &key, &label) != 0) {
1184 				error("failed to fetch key");
1185 				continue;
1186 			}
1187 			break;
1188 		default:
1189 			error("skipping unsupported certificate type %lu",
1190 			    ck_cert_type);
1191 			continue;
1192 		}
1193 		note_key(p, slotidx, __func__, key);
1194 		if (pkcs11_key_included(keysp, nkeys, key)) {
1195 			debug2_f("key already included");;
1196 			sshkey_free(key);
1197 		} else {
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);
1206 			}
1207 			*nkeys = *nkeys + 1;
1208 			debug("have %d keys", *nkeys);
1209 		}
1210 	}
1211 
1212 	ret = 0;
1213 fail:
1214 	rv = f->C_FindObjectsFinal(session);
1215 	if (rv != CKR_OK) {
1216 		error("C_FindObjectsFinal failed: %lu", rv);
1217 		ret = -1;
1218 	}
1219 
1220 	return (ret);
1221 }
1222 
1223 /*
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.
1227  */
1228 static int
pkcs11_fetch_keys(struct pkcs11_provider * p,CK_ULONG slotidx,struct sshkey *** keysp,char *** labelsp,int * nkeys)1229 pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1230     struct sshkey ***keysp, char ***labelsp, int *nkeys)
1231 {
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;
1237 	CK_RV			 rv;
1238 	CK_OBJECT_HANDLE	 obj;
1239 	CK_ULONG		 n = 0;
1240 	int			 ret = -1;
1241 
1242 	memset(&key_attr, 0, sizeof(key_attr));
1243 	memset(&obj, 0, sizeof(obj));
1244 
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);
1249 
1250 	session = p->slotinfo[slotidx].session;
1251 	f = p->function_list;
1252 
1253 	rv = f->C_FindObjectsInit(session, key_attr, 1);
1254 	if (rv != CKR_OK) {
1255 		error("C_FindObjectsInit failed: %lu", rv);
1256 		goto fail;
1257 	}
1258 
1259 	while (1) {
1260 		CK_KEY_TYPE	ck_key_type;
1261 		CK_UTF8CHAR	label[256];
1262 
1263 		rv = f->C_FindObjects(session, &obj, 1, &n);
1264 		if (rv != CKR_OK) {
1265 			error("C_FindObjects failed: %lu", rv);
1266 			goto fail;
1267 		}
1268 		if (n == 0)
1269 			break;
1270 
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;
1279 
1280 		rv = f->C_GetAttributeValue(session, obj, key_attr, 2);
1281 		if (rv != CKR_OK) {
1282 			error("C_GetAttributeValue failed: %lu", rv);
1283 			goto fail;
1284 		}
1285 
1286 		label[key_attr[1].ulValueLen] = '\0';
1287 
1288 		switch (ck_key_type) {
1289 		case CKK_RSA:
1290 			key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
1291 			break;
1292 #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
1293 		case CKK_ECDSA:
1294 			key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
1295 			break;
1296 #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
1297 		default:
1298 			/* XXX print key type? */
1299 			key = NULL;
1300 			error("skipping unsupported key type");
1301 		}
1302 
1303 		if (key == NULL) {
1304 			error("failed to fetch key");
1305 			continue;
1306 		}
1307 		note_key(p, slotidx, __func__, key);
1308 		if (pkcs11_key_included(keysp, nkeys, key)) {
1309 			debug2_f("key already included");;
1310 			sshkey_free(key);
1311 		} else {
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);
1320 			}
1321 			*nkeys = *nkeys + 1;
1322 			debug("have %d keys", *nkeys);
1323 		}
1324 	}
1325 
1326 	ret = 0;
1327 fail:
1328 	rv = f->C_FindObjectsFinal(session);
1329 	if (rv != CKR_OK) {
1330 		error("C_FindObjectsFinal failed: %lu", rv);
1331 		ret = -1;
1332 	}
1333 
1334 	return (ret);
1335 }
1336 
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++; }
1340 
1341 static struct sshkey *
pkcs11_rsa_generate_private_key(struct pkcs11_provider * p,CK_ULONG slotidx,char * label,CK_ULONG bits,CK_BYTE keyid,u_int32_t * err)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)
1344 {
1345 	struct pkcs11_slotinfo	*si;
1346 	char			*plabel = label ? label : "";
1347 	int			 npub = 0, npriv = 0;
1348 	CK_RV			 rv;
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
1356 	};
1357 	CK_BYTE			 pubExponent[] = {
1358 	    0x01, 0x00, 0x01 /* RSA_F4 in bytes */
1359 	};
1360 	pubkey_filter[0].pValue = &pubkey_class;
1361 	cert_filter[0].pValue = &cert_class;
1362 
1363 	*err = 0;
1364 
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,
1370 	    sizeof(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));
1377 
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,
1385 	    sizeof(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));
1389 
1390 	f = p->function_list;
1391 	si = &p->slotinfo[slotidx];
1392 	session = si->session;
1393 
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);
1397 		*err = rv;
1398 		return NULL;
1399 	}
1400 
1401 	return pkcs11_fetch_rsa_pubkey(p, slotidx, &pubKey);
1402 }
1403 
1404 static int
h2i(char c)1405 h2i(char c)
1406 {
1407 	if (c >= '0' && c <= '9')
1408 		return c - '0';
1409 	else if (c >= 'a' && c <= 'f')
1410 		return c - 'a' + 10;
1411 	else if (c >= 'A' && c <= 'F')
1412 		return c - 'A' + 10;
1413 	else
1414 		return -1;
1415 }
1416 
1417 static int
pkcs11_decode_hex(const char * hex,unsigned char ** dest,size_t * rlen)1418 pkcs11_decode_hex(const char *hex, unsigned char **dest, size_t *rlen)
1419 {
1420 	size_t	i, len;
1421 
1422 	if (dest)
1423 		*dest = NULL;
1424 	if (rlen)
1425 		*rlen = 0;
1426 
1427 	if ((len = strlen(hex)) % 2)
1428 		return -1;
1429 	len /= 2;
1430 
1431 	*dest = xmalloc(len);
1432 
1433 	for (i = 0; i < len; i++) {
1434 		int hi, low;
1435 
1436 		hi = h2i(hex[2 * i]);
1437 		lo = h2i(hex[(2 * i) + 1]);
1438 		if (hi == -1 || lo == -1)
1439 			return -1;
1440 		(*dest)[i] = (hi << 4) | lo;
1441 	}
1442 
1443 	if (rlen)
1444 		*rlen = len;
1445 
1446 	return 0;
1447 }
1448 
1449 static struct ec_curve_info {
1450 	const char	*name;
1451 	const char	*oid;
1452 	const char	*oid_encoded;
1453 	size_t		 size;
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},
1459 };
1460 
1461 static struct sshkey *
pkcs11_ecdsa_generate_private_key(struct pkcs11_provider * p,CK_ULONG slotidx,char * label,CK_ULONG bits,CK_BYTE keyid,u_int32_t * err)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)
1464 {
1465 	struct pkcs11_slotinfo	*si;
1466 	char			*plabel = label ? label : "";
1467 	int			 i;
1468 	size_t			 ecparams_size;
1469 	unsigned char		*ecparams = NULL;
1470 	int			 npub = 0, npriv = 0;
1471 	CK_RV			 rv;
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
1478 	};
1479 	CK_ATTRIBUTE		 tpub[16], tpriv[16];
1480 
1481 	*err = 0;
1482 
1483 	for (i = 0; ec_curve_infos[i].name; i++) {
1484 		if (ec_curve_infos[i].size == bits)
1485 			break;
1486 	}
1487 	if (!ec_curve_infos[i].name) {
1488 		error_f("invalid key size %lu", bits);
1489 		return NULL;
1490 	}
1491 	if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams,
1492 	    &ecparams_size) == -1) {
1493 		error_f("invalid oid");
1494 		return NULL;
1495 	}
1496 
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,
1502 	    sizeof(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));
1507 
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,
1515 	    sizeof(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));
1519 
1520 	f = p->function_list;
1521 	si = &p->slotinfo[slotidx];
1522 	session = si->session;
1523 
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);
1527 		*err = rv;
1528 		return NULL;
1529 	}
1530 
1531 	return pkcs11_fetch_ecdsa_pubkey(p, slotidx, &pubKey);
1532 }
1533 #endif /* WITH_PKCS11_KEYGEN */
1534 
1535 /*
1536  * register a new provider, fails if provider already exists. if
1537  * keyp is provided, fetch keys.
1538  */
1539 static int
pkcs11_register_provider(char * provider_id,char * pin,struct sshkey *** keyp,char *** labelsp,struct pkcs11_provider ** providerp,CK_ULONG user)1540 pkcs11_register_provider(char *provider_id, char *pin,
1541     struct sshkey ***keyp, char ***labelsp,
1542     struct pkcs11_provider **providerp, CK_ULONG user)
1543 {
1544 	int nkeys, need_finalize = 0;
1545 	int ret = -1;
1546 	struct pkcs11_provider *p = NULL;
1547 	void *handle = NULL;
1548 	CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **);
1549 	CK_RV rv;
1550 	CK_FUNCTION_LIST *f = NULL;
1551 	CK_TOKEN_INFO *token;
1552 	CK_ULONG i;
1553 
1554 	if (providerp == NULL)
1555 		goto fail;
1556 	*providerp = NULL;
1557 
1558 	if (keyp != NULL)
1559 		*keyp = NULL;
1560 	if (labelsp != NULL)
1561 		*labelsp = NULL;
1562 
1563 	if (pkcs11_provider_lookup(provider_id) != NULL) {
1564 		debug_f("provider already registered: %s", provider_id);
1565 		goto fail;
1566 	}
1567 	if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) {
1568 		error("provider %s is not a PKCS11 library", provider_id);
1569 		goto fail;
1570 	}
1571 	/* open shared pkcs11-library */
1572 	if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {
1573 		error("dlopen %s failed: %s", provider_id, dlerror());
1574 		goto fail;
1575 	}
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);
1580 	p->handle = handle;
1581 	/* setup the pkcs11 callbacks */
1582 	if ((rv = (*getfunctionlist)(&f)) != CKR_OK) {
1583 		error("C_GetFunctionList for provider %s failed: %lu",
1584 		    provider_id, rv);
1585 		goto fail;
1586 	}
1587 	p->function_list = f;
1588 	if ((rv = f->C_Initialize(NULL)) != CKR_OK) {
1589 		error("C_Initialize for provider %s failed: %lu",
1590 		    provider_id, rv);
1591 		goto fail;
1592 	}
1593 	need_finalize = 1;
1594 	if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) {
1595 		error("C_GetInfo for provider %s failed: %lu",
1596 		    provider_id, rv);
1597 		goto fail;
1598 	}
1599 	debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d"
1600 	    " libraryDescription <%.*s> libraryVersion %d.%d",
1601 	    provider_id,
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);
1610 		goto fail;
1611 	}
1612 	if (p->nslots == 0) {
1613 		debug_f("provider %s returned no slots", provider_id);
1614 		ret = -SSH_PKCS11_ERR_NO_SLOTS;
1615 		goto fail;
1616 	}
1617 	p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID));
1618 	if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots))
1619 	    != CKR_OK) {
1620 		error("C_GetSlotList for provider %s failed: %lu",
1621 		    provider_id, rv);
1622 		goto fail;
1623 	}
1624 	p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo));
1625 	p->valid = 1;
1626 	nkeys = 0;
1627 	for (i = 0; i < p->nslots; i++) {
1628 		token = &p->slotinfo[i].token;
1629 		if ((rv = f->C_GetTokenInfo(p->slotlist[i], token))
1630 		    != CKR_OK) {
1631 			error("C_GetTokenInfo for provider %s slot %lu "
1632 			    "failed: %lu", provider_id, (u_long)i, rv);
1633 			continue;
1634 		}
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);
1638 			continue;
1639 		}
1640 		debug("provider %s slot %lu: label <%.*s> "
1641 		    "manufacturerID <%.*s> model <%.*s> serial <%.*s> "
1642 		    "flags 0x%lx",
1643 		    provider_id, (unsigned long)i,
1644 		    RMSPACE(token->label), RMSPACE(token->manufacturerID),
1645 		    RMSPACE(token->model), RMSPACE(token->serialNumber),
1646 		    token->flags);
1647 		/*
1648 		 * open session, login with pin and retrieve public
1649 		 * keys (if keyp is provided)
1650 		 */
1651 		if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 ||
1652 		    keyp == NULL)
1653 			continue;
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) {
1658 			/*
1659 			 * Some tokens require login before they will
1660 			 * expose keys.
1661 			 */
1662 			if (pkcs11_login_slot(p, &p->slotinfo[i],
1663 			    CKU_USER) < 0) {
1664 				error("login failed");
1665 				continue;
1666 			}
1667 			pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
1668 			pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
1669 		}
1670 	}
1671 
1672 	/* now owned by caller */
1673 	*providerp = p;
1674 
1675 	TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
1676 	p->refcount++;	/* add to provider list */
1677 
1678 	return (nkeys);
1679 fail:
1680 	if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK)
1681 		error("C_Finalize for provider %s failed: %lu",
1682 		    provider_id, rv);
1683 	if (p) {
1684 		free(p->name);
1685 		free(p->slotlist);
1686 		free(p->slotinfo);
1687 		free(p);
1688 	}
1689 	if (handle)
1690 		dlclose(handle);
1691 	if (ret > 0)
1692 		ret = -1;
1693 	return (ret);
1694 }
1695 
1696 /*
1697  * register a new provider and get number of keys hold by the token,
1698  * fails if provider already exists
1699  */
1700 int
pkcs11_add_provider(char * provider_id,char * pin,struct sshkey *** keyp,char *** labelsp)1701 pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1702     char ***labelsp)
1703 {
1704 	struct pkcs11_provider *p = NULL;
1705 	int nkeys;
1706 
1707 	nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp,
1708 	    &p, CKU_USER);
1709 
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);
1715 	}
1716 	if (nkeys == 0)
1717 		debug_f("provider %s returned no keys", provider_id);
1718 
1719 	return (nkeys);
1720 }
1721 
1722 #ifdef WITH_PKCS11_KEYGEN
1723 struct sshkey *
pkcs11_gakp(char * provider_id,char * pin,unsigned int slotidx,char * label,unsigned int type,unsigned int bits,unsigned char keyid,u_int32_t * err)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)
1726 {
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;
1733 	CK_RV			 rv;
1734 
1735 	*err = 0;
1736 
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,
1740 	    &p, CKU_SO)) < 0) {
1741 		debug_f("could not register provider %s", provider_id);
1742 		goto out;
1743 	} else
1744 		reset_provider = 1;
1745 
1746 	f = p->function_list;
1747 	si = &p->slotinfo[slotidx];
1748 	session = si->session;
1749 
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);
1753 		reset_pin = 0;
1754 	} else
1755 		reset_pin = 1;
1756 
1757 	switch (type) {
1758 	case KEY_RSA:
1759 		if ((k = pkcs11_rsa_generate_private_key(p, slotidx, label,
1760 		    bits, keyid, err)) == NULL) {
1761 			debug_f("failed to generate RSA key");
1762 			goto out;
1763 		}
1764 		break;
1765 	case KEY_ECDSA:
1766 		if ((k = pkcs11_ecdsa_generate_private_key(p, slotidx, label,
1767 		    bits, keyid, err)) == NULL) {
1768 			debug_f("failed to generate ECDSA key");
1769 			goto out;
1770 		}
1771 		break;
1772 	default:
1773 		*err = SSH_PKCS11_ERR_GENERIC;
1774 		debug_f("unknown type %d", type);
1775 		goto out;
1776 	}
1777 
1778 out:
1779 	if (reset_pin)
1780 		f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
1781 		    CK_INVALID_HANDLE);
1782 
1783 	if (reset_provider)
1784 		pkcs11_del_provider(provider_id);
1785 
1786 	return (k);
1787 }
1788 
1789 struct sshkey *
pkcs11_destroy_keypair(char * provider_id,char * pin,unsigned long slotidx,unsigned char keyid,u_int32_t * err)1790 pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
1791     unsigned char keyid, u_int32_t *err)
1792 {
1793 	struct pkcs11_provider	*p = NULL;
1794 	struct pkcs11_slotinfo	*si;
1795 	struct sshkey		*k = NULL;
1796 	int			 reset_pin = 0, reset_provider = 0;
1797 	CK_ULONG		 nattrs;
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;
1804 	CK_RV			 rv;
1805 
1806 	*err = 0;
1807 
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,
1811 	    CKU_SO) < 0) {
1812 		debug_f("could not register provider %s",
1813 		    provider_id);
1814 		goto out;
1815 	} else
1816 		reset_provider = 1;
1817 
1818 	f = p->function_list;
1819 	si = &p->slotinfo[slotidx];
1820 	session = si->session;
1821 
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);
1825 		reset_pin = 0;
1826 	} else
1827 		reset_pin = 1;
1828 
1829 	/* private key */
1830 	nattrs = 0;
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));
1834 
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",
1839 			    keyid);
1840 			*err = rv;
1841 			goto out;
1842 		}
1843 	}
1844 
1845 	/* public key */
1846 	nattrs = 0;
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));
1850 
1851 	if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
1852 	    obj != CK_INVALID_HANDLE) {
1853 
1854 		/* get key type */
1855 		nattrs = 0;
1856 		FILL_ATTR(attrs, nattrs, CKA_KEY_TYPE, &key_type,
1857 		    sizeof(key_type));
1858 		rv = f->C_GetAttributeValue(session, obj, attrs, nattrs);
1859 		if (rv != CKR_OK) {
1860 			debug_f("could not get key type of public key 0x%hhx",
1861 			    keyid);
1862 			*err = rv;
1863 			key_type = -1;
1864 		}
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);
1869 
1870 		if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
1871 			debug_f("could not destroy public key 0x%hhx", keyid);
1872 			*err = rv;
1873 			goto out;
1874 		}
1875 	}
1876 
1877 out:
1878 	if (reset_pin)
1879 		f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
1880 		    CK_INVALID_HANDLE);
1881 
1882 	if (reset_provider)
1883 		pkcs11_del_provider(provider_id);
1884 
1885 	return (k);
1886 }
1887 #endif /* WITH_PKCS11_KEYGEN */
1888 #else /* ENABLE_PKCS11 */
1889 
1890 #include <sys/types.h>
1891 #include <stdarg.h>
1892 #include <stdio.h>
1893 
1894 #include "log.h"
1895 #include "sshkey.h"
1896 
1897 int
pkcs11_init(int interactive)1898 pkcs11_init(int interactive)
1899 {
1900 	error("%s: dlopen() not supported", __func__);
1901 	return (-1);
1902 }
1903 
1904 int
pkcs11_add_provider(char * provider_id,char * pin,struct sshkey *** keyp,char *** labelsp)1905 pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1906     char ***labelsp)
1907 {
1908 	error("%s: dlopen() not supported", __func__);
1909 	return (-1);
1910 }
1911 
1912 void
pkcs11_terminate(void)1913 pkcs11_terminate(void)
1914 {
1915 	error("%s: dlopen() not supported", __func__);
1916 }
1917 #endif /* ENABLE_PKCS11 */
1918