1 /* $NetBSD: pk11.c,v 1.1.1.5 2015/07/08 15:38:05 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") 5 * 6 * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH 11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * Portions copyright (c) 2008 Nominet UK. All rights reserved. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the above copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 32 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 34 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 */ 42 43 /* 44 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 45 * Use is subject to license terms. 46 */ 47 48 /* 49 * This product includes software developed by the OpenSSL Project for 50 * use in the OpenSSL Toolkit (http://www.openssl.org/). 51 * 52 * This project also referenced hw_pkcs11-0.9.7b.patch written by 53 * Afchine Madjlessi. 54 */ 55 /* 56 * ==================================================================== 57 * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. 58 * 59 * Redistribution and use in source and binary forms, with or without 60 * modification, are permitted provided that the following conditions 61 * are met: 62 * 63 * 1. Redistributions of source code must retain the above copyright 64 * notice, this list of conditions and the following disclaimer. 65 * 66 * 2. Redistributions in binary form must reproduce the above copyright 67 * notice, this list of conditions and the following disclaimer in 68 * the documentation and/or other materials provided with the 69 * distribution. 70 * 71 * 3. All advertising materials mentioning features or use of this 72 * software must display the following acknowledgment: 73 * "This product includes software developed by the OpenSSL Project 74 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 75 * 76 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 77 * endorse or promote products derived from this software without 78 * prior written permission. For written permission, please contact 79 * licensing@OpenSSL.org. 80 * 81 * 5. Products derived from this software may not be called "OpenSSL" 82 * nor may "OpenSSL" appear in their names without prior written 83 * permission of the OpenSSL Project. 84 * 85 * 6. Redistributions of any form whatsoever must retain the following 86 * acknowledgment: 87 * "This product includes software developed by the OpenSSL Project 88 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 89 * 90 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 91 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 92 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 93 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 94 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 95 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 96 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 97 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 98 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 99 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 100 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 101 * OF THE POSSIBILITY OF SUCH DAMAGE. 102 * ==================================================================== 103 * 104 * This product includes cryptographic software written by Eric Young 105 * (eay@cryptsoft.com). This product includes software written by Tim 106 * Hudson (tjh@cryptsoft.com). 107 * 108 */ 109 110 /* Id */ 111 112 #include <config.h> 113 114 #include <stdio.h> 115 #include <stdlib.h> 116 #include <string.h> 117 118 #include <isc/log.h> 119 #include <isc/mem.h> 120 #include <isc/once.h> 121 #include <isc/platform.h> 122 #include <isc/stdio.h> 123 #include <isc/thread.h> 124 #include <isc/util.h> 125 126 #include <dst/result.h> 127 128 #include <pk11/pk11.h> 129 #include <pk11/internal.h> 130 #include <pk11/result.h> 131 132 #include <pkcs11/cryptoki.h> 133 #include <pkcs11/pkcs11.h> 134 135 /* was 32 octets, Petr Spacek suggested 1024, SoftHSMv2 uses 256... */ 136 #ifndef PINLEN 137 #define PINLEN 256 138 #endif 139 140 #ifndef PK11_NO_LOGERR 141 #define PK11_NO_LOGERR 1 142 #endif 143 144 static isc_once_t once = ISC_ONCE_INIT; 145 static isc_mem_t *pk11_mctx = NULL; 146 static isc_int32_t allocsize = 0; 147 static isc_boolean_t initialized = ISC_FALSE; 148 149 typedef struct pk11_session pk11_session_t; 150 typedef struct pk11_token pk11_token_t; 151 typedef ISC_LIST(pk11_session_t) pk11_sessionlist_t; 152 153 struct pk11_session { 154 unsigned int magic; 155 CK_SESSION_HANDLE session; 156 ISC_LINK(pk11_session_t) link; 157 pk11_token_t *token; 158 }; 159 160 struct pk11_token { 161 unsigned int magic; 162 unsigned int operations; 163 ISC_LINK(pk11_token_t) link; 164 CK_SLOT_ID slotid; 165 pk11_sessionlist_t sessions; 166 isc_boolean_t logged; 167 char name[32]; 168 char manuf[32]; 169 char model[16]; 170 char serial[16]; 171 char pin[PINLEN + 1]; 172 }; 173 static ISC_LIST(pk11_token_t) tokens; 174 175 static pk11_token_t *rand_token; 176 static pk11_token_t *best_rsa_token; 177 static pk11_token_t *best_dsa_token; 178 static pk11_token_t *best_dh_token; 179 static pk11_token_t *digest_token; 180 static pk11_token_t *best_ec_token; 181 static pk11_token_t *best_gost_token; 182 static pk11_token_t *aes_token; 183 184 static isc_result_t free_all_sessions(void); 185 static isc_result_t free_session_list(pk11_sessionlist_t *slist); 186 static isc_result_t setup_session(pk11_session_t *sp, 187 pk11_token_t *token, 188 isc_boolean_t rw); 189 static void choose_slots(void); 190 static isc_result_t token_login(pk11_session_t *sp); 191 static char *percent_decode(char *x, size_t *len); 192 static isc_boolean_t pk11strcmp(const char *x, size_t lenx, 193 const char *y, size_t leny); 194 static CK_ATTRIBUTE *push_attribute(pk11_object_t *obj, 195 isc_mem_t *mctx, 196 size_t len); 197 198 static isc_mutex_t alloclock; 199 static isc_mutex_t sessionlock; 200 201 static pk11_sessionlist_t actives; 202 203 static CK_C_INITIALIZE_ARGS pk11_init_args = { 204 NULL_PTR, /* CreateMutex */ 205 NULL_PTR, /* DestroyMutex */ 206 NULL_PTR, /* LockMutex */ 207 NULL_PTR, /* UnlockMutex */ 208 CKF_OS_LOCKING_OK, /* flags */ 209 NULL_PTR, /* pReserved */ 210 }; 211 212 #ifndef PK11_LIB_LOCATION 213 #define PK11_LIB_LOCATION "unknown_provider" 214 #endif 215 216 #ifndef WIN32 217 static const char *lib_name = PK11_LIB_LOCATION; 218 #else 219 static const char *lib_name = PK11_LIB_LOCATION ".dll"; 220 #endif 221 222 void 223 pk11_set_lib_name(const char *name) { 224 lib_name = name; 225 } 226 227 const char * 228 pk11_get_lib_name(void) { 229 return (lib_name); 230 } 231 232 static void 233 initialize(void) { 234 char *pk11_provider; 235 236 RUNTIME_CHECK(isc_mutex_init(&alloclock) == ISC_R_SUCCESS); 237 RUNTIME_CHECK(isc_mutex_init(&sessionlock) == ISC_R_SUCCESS); 238 239 pk11_provider = getenv("PKCS11_PROVIDER"); 240 if (pk11_provider != NULL) 241 lib_name = pk11_provider; 242 } 243 244 void * 245 pk11_mem_get(size_t size) { 246 void *ptr; 247 248 LOCK(&alloclock); 249 if (pk11_mctx != NULL) 250 ptr = isc_mem_get(pk11_mctx, size); 251 else { 252 ptr = malloc(size); 253 if (ptr != NULL) 254 allocsize += (int)size; 255 } 256 UNLOCK(&alloclock); 257 258 if (ptr != NULL) 259 memset(ptr, 0, size); 260 return (ptr); 261 } 262 263 void 264 pk11_mem_put(void *ptr, size_t size) { 265 if (ptr != NULL) 266 memset(ptr, 0, size); 267 LOCK(&alloclock); 268 if (pk11_mctx != NULL) 269 isc_mem_put(pk11_mctx, ptr, size); 270 else { 271 if (ptr != NULL) 272 allocsize -= (int)size; 273 free(ptr); 274 } 275 UNLOCK(&alloclock); 276 } 277 278 isc_result_t 279 pk11_initialize(isc_mem_t *mctx, const char *engine) { 280 isc_result_t result; 281 CK_RV rv; 282 283 RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); 284 285 LOCK(&alloclock); 286 if ((mctx != NULL) && (pk11_mctx == NULL) && (allocsize == 0)) 287 isc_mem_attach(mctx, &pk11_mctx); 288 if (initialized) { 289 UNLOCK(&alloclock); 290 return (ISC_R_SUCCESS); 291 } else { 292 LOCK(&sessionlock); 293 initialized = ISC_TRUE; 294 UNLOCK(&alloclock); 295 } 296 297 ISC_LIST_INIT(tokens); 298 ISC_LIST_INIT(actives); 299 300 if (engine != NULL) 301 lib_name = engine; 302 303 /* Initialize the CRYPTOKI library */ 304 rv = pkcs_C_Initialize((CK_VOID_PTR) &pk11_init_args); 305 306 if (rv == 0xfe) { 307 result = PK11_R_NOPROVIDER; 308 goto unlock; 309 } 310 if (rv != CKR_OK) { 311 result = PK11_R_INITFAILED; 312 goto unlock; 313 } 314 315 choose_slots(); 316 #ifdef PKCS11CRYPTO 317 if (rand_token == NULL) { 318 result = PK11_R_NORANDOMSERVICE; 319 goto unlock; 320 } 321 if (digest_token == NULL) { 322 result = PK11_R_NODIGESTSERVICE; 323 goto unlock; 324 } 325 #if defined(ISC_PLATFORM_USESIT) && defined(AES_SIT) 326 if (aes_token == NULL) { 327 result = PK11_R_NOAESSERVICE; 328 goto unlock; 329 } 330 #endif 331 #endif /* PKCS11CRYPTO */ 332 result = ISC_R_SUCCESS; 333 unlock: 334 UNLOCK(&sessionlock); 335 return (result); 336 } 337 338 isc_result_t 339 pk11_finalize(void) { 340 pk11_token_t *token, *next; 341 isc_result_t ret; 342 343 ret = free_all_sessions(); 344 (void) pkcs_C_Finalize(NULL_PTR); 345 token = ISC_LIST_HEAD(tokens); 346 while (token != NULL) { 347 next = ISC_LIST_NEXT(token, link); 348 ISC_LIST_UNLINK(tokens, token, link); 349 if (token == rand_token) 350 rand_token = NULL; 351 if (token == best_rsa_token) 352 best_rsa_token = NULL; 353 if (token == best_dsa_token) 354 best_dsa_token = NULL; 355 if (token == best_dh_token) 356 best_dh_token = NULL; 357 if (token == digest_token) 358 digest_token = NULL; 359 if (token == best_ec_token) 360 best_ec_token = NULL; 361 if (token == best_gost_token) 362 best_gost_token = NULL; 363 if (token == aes_token) 364 aes_token = NULL; 365 pk11_mem_put(token, sizeof(*token)); 366 token = next; 367 } 368 if (pk11_mctx != NULL) 369 isc_mem_detach(&pk11_mctx); 370 initialized = ISC_FALSE; 371 return (ret); 372 } 373 374 isc_result_t 375 pk11_rand_bytes(unsigned char *buf, int num) { 376 isc_result_t ret; 377 CK_RV rv; 378 pk11_context_t ctx; 379 380 ret = pk11_get_session(&ctx, OP_RAND, ISC_FALSE, ISC_FALSE, 381 ISC_FALSE, NULL, 0); 382 if ((ret != ISC_R_SUCCESS) && 383 (ret != PK11_R_NODIGESTSERVICE) && 384 (ret != PK11_R_NOAESSERVICE)) 385 return (ret); 386 RUNTIME_CHECK(ctx.session != CK_INVALID_HANDLE); 387 rv = pkcs_C_GenerateRandom(ctx.session, 388 (CK_BYTE_PTR) buf, (CK_ULONG) num); 389 pk11_return_session(&ctx); 390 if (rv == CKR_OK) 391 return (ISC_R_SUCCESS); 392 else 393 return (DST_R_CRYPTOFAILURE); 394 } 395 396 #define SEEDSIZE 1024 397 398 static CK_BYTE seed[SEEDSIZE]; 399 400 void 401 pk11_rand_seed_fromfile(const char *randomfile) { 402 pk11_context_t ctx; 403 FILE *stream = NULL; 404 size_t cc = 0; 405 isc_result_t ret; 406 407 ret = pk11_get_session(&ctx, OP_RAND, ISC_FALSE, ISC_FALSE, 408 ISC_FALSE, NULL, 0); 409 if ((ret != ISC_R_SUCCESS) && 410 (ret != PK11_R_NODIGESTSERVICE) && 411 (ret != PK11_R_NOAESSERVICE)) 412 return; 413 RUNTIME_CHECK(ctx.session != CK_INVALID_HANDLE); 414 ret = isc_stdio_open(randomfile, "r", &stream); 415 if (ret != ISC_R_SUCCESS) 416 goto cleanup; 417 ret = isc_stdio_read(seed, 1, SEEDSIZE, stream, &cc); 418 if (ret!= ISC_R_SUCCESS) 419 goto cleanup; 420 ret = isc_stdio_close(stream); 421 stream = NULL; 422 if (ret!= ISC_R_SUCCESS) 423 goto cleanup; 424 (void) pkcs_C_SeedRandom(ctx.session, seed, (CK_ULONG) cc); 425 426 cleanup: 427 if (stream != NULL) 428 (void) isc_stdio_close(stream); 429 pk11_return_session(&ctx); 430 } 431 432 isc_result_t 433 pk11_get_session(pk11_context_t *ctx, pk11_optype_t optype, 434 isc_boolean_t need_services, isc_boolean_t rw, 435 isc_boolean_t logon, const char *pin, CK_SLOT_ID slot) 436 { 437 pk11_token_t *token = NULL; 438 pk11_sessionlist_t *freelist; 439 pk11_session_t *sp; 440 isc_result_t ret; 441 #ifdef PKCS11CRYPTO 442 isc_result_t service_ret = ISC_R_SUCCESS; 443 #else 444 UNUSED(need_services); 445 #endif 446 447 memset(ctx, 0, sizeof(pk11_context_t)); 448 ctx->handle = NULL; 449 ctx->session = CK_INVALID_HANDLE; 450 451 ret = pk11_initialize(NULL, NULL); 452 #ifdef PKCS11CRYPTO 453 if (ret == PK11_R_NORANDOMSERVICE || 454 ret == PK11_R_NODIGESTSERVICE || 455 ret == PK11_R_NOAESSERVICE) { 456 if (need_services) 457 return (ret); 458 service_ret = ret; 459 } 460 else 461 #endif /* PKCS11CRYPTO */ 462 if (ret != ISC_R_SUCCESS) 463 return (ret); 464 465 LOCK(&sessionlock); 466 /* wait for initialization to finish */ 467 UNLOCK(&sessionlock); 468 469 switch(optype) { 470 #ifdef PKCS11CRYPTO 471 case OP_RAND: 472 token = rand_token; 473 break; 474 case OP_DIGEST: 475 token = digest_token; 476 break; 477 case OP_AES: 478 token = aes_token; 479 break; 480 case OP_ANY: 481 for (token = ISC_LIST_HEAD(tokens); 482 token != NULL; 483 token = ISC_LIST_NEXT(token, link)) 484 if (token->slotid == slot) 485 break; 486 break; 487 #endif 488 default: 489 for (token = ISC_LIST_HEAD(tokens); 490 token != NULL; 491 token = ISC_LIST_NEXT(token, link)) 492 if (token->slotid == slot) 493 break; 494 #ifdef PKCS11CRYPTO 495 if ((token == NULL) || 496 ((token->operations & (1 << optype)) == 0)) 497 return (ISC_R_NOTFOUND); 498 #endif 499 break; 500 } 501 if (token == NULL) 502 return (ISC_R_NOTFOUND); 503 504 /* Override the token's PIN */ 505 if (logon && pin != NULL && *pin != '\0') { 506 if (strlen(pin) > PINLEN) 507 return ISC_R_RANGE; 508 memset(token->pin, 0, PINLEN + 1); 509 strncpy(token->pin, pin, PINLEN); 510 } 511 512 freelist = &token->sessions; 513 514 LOCK(&sessionlock); 515 sp = ISC_LIST_HEAD(*freelist); 516 if (sp != NULL) { 517 ISC_LIST_UNLINK(*freelist, sp, link); 518 ISC_LIST_APPEND(actives, sp, link); 519 UNLOCK(&sessionlock); 520 if (logon) 521 ret = token_login(sp); 522 ctx->handle = sp; 523 ctx->session = sp->session; 524 return (ret); 525 } 526 UNLOCK(&sessionlock); 527 528 sp = pk11_mem_get(sizeof(*sp)); 529 if (sp == NULL) 530 return (ISC_R_NOMEMORY); 531 sp->magic = SES_MAGIC; 532 sp->token = token; 533 sp->session = CK_INVALID_HANDLE; 534 ISC_LINK_INIT(sp, link); 535 ret = setup_session(sp, token, rw); 536 if ((ret == ISC_R_SUCCESS) && logon) 537 ret = token_login(sp); 538 LOCK(&sessionlock); 539 ISC_LIST_APPEND(actives, sp, link); 540 UNLOCK(&sessionlock); 541 ctx->handle = sp; 542 ctx->session = sp->session; 543 #ifdef PKCS11CRYPTO 544 if (ret == ISC_R_SUCCESS) 545 ret = service_ret; 546 #endif 547 return (ret); 548 } 549 550 void 551 pk11_return_session(pk11_context_t *ctx) { 552 pk11_session_t *sp = (pk11_session_t *) ctx->handle; 553 554 if (sp == NULL) 555 return; 556 ctx->handle = NULL; 557 ctx->session = CK_INVALID_HANDLE; 558 559 LOCK(&sessionlock); 560 ISC_LIST_UNLINK(actives, sp, link); 561 UNLOCK(&sessionlock); 562 if (sp->session == CK_INVALID_HANDLE) { 563 pk11_mem_put(sp, sizeof(*sp)); 564 return; 565 } 566 567 LOCK(&sessionlock); 568 ISC_LIST_APPEND(sp->token->sessions, sp, link); 569 UNLOCK(&sessionlock); 570 } 571 572 static isc_result_t 573 free_all_sessions(void) { 574 pk11_token_t *token; 575 isc_result_t ret = ISC_R_SUCCESS; 576 isc_result_t oret; 577 578 for (token = ISC_LIST_HEAD(tokens); 579 token != NULL; 580 token = ISC_LIST_NEXT(token, link)) { 581 oret = free_session_list(&token->sessions); 582 if (oret != ISC_R_SUCCESS) 583 ret = oret; 584 } 585 if (!ISC_LIST_EMPTY(actives)) { 586 ret = ISC_R_ADDRINUSE; 587 oret = free_session_list(&actives); 588 if (oret != ISC_R_SUCCESS) 589 ret = oret; 590 } 591 return (ret); 592 } 593 594 static isc_result_t 595 free_session_list(pk11_sessionlist_t *slist) { 596 pk11_session_t *sp; 597 CK_RV rv; 598 isc_result_t ret; 599 600 ret = ISC_R_SUCCESS; 601 LOCK(&sessionlock); 602 while (!ISC_LIST_EMPTY(*slist)) { 603 sp = ISC_LIST_HEAD(*slist); 604 UNLOCK(&sessionlock); 605 if (sp->session != CK_INVALID_HANDLE) { 606 rv = pkcs_C_CloseSession(sp->session); 607 if (rv != CKR_OK) 608 ret = DST_R_CRYPTOFAILURE; 609 } 610 LOCK(&sessionlock); 611 ISC_LIST_UNLINK(*slist, sp, link); 612 pk11_mem_put(sp, sizeof(*sp)); 613 } 614 UNLOCK(&sessionlock); 615 616 return (ret); 617 } 618 619 static isc_result_t 620 setup_session(pk11_session_t *sp, pk11_token_t *token, 621 isc_boolean_t rw) 622 { 623 CK_RV rv; 624 CK_FLAGS flags = CKF_SERIAL_SESSION; 625 626 if (rw) 627 flags += CKF_RW_SESSION; 628 629 rv = pkcs_C_OpenSession(token->slotid, flags, NULL_PTR, 630 NULL_PTR, &sp->session); 631 if (rv != CKR_OK) 632 return (DST_R_CRYPTOFAILURE); 633 return (ISC_R_SUCCESS); 634 } 635 636 static isc_result_t 637 token_login(pk11_session_t *sp) { 638 CK_RV rv; 639 pk11_token_t *token = sp->token; 640 isc_result_t ret = ISC_R_SUCCESS; 641 642 LOCK(&sessionlock); 643 if (!token->logged) { 644 rv = pkcs_C_Login(sp->session, CKU_USER, 645 (CK_UTF8CHAR_PTR) token->pin, 646 (CK_ULONG) strlen(token->pin)); 647 if (rv != CKR_OK) { 648 ret = ISC_R_NOPERM; 649 #if PK11_NO_LOGERR 650 pk11_error_fatalcheck(__FILE__, __LINE__, 651 "pkcs_C_Login", rv); 652 #endif 653 } else 654 token->logged = ISC_TRUE; 655 } 656 UNLOCK(&sessionlock); 657 return (ret); 658 } 659 660 static void 661 choose_slots(void) { 662 CK_MECHANISM_INFO mechInfo; 663 CK_TOKEN_INFO tokenInfo; 664 CK_RV rv; 665 CK_SLOT_ID slot; 666 CK_SLOT_ID_PTR slotList; 667 CK_ULONG slotCount; 668 pk11_token_t *token; 669 unsigned int i; 670 671 slotCount = 0; 672 PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, NULL_PTR, &slotCount)); 673 /* it's not an error if we didn't find any providers */ 674 if (slotCount == 0) 675 return; 676 slotList = pk11_mem_get(sizeof(CK_SLOT_ID_PTR) * slotCount); 677 RUNTIME_CHECK(slotList != NULL); 678 PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, slotList, &slotCount)); 679 680 for (i = 0; i < slotCount; i++) { 681 slot = slotList[i]; 682 683 rv = pkcs_C_GetTokenInfo(slot, &tokenInfo); 684 if (rv != CKR_OK) 685 continue; 686 token = pk11_mem_get(sizeof(*token)); 687 RUNTIME_CHECK(token != NULL); 688 token->magic = TOK_MAGIC; 689 token->slotid = slot; 690 ISC_LINK_INIT(token, link); 691 ISC_LIST_INIT(token->sessions); 692 memmove(token->name, tokenInfo.label, 32); 693 memmove(token->manuf, tokenInfo.manufacturerID, 32); 694 memmove(token->model, tokenInfo.model, 16); 695 memmove(token->serial, tokenInfo.serialNumber, 16); 696 ISC_LIST_APPEND(tokens, token, link); 697 if ((tokenInfo.flags & CKF_RNG) == 0) 698 goto try_rsa; 699 token->operations |= 1 << OP_RAND; 700 if (rand_token == NULL) 701 rand_token = token; 702 703 try_rsa: 704 rv = pkcs_C_GetMechanismInfo(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, 705 &mechInfo); 706 if ((rv != CKR_OK) || 707 ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0)) 708 goto try_dsa; 709 rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_RSA_PKCS, 710 &mechInfo); 711 if ((rv != CKR_OK) || 712 ((mechInfo.flags & CKF_SIGN) == 0) || 713 ((mechInfo.flags & CKF_VERIFY) == 0)) 714 goto try_dsa; 715 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA1_RSA_PKCS, 716 &mechInfo); 717 if ((rv != CKR_OK) || 718 ((mechInfo.flags & CKF_SIGN) == 0) || 719 ((mechInfo.flags & CKF_VERIFY) == 0)) 720 goto try_dsa; 721 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_RSA_PKCS, 722 &mechInfo); 723 if ((rv != CKR_OK) || 724 ((mechInfo.flags & CKF_SIGN) == 0) || 725 ((mechInfo.flags & CKF_VERIFY) == 0)) 726 goto try_dsa; 727 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512_RSA_PKCS, 728 &mechInfo); 729 if ((rv != CKR_OK) || 730 ((mechInfo.flags & CKF_SIGN) == 0) || 731 ((mechInfo.flags & CKF_VERIFY) == 0)) 732 goto try_dsa; 733 token->operations |= 1 << OP_RSA; 734 if (best_rsa_token == NULL) 735 best_rsa_token = token; 736 737 try_dsa: 738 rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_PARAMETER_GEN, 739 &mechInfo); 740 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_GENERATE) == 0)) 741 goto try_dh; 742 rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_KEY_PAIR_GEN, 743 &mechInfo); 744 if ((rv != CKR_OK) || 745 ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0)) 746 goto try_dh; 747 rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_SHA1, &mechInfo); 748 if ((rv != CKR_OK) || 749 ((mechInfo.flags & CKF_SIGN) == 0) || 750 ((mechInfo.flags & CKF_VERIFY) == 0)) 751 goto try_dh; 752 token->operations |= 1 << OP_DSA; 753 if (best_dsa_token == NULL) 754 best_dsa_token = token; 755 756 try_dh: 757 #ifdef notdef 758 rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_PARAMETER_GEN, 759 &mechInfo); 760 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_GENERATE) == 0)) 761 goto try_digest; 762 #endif 763 rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_KEY_PAIR_GEN, 764 &mechInfo); 765 if ((rv != CKR_OK) || 766 ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0)) 767 goto try_digest; 768 rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_DERIVE, 769 &mechInfo); 770 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DERIVE) == 0)) 771 goto try_digest; 772 token->operations |= 1 << OP_DH; 773 if (best_dh_token == NULL) 774 best_dh_token = token; 775 776 try_digest: 777 rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5, &mechInfo); 778 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) 779 continue; 780 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1, &mechInfo); 781 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) 782 continue; 783 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA224, &mechInfo); 784 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) 785 continue; 786 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256, &mechInfo); 787 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) 788 continue; 789 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA384, &mechInfo); 790 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) 791 continue; 792 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512, &mechInfo); 793 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) 794 continue; 795 #ifdef PKCS11CRYPTOWITHHMAC 796 rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_HMAC, &mechInfo); 797 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) 798 continue; 799 #endif 800 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1_HMAC, &mechInfo); 801 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) 802 continue; 803 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA224_HMAC, &mechInfo); 804 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) 805 continue; 806 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_HMAC, &mechInfo); 807 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) 808 continue; 809 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA384_HMAC, &mechInfo); 810 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) 811 continue; 812 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512_HMAC, &mechInfo); 813 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) 814 continue; 815 token->operations |= 1 << OP_DIGEST; 816 if (digest_token == NULL) 817 digest_token = token; 818 819 /* ECDSA requires digest */ 820 rv = pkcs_C_GetMechanismInfo(slot, CKM_EC_KEY_PAIR_GEN, 821 &mechInfo); 822 if ((rv != CKR_OK) || 823 ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0)) 824 goto try_gost; 825 rv = pkcs_C_GetMechanismInfo(slot, CKM_ECDSA, &mechInfo); 826 if ((rv != CKR_OK) || 827 ((mechInfo.flags & CKF_SIGN) == 0) || 828 ((mechInfo.flags & CKF_VERIFY) == 0)) 829 goto try_gost; 830 token->operations |= 1 << OP_EC; 831 if (best_ec_token == NULL) 832 best_ec_token = token; 833 834 try_gost: 835 /* does GOST require digest too? */ 836 rv = pkcs_C_GetMechanismInfo(slot, CKM_GOSTR3411, &mechInfo); 837 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) 838 goto try_aes; 839 rv = pkcs_C_GetMechanismInfo(slot, CKM_GOSTR3410_KEY_PAIR_GEN, 840 &mechInfo); 841 if ((rv != CKR_OK) || 842 ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0)) 843 goto try_aes; 844 rv = pkcs_C_GetMechanismInfo(slot, 845 CKM_GOSTR3410_WITH_GOSTR3411, 846 &mechInfo); 847 if ((rv != CKR_OK) || 848 ((mechInfo.flags & CKF_SIGN) == 0) || 849 ((mechInfo.flags & CKF_VERIFY) == 0)) 850 goto try_aes; 851 token->operations |= 1 << OP_GOST; 852 if (best_gost_token == NULL) 853 best_gost_token = token; 854 855 try_aes: 856 rv = pkcs_C_GetMechanismInfo(slot, CKM_AES_ECB, &mechInfo); 857 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_ENCRYPT) == 0)) 858 continue; 859 token->operations |= 1 << OP_AES; 860 if (aes_token == NULL) 861 aes_token = token; 862 } 863 864 if (slotList != NULL) 865 pk11_mem_put(slotList, sizeof(CK_SLOT_ID_PTR) * slotCount); 866 } 867 868 CK_SLOT_ID 869 pk11_get_best_token(pk11_optype_t optype) { 870 pk11_token_t *token = NULL; 871 872 switch (optype) { 873 case OP_RAND: 874 token = rand_token; 875 break; 876 case OP_RSA: 877 token = best_rsa_token; 878 break; 879 case OP_DSA: 880 token = best_dsa_token; 881 break; 882 case OP_DH: 883 token = best_dh_token; 884 break; 885 case OP_DIGEST: 886 token = digest_token; 887 break; 888 case OP_EC: 889 token = best_ec_token; 890 break; 891 case OP_GOST: 892 token = best_gost_token; 893 break; 894 case OP_AES: 895 token = aes_token; 896 break; 897 default: 898 break; 899 } 900 if (token == NULL) 901 return (0); 902 return (token->slotid); 903 } 904 905 unsigned int 906 pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt) { 907 unsigned int bitcnt, i; 908 CK_BYTE top; 909 910 if (bytecnt == 0) 911 return (0); 912 bitcnt = bytecnt * 8; 913 for (i = 0; i < bytecnt; i++) { 914 top = data[i]; 915 if (top == 0) { 916 bitcnt -= 8; 917 continue; 918 } 919 if (top & 0x80) 920 return (bitcnt); 921 if (top & 0x40) 922 return (bitcnt - 1); 923 if (top & 0x20) 924 return (bitcnt - 2); 925 if (top & 0x10) 926 return (bitcnt - 3); 927 if (top & 0x08) 928 return (bitcnt - 4); 929 if (top & 0x04) 930 return (bitcnt - 5); 931 if (top & 0x02) 932 return (bitcnt - 6); 933 if (top & 0x01) 934 return (bitcnt - 7); 935 break; 936 } 937 INSIST(0); 938 } 939 940 CK_ATTRIBUTE * 941 pk11_attribute_first(const pk11_object_t *obj) { 942 return (obj->repr); 943 } 944 945 CK_ATTRIBUTE * 946 pk11_attribute_next(const pk11_object_t *obj, CK_ATTRIBUTE *attr) { 947 CK_ATTRIBUTE *next; 948 949 next = attr + 1; 950 if ((next - obj->repr) >= obj->attrcnt) 951 return (NULL); 952 return (next); 953 } 954 955 CK_ATTRIBUTE * 956 pk11_attribute_bytype(const pk11_object_t *obj, CK_ATTRIBUTE_TYPE type) { 957 CK_ATTRIBUTE *attr; 958 959 for(attr = pk11_attribute_first(obj); 960 attr != NULL; 961 attr = pk11_attribute_next(obj, attr)) 962 if (attr->type == type) 963 return (attr); 964 return (NULL); 965 } 966 967 static char * 968 percent_decode(char *x, size_t *len) { 969 char *p, *c; 970 unsigned char v; 971 972 INSIST(len != NULL); 973 974 for (p = c = x; p[0] != '\0'; p++, c++) { 975 switch (p[0]) { 976 case '%': 977 v = 0; 978 switch (p[1]) { 979 case '0': 980 case '1': 981 case '2': 982 case '3': 983 case '4': 984 case '5': 985 case '6': 986 case '7': 987 case '8': 988 case '9': 989 v = (p[1] - '0') << 4; 990 break; 991 case 'A': 992 case 'B': 993 case 'C': 994 case 'D': 995 case 'E': 996 case 'F': 997 v = (p[1] - 'A' + 10) << 4; 998 break; 999 case 'a': 1000 case 'b': 1001 case 'c': 1002 case 'd': 1003 case 'e': 1004 case 'f': 1005 v = (p[1] - 'a' + 10) << 4; 1006 break; 1007 default: 1008 return (NULL); 1009 } 1010 switch (p[2]) { 1011 case '0': 1012 case '1': 1013 case '2': 1014 case '3': 1015 case '4': 1016 case '5': 1017 case '6': 1018 case '7': 1019 case '8': 1020 case '9': 1021 v |= (p[2] - '0') & 0x0f; 1022 break; 1023 case 'A': 1024 case 'B': 1025 case 'C': 1026 case 'D': 1027 case 'E': 1028 case 'F': 1029 v = (p[2] - 'A' + 10) & 0x0f; 1030 break; 1031 case 'a': 1032 case 'b': 1033 case 'c': 1034 case 'd': 1035 case 'e': 1036 case 'f': 1037 v = (p[2] - 'a' + 10) & 0x0f; 1038 break; 1039 default: 1040 return (NULL); 1041 } 1042 p += 2; 1043 *c = (char) v; 1044 (*len)++; 1045 break; 1046 default: 1047 *c = *p; 1048 (*len)++; 1049 } 1050 } 1051 return (x); 1052 } 1053 1054 static isc_boolean_t 1055 pk11strcmp(const char *x, size_t lenx, const char *y, size_t leny) { 1056 char buf[32]; 1057 1058 INSIST((leny == 32) || (leny == 16)); 1059 1060 memset(buf, ' ', 32); 1061 if (lenx > leny) 1062 lenx = leny; 1063 memmove(buf, x, lenx); 1064 return (ISC_TF(memcmp(buf, y, leny) == 0)); 1065 } 1066 1067 static CK_ATTRIBUTE * 1068 push_attribute(pk11_object_t *obj, isc_mem_t *mctx, size_t len) { 1069 CK_ATTRIBUTE *old = obj->repr; 1070 CK_ATTRIBUTE *attr; 1071 CK_BYTE cnt = obj->attrcnt; 1072 1073 obj->repr = isc_mem_get(mctx, (cnt + 1) * sizeof(*attr)); 1074 if (obj->repr == NULL) { 1075 obj->repr = old; 1076 return (NULL); 1077 } 1078 memset(obj->repr, 0, (cnt + 1) * sizeof(*attr)); 1079 memmove(obj->repr, old, cnt * sizeof(*attr)); 1080 attr = obj->repr + cnt; 1081 attr->ulValueLen = (CK_ULONG) len; 1082 attr->pValue = isc_mem_get(mctx, len); 1083 if (attr->pValue == NULL) { 1084 memset(obj->repr, 0, (cnt + 1) * sizeof(*attr)); 1085 isc_mem_put(mctx, obj->repr, (cnt + 1) * sizeof(*attr)); 1086 obj->repr = old; 1087 return (NULL); 1088 } 1089 memset(attr->pValue, 0, len); 1090 if (old != NULL) { 1091 memset(old, 0, cnt * sizeof(*attr)); 1092 isc_mem_put(mctx, old, cnt * sizeof(*attr)); 1093 } 1094 obj->attrcnt++; 1095 return (attr); 1096 } 1097 1098 #define DST_RET(a) { ret = a; goto err; } 1099 1100 isc_result_t 1101 pk11_parse_uri(pk11_object_t *obj, const char *label, 1102 isc_mem_t *mctx, pk11_optype_t optype) 1103 { 1104 CK_ATTRIBUTE *attr; 1105 pk11_token_t *token = NULL; 1106 char *uri, *p, *a, *na, *v; 1107 size_t len, l; 1108 FILE *stream = NULL; 1109 char pin[PINLEN + 1]; 1110 isc_boolean_t gotpin = ISC_FALSE; 1111 isc_result_t ret; 1112 1113 /* get values to work on */ 1114 len = strlen(label) + 1; 1115 uri = isc_mem_get(mctx, len); 1116 if (uri == NULL) 1117 return (ISC_R_NOMEMORY); 1118 memmove(uri, label, len); 1119 1120 /* get the URI scheme */ 1121 p = strchr(uri, ':'); 1122 if (p == NULL) 1123 DST_RET(PK11_R_NOPROVIDER); 1124 *p++ = '\0'; 1125 if (strcmp(uri, "pkcs11") != 0) 1126 DST_RET(PK11_R_NOPROVIDER); 1127 1128 /* get attributes */ 1129 for (na = p; na != NULL;) { 1130 a = na; 1131 p = strchr(a, ';'); 1132 if (p == NULL) { 1133 /* last attribute */ 1134 na = NULL; 1135 } else { 1136 *p++ = '\0'; 1137 na = p; 1138 } 1139 p = strchr(a, '='); 1140 if (p != NULL) { 1141 *p++ = '\0'; 1142 v = p; 1143 } else 1144 v = a; 1145 l = 0; 1146 v = percent_decode(v, &l); 1147 if (v == NULL) 1148 DST_RET(PK11_R_NOPROVIDER); 1149 if ((a == v) || (strcmp(a, "object") == 0)) { 1150 /* object: CKA_LABEL */ 1151 attr = pk11_attribute_bytype(obj, CKA_LABEL); 1152 if (attr != NULL) 1153 DST_RET(PK11_R_NOPROVIDER); 1154 attr = push_attribute(obj, mctx, l); 1155 if (attr == NULL) 1156 DST_RET(ISC_R_NOMEMORY); 1157 attr->type = CKA_LABEL; 1158 memmove(attr->pValue, v, l); 1159 } else if (strcmp(a, "token") == 0) { 1160 /* token: CK_TOKEN_INFO label */ 1161 if (token == NULL) 1162 for (token = ISC_LIST_HEAD(tokens); 1163 token != NULL; 1164 token = ISC_LIST_NEXT(token, link)) 1165 if (pk11strcmp(v, l, token->name, 32)) 1166 break; 1167 } else if (strcmp(a, "manufacturer") == 0) { 1168 /* manufacturer: CK_TOKEN_INFO manufacturerID */ 1169 if (token == NULL) 1170 for (token = ISC_LIST_HEAD(tokens); 1171 token != NULL; 1172 token = ISC_LIST_NEXT(token, link)) 1173 if (pk11strcmp(v, l, token->manuf, 32)) 1174 break; 1175 } else if (strcmp(a, "serial") == 0) { 1176 /* serial: CK_TOKEN_INFO serialNumber */ 1177 if (token == NULL) 1178 for (token = ISC_LIST_HEAD(tokens); 1179 token != NULL; 1180 token = ISC_LIST_NEXT(token, link)) 1181 if (pk11strcmp(v, l, token->serial, 16)) 1182 break; 1183 } else if (strcmp(a, "model") == 0) { 1184 /* model: CK_TOKEN_INFO model */ 1185 if (token == NULL) 1186 for (token = ISC_LIST_HEAD(tokens); 1187 token != NULL; 1188 token = ISC_LIST_NEXT(token, link)) 1189 if (pk11strcmp(v, l, token->model, 16)) 1190 break; 1191 } else if (strcmp(a, "library-manufacturer") == 0) { 1192 /* ignored */ 1193 } else if (strcmp(a, "library-description") == 0) { 1194 /* ignored */ 1195 } else if (strcmp(a, "library-version") == 0) { 1196 /* ignored */ 1197 } else if (strcmp(a, "object-type") == 0) { 1198 /* object-type: CKA_CLASS */ 1199 /* only private makes sense */ 1200 if (strcmp(v, "private") != 0) 1201 DST_RET(PK11_R_NOPROVIDER); 1202 } else if (strcmp(a, "id") == 0) { 1203 /* id: CKA_ID */ 1204 attr = pk11_attribute_bytype(obj, CKA_ID); 1205 if (attr != NULL) 1206 DST_RET(PK11_R_NOPROVIDER); 1207 attr = push_attribute(obj, mctx, l); 1208 if (attr == NULL) 1209 DST_RET(ISC_R_NOMEMORY); 1210 attr->type = CKA_ID; 1211 memmove(attr->pValue, v, l); 1212 } else if (strcmp(a, "pin-source") == 0) { 1213 /* pin-source: PIN */ 1214 ret = isc_stdio_open(v, "r", &stream); 1215 if (ret != ISC_R_SUCCESS) 1216 goto err; 1217 memset(pin, 0, PINLEN + 1); 1218 ret = isc_stdio_read(pin, 1, PINLEN + 1, stream, &l); 1219 if ((ret != ISC_R_SUCCESS) && (ret != ISC_R_EOF)) 1220 goto err; 1221 if (l > PINLEN) 1222 DST_RET(ISC_R_RANGE); 1223 ret = isc_stdio_close(stream); 1224 stream = NULL; 1225 if (ret != ISC_R_SUCCESS) 1226 goto err; 1227 gotpin = ISC_TRUE; 1228 } else 1229 DST_RET(PK11_R_NOPROVIDER); 1230 } 1231 1232 if ((pk11_attribute_bytype(obj, CKA_LABEL) == NULL) && 1233 (pk11_attribute_bytype(obj, CKA_ID) == NULL)) 1234 DST_RET(ISC_R_NOTFOUND); 1235 1236 if (token == NULL) { 1237 if (optype == OP_RSA) 1238 token = best_rsa_token; 1239 else if (optype == OP_DSA) 1240 token = best_dsa_token; 1241 else if (optype == OP_DH) 1242 token = best_dh_token; 1243 else if (optype == OP_EC) 1244 token = best_ec_token; 1245 } 1246 if (token == NULL) 1247 DST_RET(ISC_R_NOTFOUND); 1248 obj->slot = token->slotid; 1249 if (gotpin) { 1250 memmove(token->pin, pin, PINLEN + 1); 1251 obj->reqlogon = ISC_TRUE; 1252 } 1253 1254 ret = ISC_R_SUCCESS; 1255 1256 err: 1257 if (stream != NULL) 1258 (void) isc_stdio_close(stream); 1259 isc_mem_put(mctx, uri, len); 1260 return (ret); 1261 } 1262 1263 void 1264 pk11_error_fatalcheck(const char *file, int line, 1265 const char *funcname, CK_RV rv) 1266 { 1267 isc_error_fatal(file, line, "%s: Error = 0x%.8lX\n", funcname, rv); 1268 } 1269 1270 void 1271 pk11_dump_tokens(void) 1272 { 1273 pk11_token_t *token; 1274 isc_boolean_t first; 1275 1276 printf("DEFAULTS\n"); 1277 printf("\trand_token=%p\n", rand_token); 1278 printf("\tbest_rsa_token=%p\n", best_rsa_token); 1279 printf("\tbest_dsa_token=%p\n", best_dsa_token); 1280 printf("\tbest_dh_token=%p\n", best_dh_token); 1281 printf("\tdigest_token=%p\n", digest_token); 1282 printf("\tbest_ec_token=%p\n", best_ec_token); 1283 printf("\tbest_gost_token=%p\n", best_gost_token); 1284 printf("\taes_token=%p\n", aes_token); 1285 1286 for (token = ISC_LIST_HEAD(tokens); 1287 token != NULL; 1288 token = ISC_LIST_NEXT(token, link)) { 1289 printf("\nTOKEN\n"); 1290 printf("\taddress=%p\n", token); 1291 printf("\tslotID=%lu\n", token->slotid); 1292 printf("\tlabel=%.32s\n", token->name); 1293 printf("\tmanufacturerID=%.32s\n", token->manuf); 1294 printf("\tmodel=%.16s\n", token->model); 1295 printf("\tserialNumber=%.16s\n", token->serial); 1296 printf("\tsupported operations=0x%x (", token->operations); 1297 first = ISC_TRUE; 1298 if (token->operations & (1 << OP_RAND)) { 1299 if (!first) 1300 printf(","); 1301 first = ISC_FALSE; 1302 printf("RAND"); 1303 } 1304 if (token->operations & (1 << OP_RSA)) { 1305 if (!first) 1306 printf(","); 1307 first = ISC_FALSE; 1308 printf("RSA"); 1309 } 1310 if (token->operations & (1 << OP_DSA)) { 1311 if (!first) 1312 printf(","); 1313 first = ISC_FALSE; 1314 printf("DSA"); 1315 } 1316 if (token->operations & (1 << OP_DH)) { 1317 if (!first) 1318 printf(","); 1319 first = ISC_FALSE; 1320 printf("DH"); 1321 } 1322 if (token->operations & (1 << OP_DIGEST)) { 1323 if (!first) 1324 printf(","); 1325 first = ISC_FALSE; 1326 printf("DIGEST"); 1327 } 1328 if (token->operations & (1 << OP_EC)) { 1329 if (!first) 1330 printf(","); 1331 first = ISC_FALSE; 1332 printf("EC"); 1333 } 1334 printf(")\n"); 1335 } 1336 } 1337