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