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