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