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