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