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