1 /* $OpenBSD: ssh-pkcs11.c,v 1.43 2019/03/08 17:24:43 markus 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 char prompt[1024], *xpin = NULL; 618 619 f = p->function_list; 620 si = &p->slotinfo[slotidx]; 621 622 have_pinpad = si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH; 623 login_required = si->token.flags & CKF_LOGIN_REQUIRED; 624 625 /* fail early before opening session */ 626 if (login_required && !have_pinpad && !pkcs11_interactive && 627 (pin == NULL || strlen(pin) == 0)) { 628 error("pin required"); 629 return (-SSH_PKCS11_ERR_PIN_REQUIRED); 630 } 631 if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| 632 CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) { 633 error("C_OpenSession failed: %lu", rv); 634 return (-1); 635 } 636 if (login_required) { 637 if (have_pinpad && (pin == NULL || strlen(pin) == 0)) { 638 /* defer PIN entry to the reader keypad */ 639 rv = f->C_Login(session, CKU_USER, NULL_PTR, 0); 640 } else { 641 if (pkcs11_interactive) { 642 snprintf(prompt, sizeof(prompt), 643 "Enter PIN for '%s': ", si->token.label); 644 if ((xpin = read_passphrase(prompt, 645 RP_ALLOW_EOF)) == NULL) { 646 debug("%s: no pin specified", 647 __func__); 648 return (-SSH_PKCS11_ERR_PIN_REQUIRED); 649 } 650 pin = xpin; 651 } 652 rv = f->C_Login(session, CKU_USER, 653 (u_char *)pin, strlen(pin)); 654 if (xpin != NULL) 655 freezero(xpin, strlen(xpin)); 656 } 657 if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { 658 error("C_Login failed: %lu", rv); 659 ret = (rv == CKR_PIN_LOCKED) ? 660 -SSH_PKCS11_ERR_PIN_LOCKED : 661 -SSH_PKCS11_ERR_LOGIN_FAIL; 662 if ((rv = f->C_CloseSession(session)) != CKR_OK) 663 error("C_CloseSession failed: %lu", rv); 664 return (ret); 665 } 666 si->logged_in = 1; 667 } 668 si->session = session; 669 return (0); 670 } 671 672 static int 673 pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key) 674 { 675 int i; 676 677 for (i = 0; i < *nkeys; i++) 678 if (sshkey_equal(key, (*keysp)[i])) 679 return (1); 680 return (0); 681 } 682 683 static struct sshkey * 684 pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, 685 CK_OBJECT_HANDLE *obj) 686 { 687 CK_ATTRIBUTE key_attr[3]; 688 CK_SESSION_HANDLE session; 689 CK_FUNCTION_LIST *f = NULL; 690 CK_RV rv; 691 ASN1_OCTET_STRING *octet = NULL; 692 EC_KEY *ec = NULL; 693 EC_GROUP *group = NULL; 694 struct sshkey *key = NULL; 695 const unsigned char *attrp = NULL; 696 int i; 697 int nid; 698 699 memset(&key_attr, 0, sizeof(key_attr)); 700 key_attr[0].type = CKA_ID; 701 key_attr[1].type = CKA_EC_POINT; 702 key_attr[2].type = CKA_EC_PARAMS; 703 704 session = p->slotinfo[slotidx].session; 705 f = p->function_list; 706 707 /* figure out size of the attributes */ 708 rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); 709 if (rv != CKR_OK) { 710 error("C_GetAttributeValue failed: %lu", rv); 711 return (NULL); 712 } 713 714 /* 715 * Allow CKA_ID (always first attribute) to be empty, but 716 * ensure that none of the others are zero length. 717 * XXX assumes CKA_ID is always first. 718 */ 719 if (key_attr[1].ulValueLen == 0 || 720 key_attr[2].ulValueLen == 0) { 721 error("invalid attribute length"); 722 return (NULL); 723 } 724 725 /* allocate buffers for attributes */ 726 for (i = 0; i < 3; i++) 727 if (key_attr[i].ulValueLen > 0) 728 key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); 729 730 /* retrieve ID, public point and curve parameters of EC key */ 731 rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); 732 if (rv != CKR_OK) { 733 error("C_GetAttributeValue failed: %lu", rv); 734 goto fail; 735 } 736 737 ec = EC_KEY_new(); 738 if (ec == NULL) { 739 error("EC_KEY_new failed"); 740 goto fail; 741 } 742 743 attrp = key_attr[2].pValue; 744 group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen); 745 if (group == NULL) { 746 ossl_error("d2i_ECPKParameters failed"); 747 goto fail; 748 } 749 750 if (EC_KEY_set_group(ec, group) == 0) { 751 ossl_error("EC_KEY_set_group failed"); 752 goto fail; 753 } 754 755 if (key_attr[1].ulValueLen <= 2) { 756 error("CKA_EC_POINT too small"); 757 goto fail; 758 } 759 760 attrp = key_attr[1].pValue; 761 octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen); 762 if (octet == NULL) { 763 ossl_error("d2i_ASN1_OCTET_STRING failed"); 764 goto fail; 765 } 766 attrp = octet->data; 767 if (o2i_ECPublicKey(&ec, &attrp, octet->length) == NULL) { 768 ossl_error("o2i_ECPublicKey failed"); 769 goto fail; 770 } 771 772 nid = sshkey_ecdsa_key_to_nid(ec); 773 if (nid < 0) { 774 error("couldn't get curve nid"); 775 goto fail; 776 } 777 778 if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec)) 779 goto fail; 780 781 key = sshkey_new(KEY_UNSPEC); 782 if (key == NULL) { 783 error("sshkey_new failed"); 784 goto fail; 785 } 786 787 key->ecdsa = ec; 788 key->ecdsa_nid = nid; 789 key->type = KEY_ECDSA; 790 key->flags |= SSHKEY_FLAG_EXT; 791 ec = NULL; /* now owned by key */ 792 793 fail: 794 for (i = 0; i < 3; i++) 795 free(key_attr[i].pValue); 796 if (ec) 797 EC_KEY_free(ec); 798 if (group) 799 EC_GROUP_free(group); 800 if (octet) 801 ASN1_OCTET_STRING_free(octet); 802 803 return (key); 804 } 805 806 static struct sshkey * 807 pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, 808 CK_OBJECT_HANDLE *obj) 809 { 810 CK_ATTRIBUTE key_attr[3]; 811 CK_SESSION_HANDLE session; 812 CK_FUNCTION_LIST *f = NULL; 813 CK_RV rv; 814 RSA *rsa = NULL; 815 BIGNUM *rsa_n, *rsa_e; 816 struct sshkey *key = NULL; 817 int i; 818 819 memset(&key_attr, 0, sizeof(key_attr)); 820 key_attr[0].type = CKA_ID; 821 key_attr[1].type = CKA_MODULUS; 822 key_attr[2].type = CKA_PUBLIC_EXPONENT; 823 824 session = p->slotinfo[slotidx].session; 825 f = p->function_list; 826 827 /* figure out size of the attributes */ 828 rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); 829 if (rv != CKR_OK) { 830 error("C_GetAttributeValue failed: %lu", rv); 831 return (NULL); 832 } 833 834 /* 835 * Allow CKA_ID (always first attribute) to be empty, but 836 * ensure that none of the others are zero length. 837 * XXX assumes CKA_ID is always first. 838 */ 839 if (key_attr[1].ulValueLen == 0 || 840 key_attr[2].ulValueLen == 0) { 841 error("invalid attribute length"); 842 return (NULL); 843 } 844 845 /* allocate buffers for attributes */ 846 for (i = 0; i < 3; i++) 847 if (key_attr[i].ulValueLen > 0) 848 key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); 849 850 /* retrieve ID, modulus and public exponent of RSA key */ 851 rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); 852 if (rv != CKR_OK) { 853 error("C_GetAttributeValue failed: %lu", rv); 854 goto fail; 855 } 856 857 rsa = RSA_new(); 858 if (rsa == NULL) { 859 error("RSA_new failed"); 860 goto fail; 861 } 862 863 rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL); 864 rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); 865 if (rsa_n == NULL || rsa_e == NULL) { 866 error("BN_bin2bn failed"); 867 goto fail; 868 } 869 if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) 870 fatal("%s: set key", __func__); 871 rsa_n = rsa_e = NULL; /* transferred */ 872 873 if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) 874 goto fail; 875 876 key = sshkey_new(KEY_UNSPEC); 877 if (key == NULL) { 878 error("sshkey_new failed"); 879 goto fail; 880 } 881 882 key->rsa = rsa; 883 key->type = KEY_RSA; 884 key->flags |= SSHKEY_FLAG_EXT; 885 rsa = NULL; /* now owned by key */ 886 887 fail: 888 for (i = 0; i < 3; i++) 889 free(key_attr[i].pValue); 890 RSA_free(rsa); 891 892 return (key); 893 } 894 895 static struct sshkey * 896 pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, 897 CK_OBJECT_HANDLE *obj) 898 { 899 CK_ATTRIBUTE cert_attr[3]; 900 CK_SESSION_HANDLE session; 901 CK_FUNCTION_LIST *f = NULL; 902 CK_RV rv; 903 X509 *x509 = NULL; 904 EVP_PKEY *evp; 905 RSA *rsa = NULL; 906 EC_KEY *ec = NULL; 907 struct sshkey *key = NULL; 908 int i; 909 int nid; 910 const u_char *cp; 911 912 memset(&cert_attr, 0, sizeof(cert_attr)); 913 cert_attr[0].type = CKA_ID; 914 cert_attr[1].type = CKA_SUBJECT; 915 cert_attr[2].type = CKA_VALUE; 916 917 session = p->slotinfo[slotidx].session; 918 f = p->function_list; 919 920 /* figure out size of the attributes */ 921 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); 922 if (rv != CKR_OK) { 923 error("C_GetAttributeValue failed: %lu", rv); 924 return (NULL); 925 } 926 927 /* 928 * Allow CKA_ID (always first attribute) to be empty, but 929 * ensure that none of the others are zero length. 930 * XXX assumes CKA_ID is always first. 931 */ 932 if (cert_attr[1].ulValueLen == 0 || 933 cert_attr[2].ulValueLen == 0) { 934 error("invalid attribute length"); 935 return (NULL); 936 } 937 938 /* allocate buffers for attributes */ 939 for (i = 0; i < 3; i++) 940 if (cert_attr[i].ulValueLen > 0) 941 cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen); 942 943 /* retrieve ID, subject and value of certificate */ 944 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); 945 if (rv != CKR_OK) { 946 error("C_GetAttributeValue failed: %lu", rv); 947 goto fail; 948 } 949 950 x509 = X509_new(); 951 if (x509 == NULL) { 952 error("x509_new failed"); 953 goto fail; 954 } 955 956 cp = cert_attr[2].pValue; 957 if (d2i_X509(&x509, &cp, cert_attr[2].ulValueLen) == NULL) { 958 error("d2i_x509 failed"); 959 goto fail; 960 } 961 962 evp = X509_get_pubkey(x509); 963 if (evp == NULL) { 964 error("X509_get_pubkey failed"); 965 goto fail; 966 } 967 968 if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) { 969 if (EVP_PKEY_get0_RSA(evp) == NULL) { 970 error("invalid x509; no rsa key"); 971 goto fail; 972 } 973 if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) { 974 error("RSAPublicKey_dup failed"); 975 goto fail; 976 } 977 978 if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) 979 goto fail; 980 981 key = sshkey_new(KEY_UNSPEC); 982 if (key == NULL) { 983 error("sshkey_new failed"); 984 goto fail; 985 } 986 987 key->rsa = rsa; 988 key->type = KEY_RSA; 989 key->flags |= SSHKEY_FLAG_EXT; 990 rsa = NULL; /* now owned by key */ 991 } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) { 992 if (EVP_PKEY_get0_EC_KEY(evp) == NULL) { 993 error("invalid x509; no ec key"); 994 goto fail; 995 } 996 if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) { 997 error("EC_KEY_dup failed"); 998 goto fail; 999 } 1000 1001 nid = sshkey_ecdsa_key_to_nid(ec); 1002 if (nid < 0) { 1003 error("couldn't get curve nid"); 1004 goto fail; 1005 } 1006 1007 if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) 1008 goto fail; 1009 1010 key = sshkey_new(KEY_UNSPEC); 1011 if (key == NULL) { 1012 error("sshkey_new failed"); 1013 goto fail; 1014 } 1015 1016 key->ecdsa = ec; 1017 key->ecdsa_nid = nid; 1018 key->type = KEY_ECDSA; 1019 key->flags |= SSHKEY_FLAG_EXT; 1020 ec = NULL; /* now owned by key */ 1021 } else 1022 error("unknown certificate key type"); 1023 1024 fail: 1025 for (i = 0; i < 3; i++) 1026 free(cert_attr[i].pValue); 1027 X509_free(x509); 1028 RSA_free(rsa); 1029 EC_KEY_free(ec); 1030 1031 return (key); 1032 } 1033 1034 #if 0 1035 static int 1036 have_rsa_key(const RSA *rsa) 1037 { 1038 const BIGNUM *rsa_n, *rsa_e; 1039 1040 RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL); 1041 return rsa_n != NULL && rsa_e != NULL; 1042 } 1043 #endif 1044 1045 /* 1046 * lookup certificates for token in slot identified by slotidx, 1047 * add 'wrapped' public keys to the 'keysp' array and increment nkeys. 1048 * keysp points to an (possibly empty) array with *nkeys keys. 1049 */ 1050 static int 1051 pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, 1052 struct sshkey ***keysp, int *nkeys) 1053 { 1054 struct sshkey *key = NULL; 1055 CK_OBJECT_CLASS key_class; 1056 CK_ATTRIBUTE key_attr[1]; 1057 CK_SESSION_HANDLE session; 1058 CK_FUNCTION_LIST *f = NULL; 1059 CK_RV rv; 1060 CK_OBJECT_HANDLE obj; 1061 CK_ULONG n = 0; 1062 int ret = -1; 1063 1064 memset(&key_attr, 0, sizeof(key_attr)); 1065 memset(&obj, 0, sizeof(obj)); 1066 1067 key_class = CKO_CERTIFICATE; 1068 key_attr[0].type = CKA_CLASS; 1069 key_attr[0].pValue = &key_class; 1070 key_attr[0].ulValueLen = sizeof(key_class); 1071 1072 session = p->slotinfo[slotidx].session; 1073 f = p->function_list; 1074 1075 rv = f->C_FindObjectsInit(session, key_attr, 1); 1076 if (rv != CKR_OK) { 1077 error("C_FindObjectsInit failed: %lu", rv); 1078 goto fail; 1079 } 1080 1081 while (1) { 1082 CK_CERTIFICATE_TYPE ck_cert_type; 1083 1084 rv = f->C_FindObjects(session, &obj, 1, &n); 1085 if (rv != CKR_OK) { 1086 error("C_FindObjects failed: %lu", rv); 1087 goto fail; 1088 } 1089 if (n == 0) 1090 break; 1091 1092 memset(&ck_cert_type, 0, sizeof(ck_cert_type)); 1093 memset(&key_attr, 0, sizeof(key_attr)); 1094 key_attr[0].type = CKA_CERTIFICATE_TYPE; 1095 key_attr[0].pValue = &ck_cert_type; 1096 key_attr[0].ulValueLen = sizeof(ck_cert_type); 1097 1098 rv = f->C_GetAttributeValue(session, obj, key_attr, 1); 1099 if (rv != CKR_OK) { 1100 error("C_GetAttributeValue failed: %lu", rv); 1101 goto fail; 1102 } 1103 1104 switch (ck_cert_type) { 1105 case CKC_X_509: 1106 key = pkcs11_fetch_x509_pubkey(p, slotidx, &obj); 1107 break; 1108 default: 1109 /* XXX print key type? */ 1110 key = NULL; 1111 error("skipping unsupported certificate type"); 1112 } 1113 1114 if (key == NULL) { 1115 error("failed to fetch key"); 1116 continue; 1117 } 1118 1119 if (pkcs11_key_included(keysp, nkeys, key)) { 1120 sshkey_free(key); 1121 } else { 1122 /* expand key array and add key */ 1123 *keysp = xrecallocarray(*keysp, *nkeys, 1124 *nkeys + 1, sizeof(struct sshkey *)); 1125 (*keysp)[*nkeys] = key; 1126 *nkeys = *nkeys + 1; 1127 debug("have %d keys", *nkeys); 1128 } 1129 } 1130 1131 ret = 0; 1132 fail: 1133 rv = f->C_FindObjectsFinal(session); 1134 if (rv != CKR_OK) { 1135 error("C_FindObjectsFinal failed: %lu", rv); 1136 ret = -1; 1137 } 1138 1139 return (ret); 1140 } 1141 1142 /* 1143 * lookup public keys for token in slot identified by slotidx, 1144 * add 'wrapped' public keys to the 'keysp' array and increment nkeys. 1145 * keysp points to an (possibly empty) array with *nkeys keys. 1146 */ 1147 static int 1148 pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, 1149 struct sshkey ***keysp, int *nkeys) 1150 { 1151 struct sshkey *key = NULL; 1152 CK_OBJECT_CLASS key_class; 1153 CK_ATTRIBUTE key_attr[1]; 1154 CK_SESSION_HANDLE session; 1155 CK_FUNCTION_LIST *f = NULL; 1156 CK_RV rv; 1157 CK_OBJECT_HANDLE obj; 1158 CK_ULONG n = 0; 1159 int ret = -1; 1160 1161 memset(&key_attr, 0, sizeof(key_attr)); 1162 memset(&obj, 0, sizeof(obj)); 1163 1164 key_class = CKO_PUBLIC_KEY; 1165 key_attr[0].type = CKA_CLASS; 1166 key_attr[0].pValue = &key_class; 1167 key_attr[0].ulValueLen = sizeof(key_class); 1168 1169 session = p->slotinfo[slotidx].session; 1170 f = p->function_list; 1171 1172 rv = f->C_FindObjectsInit(session, key_attr, 1); 1173 if (rv != CKR_OK) { 1174 error("C_FindObjectsInit failed: %lu", rv); 1175 goto fail; 1176 } 1177 1178 while (1) { 1179 CK_KEY_TYPE ck_key_type; 1180 1181 rv = f->C_FindObjects(session, &obj, 1, &n); 1182 if (rv != CKR_OK) { 1183 error("C_FindObjects failed: %lu", rv); 1184 goto fail; 1185 } 1186 if (n == 0) 1187 break; 1188 1189 memset(&ck_key_type, 0, sizeof(ck_key_type)); 1190 memset(&key_attr, 0, sizeof(key_attr)); 1191 key_attr[0].type = CKA_KEY_TYPE; 1192 key_attr[0].pValue = &ck_key_type; 1193 key_attr[0].ulValueLen = sizeof(ck_key_type); 1194 1195 rv = f->C_GetAttributeValue(session, obj, key_attr, 1); 1196 if (rv != CKR_OK) { 1197 error("C_GetAttributeValue failed: %lu", rv); 1198 goto fail; 1199 } 1200 1201 switch (ck_key_type) { 1202 case CKK_RSA: 1203 key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); 1204 break; 1205 case CKK_ECDSA: 1206 key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj); 1207 break; 1208 default: 1209 /* XXX print key type? */ 1210 key = NULL; 1211 error("skipping unsupported key type"); 1212 } 1213 1214 if (key == NULL) { 1215 error("failed to fetch key"); 1216 continue; 1217 } 1218 1219 if (pkcs11_key_included(keysp, nkeys, key)) { 1220 sshkey_free(key); 1221 } else { 1222 /* expand key array and add key */ 1223 *keysp = xrecallocarray(*keysp, *nkeys, 1224 *nkeys + 1, sizeof(struct sshkey *)); 1225 (*keysp)[*nkeys] = key; 1226 *nkeys = *nkeys + 1; 1227 debug("have %d keys", *nkeys); 1228 } 1229 } 1230 1231 ret = 0; 1232 fail: 1233 rv = f->C_FindObjectsFinal(session); 1234 if (rv != CKR_OK) { 1235 error("C_FindObjectsFinal failed: %lu", rv); 1236 ret = -1; 1237 } 1238 1239 return (ret); 1240 } 1241 1242 #ifdef WITH_PKCS11_KEYGEN 1243 #define FILL_ATTR(attr, idx, typ, val, len) \ 1244 { (attr[idx]).type=(typ); (attr[idx]).pValue=(val); (attr[idx]).ulValueLen=len; idx++; } 1245 1246 static struct sshkey * 1247 pkcs11_rsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, 1248 char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err) 1249 { 1250 struct pkcs11_slotinfo *si; 1251 char *plabel = label ? label : ""; 1252 int npub = 0, npriv = 0; 1253 CK_RV rv; 1254 CK_FUNCTION_LIST *f; 1255 CK_SESSION_HANDLE session; 1256 CK_BBOOL true_val = CK_TRUE, false_val = CK_FALSE; 1257 CK_OBJECT_HANDLE pubKey, privKey; 1258 CK_ATTRIBUTE tpub[16], tpriv[16]; 1259 CK_MECHANISM mech = { 1260 CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 1261 }; 1262 CK_BYTE pubExponent[] = { 1263 0x01, 0x00, 0x01 /* RSA_F4 in bytes */ 1264 }; 1265 1266 *err = 0; 1267 1268 FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val)); 1269 FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel)); 1270 FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val)); 1271 FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val)); 1272 FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val, 1273 sizeof(false_val)); 1274 FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val)); 1275 FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val)); 1276 FILL_ATTR(tpub, npub, CKA_MODULUS_BITS, &bits, sizeof(bits)); 1277 FILL_ATTR(tpub, npub, CKA_PUBLIC_EXPONENT, pubExponent, 1278 sizeof(pubExponent)); 1279 FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid)); 1280 1281 FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val)); 1282 FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel)); 1283 FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val)); 1284 FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val)); 1285 FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val)); 1286 FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val)); 1287 FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val, 1288 sizeof(false_val)); 1289 FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val)); 1290 FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val)); 1291 FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid)); 1292 1293 f = p->function_list; 1294 si = &p->slotinfo[slotidx]; 1295 session = si->session; 1296 1297 if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv, 1298 &pubKey, &privKey)) != CKR_OK) { 1299 error("%s: key generation failed: error 0x%lx", __func__, rv); 1300 *err = rv; 1301 return NULL; 1302 } 1303 1304 return pkcs11_fetch_rsa_pubkey(p, slotidx, &pubKey); 1305 } 1306 1307 static int 1308 pkcs11_decode_hex(const char *hex, unsigned char **dest, size_t *rlen) 1309 { 1310 size_t i, len; 1311 char ptr[3]; 1312 1313 if (dest) 1314 *dest = NULL; 1315 if (rlen) 1316 *rlen = 0; 1317 1318 if ((len = strlen(hex)) % 2) 1319 return -1; 1320 len /= 2; 1321 1322 *dest = xmalloc(len); 1323 1324 ptr[2] = '\0'; 1325 for (i = 0; i < len; i++) { 1326 ptr[0] = hex[2 * i]; 1327 ptr[1] = hex[(2 * i) + 1]; 1328 if (!isxdigit(ptr[0]) || !isxdigit(ptr[1])) 1329 return -1; 1330 (*dest)[i] = (unsigned char)strtoul(ptr, NULL, 16); 1331 } 1332 1333 if (rlen) 1334 *rlen = len; 1335 1336 return 0; 1337 } 1338 1339 static struct ec_curve_info { 1340 const char *name; 1341 const char *oid; 1342 const char *oid_encoded; 1343 size_t size; 1344 } ec_curve_infos[] = { 1345 {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, 1346 {"secp384r1", "1.3.132.0.34", "06052B81040022", 384}, 1347 {"secp521r1", "1.3.132.0.35", "06052B81040023", 521}, 1348 {NULL, NULL, NULL, 0}, 1349 }; 1350 1351 static struct sshkey * 1352 pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, 1353 char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err) 1354 { 1355 struct pkcs11_slotinfo *si; 1356 char *plabel = label ? label : ""; 1357 int i; 1358 size_t ecparams_size; 1359 unsigned char *ecparams = NULL; 1360 int npub = 0, npriv = 0; 1361 CK_RV rv; 1362 CK_FUNCTION_LIST *f; 1363 CK_SESSION_HANDLE session; 1364 CK_BBOOL true_val = CK_TRUE, false_val = CK_FALSE; 1365 CK_OBJECT_HANDLE pubKey, privKey; 1366 CK_MECHANISM mech = { 1367 CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0 1368 }; 1369 CK_ATTRIBUTE tpub[16], tpriv[16]; 1370 1371 *err = 0; 1372 1373 for (i = 0; ec_curve_infos[i].name; i++) { 1374 if (ec_curve_infos[i].size == bits) 1375 break; 1376 } 1377 if (!ec_curve_infos[i].name) { 1378 error("%s: invalid key size %lu", __func__, bits); 1379 return NULL; 1380 } 1381 if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams, 1382 &ecparams_size) == -1) { 1383 error("%s: invalid oid", __func__); 1384 return NULL; 1385 } 1386 1387 FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val)); 1388 FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel)); 1389 FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val)); 1390 FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val)); 1391 FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val, 1392 sizeof(false_val)); 1393 FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val)); 1394 FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val)); 1395 FILL_ATTR(tpub, npub, CKA_EC_PARAMS, ecparams, ecparams_size); 1396 FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid)); 1397 1398 FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val)); 1399 FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel)); 1400 FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val)); 1401 FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val)); 1402 FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val)); 1403 FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val)); 1404 FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val, 1405 sizeof(false_val)); 1406 FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val)); 1407 FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val)); 1408 FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid)); 1409 1410 f = p->function_list; 1411 si = &p->slotinfo[slotidx]; 1412 session = si->session; 1413 1414 if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv, 1415 &pubKey, &privKey)) != CKR_OK) { 1416 error("%s: key generation failed: error 0x%lx", __func__, rv); 1417 *err = rv; 1418 return NULL; 1419 } 1420 1421 return pkcs11_fetch_ecdsa_pubkey(p, slotidx, &pubKey); 1422 } 1423 #endif /* WITH_PKCS11_KEYGEN */ 1424 1425 /* 1426 * register a new provider, fails if provider already exists. if 1427 * keyp is provided, fetch keys. 1428 */ 1429 static int 1430 pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, 1431 struct pkcs11_provider **providerp, CK_ULONG user) 1432 { 1433 int nkeys, need_finalize = 0; 1434 int ret = -1; 1435 struct pkcs11_provider *p = NULL; 1436 void *handle = NULL; 1437 CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **); 1438 CK_RV rv; 1439 CK_FUNCTION_LIST *f = NULL; 1440 CK_TOKEN_INFO *token; 1441 CK_ULONG i; 1442 1443 if (providerp == NULL) 1444 goto fail; 1445 *providerp = NULL; 1446 1447 if (keyp != NULL) 1448 *keyp = NULL; 1449 1450 if (pkcs11_provider_lookup(provider_id) != NULL) { 1451 debug("%s: provider already registered: %s", 1452 __func__, provider_id); 1453 goto fail; 1454 } 1455 /* open shared pkcs11-library */ 1456 if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) { 1457 error("dlopen %s failed: %s", provider_id, dlerror()); 1458 goto fail; 1459 } 1460 if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) { 1461 error("dlsym(C_GetFunctionList) failed: %s", dlerror()); 1462 goto fail; 1463 } 1464 p = xcalloc(1, sizeof(*p)); 1465 p->name = xstrdup(provider_id); 1466 p->handle = handle; 1467 /* setup the pkcs11 callbacks */ 1468 if ((rv = (*getfunctionlist)(&f)) != CKR_OK) { 1469 error("C_GetFunctionList for provider %s failed: %lu", 1470 provider_id, rv); 1471 goto fail; 1472 } 1473 p->function_list = f; 1474 if ((rv = f->C_Initialize(NULL)) != CKR_OK) { 1475 error("C_Initialize for provider %s failed: %lu", 1476 provider_id, rv); 1477 goto fail; 1478 } 1479 need_finalize = 1; 1480 if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) { 1481 error("C_GetInfo for provider %s failed: %lu", 1482 provider_id, rv); 1483 goto fail; 1484 } 1485 rmspace(p->info.manufacturerID, sizeof(p->info.manufacturerID)); 1486 rmspace(p->info.libraryDescription, sizeof(p->info.libraryDescription)); 1487 debug("provider %s: manufacturerID <%s> cryptokiVersion %d.%d" 1488 " libraryDescription <%s> libraryVersion %d.%d", 1489 provider_id, 1490 p->info.manufacturerID, 1491 p->info.cryptokiVersion.major, 1492 p->info.cryptokiVersion.minor, 1493 p->info.libraryDescription, 1494 p->info.libraryVersion.major, 1495 p->info.libraryVersion.minor); 1496 if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { 1497 error("C_GetSlotList failed: %lu", rv); 1498 goto fail; 1499 } 1500 if (p->nslots == 0) { 1501 error("%s: provider %s returned no slots", __func__, 1502 provider_id); 1503 ret = -SSH_PKCS11_ERR_NO_SLOTS; 1504 goto fail; 1505 } 1506 p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID)); 1507 if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots)) 1508 != CKR_OK) { 1509 error("C_GetSlotList for provider %s failed: %lu", 1510 provider_id, rv); 1511 goto fail; 1512 } 1513 p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo)); 1514 p->valid = 1; 1515 nkeys = 0; 1516 for (i = 0; i < p->nslots; i++) { 1517 token = &p->slotinfo[i].token; 1518 if ((rv = f->C_GetTokenInfo(p->slotlist[i], token)) 1519 != CKR_OK) { 1520 error("C_GetTokenInfo for provider %s slot %lu " 1521 "failed: %lu", provider_id, (unsigned long)i, rv); 1522 continue; 1523 } 1524 if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { 1525 debug2("%s: ignoring uninitialised token in " 1526 "provider %s slot %lu", __func__, 1527 provider_id, (unsigned long)i); 1528 continue; 1529 } 1530 rmspace(token->label, sizeof(token->label)); 1531 rmspace(token->manufacturerID, sizeof(token->manufacturerID)); 1532 rmspace(token->model, sizeof(token->model)); 1533 rmspace(token->serialNumber, sizeof(token->serialNumber)); 1534 debug("provider %s slot %lu: label <%s> manufacturerID <%s> " 1535 "model <%s> serial <%s> flags 0x%lx", 1536 provider_id, (unsigned long)i, 1537 token->label, token->manufacturerID, token->model, 1538 token->serialNumber, token->flags); 1539 /* 1540 * open session, login with pin and retrieve public 1541 * keys (if keyp is provided) 1542 */ 1543 if ((ret = pkcs11_open_session(p, i, pin, user)) == 0) { 1544 if (keyp == NULL) 1545 continue; 1546 pkcs11_fetch_keys(p, i, keyp, &nkeys); 1547 pkcs11_fetch_certs(p, i, keyp, &nkeys); 1548 } 1549 } 1550 1551 /* now owned by caller */ 1552 *providerp = p; 1553 1554 TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); 1555 p->refcount++; /* add to provider list */ 1556 1557 return (nkeys); 1558 fail: 1559 if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) 1560 error("C_Finalize for provider %s failed: %lu", 1561 provider_id, rv); 1562 if (p) { 1563 free(p->name); 1564 free(p->slotlist); 1565 free(p->slotinfo); 1566 free(p); 1567 } 1568 if (handle) 1569 dlclose(handle); 1570 return (ret); 1571 } 1572 1573 /* 1574 * register a new provider and get number of keys hold by the token, 1575 * fails if provider already exists 1576 */ 1577 int 1578 pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) 1579 { 1580 struct pkcs11_provider *p = NULL; 1581 int nkeys; 1582 1583 nkeys = pkcs11_register_provider(provider_id, pin, keyp, &p, CKU_USER); 1584 1585 /* no keys found or some other error, de-register provider */ 1586 if (nkeys <= 0 && p != NULL) { 1587 TAILQ_REMOVE(&pkcs11_providers, p, next); 1588 pkcs11_provider_finalize(p); 1589 pkcs11_provider_unref(p); 1590 } 1591 if (nkeys == 0) 1592 debug("%s: provider %s returned no keys", __func__, 1593 provider_id); 1594 1595 return (nkeys); 1596 } 1597 1598 #ifdef WITH_PKCS11_KEYGEN 1599 struct sshkey * 1600 pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label, 1601 unsigned int type, unsigned int bits, unsigned char keyid, u_int32_t *err) 1602 { 1603 struct pkcs11_provider *p = NULL; 1604 struct pkcs11_slotinfo *si; 1605 CK_FUNCTION_LIST *f; 1606 CK_SESSION_HANDLE session; 1607 struct sshkey *k = NULL; 1608 int ret = -1, reset_pin = 0, reset_provider = 0; 1609 CK_RV rv; 1610 1611 *err = 0; 1612 1613 if ((p = pkcs11_provider_lookup(provider_id)) != NULL) 1614 debug("%s: provider \"%s\" available", __func__, provider_id); 1615 else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, &p, 1616 CKU_SO)) < 0) { 1617 debug("%s: could not register provider %s", __func__, 1618 provider_id); 1619 goto out; 1620 } else 1621 reset_provider = 1; 1622 1623 f = p->function_list; 1624 si = &p->slotinfo[slotidx]; 1625 session = si->session; 1626 1627 if ((rv = f->C_SetOperationState(session , pin, strlen(pin), 1628 CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) { 1629 debug("%s: could not supply SO pin: %lu", __func__, rv); 1630 reset_pin = 0; 1631 } else 1632 reset_pin = 1; 1633 1634 switch (type) { 1635 case KEY_RSA: 1636 if ((k = pkcs11_rsa_generate_private_key(p, slotidx, label, 1637 bits, keyid, err)) == NULL) { 1638 debug("%s: failed to generate RSA key", __func__); 1639 goto out; 1640 } 1641 break; 1642 case KEY_ECDSA: 1643 if ((k = pkcs11_ecdsa_generate_private_key(p, slotidx, label, 1644 bits, keyid, err)) == NULL) { 1645 debug("%s: failed to generate ECDSA key", __func__); 1646 goto out; 1647 } 1648 break; 1649 default: 1650 *err = SSH_PKCS11_ERR_GENERIC; 1651 debug("%s: unknown type %d", __func__, type); 1652 goto out; 1653 } 1654 1655 out: 1656 if (reset_pin) 1657 f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE, 1658 CK_INVALID_HANDLE); 1659 1660 if (reset_provider) 1661 pkcs11_del_provider(provider_id); 1662 1663 return (k); 1664 } 1665 1666 struct sshkey * 1667 pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx, 1668 unsigned char keyid, u_int32_t *err) 1669 { 1670 struct pkcs11_provider *p = NULL; 1671 struct pkcs11_slotinfo *si; 1672 struct sshkey *k = NULL; 1673 int reset_pin = 0, reset_provider = 0; 1674 CK_ULONG nattrs; 1675 CK_FUNCTION_LIST *f; 1676 CK_SESSION_HANDLE session; 1677 CK_ATTRIBUTE attrs[16]; 1678 CK_OBJECT_CLASS key_class; 1679 CK_KEY_TYPE key_type; 1680 CK_OBJECT_HANDLE obj = CK_INVALID_HANDLE; 1681 CK_RV rv; 1682 1683 *err = 0; 1684 1685 if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { 1686 debug("%s: using provider \"%s\"", __func__, provider_id); 1687 } else if (pkcs11_register_provider(provider_id, pin, NULL, &p, 1688 CKU_SO) < 0) { 1689 debug("%s: could not register provider %s", __func__, 1690 provider_id); 1691 goto out; 1692 } else 1693 reset_provider = 1; 1694 1695 f = p->function_list; 1696 si = &p->slotinfo[slotidx]; 1697 session = si->session; 1698 1699 if ((rv = f->C_SetOperationState(session , pin, strlen(pin), 1700 CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) { 1701 debug("%s: could not supply SO pin: %lu", __func__, rv); 1702 reset_pin = 0; 1703 } else 1704 reset_pin = 1; 1705 1706 /* private key */ 1707 nattrs = 0; 1708 key_class = CKO_PRIVATE_KEY; 1709 FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class)); 1710 FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid)); 1711 1712 if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 && 1713 obj != CK_INVALID_HANDLE) { 1714 if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) { 1715 debug("%s: could not destroy private key 0x%hhx", 1716 __func__, keyid); 1717 *err = rv; 1718 goto out; 1719 } 1720 } 1721 1722 /* public key */ 1723 nattrs = 0; 1724 key_class = CKO_PUBLIC_KEY; 1725 FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class)); 1726 FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid)); 1727 1728 if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 && 1729 obj != CK_INVALID_HANDLE) { 1730 1731 /* get key type */ 1732 nattrs = 0; 1733 FILL_ATTR(attrs, nattrs, CKA_KEY_TYPE, &key_type, 1734 sizeof(key_type)); 1735 rv = f->C_GetAttributeValue(session, obj, attrs, nattrs); 1736 if (rv != CKR_OK) { 1737 debug("%s: could not get key type of public key 0x%hhx", 1738 __func__, keyid); 1739 *err = rv; 1740 key_type = -1; 1741 } 1742 if (key_type == CKK_RSA) 1743 k = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); 1744 else if (key_type == CKK_ECDSA) 1745 k = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj); 1746 1747 if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) { 1748 debug("%s: could not destroy public key 0x%hhx", 1749 __func__, keyid); 1750 *err = rv; 1751 goto out; 1752 } 1753 } 1754 1755 out: 1756 if (reset_pin) 1757 f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE, 1758 CK_INVALID_HANDLE); 1759 1760 if (reset_provider) 1761 pkcs11_del_provider(provider_id); 1762 1763 return (k); 1764 } 1765 #endif /* WITH_PKCS11_KEYGEN */ 1766 #else 1767 int 1768 pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) 1769 { 1770 error("dlopen() not supported"); 1771 return (-1); 1772 } 1773 #endif /* HAVE_DLOPEN */ 1774