xref: /freebsd/crypto/openssh/ssh-pkcs11.c (revision 2574974648c68c738aec3ff96644d888d7913a37)
1 /* $OpenBSD: ssh-pkcs11.c,v 1.78 2026/03/03 09:57:25 dtucker 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 #include <sys/time.h>
24 
25 #include <sys/types.h>
26 #include <sys/queue.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 
30 #include <string.h>
31 #include <dlfcn.h>
32 
33 #ifdef WITH_OPENSSL
34 #include "openbsd-compat/openssl-compat.h"
35 #include <openssl/bn.h>
36 #include <openssl/ecdsa.h>
37 #include <openssl/x509.h>
38 #include <openssl/err.h>
39 #endif
40 
41 #define CRYPTOKI_COMPAT
42 #include "pkcs11.h"
43 
44 #define SSHKEY_INTERNAL
45 #include "sshkey.h"
46 
47 #include "log.h"
48 #include "misc.h"
49 #include "sshbuf.h"
50 #include "ssh-pkcs11.h"
51 #include "digest.h"
52 #include "xmalloc.h"
53 #include "crypto_api.h"
54 
55 struct pkcs11_slotinfo {
56 	CK_TOKEN_INFO		token;
57 	CK_SESSION_HANDLE	session;
58 	int			logged_in;
59 };
60 
61 struct pkcs11_provider {
62 	char			*name;
63 	void			*handle;
64 	CK_FUNCTION_LIST	*function_list;
65 	CK_INFO			info;
66 	CK_ULONG		nslots;
67 	CK_SLOT_ID		*slotlist;
68 	struct pkcs11_slotinfo	*slotinfo;
69 	int			valid;
70 	int			refcount;
71 	TAILQ_ENTRY(pkcs11_provider) next;
72 };
73 
74 TAILQ_HEAD(, pkcs11_provider) pkcs11_providers;
75 
76 struct pkcs11_key {
77 	struct sshbuf		*keyblob;
78 	struct pkcs11_provider	*provider;
79 	CK_ULONG		slotidx;
80 	char			*keyid;
81 	int			keyid_len;
82 	TAILQ_ENTRY(pkcs11_key)	next;
83 };
84 
85 TAILQ_HEAD(, pkcs11_key) pkcs11_keys; /* XXX a tree would be better */
86 
87 int pkcs11_interactive = 0;
88 
89 #if defined(OPENSSL_HAS_ECC) || defined(OPENSSL_HAS_ED25519)
90 static void
ossl_error(const char * msg)91 ossl_error(const char *msg)
92 {
93 	unsigned long    e;
94 
95 	error_f("%s", msg);
96 	while ((e = ERR_get_error()) != 0)
97 		error_f("libcrypto error: %s", ERR_error_string(e, NULL));
98 }
99 #endif
100 
101 /*
102  * finalize a provider shared library, it's no longer usable.
103  * however, there might still be keys referencing this provider,
104  * so the actual freeing of memory is handled by pkcs11_provider_unref().
105  * this is called when a provider gets unregistered.
106  */
107 static void
pkcs11_provider_finalize(struct pkcs11_provider * p)108 pkcs11_provider_finalize(struct pkcs11_provider *p)
109 {
110 	CK_RV rv;
111 	CK_ULONG i;
112 
113 	debug_f("provider \"%s\" refcount %d valid %d",
114 	    p->name, p->refcount, p->valid);
115 	if (!p->valid)
116 		return;
117 	for (i = 0; i < p->nslots; i++) {
118 		if (p->slotinfo[i].session &&
119 		    (rv = p->function_list->C_CloseSession(
120 		    p->slotinfo[i].session)) != CKR_OK)
121 			error("C_CloseSession failed: %lu", rv);
122 	}
123 	if ((rv = p->function_list->C_Finalize(NULL)) != CKR_OK)
124 		error("C_Finalize failed: %lu", rv);
125 	p->valid = 0;
126 	p->function_list = NULL;
127 	dlclose(p->handle);
128 }
129 
130 /*
131  * remove a reference to the provider.
132  * called when a key gets destroyed or when the provider is unregistered.
133  */
134 static void
pkcs11_provider_unref(struct pkcs11_provider * p)135 pkcs11_provider_unref(struct pkcs11_provider *p)
136 {
137 	debug_f("provider \"%s\" refcount %d", p->name, p->refcount);
138 	if (--p->refcount <= 0) {
139 		if (p->valid)
140 			error_f("provider \"%s\" still valid", p->name);
141 		free(p->name);
142 		free(p->slotlist);
143 		free(p->slotinfo);
144 		free(p);
145 	}
146 }
147 
148 /* lookup provider by name */
149 static struct pkcs11_provider *
pkcs11_provider_lookup(char * provider_id)150 pkcs11_provider_lookup(char *provider_id)
151 {
152 	struct pkcs11_provider *p;
153 
154 	TAILQ_FOREACH(p, &pkcs11_providers, next) {
155 		debug("check provider \"%s\"", p->name);
156 		if (!strcmp(provider_id, p->name))
157 			return (p);
158 	}
159 	return (NULL);
160 }
161 
162 /* unregister provider by name */
163 int
pkcs11_del_provider(char * provider_id)164 pkcs11_del_provider(char *provider_id)
165 {
166 	struct pkcs11_provider *p;
167 
168 	if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
169 		TAILQ_REMOVE(&pkcs11_providers, p, next);
170 		pkcs11_provider_finalize(p);
171 		pkcs11_provider_unref(p);
172 		return (0);
173 	}
174 	return (-1);
175 }
176 
177 /* release a wrapped object */
178 static void
pkcs11_k11_free(struct pkcs11_key * k11)179 pkcs11_k11_free(struct pkcs11_key *k11)
180 {
181 	if (k11 == NULL)
182 		return;
183 	if (k11->provider)
184 		pkcs11_provider_unref(k11->provider);
185 	free(k11->keyid);
186 	sshbuf_free(k11->keyblob);
187 	free(k11);
188 }
189 
190 /* find a single 'obj' for given attributes */
191 static int
pkcs11_find(struct pkcs11_provider * p,CK_ULONG slotidx,CK_ATTRIBUTE * attr,CK_ULONG nattr,CK_OBJECT_HANDLE * obj)192 pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr,
193     CK_ULONG nattr, CK_OBJECT_HANDLE *obj)
194 {
195 	CK_FUNCTION_LIST	*f;
196 	CK_SESSION_HANDLE	session;
197 	CK_ULONG		nfound = 0;
198 	CK_RV			rv;
199 	int			ret = -1;
200 
201 	f = p->function_list;
202 	session = p->slotinfo[slotidx].session;
203 	if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) {
204 		error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv);
205 		return (-1);
206 	}
207 	if ((rv = f->C_FindObjects(session, obj, 1, &nfound)) != CKR_OK ||
208 	    nfound != 1) {
209 		debug("C_FindObjects failed (nfound %lu nattr %lu): %lu",
210 		    nfound, nattr, rv);
211 	} else
212 		ret = 0;
213 	if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK)
214 		error("C_FindObjectsFinal failed: %lu", rv);
215 	return (ret);
216 }
217 
218 static int
pkcs11_login_slot(struct pkcs11_provider * provider,struct pkcs11_slotinfo * si,CK_USER_TYPE type)219 pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si,
220     CK_USER_TYPE type)
221 {
222 	char			*pin = NULL, prompt[1024];
223 	CK_RV			 rv;
224 
225 	if (provider == NULL || si == NULL || !provider->valid) {
226 		error("no pkcs11 (valid) provider found");
227 		return (-1);
228 	}
229 
230 	if (!pkcs11_interactive) {
231 		error("need pin entry%s",
232 		    (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ?
233 		    " on reader keypad" : "");
234 		return (-1);
235 	}
236 	if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
237 		verbose("Deferring PIN entry to reader keypad.");
238 	else {
239 		snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
240 		    si->token.label);
241 		if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) {
242 			debug_f("no pin specified");
243 			return (-1);	/* bail out */
244 		}
245 	}
246 	rv = provider->function_list->C_Login(si->session, type, (u_char *)pin,
247 	    (pin != NULL) ? strlen(pin) : 0);
248 	if (pin != NULL)
249 		freezero(pin, strlen(pin));
250 
251 	switch (rv) {
252 	case CKR_OK:
253 	case CKR_USER_ALREADY_LOGGED_IN:
254 		/* success */
255 		break;
256 	case CKR_PIN_LEN_RANGE:
257 		error("PKCS#11 login failed: PIN length out of range");
258 		return -1;
259 	case CKR_PIN_INCORRECT:
260 		error("PKCS#11 login failed: PIN incorrect");
261 		return -1;
262 	case CKR_PIN_LOCKED:
263 		error("PKCS#11 login failed: PIN locked");
264 		return -1;
265 	default:
266 		error("PKCS#11 login failed: error %lu", rv);
267 		return -1;
268 	}
269 	si->logged_in = 1;
270 	return (0);
271 }
272 
273 static int
pkcs11_login(struct pkcs11_key * k11,CK_USER_TYPE type)274 pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type)
275 {
276 	if (k11 == NULL || k11->provider == NULL || !k11->provider->valid) {
277 		error("no pkcs11 (valid) provider found");
278 		return (-1);
279 	}
280 
281 	return pkcs11_login_slot(k11->provider,
282 	    &k11->provider->slotinfo[k11->slotidx], type);
283 }
284 
285 
286 static int
pkcs11_check_obj_bool_attrib(struct pkcs11_key * k11,CK_OBJECT_HANDLE obj,CK_ATTRIBUTE_TYPE type,int * val)287 pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj,
288     CK_ATTRIBUTE_TYPE type, int *val)
289 {
290 	struct pkcs11_slotinfo	*si;
291 	CK_FUNCTION_LIST	*f;
292 	CK_BBOOL		flag = 0;
293 	CK_ATTRIBUTE		attr;
294 	CK_RV			 rv;
295 
296 	*val = 0;
297 
298 	if (!k11->provider || !k11->provider->valid) {
299 		error("no pkcs11 (valid) provider found");
300 		return (-1);
301 	}
302 
303 	f = k11->provider->function_list;
304 	si = &k11->provider->slotinfo[k11->slotidx];
305 
306 	attr.type = type;
307 	attr.pValue = &flag;
308 	attr.ulValueLen = sizeof(flag);
309 
310 	rv = f->C_GetAttributeValue(si->session, obj, &attr, 1);
311 	if (rv != CKR_OK) {
312 		error("C_GetAttributeValue failed: %lu", rv);
313 		return (-1);
314 	}
315 	*val = flag != 0;
316 	debug_f("provider \"%s\" slot %lu object %lu: attrib %lu = %d",
317 	    k11->provider->name, k11->slotidx, obj, type, *val);
318 	return (0);
319 }
320 
321 static int
pkcs11_get_key(struct pkcs11_key * k11,CK_MECHANISM_TYPE mech_type)322 pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
323 {
324 	struct pkcs11_slotinfo	*si;
325 	CK_FUNCTION_LIST	*f;
326 	CK_OBJECT_HANDLE	 obj;
327 	CK_RV			 rv;
328 	CK_OBJECT_CLASS		 private_key_class;
329 	CK_BBOOL		 true_val;
330 	CK_MECHANISM		 mech;
331 	CK_ATTRIBUTE		 key_filter[3];
332 	int			 always_auth = 0;
333 	int			 did_login = 0;
334 
335 	if (!k11->provider || !k11->provider->valid) {
336 		error("no pkcs11 (valid) provider found");
337 		return (-1);
338 	}
339 
340 	f = k11->provider->function_list;
341 	si = &k11->provider->slotinfo[k11->slotidx];
342 
343 	if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
344 		if (pkcs11_login(k11, CKU_USER) < 0) {
345 			error("login failed");
346 			return (-1);
347 		}
348 		did_login = 1;
349 	}
350 
351 	memset(&key_filter, 0, sizeof(key_filter));
352 	private_key_class = CKO_PRIVATE_KEY;
353 	key_filter[0].type = CKA_CLASS;
354 	key_filter[0].pValue = &private_key_class;
355 	key_filter[0].ulValueLen = sizeof(private_key_class);
356 
357 	key_filter[1].type = CKA_ID;
358 	key_filter[1].pValue = k11->keyid;
359 	key_filter[1].ulValueLen = k11->keyid_len;
360 
361 	true_val = CK_TRUE;
362 	key_filter[2].type = CKA_SIGN;
363 	key_filter[2].pValue = &true_val;
364 	key_filter[2].ulValueLen = sizeof(true_val);
365 
366 	/* try to find object w/CKA_SIGN first, retry w/o */
367 	if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 &&
368 	    pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) {
369 		error("cannot find private key");
370 		return (-1);
371 	}
372 
373 	memset(&mech, 0, sizeof(mech));
374 	mech.mechanism = mech_type;
375 	mech.pParameter = NULL_PTR;
376 	mech.ulParameterLen = 0;
377 
378 	if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
379 		error("C_SignInit failed: %lu", rv);
380 		return (-1);
381 	}
382 
383 	pkcs11_check_obj_bool_attrib(k11, obj, CKA_ALWAYS_AUTHENTICATE,
384 	    &always_auth); /* ignore errors here */
385 	if (always_auth && !did_login) {
386 		debug_f("always-auth key");
387 		if (pkcs11_login(k11, CKU_CONTEXT_SPECIFIC) < 0) {
388 			error("login failed for always-auth key");
389 			return (-1);
390 		}
391 	}
392 
393 	return (0);
394 }
395 
396 /* record the key information later use lookup by keyblob */
397 static int
pkcs11_record_key(struct pkcs11_provider * provider,CK_ULONG slotidx,CK_ATTRIBUTE * keyid_attrib,struct sshkey * key)398 pkcs11_record_key(struct pkcs11_provider *provider, CK_ULONG slotidx,
399     CK_ATTRIBUTE *keyid_attrib, struct sshkey *key)
400 {
401 	struct sshbuf *keyblob;
402 	struct pkcs11_key *k11;
403 	int r;
404 	char *hex;
405 
406 	hex = tohex(keyid_attrib->pValue, keyid_attrib->ulValueLen);
407 	debug_f("%s key: provider %s slot %lu keyid %s",
408 	    sshkey_type(key), provider->name, (u_long)slotidx, hex);
409 	free(hex);
410 
411 	if ((keyblob = sshbuf_new()) == NULL)
412 		fatal_f("sshbuf_new failed");
413 	if ((r = sshkey_putb(key, keyblob)) != 0)
414 		fatal_fr(r, "sshkey_putb");
415 
416 	/* Check if we've already recorded this key in a different slot */
417 	TAILQ_FOREACH(k11, &pkcs11_keys, next) {
418 		if (sshbuf_equals(k11->keyblob, keyblob) == 0) {
419 			hex = tohex(k11->keyid, k11->keyid_len);
420 			debug_f("Already seen this key at "
421 			    "provider %s slot %lu keyid %s",
422 			    k11->provider->name, k11->slotidx, hex);
423 			free(hex);
424 			sshbuf_free(keyblob);
425 			return -1;
426 		}
427 	}
428 
429 	k11 = xcalloc(1, sizeof(*k11));
430 	k11->provider = provider;
431 	k11->keyblob = keyblob;
432 	provider->refcount++;	/* provider referenced by RSA key */
433 	k11->slotidx = slotidx;
434 	/* identify key object on smartcard */
435 	k11->keyid_len = keyid_attrib->ulValueLen;
436 	if (k11->keyid_len > 0) {
437 		k11->keyid = xmalloc(k11->keyid_len);
438 		memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
439 	}
440 	TAILQ_INSERT_TAIL(&pkcs11_keys, k11, next);
441 
442 	return 0;
443 }
444 
445 /* retrieve the key information by keyblob */
446 static struct pkcs11_key *
pkcs11_lookup_key(struct sshkey * key)447 pkcs11_lookup_key(struct sshkey *key)
448 {
449 	struct pkcs11_key *k11, *found = NULL;
450 	struct sshbuf *keyblob;
451 	int r;
452 
453 	if ((keyblob = sshbuf_new()) == NULL)
454 		fatal_f("sshbuf_new failed");
455 	if ((r = sshkey_putb(key, keyblob)) != 0)
456 		fatal_fr(r, "sshkey_putb");
457 	TAILQ_FOREACH(k11, &pkcs11_keys, next) {
458 		if (sshbuf_equals(k11->keyblob, keyblob) == 0) {
459 			found = k11;
460 			break;
461 		}
462 	}
463 	sshbuf_free(keyblob);
464 	return found;
465 }
466 
467 #ifdef WITH_OPENSSL
468 /*
469  * See:
470  * https://datatracker.ietf.org/doc/html/rfc8017#section-9.2
471  */
472 
473 /*
474  * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
475  *	oiw(14) secsig(3) algorithms(2) 26 }
476  */
477 static const u_char id_sha1[] = {
478 	0x30, 0x21, /* type Sequence, length 0x21 (33) */
479 	0x30, 0x09, /* type Sequence, length 0x09 */
480 	0x06, 0x05, /* type OID, length 0x05 */
481 	0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
482 	0x05, 0x00, /* NULL */
483 	0x04, 0x14  /* Octet string, length 0x14 (20), followed by sha1 hash */
484 };
485 
486 /*
487  * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
488  *      organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
489  *      id-sha256(1) }
490  */
491 static const u_char id_sha256[] = {
492 	0x30, 0x31, /* type Sequence, length 0x31 (49) */
493 	0x30, 0x0d, /* type Sequence, length 0x0d (13) */
494 	0x06, 0x09, /* type OID, length 0x09 */
495 	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */
496 	0x05, 0x00, /* NULL */
497 	0x04, 0x20  /* Octet string, length 0x20 (32), followed by sha256 hash */
498 };
499 
500 /*
501  * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
502  *      organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
503  *      id-sha256(3) }
504  */
505 static const u_char id_sha512[] = {
506 	0x30, 0x51, /* type Sequence, length 0x51 (81) */
507 	0x30, 0x0d, /* type Sequence, length 0x0d (13) */
508 	0x06, 0x09, /* type OID, length 0x09 */
509 	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */
510 	0x05, 0x00, /* NULL */
511 	0x04, 0x40  /* Octet string, length 0x40 (64), followed by sha512 hash */
512 };
513 
514 static int
rsa_hash_alg_oid(int hash_alg,const u_char ** oidp,size_t * oidlenp)515 rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp)
516 {
517 	switch (hash_alg) {
518 	case SSH_DIGEST_SHA1:
519 		*oidp = id_sha1;
520 		*oidlenp = sizeof(id_sha1);
521 		break;
522 	case SSH_DIGEST_SHA256:
523 		*oidp = id_sha256;
524 		*oidlenp = sizeof(id_sha256);
525 		break;
526 	case SSH_DIGEST_SHA512:
527 		*oidp = id_sha512;
528 		*oidlenp = sizeof(id_sha512);
529 		break;
530 	default:
531 		return SSH_ERR_INVALID_ARGUMENT;
532 	}
533 	return 0;
534 }
535 
536 static int
pkcs11_sign_rsa(struct sshkey * key,u_char ** sigp,size_t * lenp,const u_char * data,size_t datalen,const char * alg,const char * sk_provider,const char * sk_pin,u_int compat)537 pkcs11_sign_rsa(struct sshkey *key,
538     u_char **sigp, size_t *lenp,
539     const u_char *data, size_t datalen,
540     const char *alg, const char *sk_provider,
541     const char *sk_pin, u_int compat)
542 {
543 	struct pkcs11_key	*k11;
544 	struct pkcs11_slotinfo	*si;
545 	CK_FUNCTION_LIST	*f;
546 	CK_ULONG		slen = 0;
547 	CK_RV			rv;
548 	int			hashalg, r, diff, siglen, ret = -1;
549 	u_char			*oid_dgst = NULL, *sig = NULL;
550 	size_t			dgst_len, oid_len, oid_dgst_len = 0;
551 	const u_char		*oid;
552 
553 	if (sigp != NULL)
554 		*sigp = NULL;
555 	if (lenp != NULL)
556 		*lenp = 0;
557 
558 	if ((k11 = pkcs11_lookup_key(key)) == NULL) {
559 		error_f("no key found");
560 		return SSH_ERR_KEY_NOT_FOUND;
561 	}
562 
563 	debug3_f("sign with alg \"%s\" using provider %s slotidx %lu",
564 	    alg == NULL ? "" : alg, k11->provider->name, (u_long)k11->slotidx);
565 
566 	if (pkcs11_get_key(k11, CKM_RSA_PKCS) == -1) {
567 		error("pkcs11_get_key failed");
568 		return SSH_ERR_AGENT_FAILURE;
569 	}
570 
571 	f = k11->provider->function_list;
572 	si = &k11->provider->slotinfo[k11->slotidx];
573 
574 	if ((siglen = EVP_PKEY_size(key->pkey)) <= 0)
575 		return SSH_ERR_INVALID_ARGUMENT;
576 	sig = xmalloc(siglen);
577 	slen = (CK_ULONG)siglen;
578 
579 	/* Determine hash algorithm and OID for signature */
580 	if (alg == NULL || *alg == '\0')
581 		hashalg = SSH_DIGEST_SHA1;
582 	else if ((hashalg = ssh_rsa_hash_id_from_keyname(alg)) == -1)
583 		fatal_f("couldn't determine RSA hash alg \"%s\"", alg);
584 	if ((r = rsa_hash_alg_oid(hashalg, &oid, &oid_len)) != 0)
585 		fatal_fr(r, "rsa_hash_alg_oid failed");
586 	if ((dgst_len = ssh_digest_bytes(hashalg)) == 0)
587 		fatal_f("bad hash alg %d", hashalg);
588 
589 	/* Prepare { oid || digest } */
590 	oid_dgst_len = oid_len + dgst_len;
591 	oid_dgst = xcalloc(1, oid_dgst_len);
592 	memcpy(oid_dgst, oid, oid_len);
593 	if ((r = ssh_digest_memory(hashalg, data, datalen,
594 	    oid_dgst + oid_len, dgst_len)) == -1)
595 		fatal_fr(r, "hash failed");
596 
597 	/* XXX handle CKR_BUFFER_TOO_SMALL */
598 	if ((rv = f->C_Sign(si->session, (CK_BYTE *)oid_dgst,
599 	    oid_dgst_len, sig, &slen)) != CKR_OK) {
600 		error("C_Sign failed: %lu", rv);
601 		goto done;
602 	}
603 
604 	if (slen < (CK_ULONG)siglen) {
605 		diff = siglen - slen;
606 		debug3_f("repack %lu < %d (diff %d)",
607 		    (u_long)slen, siglen, diff);
608 		memmove(sig + diff, sig, slen);
609 		explicit_bzero(sig, diff);
610 	} else if (slen > (size_t)siglen)
611 		fatal_f("bad C_Sign length");
612 
613 	if ((ret = ssh_rsa_encode_store_sig(hashalg, sig, siglen,
614 	    sigp, lenp)) != 0)
615 		fatal_fr(ret, "couldn't store signature");
616 
617 	/* success */
618 	ret = 0;
619  done:
620 	freezero(oid_dgst, oid_dgst_len);
621 	free(sig);
622 	return ret;
623 }
624 
625 #ifdef OPENSSL_HAS_ECC
626 static int
pkcs11_sign_ecdsa(struct sshkey * key,u_char ** sigp,size_t * lenp,const u_char * data,size_t datalen,const char * alg,const char * sk_provider,const char * sk_pin,u_int compat)627 pkcs11_sign_ecdsa(struct sshkey *key,
628     u_char **sigp, size_t *lenp,
629     const u_char *data, size_t datalen,
630     const char *alg, const char *sk_provider,
631     const char *sk_pin, u_int compat)
632 {
633 	struct pkcs11_key	*k11;
634 	struct pkcs11_slotinfo	*si;
635 	CK_FUNCTION_LIST	*f;
636 	CK_ULONG		slen = 0, bnlen;
637 	CK_RV			rv;
638 	BIGNUM			*sig_r = NULL, *sig_s = NULL;
639 	u_char			*sig = NULL, *dgst = NULL;
640 	size_t			dgst_len = 0;
641 	int			hashalg, ret = -1, r, siglen;
642 
643 	if (sigp != NULL)
644 		*sigp = NULL;
645 	if (lenp != NULL)
646 		*lenp = 0;
647 
648 	if ((k11 = pkcs11_lookup_key(key)) == NULL) {
649 		error_f("no key found");
650 		return SSH_ERR_KEY_NOT_FOUND;
651 	}
652 
653 	if (pkcs11_get_key(k11, CKM_ECDSA) == -1) {
654 		error("pkcs11_get_key failed");
655 		return SSH_ERR_AGENT_FAILURE;
656 	}
657 
658 	debug3_f("sign using provider %s slotidx %lu",
659 	    k11->provider->name, (u_long)k11->slotidx);
660 
661 	f = k11->provider->function_list;
662 	si = &k11->provider->slotinfo[k11->slotidx];
663 
664 	/* Prepare digest to be signed */
665 	if ((hashalg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1)
666 		fatal_f("couldn't determine ECDSA hash alg");
667 	if ((dgst_len = ssh_digest_bytes(hashalg)) == 0)
668 		fatal_f("bad hash alg %d", hashalg);
669 	dgst = xcalloc(1, dgst_len);
670 	if ((r = ssh_digest_memory(hashalg, data, datalen,
671 	    dgst, dgst_len)) == -1)
672 		fatal_fr(r, "hash failed");
673 
674 	if ((siglen = EVP_PKEY_size(key->pkey)) <= 0)
675 		return SSH_ERR_INVALID_ARGUMENT;
676 	sig = xmalloc(siglen);
677 	slen = (CK_ULONG)siglen;
678 
679 	/* XXX handle CKR_BUFFER_TOO_SMALL */
680 	rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, &slen);
681 	if (rv != CKR_OK) {
682 		error("C_Sign failed: %lu", rv);
683 		goto done;
684 	}
685 	if (slen < 64 || slen > 132 || slen % 2) {
686 		error_f("bad signature length: %lu", (u_long)slen);
687 		goto done;
688 	}
689 	bnlen = slen/2;
690 	if ((sig_r = BN_bin2bn(sig, bnlen, NULL)) == NULL ||
691 	    (sig_s = BN_bin2bn(sig+bnlen, bnlen, NULL)) == NULL) {
692 		ossl_error("BN_bin2bn failed");
693 		goto done;
694 	}
695 
696 	if ((ret = ssh_ecdsa_encode_store_sig(key, sig_r, sig_s,
697 	    sigp, lenp)) != 0)
698 		fatal_fr(ret, "couldn't store signature");
699 
700 	/* success */
701 	ret = 0;
702  done:
703 	freezero(dgst, dgst_len);
704 	BN_free(sig_r);
705 	BN_free(sig_s);
706 	free(sig);
707 	return ret;
708 }
709 #endif /* OPENSSL_HAS_ECC */
710 #endif /* WITH_OPENSSL */
711 
712 static int
pkcs11_sign_ed25519(struct sshkey * key,u_char ** sigp,size_t * lenp,const u_char * data,size_t datalen,const char * alg,const char * sk_provider,const char * sk_pin,u_int compat)713 pkcs11_sign_ed25519(struct sshkey *key,
714     u_char **sigp, size_t *lenp,
715     const u_char *data, size_t datalen,
716     const char *alg, const char *sk_provider,
717     const char *sk_pin, u_int compat)
718 {
719 	struct pkcs11_key	*k11;
720 	struct pkcs11_slotinfo	*si;
721 	CK_FUNCTION_LIST	*f;
722 	CK_ULONG		slen = 0;
723 	CK_RV			rv;
724 	u_char			*sig = NULL;
725 	CK_BYTE			*xdata = NULL;
726 	int			ret = -1;
727 
728 	if (sigp != NULL)
729 		*sigp = NULL;
730 	if (lenp != NULL)
731 		*lenp = 0;
732 
733 	if ((k11 = pkcs11_lookup_key(key)) == NULL) {
734 		error_f("no key found");
735 		return SSH_ERR_KEY_NOT_FOUND;
736 	}
737 
738 	if (pkcs11_get_key(k11, CKM_EDDSA) == -1) {
739 		error("pkcs11_get_key failed");
740 		return SSH_ERR_AGENT_FAILURE;
741 	}
742 
743 	debug3_f("sign using provider %s slotidx %lu",
744 	    k11->provider->name, (u_long)k11->slotidx);
745 
746 	f = k11->provider->function_list;
747 	si = &k11->provider->slotinfo[k11->slotidx];
748 
749 	xdata = xmalloc(datalen);
750 	memcpy(xdata, data, datalen);
751 	sig = xmalloc(crypto_sign_ed25519_BYTES);
752 	slen = crypto_sign_ed25519_BYTES;
753 
754 	rv = f->C_Sign(si->session, xdata, datalen, sig, &slen);
755 	if (rv != CKR_OK) {
756 		error("C_Sign failed: %lu", rv);
757 		goto done;
758 	}
759 	if (slen != crypto_sign_ed25519_BYTES) {
760 		error_f("bad signature length: %lu", (u_long)slen);
761 		goto done;
762 	}
763 	if ((ret = ssh_ed25519_encode_store_sig(sig, slen, sigp, lenp)) != 0)
764 		fatal_fr(ret, "couldn't store signature");
765 
766 	/* success */
767 	ret = 0;
768  done:
769 	if (xdata != NULL)
770 		freezero(xdata, datalen);
771 	free(sig);
772 	return ret;
773 }
774 
775 /* remove trailing spaces */
776 static char *
rmspace(u_char * buf,size_t len)777 rmspace(u_char *buf, size_t len)
778 {
779 	size_t i;
780 
781 	if (len == 0)
782 		return buf;
783 	for (i = len - 1; i > 0; i--)
784 		if (buf[i] == ' ')
785 			buf[i] = '\0';
786 		else
787 			break;
788 	return buf;
789 }
790 /* Used to printf fixed-width, space-padded, unterminated strings using %.*s */
791 #define RMSPACE(s) (int)sizeof(s), rmspace(s, sizeof(s))
792 
793 /*
794  * open a pkcs11 session and login if required.
795  * if pin == NULL we delay login until key use
796  */
797 static int
pkcs11_open_session(struct pkcs11_provider * p,CK_ULONG slotidx,char * pin,CK_ULONG user)798 pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin,
799     CK_ULONG user)
800 {
801 	struct pkcs11_slotinfo	*si;
802 	CK_FUNCTION_LIST	*f;
803 	CK_RV			rv;
804 	CK_SESSION_HANDLE	session;
805 	int			login_required, ret;
806 
807 	f = p->function_list;
808 	si = &p->slotinfo[slotidx];
809 
810 	login_required = si->token.flags & CKF_LOGIN_REQUIRED;
811 
812 	/* fail early before opening session */
813 	if (login_required && !pkcs11_interactive &&
814 	    (pin == NULL || strlen(pin) == 0)) {
815 		error("pin required");
816 		return (-SSH_PKCS11_ERR_PIN_REQUIRED);
817 	}
818 	if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION|
819 	    CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) {
820 		error("C_OpenSession failed: %lu", rv);
821 		return (-1);
822 	}
823 	if (login_required && pin != NULL && strlen(pin) != 0) {
824 		rv = f->C_Login(session, user, (u_char *)pin, strlen(pin));
825 		if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
826 			error("C_Login failed: %lu", rv);
827 			ret = (rv == CKR_PIN_LOCKED) ?
828 			    -SSH_PKCS11_ERR_PIN_LOCKED :
829 			    -SSH_PKCS11_ERR_LOGIN_FAIL;
830 			if ((rv = f->C_CloseSession(session)) != CKR_OK)
831 				error("C_CloseSession failed: %lu", rv);
832 			return (ret);
833 		}
834 		si->logged_in = 1;
835 	}
836 	si->session = session;
837 	return (0);
838 }
839 
840 static int
pkcs11_key_included(struct sshkey *** keysp,int * nkeys,struct sshkey * key)841 pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key)
842 {
843 	int i;
844 
845 	for (i = 0; i < *nkeys; i++)
846 		if (sshkey_equal(key, (*keysp)[i]))
847 			return (1);
848 	return (0);
849 }
850 
851 #ifdef WITH_OPENSSL
852 #ifdef OPENSSL_HAS_ECC
853 static struct sshkey *
pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider * p,CK_ULONG slotidx,CK_OBJECT_HANDLE * obj)854 pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
855     CK_OBJECT_HANDLE *obj)
856 {
857 	CK_ATTRIBUTE		 key_attr[3];
858 	CK_SESSION_HANDLE	 session;
859 	CK_FUNCTION_LIST	*f = NULL;
860 	CK_RV			 rv;
861 	ASN1_OCTET_STRING	*octet = NULL;
862 	EC_KEY			*ec = NULL;
863 	EC_GROUP		*group = NULL;
864 	struct sshkey		*key = NULL;
865 	const unsigned char	*attrp = NULL;
866 	int			 success = -1, r, i, nid;
867 
868 	memset(&key_attr, 0, sizeof(key_attr));
869 	key_attr[0].type = CKA_ID;
870 	key_attr[1].type = CKA_EC_POINT;
871 	key_attr[2].type = CKA_EC_PARAMS;
872 
873 	session = p->slotinfo[slotidx].session;
874 	f = p->function_list;
875 
876 	/* figure out size of the attributes */
877 	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
878 	if (rv != CKR_OK) {
879 		error("C_GetAttributeValue failed: %lu", rv);
880 		return (NULL);
881 	}
882 
883 	/*
884 	 * Allow CKA_ID (always first attribute) to be empty, but
885 	 * ensure that none of the others are zero length.
886 	 * XXX assumes CKA_ID is always first.
887 	 */
888 	if (key_attr[1].ulValueLen == 0 ||
889 	    key_attr[2].ulValueLen == 0) {
890 		error("invalid attribute length");
891 		return (NULL);
892 	}
893 
894 	/* allocate buffers for attributes */
895 	for (i = 0; i < 3; i++)
896 		if (key_attr[i].ulValueLen > 0)
897 			key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
898 
899 	/* retrieve ID, public point and curve parameters of EC key */
900 	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
901 	if (rv != CKR_OK) {
902 		error("C_GetAttributeValue failed: %lu", rv);
903 		goto fail;
904 	}
905 
906 	ec = EC_KEY_new();
907 	if (ec == NULL) {
908 		error("EC_KEY_new failed");
909 		goto fail;
910 	}
911 
912 	attrp = key_attr[2].pValue;
913 	group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen);
914 	if (group == NULL) {
915 		ossl_error("d2i_ECPKParameters failed");
916 		goto fail;
917 	}
918 
919 	if (EC_KEY_set_group(ec, group) == 0) {
920 		ossl_error("EC_KEY_set_group failed");
921 		goto fail;
922 	}
923 
924 	if (key_attr[1].ulValueLen <= 2) {
925 		error("CKA_EC_POINT too small");
926 		goto fail;
927 	}
928 
929 	attrp = key_attr[1].pValue;
930 	octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen);
931 	if (octet == NULL) {
932 		ossl_error("d2i_ASN1_OCTET_STRING failed");
933 		goto fail;
934 	}
935 	attrp = ASN1_STRING_get0_data(octet);
936 	if (o2i_ECPublicKey(&ec, &attrp, ASN1_STRING_length(octet)) == NULL) {
937 		ossl_error("o2i_ECPublicKey failed");
938 		goto fail;
939 	}
940 	if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(ec),
941 	    EC_KEY_get0_public_key(ec))) != 0) {
942 		error_fr(r, "invalid EC key");
943 		goto fail;
944 	}
945 
946 	nid = sshkey_ecdsa_key_to_nid(ec);
947 	if (nid < 0) {
948 		error("couldn't get curve nid");
949 		goto fail;
950 	}
951 
952 	key = sshkey_new(KEY_UNSPEC);
953 	if (key == NULL) {
954 		error("sshkey_new failed");
955 		goto fail;
956 	}
957 
958 	EVP_PKEY_free(key->pkey);
959 	if ((key->pkey = EVP_PKEY_new()) == NULL)
960 		fatal("EVP_PKEY_new failed");
961 	if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1)
962 		fatal("EVP_PKEY_set1_EC_KEY failed");
963 	key->ecdsa_nid = nid;
964 	key->type = KEY_ECDSA;
965 	key->flags |= SSHKEY_FLAG_EXT;
966 	if (pkcs11_record_key(p, slotidx, &key_attr[0], key))
967 		goto fail;
968 	/* success */
969 	success = 0;
970 fail:
971 	if (success != 0) {
972 		sshkey_free(key);
973 		key = NULL;
974 	}
975 	for (i = 0; i < 3; i++)
976 		free(key_attr[i].pValue);
977 	if (ec)
978 		EC_KEY_free(ec);
979 	if (group)
980 		EC_GROUP_free(group);
981 	if (octet)
982 		ASN1_OCTET_STRING_free(octet);
983 
984 	return (key);
985 }
986 #endif /* OPENSSL_HAS_ECC */
987 
988 static struct sshkey *
pkcs11_fetch_rsa_pubkey(struct pkcs11_provider * p,CK_ULONG slotidx,CK_OBJECT_HANDLE * obj)989 pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
990     CK_OBJECT_HANDLE *obj)
991 {
992 	CK_ATTRIBUTE		 key_attr[3];
993 	CK_SESSION_HANDLE	 session;
994 	CK_FUNCTION_LIST	*f = NULL;
995 	CK_RV			 rv;
996 	RSA			*rsa = NULL;
997 	BIGNUM			*rsa_n, *rsa_e;
998 	struct sshkey		*key = NULL;
999 	int			 i, success = -1;
1000 
1001 	memset(&key_attr, 0, sizeof(key_attr));
1002 	key_attr[0].type = CKA_ID;
1003 	key_attr[1].type = CKA_MODULUS;
1004 	key_attr[2].type = CKA_PUBLIC_EXPONENT;
1005 
1006 	session = p->slotinfo[slotidx].session;
1007 	f = p->function_list;
1008 
1009 	/* figure out size of the attributes */
1010 	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
1011 	if (rv != CKR_OK) {
1012 		error("C_GetAttributeValue failed: %lu", rv);
1013 		return (NULL);
1014 	}
1015 
1016 	/*
1017 	 * Allow CKA_ID (always first attribute) to be empty, but
1018 	 * ensure that none of the others are zero length.
1019 	 * XXX assumes CKA_ID is always first.
1020 	 */
1021 	if (key_attr[1].ulValueLen == 0 ||
1022 	    key_attr[2].ulValueLen == 0) {
1023 		error("invalid attribute length");
1024 		return (NULL);
1025 	}
1026 
1027 	/* allocate buffers for attributes */
1028 	for (i = 0; i < 3; i++)
1029 		if (key_attr[i].ulValueLen > 0)
1030 			key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
1031 
1032 	/* retrieve ID, modulus and public exponent of RSA key */
1033 	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
1034 	if (rv != CKR_OK) {
1035 		error("C_GetAttributeValue failed: %lu", rv);
1036 		goto fail;
1037 	}
1038 
1039 	rsa = RSA_new();
1040 	if (rsa == NULL) {
1041 		error("RSA_new failed");
1042 		goto fail;
1043 	}
1044 
1045 	rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL);
1046 	rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL);
1047 	if (rsa_n == NULL || rsa_e == NULL) {
1048 		error("BN_bin2bn failed");
1049 		goto fail;
1050 	}
1051 	if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL))
1052 		fatal_f("set key");
1053 	rsa_n = rsa_e = NULL; /* transferred */
1054 
1055 	key = sshkey_new(KEY_UNSPEC);
1056 	if (key == NULL) {
1057 		error("sshkey_new failed");
1058 		goto fail;
1059 	}
1060 
1061 	EVP_PKEY_free(key->pkey);
1062 	if ((key->pkey = EVP_PKEY_new()) == NULL)
1063 		fatal("EVP_PKEY_new failed");
1064 	if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1)
1065 		fatal("EVP_PKEY_set1_RSA failed");
1066 	key->type = KEY_RSA;
1067 	key->flags |= SSHKEY_FLAG_EXT;
1068 	if (EVP_PKEY_bits(key->pkey) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
1069 		error_f("RSA key too small %d < minimum %d",
1070 		    EVP_PKEY_bits(key->pkey), SSH_RSA_MINIMUM_MODULUS_SIZE);
1071 		goto fail;
1072 	}
1073 	if (pkcs11_record_key(p, slotidx, &key_attr[0], key))
1074 		goto fail;
1075 	/* success */
1076 	success = 0;
1077 fail:
1078 	for (i = 0; i < 3; i++)
1079 		free(key_attr[i].pValue);
1080 	RSA_free(rsa);
1081 	if (success != 0) {
1082 		sshkey_free(key);
1083 		key = NULL;
1084 	}
1085 	return key;
1086 }
1087 #endif /* WITH_OPENSSL */
1088 
1089 static struct sshkey *
pkcs11_fetch_ed25519_pubkey(struct pkcs11_provider * p,CK_ULONG slotidx,CK_OBJECT_HANDLE * obj)1090 pkcs11_fetch_ed25519_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
1091     CK_OBJECT_HANDLE *obj)
1092 {
1093 	CK_ATTRIBUTE		 key_attr[3];
1094 	CK_SESSION_HANDLE	 session;
1095 	CK_FUNCTION_LIST	*f = NULL;
1096 	CK_RV			 rv;
1097 	struct sshkey		*key = NULL;
1098 	const unsigned char	*d = NULL;
1099 	size_t			len;
1100 	char			*hex = NULL;
1101 	int			 success = -1, i;
1102 	/* https://docs.oasis-open.org/pkcs11/pkcs11-curr/v3.0/os/pkcs11-curr-v3.0-os.html#_Toc30061180 */
1103 	const u_char		 id1[14] = {
1104 		0x13, 0x0c, 0x65, 0x64, 0x77, 0x61, 0x72, 0x64,
1105 		0x73, 0x32, 0x35, 0x35, 0x31, 0x39,
1106 	}; /* PrintableString { "edwards25519" } */
1107 	const u_char		 id2[5] = {
1108 		0x06, 0x03, 0x2b, 0x65, 0x70,
1109 	}; /* OBJECT_IDENTIFIER { 1.3.101.112 } */
1110 
1111 	memset(&key_attr, 0, sizeof(key_attr));
1112 	key_attr[0].type = CKA_ID;
1113 	key_attr[1].type = CKA_EC_POINT; /* XXX or CKA_VALUE ? */
1114 	key_attr[2].type = CKA_EC_PARAMS;
1115 
1116 	session = p->slotinfo[slotidx].session;
1117 	f = p->function_list;
1118 
1119 	/* figure out size of the attributes */
1120 	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
1121 	if (rv != CKR_OK) {
1122 		error("C_GetAttributeValue failed: %lu", rv);
1123 		return (NULL);
1124 	}
1125 
1126 	/*
1127 	 * Allow CKA_ID (always first attribute) to be empty, but
1128 	 * ensure that none of the others are zero length.
1129 	 * XXX assumes CKA_ID is always first.
1130 	 */
1131 	if (key_attr[1].ulValueLen == 0 ||
1132 	    key_attr[2].ulValueLen == 0) {
1133 		error("invalid attribute length");
1134 		return (NULL);
1135 	}
1136 
1137 	/* allocate buffers for attributes */
1138 	for (i = 0; i < 3; i++) {
1139 		if (key_attr[i].ulValueLen > 0)
1140 			key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
1141 	}
1142 
1143 	/* retrieve ID, public point and curve parameters of EC key */
1144 	rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
1145 	if (rv != CKR_OK) {
1146 		error("C_GetAttributeValue failed: %lu", rv);
1147 		goto fail;
1148 	}
1149 
1150 	/* Expect one of the supported identifiers in CKA_EC_PARAMS */
1151 	d = (u_char *)key_attr[2].pValue;
1152 	len = key_attr[2].ulValueLen;
1153 	if ((len != sizeof(id1) || memcmp(d, id1, sizeof(id1)) != 0) &&
1154 	    (len != sizeof(id2) || memcmp(d, id2, sizeof(id2)) != 0)) {
1155 		hex = tohex(d, len);
1156 		logit_f("unsupported CKA_EC_PARAMS: %s (len %zu)", hex, len);
1157 		goto fail;
1158 	}
1159 
1160 	/*
1161 	 * Expect either a raw 32 byte pubkey or an OCTET STRING with
1162 	 * a 32 byte pubkey in CKA_VALUE
1163 	 */
1164 	d = (u_char *)key_attr[1].pValue;
1165 	len = key_attr[1].ulValueLen;
1166 	if (len == ED25519_PK_SZ + 2 && d[0] == 0x04 && d[1] == ED25519_PK_SZ) {
1167 		d += 2;
1168 		len -= 2;
1169 	}
1170 	if (len != ED25519_PK_SZ) {
1171 		hex = tohex(key_attr[1].pValue, key_attr[1].ulValueLen);
1172 		logit_f("CKA_EC_POINT invalid octet str: %s (len %lu)",
1173 		    hex, (u_long)key_attr[1].ulValueLen);
1174 		goto fail;
1175 	}
1176 
1177 	if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
1178 		fatal_f("sshkey_new failed");
1179 	key->ed25519_pk = xmalloc(ED25519_PK_SZ);
1180 	memcpy(key->ed25519_pk, d, ED25519_PK_SZ);
1181 	key->type = KEY_ED25519;
1182 	key->flags |= SSHKEY_FLAG_EXT;
1183 	if (pkcs11_record_key(p, slotidx, &key_attr[0], key))
1184 		goto fail;
1185 	/* success */
1186 	success = 0;
1187  fail:
1188 	if (success != 0) {
1189 		sshkey_free(key);
1190 		key = NULL;
1191 	}
1192 	free(hex);
1193 	for (i = 0; i < 3; i++)
1194 		free(key_attr[i].pValue);
1195 	return key;
1196 }
1197 
1198 #ifdef WITH_OPENSSL
1199 static int
pkcs11_fetch_x509_pubkey(struct pkcs11_provider * p,CK_ULONG slotidx,CK_OBJECT_HANDLE * obj,struct sshkey ** keyp,char ** labelp)1200 pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
1201     CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp)
1202 {
1203 	CK_ATTRIBUTE		 cert_attr[3];
1204 	CK_SESSION_HANDLE	 session;
1205 	CK_FUNCTION_LIST	*f = NULL;
1206 	CK_RV			 rv;
1207 	X509			*x509 = NULL;
1208 	X509_NAME		*x509_name = NULL;
1209 	EVP_PKEY		*evp;
1210 	RSA			*rsa = NULL;
1211 
1212 	struct sshkey		*key = NULL;
1213 	int			 i, success = -1;
1214 	const u_char		*cp;
1215 	char			*subject = NULL;
1216 #ifdef OPENSSL_HAS_ED25519
1217 	size_t			len;
1218 #endif /* OPENSSL_HAS_ED25519 */
1219 #ifdef OPENSSL_HAS_ECC
1220 	EC_KEY			*ec = NULL;
1221 	int			r, nid;
1222 #endif
1223 
1224 	*keyp = NULL;
1225 	*labelp = NULL;
1226 
1227 	memset(&cert_attr, 0, sizeof(cert_attr));
1228 	cert_attr[0].type = CKA_ID;
1229 	cert_attr[1].type = CKA_SUBJECT;
1230 	cert_attr[2].type = CKA_VALUE;
1231 
1232 	session = p->slotinfo[slotidx].session;
1233 	f = p->function_list;
1234 
1235 	/* figure out size of the attributes */
1236 	rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
1237 	if (rv != CKR_OK) {
1238 		error("C_GetAttributeValue failed: %lu", rv);
1239 		return -1;
1240 	}
1241 
1242 	/*
1243 	 * Allow CKA_ID (always first attribute) to be empty, but
1244 	 * ensure that none of the others are zero length.
1245 	 * XXX assumes CKA_ID is always first.
1246 	 */
1247 	if (cert_attr[1].ulValueLen == 0 ||
1248 	    cert_attr[2].ulValueLen == 0) {
1249 		error("invalid attribute length");
1250 		return -1;
1251 	}
1252 
1253 	/* allocate buffers for attributes */
1254 	for (i = 0; i < 3; i++)
1255 		if (cert_attr[i].ulValueLen > 0)
1256 			cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen);
1257 
1258 	/* retrieve ID, subject and value of certificate */
1259 	rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
1260 	if (rv != CKR_OK) {
1261 		error("C_GetAttributeValue failed: %lu", rv);
1262 		goto out;
1263 	}
1264 
1265 	/* Decode DER-encoded cert subject */
1266 	cp = cert_attr[1].pValue;
1267 	if ((x509_name = d2i_X509_NAME(NULL, &cp,
1268 	    cert_attr[1].ulValueLen)) == NULL ||
1269 	    (subject = X509_NAME_oneline(x509_name, NULL, 0)) == NULL)
1270 		subject = xstrdup("invalid subject");
1271 	X509_NAME_free(x509_name);
1272 
1273 	cp = cert_attr[2].pValue;
1274 	if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) {
1275 		error("d2i_x509 failed");
1276 		goto out;
1277 	}
1278 
1279 	if ((evp = X509_get_pubkey(x509)) == NULL) {
1280 		error("X509_get_pubkey failed");
1281 		goto out;
1282 	}
1283 
1284 	if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) {
1285 		if (EVP_PKEY_get0_RSA(evp) == NULL) {
1286 			error("invalid x509; no rsa key");
1287 			goto out;
1288 		}
1289 		if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) {
1290 			error("RSAPublicKey_dup failed");
1291 			goto out;
1292 		}
1293 
1294 		key = sshkey_new(KEY_UNSPEC);
1295 		if (key == NULL) {
1296 			error("sshkey_new failed");
1297 			goto out;
1298 		}
1299 
1300 		EVP_PKEY_free(key->pkey);
1301 		if ((key->pkey = EVP_PKEY_new()) == NULL)
1302 			fatal("EVP_PKEY_new failed");
1303 		if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1)
1304 			fatal("EVP_PKEY_set1_RSA failed");
1305 		key->type = KEY_RSA;
1306 		key->flags |= SSHKEY_FLAG_EXT;
1307 		if (EVP_PKEY_bits(key->pkey) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
1308 			error_f("RSA key too small %d < minimum %d",
1309 			    EVP_PKEY_bits(key->pkey),
1310 			    SSH_RSA_MINIMUM_MODULUS_SIZE);
1311 			goto out;
1312 		}
1313 		if (pkcs11_record_key(p, slotidx, &cert_attr[0], key))
1314 			goto out;
1315 		/* success */
1316 		success = 0;
1317 #ifdef OPENSSL_HAS_ECC
1318 	} else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
1319 		if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {
1320 			error("invalid x509; no ec key");
1321 			goto out;
1322 		}
1323 		if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) {
1324 			error("EC_KEY_dup failed");
1325 			goto out;
1326 		}
1327 		if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(ec),
1328 		    EC_KEY_get0_public_key(ec))) != 0) {
1329 			error_fr(r, "invalid EC key");
1330 			goto out;
1331 		}
1332 		nid = sshkey_ecdsa_key_to_nid(ec);
1333 		if (nid < 0) {
1334 			error("couldn't get curve nid");
1335 			goto out;
1336 		}
1337 
1338 		key = sshkey_new(KEY_UNSPEC);
1339 		if (key == NULL) {
1340 			error("sshkey_new failed");
1341 			goto out;
1342 		}
1343 
1344 		EVP_PKEY_free(key->pkey);
1345 		if ((key->pkey = EVP_PKEY_new()) == NULL)
1346 			fatal("EVP_PKEY_new failed");
1347 		if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1)
1348 			fatal("EVP_PKEY_set1_EC_KEY failed");
1349 		key->ecdsa_nid = nid;
1350 		key->type = KEY_ECDSA;
1351 		key->flags |= SSHKEY_FLAG_EXT;
1352 		if (pkcs11_record_key(p, slotidx, &cert_attr[0], key))
1353 			goto out;
1354 		/* success */
1355 		success = 0;
1356 #endif /* OPENSSL_HAS_ECC */
1357 #ifdef OPENSSL_HAS_ED25519
1358 	} else if (EVP_PKEY_base_id(evp) == EVP_PKEY_ED25519) {
1359 		if ((key = sshkey_new(KEY_UNSPEC)) == NULL ||
1360 		    (key->ed25519_pk = calloc(1, ED25519_PK_SZ)) == NULL)
1361 			fatal_f("allocation failed");
1362 		len = ED25519_PK_SZ;
1363 		if (!EVP_PKEY_get_raw_public_key(evp, key->ed25519_pk, &len)) {
1364 			ossl_error("EVP_PKEY_get_raw_public_key failed");
1365 			goto out;
1366 		}
1367 		if (len != ED25519_PK_SZ) {
1368 			error_f("incorrect returned public key "
1369 			    "length for ed25519");
1370 			goto out;
1371 		}
1372 		key->type = KEY_ED25519;
1373 		key->flags |= SSHKEY_FLAG_EXT;
1374 		if (pkcs11_record_key(p, slotidx, &cert_attr[0], key))
1375 			goto out;
1376 		/* success */
1377 		success = 0;
1378 #endif /* OPENSSL_HAS_ED25519 */
1379 	} else {
1380 		error("unknown certificate key type");
1381 		goto out;
1382 	}
1383  out:
1384 	for (i = 0; i < 3; i++)
1385 		free(cert_attr[i].pValue);
1386 	X509_free(x509);
1387 	RSA_free(rsa);
1388 #ifdef OPENSSL_HAS_ECC
1389 	EC_KEY_free(ec);
1390 #endif /* OPENSSL_HAS_ECC */
1391 	if (success != 0 || key == NULL) {
1392 		sshkey_free(key);
1393 		free(subject);
1394 		return -1;
1395 	}
1396 	/* success */
1397 	*keyp = key;
1398 	*labelp = subject;
1399 	return 0;
1400 }
1401 #endif /* WITH_OPENSSL */
1402 
1403 static void
note_key(struct pkcs11_provider * p,CK_ULONG slotidx,const char * context,struct sshkey * key)1404 note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context,
1405     struct sshkey *key)
1406 {
1407 	char *fp;
1408 
1409 	if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
1410 	    SSH_FP_DEFAULT)) == NULL) {
1411 		error_f("sshkey_fingerprint failed");
1412 		return;
1413 	}
1414 	debug2("%s: provider %s slot %lu: %s %s", context, p->name,
1415 	    (u_long)slotidx, sshkey_type(key), fp);
1416 	free(fp);
1417 }
1418 
1419 #ifdef WITH_OPENSSL /* libcrypto needed for certificate parsing */
1420 /*
1421  * lookup certificates for token in slot identified by slotidx,
1422  * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
1423  * keysp points to an (possibly empty) array with *nkeys keys.
1424  */
1425 static int
pkcs11_fetch_certs(struct pkcs11_provider * p,CK_ULONG slotidx,struct sshkey *** keysp,char *** labelsp,int * nkeys)1426 pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
1427     struct sshkey ***keysp, char ***labelsp, int *nkeys)
1428 {
1429 	struct sshkey		*key = NULL;
1430 	CK_OBJECT_CLASS		 key_class;
1431 	CK_ATTRIBUTE		 key_attr[1];
1432 	CK_SESSION_HANDLE	 session;
1433 	CK_FUNCTION_LIST	*f = NULL;
1434 	CK_RV			 rv;
1435 	CK_OBJECT_HANDLE	 obj;
1436 	CK_ULONG		 n = 0;
1437 	int			 ret = -1;
1438 	char			*label;
1439 
1440 	memset(&key_attr, 0, sizeof(key_attr));
1441 	memset(&obj, 0, sizeof(obj));
1442 
1443 	key_class = CKO_CERTIFICATE;
1444 	key_attr[0].type = CKA_CLASS;
1445 	key_attr[0].pValue = &key_class;
1446 	key_attr[0].ulValueLen = sizeof(key_class);
1447 
1448 	session = p->slotinfo[slotidx].session;
1449 	f = p->function_list;
1450 
1451 	rv = f->C_FindObjectsInit(session, key_attr, 1);
1452 	if (rv != CKR_OK) {
1453 		error("C_FindObjectsInit failed: %lu", rv);
1454 		goto fail;
1455 	}
1456 
1457 	while (1) {
1458 		CK_CERTIFICATE_TYPE	ck_cert_type;
1459 
1460 		rv = f->C_FindObjects(session, &obj, 1, &n);
1461 		if (rv != CKR_OK) {
1462 			error("C_FindObjects failed: %lu", rv);
1463 			goto fail;
1464 		}
1465 		if (n == 0)
1466 			break;
1467 
1468 		memset(&ck_cert_type, 0, sizeof(ck_cert_type));
1469 		memset(&key_attr, 0, sizeof(key_attr));
1470 		key_attr[0].type = CKA_CERTIFICATE_TYPE;
1471 		key_attr[0].pValue = &ck_cert_type;
1472 		key_attr[0].ulValueLen = sizeof(ck_cert_type);
1473 
1474 		rv = f->C_GetAttributeValue(session, obj, key_attr, 1);
1475 		if (rv != CKR_OK) {
1476 			error("C_GetAttributeValue failed: %lu", rv);
1477 			goto fail;
1478 		}
1479 
1480 		key = NULL;
1481 		label = NULL;
1482 		switch (ck_cert_type) {
1483 		case CKC_X_509:
1484 			if (pkcs11_fetch_x509_pubkey(p, slotidx, &obj,
1485 			    &key, &label) != 0) {
1486 				debug_f("failed to fetch key");
1487 				continue;
1488 			}
1489 			break;
1490 		default:
1491 			error("skipping unsupported certificate type %lu",
1492 			    ck_cert_type);
1493 			continue;
1494 		}
1495 		note_key(p, slotidx, __func__, key);
1496 		if (pkcs11_key_included(keysp, nkeys, key)) {
1497 			debug2_f("key already included");
1498 			sshkey_free(key);
1499 		} else {
1500 			/* expand key array and add key */
1501 			*keysp = xrecallocarray(*keysp, *nkeys,
1502 			    *nkeys + 1, sizeof(struct sshkey *));
1503 			(*keysp)[*nkeys] = key;
1504 			if (labelsp != NULL) {
1505 				*labelsp = xrecallocarray(*labelsp, *nkeys,
1506 				    *nkeys + 1, sizeof(char *));
1507 				(*labelsp)[*nkeys] = xstrdup((char *)label);
1508 			}
1509 			*nkeys = *nkeys + 1;
1510 			debug("have %d keys", *nkeys);
1511 		}
1512 	}
1513 
1514 	ret = 0;
1515 fail:
1516 	rv = f->C_FindObjectsFinal(session);
1517 	if (rv != CKR_OK) {
1518 		error("C_FindObjectsFinal failed: %lu", rv);
1519 		ret = -1;
1520 	}
1521 
1522 	return (ret);
1523 }
1524 #endif /* WITH_OPENSSL */
1525 
1526 /*
1527  * lookup public keys for token in slot identified by slotidx,
1528  * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
1529  * keysp points to an (possibly empty) array with *nkeys keys.
1530  */
1531 static int
pkcs11_fetch_keys(struct pkcs11_provider * p,CK_ULONG slotidx,struct sshkey *** keysp,char *** labelsp,int * nkeys)1532 pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1533     struct sshkey ***keysp, char ***labelsp, int *nkeys)
1534 {
1535 	struct sshkey		*key = NULL;
1536 	CK_OBJECT_CLASS		 key_class;
1537 	CK_ATTRIBUTE		 key_attr[2];
1538 	CK_SESSION_HANDLE	 session;
1539 	CK_FUNCTION_LIST	*f = NULL;
1540 	CK_RV			 rv;
1541 	CK_OBJECT_HANDLE	 obj;
1542 	CK_ULONG		 n = 0;
1543 	int			 ret = -1;
1544 
1545 	memset(&key_attr, 0, sizeof(key_attr));
1546 	memset(&obj, 0, sizeof(obj));
1547 
1548 	key_class = CKO_PUBLIC_KEY;
1549 	key_attr[0].type = CKA_CLASS;
1550 	key_attr[0].pValue = &key_class;
1551 	key_attr[0].ulValueLen = sizeof(key_class);
1552 
1553 	session = p->slotinfo[slotidx].session;
1554 	f = p->function_list;
1555 
1556 	rv = f->C_FindObjectsInit(session, key_attr, 1);
1557 	if (rv != CKR_OK) {
1558 		error("C_FindObjectsInit failed: %lu", rv);
1559 		goto fail;
1560 	}
1561 
1562 	while (1) {
1563 		CK_KEY_TYPE	ck_key_type;
1564 		CK_UTF8CHAR	label[256];
1565 
1566 		rv = f->C_FindObjects(session, &obj, 1, &n);
1567 		if (rv != CKR_OK) {
1568 			error("C_FindObjects failed: %lu", rv);
1569 			goto fail;
1570 		}
1571 		if (n == 0)
1572 			break;
1573 
1574 		memset(&ck_key_type, 0, sizeof(ck_key_type));
1575 		memset(&key_attr, 0, sizeof(key_attr));
1576 		key_attr[0].type = CKA_KEY_TYPE;
1577 		key_attr[0].pValue = &ck_key_type;
1578 		key_attr[0].ulValueLen = sizeof(ck_key_type);
1579 		key_attr[1].type = CKA_LABEL;
1580 		key_attr[1].pValue = &label;
1581 		key_attr[1].ulValueLen = sizeof(label) - 1;
1582 
1583 		rv = f->C_GetAttributeValue(session, obj, key_attr, 2);
1584 		if (rv != CKR_OK) {
1585 			error("C_GetAttributeValue failed: %lu", rv);
1586 			goto fail;
1587 		}
1588 
1589 		label[key_attr[1].ulValueLen] = '\0';
1590 
1591 		switch (ck_key_type) {
1592 #ifdef WITH_OPENSSL
1593 		case CKK_RSA:
1594 			key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
1595 			break;
1596 #ifdef OPENSSL_HAS_ECC
1597 		case CKK_ECDSA:
1598 			key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
1599 			break;
1600 #endif /* OPENSSL_HAS_ECC */
1601 #endif /* WITH_OPENSSL */
1602 		case CKK_EC_EDWARDS:
1603 			key = pkcs11_fetch_ed25519_pubkey(p, slotidx, &obj);
1604 			break;
1605 		default:
1606 			/* XXX print key type? */
1607 			key = NULL;
1608 			error("skipping unsupported key type 0x%lx",
1609 			    (u_long)ck_key_type);
1610 		}
1611 
1612 		if (key == NULL) {
1613 			debug_f("failed to fetch key");
1614 			continue;
1615 		}
1616 		note_key(p, slotidx, __func__, key);
1617 		if (pkcs11_key_included(keysp, nkeys, key)) {
1618 			debug2_f("key already included");
1619 			sshkey_free(key);
1620 		} else {
1621 			/* expand key array and add key */
1622 			*keysp = xrecallocarray(*keysp, *nkeys,
1623 			    *nkeys + 1, sizeof(struct sshkey *));
1624 			(*keysp)[*nkeys] = key;
1625 			if (labelsp != NULL) {
1626 				*labelsp = xrecallocarray(*labelsp, *nkeys,
1627 				    *nkeys + 1, sizeof(char *));
1628 				(*labelsp)[*nkeys] = xstrdup((char *)label);
1629 			}
1630 			*nkeys = *nkeys + 1;
1631 			debug("have %d keys", *nkeys);
1632 		}
1633 	}
1634 
1635 	ret = 0;
1636 fail:
1637 	rv = f->C_FindObjectsFinal(session);
1638 	if (rv != CKR_OK) {
1639 		error("C_FindObjectsFinal failed: %lu", rv);
1640 		ret = -1;
1641 	}
1642 
1643 	return (ret);
1644 }
1645 
1646 #ifdef WITH_PKCS11_KEYGEN
1647 #define FILL_ATTR(attr, idx, typ, val, len) \
1648 	{ (attr[idx]).type=(typ); (attr[idx]).pValue=(val); (attr[idx]).ulValueLen=len; idx++; }
1649 
1650 static struct sshkey *
pkcs11_rsa_generate_private_key(struct pkcs11_provider * p,CK_ULONG slotidx,char * label,CK_ULONG bits,CK_BYTE keyid,uint32_t * err)1651 pkcs11_rsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
1652     char *label, CK_ULONG bits, CK_BYTE keyid, uint32_t *err)
1653 {
1654 	struct pkcs11_slotinfo	*si;
1655 	char			*plabel = label ? label : "";
1656 	int			 npub = 0, npriv = 0;
1657 	CK_RV			 rv;
1658 	CK_FUNCTION_LIST	*f;
1659 	CK_SESSION_HANDLE	 session;
1660 	CK_BBOOL		 true_val = CK_TRUE, false_val = CK_FALSE;
1661 	CK_OBJECT_HANDLE	 pubKey, privKey;
1662 	CK_ATTRIBUTE		 tpub[16], tpriv[16];
1663 	CK_MECHANISM		 mech = {
1664 	    CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0
1665 	};
1666 	CK_BYTE			 pubExponent[] = {
1667 	    0x01, 0x00, 0x01 /* RSA_F4 in bytes */
1668 	};
1669 	pubkey_filter[0].pValue = &pubkey_class;
1670 	cert_filter[0].pValue = &cert_class;
1671 
1672 	*err = 0;
1673 
1674 	FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val));
1675 	FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel));
1676 	FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val));
1677 	FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val));
1678 	FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val,
1679 	    sizeof(false_val));
1680 	FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val));
1681 	FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val));
1682 	FILL_ATTR(tpub, npub, CKA_MODULUS_BITS, &bits, sizeof(bits));
1683 	FILL_ATTR(tpub, npub, CKA_PUBLIC_EXPONENT, pubExponent,
1684 	    sizeof(pubExponent));
1685 	FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid));
1686 
1687 	FILL_ATTR(tpriv, npriv, CKA_TOKEN,  &true_val, sizeof(true_val));
1688 	FILL_ATTR(tpriv, npriv, CKA_LABEL,  plabel, strlen(plabel));
1689 	FILL_ATTR(tpriv, npriv, CKA_PRIVATE,  &true_val, sizeof(true_val));
1690 	FILL_ATTR(tpriv, npriv, CKA_SENSITIVE,  &true_val, sizeof(true_val));
1691 	FILL_ATTR(tpriv, npriv, CKA_DECRYPT,  &false_val, sizeof(false_val));
1692 	FILL_ATTR(tpriv, npriv, CKA_SIGN,  &true_val, sizeof(true_val));
1693 	FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER,  &false_val,
1694 	    sizeof(false_val));
1695 	FILL_ATTR(tpriv, npriv, CKA_UNWRAP,  &false_val, sizeof(false_val));
1696 	FILL_ATTR(tpriv, npriv, CKA_DERIVE,  &false_val, sizeof(false_val));
1697 	FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid));
1698 
1699 	f = p->function_list;
1700 	si = &p->slotinfo[slotidx];
1701 	session = si->session;
1702 
1703 	if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
1704 	    &pubKey, &privKey)) != CKR_OK) {
1705 		error_f("key generation failed: error 0x%lx", rv);
1706 		*err = rv;
1707 		return NULL;
1708 	}
1709 
1710 	return pkcs11_fetch_rsa_pubkey(p, slotidx, &pubKey);
1711 }
1712 
1713 static int
h2i(char c)1714 h2i(char c)
1715 {
1716 	if (c >= '0' && c <= '9')
1717 		return c - '0';
1718 	else if (c >= 'a' && c <= 'f')
1719 		return c - 'a' + 10;
1720 	else if (c >= 'A' && c <= 'F')
1721 		return c - 'A' + 10;
1722 	else
1723 		return -1;
1724 }
1725 
1726 static int
pkcs11_decode_hex(const char * hex,unsigned char ** dest,size_t * rlen)1727 pkcs11_decode_hex(const char *hex, unsigned char **dest, size_t *rlen)
1728 {
1729 	size_t	i, len;
1730 
1731 	if (dest)
1732 		*dest = NULL;
1733 	if (rlen)
1734 		*rlen = 0;
1735 
1736 	if ((len = strlen(hex)) % 2)
1737 		return -1;
1738 	len /= 2;
1739 
1740 	*dest = xmalloc(len);
1741 
1742 	for (i = 0; i < len; i++) {
1743 		int hi, lo;
1744 
1745 		hi = h2i(hex[2 * i]);
1746 		lo = h2i(hex[(2 * i) + 1]);
1747 		if (hi == -1 || lo == -1)
1748 			return -1;
1749 		(*dest)[i] = (hi << 4) | lo;
1750 	}
1751 
1752 	if (rlen)
1753 		*rlen = len;
1754 
1755 	return 0;
1756 }
1757 
1758 static struct ec_curve_info {
1759 	const char	*name;
1760 	const char	*oid;
1761 	const char	*oid_encoded;
1762 	size_t		 size;
1763 } ec_curve_infos[] = {
1764 	{"prime256v1",	"1.2.840.10045.3.1.7",	"06082A8648CE3D030107", 256},
1765 	{"secp384r1",	"1.3.132.0.34",		"06052B81040022",	384},
1766 	{"secp521r1",	"1.3.132.0.35",		"06052B81040023",	521},
1767 	{NULL,		NULL,			NULL,			0},
1768 };
1769 
1770 static struct sshkey *
pkcs11_ecdsa_generate_private_key(struct pkcs11_provider * p,CK_ULONG slotidx,char * label,CK_ULONG bits,CK_BYTE keyid,uint32_t * err)1771 pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
1772     char *label, CK_ULONG bits, CK_BYTE keyid, uint32_t *err)
1773 {
1774 	struct pkcs11_slotinfo	*si;
1775 	char			*plabel = label ? label : "";
1776 	int			 i;
1777 	size_t			 ecparams_size;
1778 	unsigned char		*ecparams = NULL;
1779 	int			 npub = 0, npriv = 0;
1780 	CK_RV			 rv;
1781 	CK_FUNCTION_LIST	*f;
1782 	CK_SESSION_HANDLE	 session;
1783 	CK_BBOOL		 true_val = CK_TRUE, false_val = CK_FALSE;
1784 	CK_OBJECT_HANDLE	 pubKey, privKey;
1785 	CK_MECHANISM		 mech = {
1786 	    CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0
1787 	};
1788 	CK_ATTRIBUTE		 tpub[16], tpriv[16];
1789 
1790 	*err = 0;
1791 
1792 	for (i = 0; ec_curve_infos[i].name; i++) {
1793 		if (ec_curve_infos[i].size == bits)
1794 			break;
1795 	}
1796 	if (!ec_curve_infos[i].name) {
1797 		error_f("invalid key size %lu", bits);
1798 		return NULL;
1799 	}
1800 	if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams,
1801 	    &ecparams_size) == -1) {
1802 		error_f("invalid oid");
1803 		return NULL;
1804 	}
1805 
1806 	FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val));
1807 	FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel));
1808 	FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val));
1809 	FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val));
1810 	FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val,
1811 	    sizeof(false_val));
1812 	FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val));
1813 	FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val));
1814 	FILL_ATTR(tpub, npub, CKA_EC_PARAMS, ecparams, ecparams_size);
1815 	FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid));
1816 
1817 	FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val));
1818 	FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel));
1819 	FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val));
1820 	FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val));
1821 	FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val));
1822 	FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val));
1823 	FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val,
1824 	    sizeof(false_val));
1825 	FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val));
1826 	FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val));
1827 	FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid));
1828 
1829 	f = p->function_list;
1830 	si = &p->slotinfo[slotidx];
1831 	session = si->session;
1832 
1833 	if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
1834 	    &pubKey, &privKey)) != CKR_OK) {
1835 		error_f("key generation failed: error 0x%lx", rv);
1836 		*err = rv;
1837 		return NULL;
1838 	}
1839 
1840 	return pkcs11_fetch_ecdsa_pubkey(p, slotidx, &pubKey);
1841 }
1842 #endif /* WITH_PKCS11_KEYGEN */
1843 
1844 /*
1845  * register a new provider, fails if provider already exists. if
1846  * keyp is provided, fetch keys.
1847  */
1848 static int
pkcs11_register_provider(char * provider_id,char * pin,struct sshkey *** keyp,char *** labelsp,struct pkcs11_provider ** providerp,CK_ULONG user)1849 pkcs11_register_provider(char *provider_id, char *pin,
1850     struct sshkey ***keyp, char ***labelsp,
1851     struct pkcs11_provider **providerp, CK_ULONG user)
1852 {
1853 	int nkeys, need_finalize = 0;
1854 	int ret = -1;
1855 	struct pkcs11_provider *p = NULL;
1856 	void *handle = NULL;
1857 	CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **);
1858 	CK_RV rv;
1859 	CK_FUNCTION_LIST *f = NULL;
1860 	CK_TOKEN_INFO *token;
1861 	CK_ULONG i;
1862 
1863 	if (providerp == NULL)
1864 		goto fail;
1865 	*providerp = NULL;
1866 
1867 	if (keyp != NULL)
1868 		*keyp = NULL;
1869 	if (labelsp != NULL)
1870 		*labelsp = NULL;
1871 
1872 	if (pkcs11_provider_lookup(provider_id) != NULL) {
1873 		debug_f("provider already registered: %s", provider_id);
1874 		goto fail;
1875 	}
1876 	if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) {
1877 		error("provider %s is not a PKCS11 library", provider_id);
1878 		goto fail;
1879 	}
1880 	/* open shared pkcs11-library */
1881 	if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {
1882 		error("dlopen %s failed: %s", provider_id, dlerror());
1883 		goto fail;
1884 	}
1885 	if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL)
1886 		fatal("dlsym(C_GetFunctionList) failed: %s", dlerror());
1887 	p = xcalloc(1, sizeof(*p));
1888 	p->name = xstrdup(provider_id);
1889 	p->handle = handle;
1890 	/* set up the pkcs11 callbacks */
1891 	if ((rv = (*getfunctionlist)(&f)) != CKR_OK) {
1892 		error("C_GetFunctionList for provider %s failed: %lu",
1893 		    provider_id, rv);
1894 		goto fail;
1895 	}
1896 	p->function_list = f;
1897 	if ((rv = f->C_Initialize(NULL)) != CKR_OK) {
1898 		error("C_Initialize for provider %s failed: %lu",
1899 		    provider_id, rv);
1900 		goto fail;
1901 	}
1902 	need_finalize = 1;
1903 	if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) {
1904 		error("C_GetInfo for provider %s failed: %lu",
1905 		    provider_id, rv);
1906 		goto fail;
1907 	}
1908 	debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d"
1909 	    " libraryDescription <%.*s> libraryVersion %d.%d",
1910 	    provider_id,
1911 	    RMSPACE(p->info.manufacturerID),
1912 	    p->info.cryptokiVersion.major,
1913 	    p->info.cryptokiVersion.minor,
1914 	    RMSPACE(p->info.libraryDescription),
1915 	    p->info.libraryVersion.major,
1916 	    p->info.libraryVersion.minor);
1917 	if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) {
1918 		error("C_GetSlotList failed: %lu", rv);
1919 		goto fail;
1920 	}
1921 	if (p->nslots == 0) {
1922 		debug_f("provider %s returned no slots", provider_id);
1923 		ret = -SSH_PKCS11_ERR_NO_SLOTS;
1924 		goto fail;
1925 	}
1926 	p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID));
1927 	if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots))
1928 	    != CKR_OK) {
1929 		error("C_GetSlotList for provider %s failed: %lu",
1930 		    provider_id, rv);
1931 		goto fail;
1932 	}
1933 	p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo));
1934 	p->valid = 1;
1935 	nkeys = 0;
1936 	for (i = 0; i < p->nslots; i++) {
1937 		token = &p->slotinfo[i].token;
1938 		if ((rv = f->C_GetTokenInfo(p->slotlist[i], token))
1939 		    != CKR_OK) {
1940 			error("C_GetTokenInfo for provider %s slot %lu "
1941 			    "failed: %lu", provider_id, (u_long)i, rv);
1942 			continue;
1943 		}
1944 		if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) {
1945 			debug2_f("ignoring uninitialised token in "
1946 			    "provider %s slot %lu", provider_id, (u_long)i);
1947 			continue;
1948 		}
1949 		debug("provider %s slot %lu: label <%.*s> "
1950 		    "manufacturerID <%.*s> model <%.*s> serial <%.*s> "
1951 		    "flags 0x%lx",
1952 		    provider_id, (unsigned long)i,
1953 		    RMSPACE(token->label), RMSPACE(token->manufacturerID),
1954 		    RMSPACE(token->model), RMSPACE(token->serialNumber),
1955 		    token->flags);
1956 		/*
1957 		 * open session, login with pin and retrieve public
1958 		 * keys (if keyp is provided)
1959 		 */
1960 		if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 ||
1961 		    keyp == NULL)
1962 			continue;
1963 		pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
1964 #ifdef WITH_OPENSSL
1965 		pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
1966 #endif
1967 		if (nkeys == 0 && !p->slotinfo[i].logged_in &&
1968 		    pkcs11_interactive) {
1969 			/*
1970 			 * Some tokens require login before they will
1971 			 * expose keys.
1972 			 */
1973 			if (pkcs11_login_slot(p, &p->slotinfo[i],
1974 			    CKU_USER) < 0) {
1975 				error("login failed");
1976 				continue;
1977 			}
1978 			pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
1979 #ifdef WITH_OPENSSL
1980 			pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
1981 #endif
1982 		}
1983 	}
1984 
1985 	/* now owned by caller */
1986 	*providerp = p;
1987 
1988 	TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
1989 	p->refcount++;	/* add to provider list */
1990 
1991 	return (nkeys);
1992 fail:
1993 	if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK)
1994 		error("C_Finalize for provider %s failed: %lu",
1995 		    provider_id, rv);
1996 	if (p) {
1997 		free(p->name);
1998 		free(p->slotlist);
1999 		free(p->slotinfo);
2000 		free(p);
2001 	}
2002 	if (handle)
2003 		dlclose(handle);
2004 	if (ret > 0)
2005 		ret = -1;
2006 	return (ret);
2007 }
2008 
2009 int
pkcs11_init(int interactive)2010 pkcs11_init(int interactive)
2011 {
2012 	debug3_f("called, interactive = %d", interactive);
2013 
2014 	pkcs11_interactive = interactive;
2015 	TAILQ_INIT(&pkcs11_providers);
2016 	TAILQ_INIT(&pkcs11_keys);
2017 	return (0);
2018 }
2019 
2020 /* unregister all providers, keys might still point to the providers */
2021 void
pkcs11_terminate(void)2022 pkcs11_terminate(void)
2023 {
2024 	struct pkcs11_provider *p;
2025 	struct pkcs11_key *k11;
2026 
2027 	debug3_f("called");
2028 
2029 	while ((k11 = TAILQ_FIRST(&pkcs11_keys)) != NULL) {
2030 		TAILQ_REMOVE(&pkcs11_keys, k11, next);
2031 		pkcs11_k11_free(k11);
2032 	}
2033 	while ((p = TAILQ_FIRST(&pkcs11_providers)) != NULL) {
2034 		TAILQ_REMOVE(&pkcs11_providers, p, next);
2035 		pkcs11_provider_finalize(p);
2036 		pkcs11_provider_unref(p);
2037 	}
2038 }
2039 
2040 /*
2041  * register a new provider and get number of keys hold by the token,
2042  * fails if provider already exists
2043  */
2044 int
pkcs11_add_provider(char * provider_id,char * pin,struct sshkey *** keyp,char *** labelsp)2045 pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
2046     char ***labelsp)
2047 {
2048 	struct pkcs11_provider *p = NULL;
2049 	int nkeys;
2050 
2051 	nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp,
2052 	    &p, CKU_USER);
2053 
2054 	/* no keys found or some other error, de-register provider */
2055 	if (nkeys <= 0 && p != NULL) {
2056 		TAILQ_REMOVE(&pkcs11_providers, p, next);
2057 		pkcs11_provider_finalize(p);
2058 		pkcs11_provider_unref(p);
2059 	}
2060 	if (nkeys == 0)
2061 		debug_f("provider %s returned no keys", provider_id);
2062 
2063 	return (nkeys);
2064 }
2065 
2066 int
pkcs11_sign(struct sshkey * key,u_char ** sigp,size_t * lenp,const u_char * data,size_t datalen,const char * alg,const char * sk_provider,const char * sk_pin,u_int compat)2067 pkcs11_sign(struct sshkey *key,
2068     u_char **sigp, size_t *lenp,
2069     const u_char *data, size_t datalen,
2070     const char *alg, const char *sk_provider,
2071     const char *sk_pin, u_int compat)
2072 {
2073 	switch (key->type) {
2074 	case KEY_RSA:
2075 	case KEY_RSA_CERT:
2076 #ifdef WITH_OPENSSL
2077 		return pkcs11_sign_rsa(key, sigp, lenp, data, datalen,
2078 		    alg, sk_provider, sk_pin, compat);
2079 #ifdef OPENSSL_HAS_ECC
2080 	case KEY_ECDSA:
2081 	case KEY_ECDSA_CERT:
2082 		return pkcs11_sign_ecdsa(key, sigp, lenp, data, datalen,
2083 		    alg, sk_provider, sk_pin, compat);
2084 #endif /* OPENSSL_HAS_ECC */
2085 #endif /* WITH_OPENSSL */
2086 	case KEY_ED25519:
2087 	case KEY_ED25519_CERT:
2088 		return pkcs11_sign_ed25519(key, sigp, lenp, data, datalen,
2089 		    alg, sk_provider, sk_pin, compat);
2090 	default:
2091 		return SSH_ERR_KEY_TYPE_UNKNOWN;
2092 	}
2093 }
2094 
2095 void
pkcs11_key_free(struct sshkey * key)2096 pkcs11_key_free(struct sshkey *key)
2097 {
2098 	/* never called */
2099 }
2100 
2101 #ifdef WITH_PKCS11_KEYGEN
2102 struct sshkey *
pkcs11_gakp(char * provider_id,char * pin,unsigned int slotidx,char * label,unsigned int type,unsigned int bits,unsigned char keyid,uint32_t * err)2103 pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label,
2104     unsigned int type, unsigned int bits, unsigned char keyid, uint32_t *err)
2105 {
2106 	struct pkcs11_provider	*p = NULL;
2107 	struct pkcs11_slotinfo	*si;
2108 	CK_FUNCTION_LIST	*f;
2109 	CK_SESSION_HANDLE	 session;
2110 	struct sshkey		*k = NULL;
2111 	int			 ret = -1, reset_pin = 0, reset_provider = 0;
2112 	CK_RV			 rv;
2113 
2114 	*err = 0;
2115 
2116 	if ((p = pkcs11_provider_lookup(provider_id)) != NULL)
2117 		debug_f("provider \"%s\" available", provider_id);
2118 	else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL,
2119 	    &p, CKU_SO)) < 0) {
2120 		debug_f("could not register provider %s", provider_id);
2121 		goto out;
2122 	} else
2123 		reset_provider = 1;
2124 
2125 	f = p->function_list;
2126 	si = &p->slotinfo[slotidx];
2127 	session = si->session;
2128 
2129 	if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
2130 	    CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
2131 		debug_f("could not supply SO pin: %lu", rv);
2132 		reset_pin = 0;
2133 	} else
2134 		reset_pin = 1;
2135 
2136 	switch (type) {
2137 	case KEY_RSA:
2138 		if ((k = pkcs11_rsa_generate_private_key(p, slotidx, label,
2139 		    bits, keyid, err)) == NULL) {
2140 			debug_f("failed to generate RSA key");
2141 			goto out;
2142 		}
2143 		break;
2144 	case KEY_ECDSA:
2145 		if ((k = pkcs11_ecdsa_generate_private_key(p, slotidx, label,
2146 		    bits, keyid, err)) == NULL) {
2147 			debug_f("failed to generate ECDSA key");
2148 			goto out;
2149 		}
2150 		break;
2151 	default:
2152 		*err = SSH_PKCS11_ERR_GENERIC;
2153 		debug_f("unknown type %d", type);
2154 		goto out;
2155 	}
2156 
2157 out:
2158 	if (reset_pin)
2159 		f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
2160 		    CK_INVALID_HANDLE);
2161 
2162 	if (reset_provider)
2163 		pkcs11_del_provider(provider_id);
2164 
2165 	return (k);
2166 }
2167 
2168 struct sshkey *
pkcs11_destroy_keypair(char * provider_id,char * pin,unsigned long slotidx,unsigned char keyid,uint32_t * err)2169 pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
2170     unsigned char keyid, uint32_t *err)
2171 {
2172 	struct pkcs11_provider	*p = NULL;
2173 	struct pkcs11_slotinfo	*si;
2174 	struct sshkey		*k = NULL;
2175 	int			 reset_pin = 0, reset_provider = 0;
2176 	CK_ULONG		 nattrs;
2177 	CK_FUNCTION_LIST	*f;
2178 	CK_SESSION_HANDLE	 session;
2179 	CK_ATTRIBUTE		 attrs[16];
2180 	CK_OBJECT_CLASS		 key_class;
2181 	CK_KEY_TYPE		 key_type;
2182 	CK_OBJECT_HANDLE	 obj = CK_INVALID_HANDLE;
2183 	CK_RV			 rv;
2184 
2185 	*err = 0;
2186 
2187 	if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
2188 		debug_f("using provider \"%s\"", provider_id);
2189 	} else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p,
2190 	    CKU_SO) < 0) {
2191 		debug_f("could not register provider %s",
2192 		    provider_id);
2193 		goto out;
2194 	} else
2195 		reset_provider = 1;
2196 
2197 	f = p->function_list;
2198 	si = &p->slotinfo[slotidx];
2199 	session = si->session;
2200 
2201 	if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
2202 	    CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
2203 		debug_f("could not supply SO pin: %lu", rv);
2204 		reset_pin = 0;
2205 	} else
2206 		reset_pin = 1;
2207 
2208 	/* private key */
2209 	nattrs = 0;
2210 	key_class = CKO_PRIVATE_KEY;
2211 	FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class));
2212 	FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid));
2213 
2214 	if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
2215 	    obj != CK_INVALID_HANDLE) {
2216 		if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
2217 			debug_f("could not destroy private key 0x%hhx",
2218 			    keyid);
2219 			*err = rv;
2220 			goto out;
2221 		}
2222 	}
2223 
2224 	/* public key */
2225 	nattrs = 0;
2226 	key_class = CKO_PUBLIC_KEY;
2227 	FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class));
2228 	FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid));
2229 
2230 	if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
2231 	    obj != CK_INVALID_HANDLE) {
2232 
2233 		/* get key type */
2234 		nattrs = 0;
2235 		FILL_ATTR(attrs, nattrs, CKA_KEY_TYPE, &key_type,
2236 		    sizeof(key_type));
2237 		rv = f->C_GetAttributeValue(session, obj, attrs, nattrs);
2238 		if (rv != CKR_OK) {
2239 			debug_f("could not get key type of public key 0x%hhx",
2240 			    keyid);
2241 			*err = rv;
2242 			key_type = -1;
2243 		}
2244 		switch (key_type) {
2245 #ifdef WITH_OPENSSL
2246 		case CKK_RSA:
2247 			k = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
2248 			break;
2249 #ifdef OPENSSL_HAS_ECC
2250 		case CKK_ECDSA:
2251 			k = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
2252 			break;
2253 #endif /* OPENSSL_HAS_ECC */
2254 #endif /* WITH_OPENSSL */
2255 		case CKK_EC_EDWARDS:
2256 			k = pkcs11_fetch_ed25519_pubkey(p, slotidx, &obj);
2257 			break;
2258 		default:
2259 			debug_f("unsupported key type %lu", (u_long)key_type);
2260 			break;
2261 		}
2262 
2263 		if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
2264 			debug_f("could not destroy public key 0x%hhx", keyid);
2265 			*err = rv;
2266 			goto out;
2267 		}
2268 	}
2269 
2270 out:
2271 	if (reset_pin)
2272 		f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
2273 		    CK_INVALID_HANDLE);
2274 
2275 	if (reset_provider)
2276 		pkcs11_del_provider(provider_id);
2277 
2278 	return (k);
2279 }
2280 #endif /* WITH_PKCS11_KEYGEN */
2281 #else /* ENABLE_PKCS11 */
2282 
2283 #include <sys/types.h>
2284 #include <stdarg.h>
2285 #include <stdio.h>
2286 
2287 #include "log.h"
2288 #include "sshkey.h"
2289 #include "ssherr.h"
2290 #include "ssh-pkcs11.h"
2291 
2292 int
pkcs11_init(int interactive)2293 pkcs11_init(int interactive)
2294 {
2295 	error_f("PKCS#11 not supported");
2296 	return (-1);
2297 }
2298 
2299 int
pkcs11_add_provider(char * provider_id,char * pin,struct sshkey *** keyp,char *** labelsp)2300 pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
2301     char ***labelsp)
2302 {
2303 	error_f("PKCS#11 not supported");
2304 	return (-1);
2305 }
2306 
2307 void
pkcs11_key_free(struct sshkey * key)2308 pkcs11_key_free(struct sshkey *key)
2309 {
2310 	error_f("PKCS#11 not supported");
2311 }
2312 
2313 int
pkcs11_sign(struct sshkey * key,u_char ** sigp,size_t * lenp,const u_char * data,size_t datalen,const char * alg,const char * sk_provider,const char * sk_pin,u_int compat)2314 pkcs11_sign(struct sshkey *key,
2315     u_char **sigp, size_t *lenp,
2316     const u_char *data, size_t datalen,
2317     const char *alg, const char *sk_provider,
2318     const char *sk_pin, u_int compat)
2319 {
2320 	error_f("PKCS#11 not supported");
2321 	return SSH_ERR_FEATURE_UNSUPPORTED;
2322 }
2323 
2324 void
pkcs11_terminate(void)2325 pkcs11_terminate(void)
2326 {
2327 	error_f("PKCS#11 not supported");
2328 }
2329 #endif /* ENABLE_PKCS11 */
2330