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