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