1 /* $OpenBSD: ssh-pkcs11.c,v 1.64 2024/09/20 02:00:46 jsg 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 if (RSA_set_method(rsa, rsa_method) != 1) 497 fatal_f("RSA_set_method failed"); 498 if (RSA_set_ex_data(rsa, rsa_idx, k11) != 1) 499 fatal_f("RSA_set_ex_data failed"); 500 return (0); 501 } 502 503 /* openssl callback doing the actual signing operation */ 504 static ECDSA_SIG * 505 ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, 506 const BIGNUM *rp, EC_KEY *ec) 507 { 508 struct pkcs11_key *k11; 509 struct pkcs11_slotinfo *si; 510 CK_FUNCTION_LIST *f; 511 CK_ULONG siglen = 0, bnlen; 512 CK_RV rv; 513 ECDSA_SIG *ret = NULL; 514 u_char *sig; 515 BIGNUM *r = NULL, *s = NULL; 516 517 if ((k11 = EC_KEY_get_ex_data(ec, ec_key_idx)) == NULL) { 518 ossl_error("EC_KEY_get_ex_data failed for ec"); 519 return (NULL); 520 } 521 522 if (pkcs11_get_key(k11, CKM_ECDSA) == -1) { 523 error("pkcs11_get_key failed"); 524 return (NULL); 525 } 526 527 f = k11->provider->function_list; 528 si = &k11->provider->slotinfo[k11->slotidx]; 529 530 siglen = ECDSA_size(ec); 531 sig = xmalloc(siglen); 532 533 /* XXX handle CKR_BUFFER_TOO_SMALL */ 534 rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, &siglen); 535 if (rv != CKR_OK) { 536 error("C_Sign failed: %lu", rv); 537 goto done; 538 } 539 if (siglen < 64 || siglen > 132 || siglen % 2) { 540 error_f("bad signature length: %lu", (u_long)siglen); 541 goto done; 542 } 543 bnlen = siglen/2; 544 if ((ret = ECDSA_SIG_new()) == NULL) { 545 error("ECDSA_SIG_new failed"); 546 goto done; 547 } 548 if ((r = BN_bin2bn(sig, bnlen, NULL)) == NULL || 549 (s = BN_bin2bn(sig+bnlen, bnlen, NULL)) == NULL) { 550 ossl_error("BN_bin2bn failed"); 551 ECDSA_SIG_free(ret); 552 ret = NULL; 553 goto done; 554 } 555 if (!ECDSA_SIG_set0(ret, r, s)) { 556 error_f("ECDSA_SIG_set0 failed"); 557 ECDSA_SIG_free(ret); 558 ret = NULL; 559 goto done; 560 } 561 r = s = NULL; /* now owned by ret */ 562 /* success */ 563 done: 564 BN_free(r); 565 BN_free(s); 566 free(sig); 567 568 return (ret); 569 } 570 571 static int 572 pkcs11_ecdsa_start_wrapper(void) 573 { 574 int (*orig_sign)(int, const unsigned char *, int, unsigned char *, 575 unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL; 576 577 if (ec_key_method != NULL) 578 return (0); 579 ec_key_idx = EC_KEY_get_ex_new_index(0, "ssh-pkcs11-ecdsa", 580 NULL, NULL, pkcs11_k11_free); 581 if (ec_key_idx == -1) 582 return (-1); 583 ec_key_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL()); 584 if (ec_key_method == NULL) 585 return (-1); 586 EC_KEY_METHOD_get_sign(ec_key_method, &orig_sign, NULL, NULL); 587 EC_KEY_METHOD_set_sign(ec_key_method, orig_sign, NULL, ecdsa_do_sign); 588 return (0); 589 } 590 591 static int 592 pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, 593 CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec) 594 { 595 struct pkcs11_key *k11; 596 597 if (pkcs11_ecdsa_start_wrapper() == -1) 598 return (-1); 599 600 k11 = xcalloc(1, sizeof(*k11)); 601 k11->provider = provider; 602 provider->refcount++; /* provider referenced by ECDSA key */ 603 k11->slotidx = slotidx; 604 /* identify key object on smartcard */ 605 k11->keyid_len = keyid_attrib->ulValueLen; 606 if (k11->keyid_len > 0) { 607 k11->keyid = xmalloc(k11->keyid_len); 608 memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); 609 } 610 if (EC_KEY_set_method(ec, ec_key_method) != 1) 611 fatal_f("EC_KEY_set_method failed"); 612 if (EC_KEY_set_ex_data(ec, ec_key_idx, k11) != 1) 613 fatal_f("EC_KEY_set_ex_data failed"); 614 615 return (0); 616 } 617 618 /* remove trailing spaces */ 619 static char * 620 rmspace(u_char *buf, size_t len) 621 { 622 size_t i; 623 624 if (len == 0) 625 return buf; 626 for (i = len - 1; i > 0; i--) 627 if (buf[i] == ' ') 628 buf[i] = '\0'; 629 else 630 break; 631 return buf; 632 } 633 /* Used to printf fixed-width, space-padded, unterminated strings using %.*s */ 634 #define RMSPACE(s) (int)sizeof(s), rmspace(s, sizeof(s)) 635 636 /* 637 * open a pkcs11 session and login if required. 638 * if pin == NULL we delay login until key use 639 */ 640 static int 641 pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, 642 CK_ULONG user) 643 { 644 struct pkcs11_slotinfo *si; 645 CK_FUNCTION_LIST *f; 646 CK_RV rv; 647 CK_SESSION_HANDLE session; 648 int login_required, ret; 649 650 f = p->function_list; 651 si = &p->slotinfo[slotidx]; 652 653 login_required = si->token.flags & CKF_LOGIN_REQUIRED; 654 655 /* fail early before opening session */ 656 if (login_required && !pkcs11_interactive && 657 (pin == NULL || strlen(pin) == 0)) { 658 error("pin required"); 659 return (-SSH_PKCS11_ERR_PIN_REQUIRED); 660 } 661 if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| 662 CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) { 663 error("C_OpenSession failed: %lu", rv); 664 return (-1); 665 } 666 if (login_required && pin != NULL && strlen(pin) != 0) { 667 rv = f->C_Login(session, user, (u_char *)pin, strlen(pin)); 668 if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { 669 error("C_Login failed: %lu", rv); 670 ret = (rv == CKR_PIN_LOCKED) ? 671 -SSH_PKCS11_ERR_PIN_LOCKED : 672 -SSH_PKCS11_ERR_LOGIN_FAIL; 673 if ((rv = f->C_CloseSession(session)) != CKR_OK) 674 error("C_CloseSession failed: %lu", rv); 675 return (ret); 676 } 677 si->logged_in = 1; 678 } 679 si->session = session; 680 return (0); 681 } 682 683 static int 684 pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key) 685 { 686 int i; 687 688 for (i = 0; i < *nkeys; i++) 689 if (sshkey_equal(key, (*keysp)[i])) 690 return (1); 691 return (0); 692 } 693 694 static struct sshkey * 695 pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, 696 CK_OBJECT_HANDLE *obj) 697 { 698 CK_ATTRIBUTE key_attr[3]; 699 CK_SESSION_HANDLE session; 700 CK_FUNCTION_LIST *f = NULL; 701 CK_RV rv; 702 ASN1_OCTET_STRING *octet = NULL; 703 EC_KEY *ec = NULL; 704 EC_GROUP *group = NULL; 705 struct sshkey *key = NULL; 706 const unsigned char *attrp = NULL; 707 int i; 708 int nid; 709 710 memset(&key_attr, 0, sizeof(key_attr)); 711 key_attr[0].type = CKA_ID; 712 key_attr[1].type = CKA_EC_POINT; 713 key_attr[2].type = CKA_EC_PARAMS; 714 715 session = p->slotinfo[slotidx].session; 716 f = p->function_list; 717 718 /* figure out size of the attributes */ 719 rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); 720 if (rv != CKR_OK) { 721 error("C_GetAttributeValue failed: %lu", rv); 722 return (NULL); 723 } 724 725 /* 726 * Allow CKA_ID (always first attribute) to be empty, but 727 * ensure that none of the others are zero length. 728 * XXX assumes CKA_ID is always first. 729 */ 730 if (key_attr[1].ulValueLen == 0 || 731 key_attr[2].ulValueLen == 0) { 732 error("invalid attribute length"); 733 return (NULL); 734 } 735 736 /* allocate buffers for attributes */ 737 for (i = 0; i < 3; i++) 738 if (key_attr[i].ulValueLen > 0) 739 key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); 740 741 /* retrieve ID, public point and curve parameters of EC key */ 742 rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); 743 if (rv != CKR_OK) { 744 error("C_GetAttributeValue failed: %lu", rv); 745 goto fail; 746 } 747 748 ec = EC_KEY_new(); 749 if (ec == NULL) { 750 error("EC_KEY_new failed"); 751 goto fail; 752 } 753 754 attrp = key_attr[2].pValue; 755 group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen); 756 if (group == NULL) { 757 ossl_error("d2i_ECPKParameters failed"); 758 goto fail; 759 } 760 761 if (EC_KEY_set_group(ec, group) == 0) { 762 ossl_error("EC_KEY_set_group failed"); 763 goto fail; 764 } 765 766 if (key_attr[1].ulValueLen <= 2) { 767 error("CKA_EC_POINT too small"); 768 goto fail; 769 } 770 771 attrp = key_attr[1].pValue; 772 octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen); 773 if (octet == NULL) { 774 ossl_error("d2i_ASN1_OCTET_STRING failed"); 775 goto fail; 776 } 777 attrp = octet->data; 778 if (o2i_ECPublicKey(&ec, &attrp, octet->length) == NULL) { 779 ossl_error("o2i_ECPublicKey failed"); 780 goto fail; 781 } 782 783 nid = sshkey_ecdsa_key_to_nid(ec); 784 if (nid < 0) { 785 error("couldn't get curve nid"); 786 goto fail; 787 } 788 789 if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec)) 790 goto fail; 791 792 key = sshkey_new(KEY_UNSPEC); 793 if (key == NULL) { 794 error("sshkey_new failed"); 795 goto fail; 796 } 797 798 EVP_PKEY_free(key->pkey); 799 if ((key->pkey = EVP_PKEY_new()) == NULL) 800 fatal("EVP_PKEY_new failed"); 801 if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1) 802 fatal("EVP_PKEY_set1_EC_KEY failed"); 803 key->ecdsa_nid = nid; 804 key->type = KEY_ECDSA; 805 key->flags |= SSHKEY_FLAG_EXT; 806 807 fail: 808 for (i = 0; i < 3; i++) 809 free(key_attr[i].pValue); 810 if (ec) 811 EC_KEY_free(ec); 812 if (group) 813 EC_GROUP_free(group); 814 if (octet) 815 ASN1_OCTET_STRING_free(octet); 816 817 return (key); 818 } 819 820 static struct sshkey * 821 pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, 822 CK_OBJECT_HANDLE *obj) 823 { 824 CK_ATTRIBUTE key_attr[3]; 825 CK_SESSION_HANDLE session; 826 CK_FUNCTION_LIST *f = NULL; 827 CK_RV rv; 828 RSA *rsa = NULL; 829 BIGNUM *rsa_n, *rsa_e; 830 struct sshkey *key = NULL; 831 int i; 832 833 memset(&key_attr, 0, sizeof(key_attr)); 834 key_attr[0].type = CKA_ID; 835 key_attr[1].type = CKA_MODULUS; 836 key_attr[2].type = CKA_PUBLIC_EXPONENT; 837 838 session = p->slotinfo[slotidx].session; 839 f = p->function_list; 840 841 /* figure out size of the attributes */ 842 rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); 843 if (rv != CKR_OK) { 844 error("C_GetAttributeValue failed: %lu", rv); 845 return (NULL); 846 } 847 848 /* 849 * Allow CKA_ID (always first attribute) to be empty, but 850 * ensure that none of the others are zero length. 851 * XXX assumes CKA_ID is always first. 852 */ 853 if (key_attr[1].ulValueLen == 0 || 854 key_attr[2].ulValueLen == 0) { 855 error("invalid attribute length"); 856 return (NULL); 857 } 858 859 /* allocate buffers for attributes */ 860 for (i = 0; i < 3; i++) 861 if (key_attr[i].ulValueLen > 0) 862 key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); 863 864 /* retrieve ID, modulus and public exponent of RSA key */ 865 rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); 866 if (rv != CKR_OK) { 867 error("C_GetAttributeValue failed: %lu", rv); 868 goto fail; 869 } 870 871 rsa = RSA_new(); 872 if (rsa == NULL) { 873 error("RSA_new failed"); 874 goto fail; 875 } 876 877 rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL); 878 rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); 879 if (rsa_n == NULL || rsa_e == NULL) { 880 error("BN_bin2bn failed"); 881 goto fail; 882 } 883 if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) 884 fatal_f("set key"); 885 rsa_n = rsa_e = NULL; /* transferred */ 886 887 if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) 888 goto fail; 889 890 key = sshkey_new(KEY_UNSPEC); 891 if (key == NULL) { 892 error("sshkey_new failed"); 893 goto fail; 894 } 895 896 EVP_PKEY_free(key->pkey); 897 if ((key->pkey = EVP_PKEY_new()) == NULL) 898 fatal("EVP_PKEY_new failed"); 899 if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) 900 fatal("EVP_PKEY_set1_RSA failed"); 901 key->type = KEY_RSA; 902 key->flags |= SSHKEY_FLAG_EXT; 903 904 fail: 905 for (i = 0; i < 3; i++) 906 free(key_attr[i].pValue); 907 RSA_free(rsa); 908 909 return (key); 910 } 911 912 static int 913 pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, 914 CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) 915 { 916 CK_ATTRIBUTE cert_attr[3]; 917 CK_SESSION_HANDLE session; 918 CK_FUNCTION_LIST *f = NULL; 919 CK_RV rv; 920 X509 *x509 = NULL; 921 X509_NAME *x509_name = NULL; 922 EVP_PKEY *evp; 923 RSA *rsa = NULL; 924 EC_KEY *ec = NULL; 925 struct sshkey *key = NULL; 926 int i; 927 int nid; 928 const u_char *cp; 929 char *subject = NULL; 930 931 *keyp = NULL; 932 *labelp = NULL; 933 934 memset(&cert_attr, 0, sizeof(cert_attr)); 935 cert_attr[0].type = CKA_ID; 936 cert_attr[1].type = CKA_SUBJECT; 937 cert_attr[2].type = CKA_VALUE; 938 939 session = p->slotinfo[slotidx].session; 940 f = p->function_list; 941 942 /* figure out size of the attributes */ 943 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); 944 if (rv != CKR_OK) { 945 error("C_GetAttributeValue failed: %lu", rv); 946 return -1; 947 } 948 949 /* 950 * Allow CKA_ID (always first attribute) to be empty, but 951 * ensure that none of the others are zero length. 952 * XXX assumes CKA_ID is always first. 953 */ 954 if (cert_attr[1].ulValueLen == 0 || 955 cert_attr[2].ulValueLen == 0) { 956 error("invalid attribute length"); 957 return -1; 958 } 959 960 /* allocate buffers for attributes */ 961 for (i = 0; i < 3; i++) 962 if (cert_attr[i].ulValueLen > 0) 963 cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen); 964 965 /* retrieve ID, subject and value of certificate */ 966 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); 967 if (rv != CKR_OK) { 968 error("C_GetAttributeValue failed: %lu", rv); 969 goto out; 970 } 971 972 /* Decode DER-encoded cert subject */ 973 cp = cert_attr[1].pValue; 974 if ((x509_name = d2i_X509_NAME(NULL, &cp, 975 cert_attr[1].ulValueLen)) == NULL || 976 (subject = X509_NAME_oneline(x509_name, NULL, 0)) == NULL) 977 subject = xstrdup("invalid subject"); 978 X509_NAME_free(x509_name); 979 980 cp = cert_attr[2].pValue; 981 if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) { 982 error("d2i_x509 failed"); 983 goto out; 984 } 985 986 if ((evp = X509_get_pubkey(x509)) == NULL) { 987 error("X509_get_pubkey failed"); 988 goto out; 989 } 990 991 if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) { 992 if (EVP_PKEY_get0_RSA(evp) == NULL) { 993 error("invalid x509; no rsa key"); 994 goto out; 995 } 996 if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) { 997 error("RSAPublicKey_dup failed"); 998 goto out; 999 } 1000 1001 if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) 1002 goto out; 1003 1004 key = sshkey_new(KEY_UNSPEC); 1005 if (key == NULL) { 1006 error("sshkey_new failed"); 1007 goto out; 1008 } 1009 1010 EVP_PKEY_free(key->pkey); 1011 if ((key->pkey = EVP_PKEY_new()) == NULL) 1012 fatal("EVP_PKEY_new failed"); 1013 if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) 1014 fatal("EVP_PKEY_set1_RSA failed"); 1015 key->type = KEY_RSA; 1016 key->flags |= SSHKEY_FLAG_EXT; 1017 } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) { 1018 if (EVP_PKEY_get0_EC_KEY(evp) == NULL) { 1019 error("invalid x509; no ec key"); 1020 goto out; 1021 } 1022 if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) { 1023 error("EC_KEY_dup failed"); 1024 goto out; 1025 } 1026 1027 nid = sshkey_ecdsa_key_to_nid(ec); 1028 if (nid < 0) { 1029 error("couldn't get curve nid"); 1030 goto out; 1031 } 1032 1033 if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) 1034 goto out; 1035 1036 key = sshkey_new(KEY_UNSPEC); 1037 if (key == NULL) { 1038 error("sshkey_new failed"); 1039 goto out; 1040 } 1041 1042 EVP_PKEY_free(key->pkey); 1043 if ((key->pkey = EVP_PKEY_new()) == NULL) 1044 fatal("EVP_PKEY_new failed"); 1045 if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1) 1046 fatal("EVP_PKEY_set1_EC_KEY failed"); 1047 key->ecdsa_nid = nid; 1048 key->type = KEY_ECDSA; 1049 key->flags |= SSHKEY_FLAG_EXT; 1050 } else { 1051 error("unknown certificate key type"); 1052 goto out; 1053 } 1054 out: 1055 for (i = 0; i < 3; i++) 1056 free(cert_attr[i].pValue); 1057 X509_free(x509); 1058 RSA_free(rsa); 1059 EC_KEY_free(ec); 1060 if (key == NULL) { 1061 free(subject); 1062 return -1; 1063 } 1064 /* success */ 1065 *keyp = key; 1066 *labelp = subject; 1067 return 0; 1068 } 1069 1070 #if 0 1071 static int 1072 have_rsa_key(const RSA *rsa) 1073 { 1074 const BIGNUM *rsa_n, *rsa_e; 1075 1076 RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL); 1077 return rsa_n != NULL && rsa_e != NULL; 1078 } 1079 #endif 1080 1081 static void 1082 note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context, 1083 struct sshkey *key) 1084 { 1085 char *fp; 1086 1087 if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, 1088 SSH_FP_DEFAULT)) == NULL) { 1089 error_f("sshkey_fingerprint failed"); 1090 return; 1091 } 1092 debug2("%s: provider %s slot %lu: %s %s", context, p->name, 1093 (u_long)slotidx, sshkey_type(key), fp); 1094 free(fp); 1095 } 1096 1097 /* 1098 * lookup certificates for token in slot identified by slotidx, 1099 * add 'wrapped' public keys to the 'keysp' array and increment nkeys. 1100 * keysp points to an (possibly empty) array with *nkeys keys. 1101 */ 1102 static int 1103 pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, 1104 struct sshkey ***keysp, char ***labelsp, int *nkeys) 1105 { 1106 struct sshkey *key = NULL; 1107 CK_OBJECT_CLASS key_class; 1108 CK_ATTRIBUTE key_attr[1]; 1109 CK_SESSION_HANDLE session; 1110 CK_FUNCTION_LIST *f = NULL; 1111 CK_RV rv; 1112 CK_OBJECT_HANDLE obj; 1113 CK_ULONG n = 0; 1114 int ret = -1; 1115 char *label; 1116 1117 memset(&key_attr, 0, sizeof(key_attr)); 1118 memset(&obj, 0, sizeof(obj)); 1119 1120 key_class = CKO_CERTIFICATE; 1121 key_attr[0].type = CKA_CLASS; 1122 key_attr[0].pValue = &key_class; 1123 key_attr[0].ulValueLen = sizeof(key_class); 1124 1125 session = p->slotinfo[slotidx].session; 1126 f = p->function_list; 1127 1128 rv = f->C_FindObjectsInit(session, key_attr, 1); 1129 if (rv != CKR_OK) { 1130 error("C_FindObjectsInit failed: %lu", rv); 1131 goto fail; 1132 } 1133 1134 while (1) { 1135 CK_CERTIFICATE_TYPE ck_cert_type; 1136 1137 rv = f->C_FindObjects(session, &obj, 1, &n); 1138 if (rv != CKR_OK) { 1139 error("C_FindObjects failed: %lu", rv); 1140 goto fail; 1141 } 1142 if (n == 0) 1143 break; 1144 1145 memset(&ck_cert_type, 0, sizeof(ck_cert_type)); 1146 memset(&key_attr, 0, sizeof(key_attr)); 1147 key_attr[0].type = CKA_CERTIFICATE_TYPE; 1148 key_attr[0].pValue = &ck_cert_type; 1149 key_attr[0].ulValueLen = sizeof(ck_cert_type); 1150 1151 rv = f->C_GetAttributeValue(session, obj, key_attr, 1); 1152 if (rv != CKR_OK) { 1153 error("C_GetAttributeValue failed: %lu", rv); 1154 goto fail; 1155 } 1156 1157 key = NULL; 1158 label = NULL; 1159 switch (ck_cert_type) { 1160 case CKC_X_509: 1161 if (pkcs11_fetch_x509_pubkey(p, slotidx, &obj, 1162 &key, &label) != 0) { 1163 error("failed to fetch key"); 1164 continue; 1165 } 1166 break; 1167 default: 1168 error("skipping unsupported certificate type %lu", 1169 ck_cert_type); 1170 continue; 1171 } 1172 note_key(p, slotidx, __func__, key); 1173 if (pkcs11_key_included(keysp, nkeys, key)) { 1174 debug2_f("key already included"); 1175 sshkey_free(key); 1176 } else { 1177 /* expand key array and add key */ 1178 *keysp = xrecallocarray(*keysp, *nkeys, 1179 *nkeys + 1, sizeof(struct sshkey *)); 1180 (*keysp)[*nkeys] = key; 1181 if (labelsp != NULL) { 1182 *labelsp = xrecallocarray(*labelsp, *nkeys, 1183 *nkeys + 1, sizeof(char *)); 1184 (*labelsp)[*nkeys] = xstrdup((char *)label); 1185 } 1186 *nkeys = *nkeys + 1; 1187 debug("have %d keys", *nkeys); 1188 } 1189 } 1190 1191 ret = 0; 1192 fail: 1193 rv = f->C_FindObjectsFinal(session); 1194 if (rv != CKR_OK) { 1195 error("C_FindObjectsFinal failed: %lu", rv); 1196 ret = -1; 1197 } 1198 1199 return (ret); 1200 } 1201 1202 /* 1203 * lookup public keys for token in slot identified by slotidx, 1204 * add 'wrapped' public keys to the 'keysp' array and increment nkeys. 1205 * keysp points to an (possibly empty) array with *nkeys keys. 1206 */ 1207 static int 1208 pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, 1209 struct sshkey ***keysp, char ***labelsp, int *nkeys) 1210 { 1211 struct sshkey *key = NULL; 1212 CK_OBJECT_CLASS key_class; 1213 CK_ATTRIBUTE key_attr[2]; 1214 CK_SESSION_HANDLE session; 1215 CK_FUNCTION_LIST *f = NULL; 1216 CK_RV rv; 1217 CK_OBJECT_HANDLE obj; 1218 CK_ULONG n = 0; 1219 int ret = -1; 1220 1221 memset(&key_attr, 0, sizeof(key_attr)); 1222 memset(&obj, 0, sizeof(obj)); 1223 1224 key_class = CKO_PUBLIC_KEY; 1225 key_attr[0].type = CKA_CLASS; 1226 key_attr[0].pValue = &key_class; 1227 key_attr[0].ulValueLen = sizeof(key_class); 1228 1229 session = p->slotinfo[slotidx].session; 1230 f = p->function_list; 1231 1232 rv = f->C_FindObjectsInit(session, key_attr, 1); 1233 if (rv != CKR_OK) { 1234 error("C_FindObjectsInit failed: %lu", rv); 1235 goto fail; 1236 } 1237 1238 while (1) { 1239 CK_KEY_TYPE ck_key_type; 1240 CK_UTF8CHAR label[256]; 1241 1242 rv = f->C_FindObjects(session, &obj, 1, &n); 1243 if (rv != CKR_OK) { 1244 error("C_FindObjects failed: %lu", rv); 1245 goto fail; 1246 } 1247 if (n == 0) 1248 break; 1249 1250 memset(&ck_key_type, 0, sizeof(ck_key_type)); 1251 memset(&key_attr, 0, sizeof(key_attr)); 1252 key_attr[0].type = CKA_KEY_TYPE; 1253 key_attr[0].pValue = &ck_key_type; 1254 key_attr[0].ulValueLen = sizeof(ck_key_type); 1255 key_attr[1].type = CKA_LABEL; 1256 key_attr[1].pValue = &label; 1257 key_attr[1].ulValueLen = sizeof(label) - 1; 1258 1259 rv = f->C_GetAttributeValue(session, obj, key_attr, 2); 1260 if (rv != CKR_OK) { 1261 error("C_GetAttributeValue failed: %lu", rv); 1262 goto fail; 1263 } 1264 1265 label[key_attr[1].ulValueLen] = '\0'; 1266 1267 switch (ck_key_type) { 1268 case CKK_RSA: 1269 key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); 1270 break; 1271 case CKK_ECDSA: 1272 key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj); 1273 break; 1274 default: 1275 /* XXX print key type? */ 1276 key = NULL; 1277 error("skipping unsupported key type"); 1278 } 1279 1280 if (key == NULL) { 1281 error("failed to fetch key"); 1282 continue; 1283 } 1284 note_key(p, slotidx, __func__, key); 1285 if (pkcs11_key_included(keysp, nkeys, key)) { 1286 debug2_f("key already included"); 1287 sshkey_free(key); 1288 } else { 1289 /* expand key array and add key */ 1290 *keysp = xrecallocarray(*keysp, *nkeys, 1291 *nkeys + 1, sizeof(struct sshkey *)); 1292 (*keysp)[*nkeys] = key; 1293 if (labelsp != NULL) { 1294 *labelsp = xrecallocarray(*labelsp, *nkeys, 1295 *nkeys + 1, sizeof(char *)); 1296 (*labelsp)[*nkeys] = xstrdup((char *)label); 1297 } 1298 *nkeys = *nkeys + 1; 1299 debug("have %d keys", *nkeys); 1300 } 1301 } 1302 1303 ret = 0; 1304 fail: 1305 rv = f->C_FindObjectsFinal(session); 1306 if (rv != CKR_OK) { 1307 error("C_FindObjectsFinal failed: %lu", rv); 1308 ret = -1; 1309 } 1310 1311 return (ret); 1312 } 1313 1314 #ifdef WITH_PKCS11_KEYGEN 1315 #define FILL_ATTR(attr, idx, typ, val, len) \ 1316 { (attr[idx]).type=(typ); (attr[idx]).pValue=(val); (attr[idx]).ulValueLen=len; idx++; } 1317 1318 static struct sshkey * 1319 pkcs11_rsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, 1320 char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err) 1321 { 1322 struct pkcs11_slotinfo *si; 1323 char *plabel = label ? label : ""; 1324 int npub = 0, npriv = 0; 1325 CK_RV rv; 1326 CK_FUNCTION_LIST *f; 1327 CK_SESSION_HANDLE session; 1328 CK_BBOOL true_val = CK_TRUE, false_val = CK_FALSE; 1329 CK_OBJECT_HANDLE pubKey, privKey; 1330 CK_ATTRIBUTE tpub[16], tpriv[16]; 1331 CK_MECHANISM mech = { 1332 CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 1333 }; 1334 CK_BYTE pubExponent[] = { 1335 0x01, 0x00, 0x01 /* RSA_F4 in bytes */ 1336 }; 1337 1338 *err = 0; 1339 1340 FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val)); 1341 FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel)); 1342 FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val)); 1343 FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val)); 1344 FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val, 1345 sizeof(false_val)); 1346 FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val)); 1347 FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val)); 1348 FILL_ATTR(tpub, npub, CKA_MODULUS_BITS, &bits, sizeof(bits)); 1349 FILL_ATTR(tpub, npub, CKA_PUBLIC_EXPONENT, pubExponent, 1350 sizeof(pubExponent)); 1351 FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid)); 1352 1353 FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val)); 1354 FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel)); 1355 FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val)); 1356 FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val)); 1357 FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val)); 1358 FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val)); 1359 FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val, 1360 sizeof(false_val)); 1361 FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val)); 1362 FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val)); 1363 FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid)); 1364 1365 f = p->function_list; 1366 si = &p->slotinfo[slotidx]; 1367 session = si->session; 1368 1369 if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv, 1370 &pubKey, &privKey)) != CKR_OK) { 1371 error_f("key generation failed: error 0x%lx", rv); 1372 *err = rv; 1373 return NULL; 1374 } 1375 1376 return pkcs11_fetch_rsa_pubkey(p, slotidx, &pubKey); 1377 } 1378 1379 static int 1380 h2i(char c) 1381 { 1382 if (c >= '0' && c <= '9') 1383 return c - '0'; 1384 else if (c >= 'a' && c <= 'f') 1385 return c - 'a' + 10; 1386 else if (c >= 'A' && c <= 'F') 1387 return c - 'A' + 10; 1388 else 1389 return -1; 1390 } 1391 1392 static int 1393 pkcs11_decode_hex(const char *hex, unsigned char **dest, size_t *rlen) 1394 { 1395 size_t i, len; 1396 1397 if (dest) 1398 *dest = NULL; 1399 if (rlen) 1400 *rlen = 0; 1401 1402 if ((len = strlen(hex)) % 2) 1403 return -1; 1404 len /= 2; 1405 1406 *dest = xmalloc(len); 1407 1408 for (i = 0; i < len; i++) { 1409 int hi, low; 1410 1411 hi = h2i(hex[2 * i]); 1412 lo = h2i(hex[(2 * i) + 1]); 1413 if (hi == -1 || lo == -1) 1414 return -1; 1415 (*dest)[i] = (hi << 4) | lo; 1416 } 1417 1418 if (rlen) 1419 *rlen = len; 1420 1421 return 0; 1422 } 1423 1424 static struct ec_curve_info { 1425 const char *name; 1426 const char *oid; 1427 const char *oid_encoded; 1428 size_t size; 1429 } ec_curve_infos[] = { 1430 {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, 1431 {"secp384r1", "1.3.132.0.34", "06052B81040022", 384}, 1432 {"secp521r1", "1.3.132.0.35", "06052B81040023", 521}, 1433 {NULL, NULL, NULL, 0}, 1434 }; 1435 1436 static struct sshkey * 1437 pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, 1438 char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err) 1439 { 1440 struct pkcs11_slotinfo *si; 1441 char *plabel = label ? label : ""; 1442 int i; 1443 size_t ecparams_size; 1444 unsigned char *ecparams = NULL; 1445 int npub = 0, npriv = 0; 1446 CK_RV rv; 1447 CK_FUNCTION_LIST *f; 1448 CK_SESSION_HANDLE session; 1449 CK_BBOOL true_val = CK_TRUE, false_val = CK_FALSE; 1450 CK_OBJECT_HANDLE pubKey, privKey; 1451 CK_MECHANISM mech = { 1452 CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0 1453 }; 1454 CK_ATTRIBUTE tpub[16], tpriv[16]; 1455 1456 *err = 0; 1457 1458 for (i = 0; ec_curve_infos[i].name; i++) { 1459 if (ec_curve_infos[i].size == bits) 1460 break; 1461 } 1462 if (!ec_curve_infos[i].name) { 1463 error_f("invalid key size %lu", bits); 1464 return NULL; 1465 } 1466 if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams, 1467 &ecparams_size) == -1) { 1468 error_f("invalid oid"); 1469 return NULL; 1470 } 1471 1472 FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val)); 1473 FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel)); 1474 FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val)); 1475 FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val)); 1476 FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val, 1477 sizeof(false_val)); 1478 FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val)); 1479 FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val)); 1480 FILL_ATTR(tpub, npub, CKA_EC_PARAMS, ecparams, ecparams_size); 1481 FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid)); 1482 1483 FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val)); 1484 FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel)); 1485 FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val)); 1486 FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val)); 1487 FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val)); 1488 FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val)); 1489 FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val, 1490 sizeof(false_val)); 1491 FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val)); 1492 FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val)); 1493 FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid)); 1494 1495 f = p->function_list; 1496 si = &p->slotinfo[slotidx]; 1497 session = si->session; 1498 1499 if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv, 1500 &pubKey, &privKey)) != CKR_OK) { 1501 error_f("key generation failed: error 0x%lx", rv); 1502 *err = rv; 1503 return NULL; 1504 } 1505 1506 return pkcs11_fetch_ecdsa_pubkey(p, slotidx, &pubKey); 1507 } 1508 #endif /* WITH_PKCS11_KEYGEN */ 1509 1510 /* 1511 * register a new provider, fails if provider already exists. if 1512 * keyp is provided, fetch keys. 1513 */ 1514 static int 1515 pkcs11_register_provider(char *provider_id, char *pin, 1516 struct sshkey ***keyp, char ***labelsp, 1517 struct pkcs11_provider **providerp, CK_ULONG user) 1518 { 1519 int nkeys, need_finalize = 0; 1520 int ret = -1; 1521 struct pkcs11_provider *p = NULL; 1522 void *handle = NULL; 1523 CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **); 1524 CK_RV rv; 1525 CK_FUNCTION_LIST *f = NULL; 1526 CK_TOKEN_INFO *token; 1527 CK_ULONG i; 1528 1529 if (providerp == NULL) 1530 goto fail; 1531 *providerp = NULL; 1532 1533 if (keyp != NULL) 1534 *keyp = NULL; 1535 if (labelsp != NULL) 1536 *labelsp = NULL; 1537 1538 if (pkcs11_provider_lookup(provider_id) != NULL) { 1539 debug_f("provider already registered: %s", provider_id); 1540 goto fail; 1541 } 1542 if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) { 1543 error("provider %s is not a PKCS11 library", provider_id); 1544 goto fail; 1545 } 1546 /* open shared pkcs11-library */ 1547 if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) { 1548 error("dlopen %s failed: %s", provider_id, dlerror()); 1549 goto fail; 1550 } 1551 if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) 1552 fatal("dlsym(C_GetFunctionList) failed: %s", dlerror()); 1553 p = xcalloc(1, sizeof(*p)); 1554 p->name = xstrdup(provider_id); 1555 p->handle = handle; 1556 /* setup the pkcs11 callbacks */ 1557 if ((rv = (*getfunctionlist)(&f)) != CKR_OK) { 1558 error("C_GetFunctionList for provider %s failed: %lu", 1559 provider_id, rv); 1560 goto fail; 1561 } 1562 p->function_list = f; 1563 if ((rv = f->C_Initialize(NULL)) != CKR_OK) { 1564 error("C_Initialize for provider %s failed: %lu", 1565 provider_id, rv); 1566 goto fail; 1567 } 1568 need_finalize = 1; 1569 if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) { 1570 error("C_GetInfo for provider %s failed: %lu", 1571 provider_id, rv); 1572 goto fail; 1573 } 1574 debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d" 1575 " libraryDescription <%.*s> libraryVersion %d.%d", 1576 provider_id, 1577 RMSPACE(p->info.manufacturerID), 1578 p->info.cryptokiVersion.major, 1579 p->info.cryptokiVersion.minor, 1580 RMSPACE(p->info.libraryDescription), 1581 p->info.libraryVersion.major, 1582 p->info.libraryVersion.minor); 1583 if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { 1584 error("C_GetSlotList failed: %lu", rv); 1585 goto fail; 1586 } 1587 if (p->nslots == 0) { 1588 debug_f("provider %s returned no slots", provider_id); 1589 ret = -SSH_PKCS11_ERR_NO_SLOTS; 1590 goto fail; 1591 } 1592 p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID)); 1593 if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots)) 1594 != CKR_OK) { 1595 error("C_GetSlotList for provider %s failed: %lu", 1596 provider_id, rv); 1597 goto fail; 1598 } 1599 p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo)); 1600 p->valid = 1; 1601 nkeys = 0; 1602 for (i = 0; i < p->nslots; i++) { 1603 token = &p->slotinfo[i].token; 1604 if ((rv = f->C_GetTokenInfo(p->slotlist[i], token)) 1605 != CKR_OK) { 1606 error("C_GetTokenInfo for provider %s slot %lu " 1607 "failed: %lu", provider_id, (u_long)i, rv); 1608 continue; 1609 } 1610 if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { 1611 debug2_f("ignoring uninitialised token in " 1612 "provider %s slot %lu", provider_id, (u_long)i); 1613 continue; 1614 } 1615 debug("provider %s slot %lu: label <%.*s> " 1616 "manufacturerID <%.*s> model <%.*s> serial <%.*s> " 1617 "flags 0x%lx", 1618 provider_id, (unsigned long)i, 1619 RMSPACE(token->label), RMSPACE(token->manufacturerID), 1620 RMSPACE(token->model), RMSPACE(token->serialNumber), 1621 token->flags); 1622 /* 1623 * open session, login with pin and retrieve public 1624 * keys (if keyp is provided) 1625 */ 1626 if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || 1627 keyp == NULL) 1628 continue; 1629 pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); 1630 pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); 1631 if (nkeys == 0 && !p->slotinfo[i].logged_in && 1632 pkcs11_interactive) { 1633 /* 1634 * Some tokens require login before they will 1635 * expose keys. 1636 */ 1637 if (pkcs11_login_slot(p, &p->slotinfo[i], 1638 CKU_USER) < 0) { 1639 error("login failed"); 1640 continue; 1641 } 1642 pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); 1643 pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); 1644 } 1645 } 1646 1647 /* now owned by caller */ 1648 *providerp = p; 1649 1650 TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); 1651 p->refcount++; /* add to provider list */ 1652 1653 return (nkeys); 1654 fail: 1655 if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) 1656 error("C_Finalize for provider %s failed: %lu", 1657 provider_id, rv); 1658 if (p) { 1659 free(p->name); 1660 free(p->slotlist); 1661 free(p->slotinfo); 1662 free(p); 1663 } 1664 if (handle) 1665 dlclose(handle); 1666 if (ret > 0) 1667 ret = -1; 1668 return (ret); 1669 } 1670 1671 /* 1672 * register a new provider and get number of keys hold by the token, 1673 * fails if provider already exists 1674 */ 1675 int 1676 pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, 1677 char ***labelsp) 1678 { 1679 struct pkcs11_provider *p = NULL; 1680 int nkeys; 1681 1682 nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp, 1683 &p, CKU_USER); 1684 1685 /* no keys found or some other error, de-register provider */ 1686 if (nkeys <= 0 && p != NULL) { 1687 TAILQ_REMOVE(&pkcs11_providers, p, next); 1688 pkcs11_provider_finalize(p); 1689 pkcs11_provider_unref(p); 1690 } 1691 if (nkeys == 0) 1692 debug_f("provider %s returned no keys", provider_id); 1693 1694 return (nkeys); 1695 } 1696 1697 #ifdef WITH_PKCS11_KEYGEN 1698 struct sshkey * 1699 pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label, 1700 unsigned int type, unsigned int bits, unsigned char keyid, u_int32_t *err) 1701 { 1702 struct pkcs11_provider *p = NULL; 1703 struct pkcs11_slotinfo *si; 1704 CK_FUNCTION_LIST *f; 1705 CK_SESSION_HANDLE session; 1706 struct sshkey *k = NULL; 1707 int ret = -1, reset_pin = 0, reset_provider = 0; 1708 CK_RV rv; 1709 1710 *err = 0; 1711 1712 if ((p = pkcs11_provider_lookup(provider_id)) != NULL) 1713 debug_f("provider \"%s\" available", provider_id); 1714 else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL, 1715 &p, CKU_SO)) < 0) { 1716 debug_f("could not register provider %s", provider_id); 1717 goto out; 1718 } else 1719 reset_provider = 1; 1720 1721 f = p->function_list; 1722 si = &p->slotinfo[slotidx]; 1723 session = si->session; 1724 1725 if ((rv = f->C_SetOperationState(session , pin, strlen(pin), 1726 CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) { 1727 debug_f("could not supply SO pin: %lu", rv); 1728 reset_pin = 0; 1729 } else 1730 reset_pin = 1; 1731 1732 switch (type) { 1733 case KEY_RSA: 1734 if ((k = pkcs11_rsa_generate_private_key(p, slotidx, label, 1735 bits, keyid, err)) == NULL) { 1736 debug_f("failed to generate RSA key"); 1737 goto out; 1738 } 1739 break; 1740 case KEY_ECDSA: 1741 if ((k = pkcs11_ecdsa_generate_private_key(p, slotidx, label, 1742 bits, keyid, err)) == NULL) { 1743 debug_f("failed to generate ECDSA key"); 1744 goto out; 1745 } 1746 break; 1747 default: 1748 *err = SSH_PKCS11_ERR_GENERIC; 1749 debug_f("unknown type %d", type); 1750 goto out; 1751 } 1752 1753 out: 1754 if (reset_pin) 1755 f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE, 1756 CK_INVALID_HANDLE); 1757 1758 if (reset_provider) 1759 pkcs11_del_provider(provider_id); 1760 1761 return (k); 1762 } 1763 1764 struct sshkey * 1765 pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx, 1766 unsigned char keyid, u_int32_t *err) 1767 { 1768 struct pkcs11_provider *p = NULL; 1769 struct pkcs11_slotinfo *si; 1770 struct sshkey *k = NULL; 1771 int reset_pin = 0, reset_provider = 0; 1772 CK_ULONG nattrs; 1773 CK_FUNCTION_LIST *f; 1774 CK_SESSION_HANDLE session; 1775 CK_ATTRIBUTE attrs[16]; 1776 CK_OBJECT_CLASS key_class; 1777 CK_KEY_TYPE key_type; 1778 CK_OBJECT_HANDLE obj = CK_INVALID_HANDLE; 1779 CK_RV rv; 1780 1781 *err = 0; 1782 1783 if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { 1784 debug_f("using provider \"%s\"", provider_id); 1785 } else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p, 1786 CKU_SO) < 0) { 1787 debug_f("could not register provider %s", 1788 provider_id); 1789 goto out; 1790 } else 1791 reset_provider = 1; 1792 1793 f = p->function_list; 1794 si = &p->slotinfo[slotidx]; 1795 session = si->session; 1796 1797 if ((rv = f->C_SetOperationState(session , pin, strlen(pin), 1798 CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) { 1799 debug_f("could not supply SO pin: %lu", rv); 1800 reset_pin = 0; 1801 } else 1802 reset_pin = 1; 1803 1804 /* private key */ 1805 nattrs = 0; 1806 key_class = CKO_PRIVATE_KEY; 1807 FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class)); 1808 FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid)); 1809 1810 if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 && 1811 obj != CK_INVALID_HANDLE) { 1812 if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) { 1813 debug_f("could not destroy private key 0x%hhx", 1814 keyid); 1815 *err = rv; 1816 goto out; 1817 } 1818 } 1819 1820 /* public key */ 1821 nattrs = 0; 1822 key_class = CKO_PUBLIC_KEY; 1823 FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class)); 1824 FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid)); 1825 1826 if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 && 1827 obj != CK_INVALID_HANDLE) { 1828 1829 /* get key type */ 1830 nattrs = 0; 1831 FILL_ATTR(attrs, nattrs, CKA_KEY_TYPE, &key_type, 1832 sizeof(key_type)); 1833 rv = f->C_GetAttributeValue(session, obj, attrs, nattrs); 1834 if (rv != CKR_OK) { 1835 debug_f("could not get key type of public key 0x%hhx", 1836 keyid); 1837 *err = rv; 1838 key_type = -1; 1839 } 1840 if (key_type == CKK_RSA) 1841 k = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); 1842 else if (key_type == CKK_ECDSA) 1843 k = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj); 1844 1845 if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) { 1846 debug_f("could not destroy public key 0x%hhx", keyid); 1847 *err = rv; 1848 goto out; 1849 } 1850 } 1851 1852 out: 1853 if (reset_pin) 1854 f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE, 1855 CK_INVALID_HANDLE); 1856 1857 if (reset_provider) 1858 pkcs11_del_provider(provider_id); 1859 1860 return (k); 1861 } 1862 #endif /* WITH_PKCS11_KEYGEN */ 1863 #else 1864 int 1865 pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, 1866 char ***labelsp) 1867 { 1868 error("dlopen() not supported"); 1869 return (-1); 1870 } 1871 #endif /* HAVE_DLOPEN */ 1872