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