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