1/* 2 * OpenVPN -- An application to securely tunnel IP networks 3 * over a single TCP/UDP port, with support for SSL/TLS-based 4 * session authentication and key exchange, 5 * packet encryption, packet authentication, and 6 * packet compression. 7 * 8 * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 12 * as published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program (see the file COPYING included with this 21 * distribution); if not, write to the Free Software Foundation, Inc., 22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#elif defined(_MSC_VER) 28#include "config-msvc.h" 29#endif 30 31#include "syshead.h" 32 33#if defined(ENABLE_PKCS11) 34 35#include <pkcs11-helper-1.0/pkcs11h-certificate.h> 36#include "basic.h" 37#include "error.h" 38#include "manage.h" 39#include "base64.h" 40#include "pkcs11.h" 41#include "misc.h" 42#include "otime.h" 43#include "console.h" 44#include "pkcs11_backend.h" 45 46static 47time_t 48__mytime (void) { 49 return openvpn_time (NULL); 50} 51 52#if !defined(_WIN32) 53static 54int 55__mygettimeofday (struct timeval *tv) { 56 return gettimeofday (tv, NULL); 57} 58#endif 59 60static 61void 62__mysleep (const unsigned long usec) { 63#if defined(_WIN32) 64 Sleep (usec/1000); 65#else 66 usleep (usec); 67#endif 68} 69 70 71static pkcs11h_engine_system_t s_pkcs11h_sys_engine = { 72 malloc, 73 free, 74 __mytime, 75 __mysleep, 76#if defined(_WIN32) 77 NULL 78#else 79 __mygettimeofday 80#endif 81}; 82 83static 84unsigned 85_pkcs11_msg_pkcs112openvpn ( 86 const unsigned flags 87) { 88 unsigned openvpn_flags; 89 90 switch (flags) { 91 case PKCS11H_LOG_DEBUG2: 92 openvpn_flags = D_PKCS11_DEBUG; 93 break; 94 case PKCS11H_LOG_DEBUG1: 95 openvpn_flags = D_SHOW_PKCS11; 96 break; 97 case PKCS11H_LOG_INFO: 98 openvpn_flags = M_INFO; 99 break; 100 case PKCS11H_LOG_WARN: 101 openvpn_flags = M_WARN; 102 break; 103 case PKCS11H_LOG_ERROR: 104 openvpn_flags = M_FATAL; 105 break; 106 default: 107 openvpn_flags = M_FATAL; 108 break; 109 } 110 111#if defined(ENABLE_PKCS11_FORCE_DEBUG) 112 openvpn_flags=M_INFO; 113#endif 114 115 return openvpn_flags; 116} 117 118static 119unsigned 120_pkcs11_msg_openvpn2pkcs11 ( 121 const unsigned flags 122) { 123 unsigned pkcs11_flags; 124 125 if ((flags & D_PKCS11_DEBUG) != 0) { 126 pkcs11_flags = PKCS11H_LOG_DEBUG2; 127 } 128 else if ((flags & D_SHOW_PKCS11) != 0) { 129 pkcs11_flags = PKCS11H_LOG_DEBUG1; 130 } 131 else if ((flags & M_INFO) != 0) { 132 pkcs11_flags = PKCS11H_LOG_INFO; 133 } 134 else if ((flags & M_WARN) != 0) { 135 pkcs11_flags = PKCS11H_LOG_WARN; 136 } 137 else if ((flags & M_FATAL) != 0) { 138 pkcs11_flags = PKCS11H_LOG_ERROR; 139 } 140 else { 141 pkcs11_flags = PKCS11H_LOG_ERROR; 142 } 143 144#if defined(ENABLE_PKCS11_FORCE_DEBUG) 145 pkcs11_flags = PKCS11H_LOG_DEBUG2; 146#endif 147 148 return pkcs11_flags; 149} 150 151static 152void 153_pkcs11_openvpn_log ( 154 void * const global_data, 155 unsigned flags, 156 const char * const szFormat, 157 va_list args 158) { 159 char Buffer[10*1024]; 160 161 (void)global_data; 162 163 vsnprintf (Buffer, sizeof (Buffer), szFormat, args); 164 Buffer[sizeof (Buffer)-1] = 0; 165 166 msg (_pkcs11_msg_pkcs112openvpn (flags), "%s", Buffer); 167} 168 169static 170PKCS11H_BOOL 171_pkcs11_openvpn_token_prompt ( 172 void * const global_data, 173 void * const user_data, 174 const pkcs11h_token_id_t token, 175 const unsigned retry 176) { 177 struct user_pass token_resp; 178 179 (void)global_data; 180 (void)user_data; 181 (void)retry; 182 183 ASSERT (token!=NULL); 184 185 CLEAR (token_resp); 186 token_resp.defined = false; 187 token_resp.nocache = true; 188 openvpn_snprintf ( 189 token_resp.username, 190 sizeof (token_resp.username), 191 "Please insert %s token", 192 token->label 193 ); 194 195 if ( 196 !get_user_pass ( 197 &token_resp, 198 NULL, 199 "token-insertion-request", 200 GET_USER_PASS_MANAGEMENT|GET_USER_PASS_NEED_OK|GET_USER_PASS_NOFATAL 201 ) 202 ) { 203 return false; 204 } 205 else { 206 return strcmp (token_resp.password, "ok") == 0; 207 } 208} 209 210static 211PKCS11H_BOOL 212_pkcs11_openvpn_pin_prompt ( 213 void * const global_data, 214 void * const user_data, 215 const pkcs11h_token_id_t token, 216 const unsigned retry, 217 char * const pin, 218 const size_t pin_max 219) { 220 struct user_pass token_pass; 221 char prompt[1024]; 222 223 (void)global_data; 224 (void)user_data; 225 (void)retry; 226 227 ASSERT (token!=NULL); 228 229 openvpn_snprintf (prompt, sizeof (prompt), "%s token", token->label); 230 231 token_pass.defined = false; 232 token_pass.nocache = true; 233 234 if ( 235 !get_user_pass ( 236 &token_pass, 237 NULL, 238 prompt, 239 GET_USER_PASS_MANAGEMENT|GET_USER_PASS_PASSWORD_ONLY|GET_USER_PASS_NOFATAL 240 ) 241 ) { 242 return false; 243 } 244 else { 245 strncpynt (pin, token_pass.password, pin_max); 246 purge_user_pass (&token_pass, true); 247 248 if (strlen (pin) == 0) { 249 return false; 250 } 251 else { 252 return true; 253 } 254 } 255} 256 257bool 258pkcs11_initialize ( 259 const bool protected_auth, 260 const int nPINCachePeriod 261) { 262 CK_RV rv = CKR_FUNCTION_FAILED; 263 264 dmsg ( 265 D_PKCS11_DEBUG, 266 "PKCS#11: pkcs11_initialize - entered" 267 ); 268 269 if ((rv = pkcs11h_engine_setSystem (&s_pkcs11h_sys_engine)) != CKR_OK) { 270 msg (M_FATAL, "PKCS#11: Cannot initialize system engine %ld-'%s'", rv, pkcs11h_getMessage (rv)); 271 goto cleanup; 272 } 273 274 if ((rv = pkcs11h_initialize ()) != CKR_OK) { 275 msg (M_FATAL, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage (rv)); 276 goto cleanup; 277 } 278 279 if ((rv = pkcs11h_setLogHook (_pkcs11_openvpn_log, NULL)) != CKR_OK) { 280 msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv)); 281 goto cleanup; 282 } 283 284 pkcs11h_setLogLevel (_pkcs11_msg_openvpn2pkcs11 (get_debug_level ())); 285 286 if ((rv = pkcs11h_setForkMode (TRUE)) != CKR_OK) { 287 msg (M_FATAL, "PKCS#11: Cannot set fork mode %ld-'%s'", rv, pkcs11h_getMessage (rv)); 288 goto cleanup; 289 } 290 291 if ((rv = pkcs11h_setTokenPromptHook (_pkcs11_openvpn_token_prompt, NULL)) != CKR_OK) { 292 msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv)); 293 goto cleanup; 294 } 295 296 if ((rv = pkcs11h_setPINPromptHook (_pkcs11_openvpn_pin_prompt, NULL)) != CKR_OK) { 297 msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv)); 298 goto cleanup; 299 } 300 301 if ((rv = pkcs11h_setProtectedAuthentication (protected_auth)) != CKR_OK) { 302 msg (M_FATAL, "PKCS#11: Cannot set protected authentication mode %ld-'%s'", rv, pkcs11h_getMessage (rv)); 303 goto cleanup; 304 } 305 306 if ((rv = pkcs11h_setPINCachePeriod (nPINCachePeriod)) != CKR_OK) { 307 msg (M_FATAL, "PKCS#11: Cannot set Pcache period %ld-'%s'", rv, pkcs11h_getMessage (rv)); 308 goto cleanup; 309 } 310 311 rv = CKR_OK; 312 313cleanup: 314 dmsg ( 315 D_PKCS11_DEBUG, 316 "PKCS#11: pkcs11_initialize - return %ld-'%s'", 317 rv, 318 pkcs11h_getMessage (rv) 319 ); 320 321 return rv == CKR_OK; 322} 323 324void 325pkcs11_terminate () { 326 dmsg ( 327 D_PKCS11_DEBUG, 328 "PKCS#11: pkcs11_terminate - entered" 329 ); 330 331 pkcs11h_terminate (); 332 333 dmsg ( 334 D_PKCS11_DEBUG, 335 "PKCS#11: pkcs11_terminate - return" 336 ); 337} 338 339void 340pkcs11_forkFixup () { 341 pkcs11h_forkFixup (); 342} 343 344bool 345pkcs11_addProvider ( 346 const char * const provider, 347 const bool protected_auth, 348 const unsigned private_mode, 349 const bool cert_private 350) { 351 CK_RV rv = CKR_OK; 352 353 ASSERT (provider!=NULL); 354 355 dmsg ( 356 D_PKCS11_DEBUG, 357 "PKCS#11: pkcs11_addProvider - entered - provider='%s', private_mode=%08x", 358 provider, 359 private_mode 360 ); 361 362 msg ( 363 M_INFO, 364 "PKCS#11: Adding PKCS#11 provider '%s'", 365 provider 366 ); 367 368 if ( 369 (rv = pkcs11h_addProvider ( 370 provider, 371 provider, 372 protected_auth, 373 private_mode, 374 PKCS11H_SLOTEVENT_METHOD_AUTO, 375 0, 376 cert_private 377 )) != CKR_OK 378 ) { 379 msg (M_WARN, "PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv, pkcs11h_getMessage (rv)); 380 } 381 382 dmsg ( 383 D_PKCS11_DEBUG, 384 "PKCS#11: pkcs11_addProvider - return rv=%ld-'%s'", 385 rv, 386 pkcs11h_getMessage (rv) 387 ); 388 389 return rv == CKR_OK; 390} 391 392int 393pkcs11_logout() { 394 return pkcs11h_logout () == CKR_OK; 395} 396 397int 398pkcs11_management_id_count () { 399 pkcs11h_certificate_id_list_t id_list = NULL; 400 pkcs11h_certificate_id_list_t t = NULL; 401 CK_RV rv = CKR_OK; 402 int count = 0; 403 404 dmsg ( 405 D_PKCS11_DEBUG, 406 "PKCS#11: pkcs11_management_id_count - entered" 407 ); 408 409 if ( 410 (rv = pkcs11h_certificate_enumCertificateIds ( 411 PKCS11H_ENUM_METHOD_CACHE_EXIST, 412 NULL, 413 PKCS11H_PROMPT_MASK_ALLOW_ALL, 414 NULL, 415 &id_list 416 )) != CKR_OK 417 ) { 418 msg (M_WARN, "PKCS#11: Cannot get certificate list %ld-'%s'", rv, pkcs11h_getMessage (rv)); 419 goto cleanup; 420 } 421 422 for (count = 0, t = id_list; t != NULL; t = t->next) { 423 count++; 424 } 425 426cleanup: 427 428 if (id_list != NULL) { 429 pkcs11h_certificate_freeCertificateIdList (id_list); 430 id_list = NULL; 431 } 432 433 dmsg ( 434 D_PKCS11_DEBUG, 435 "PKCS#11: pkcs11_management_id_count - return count=%d", 436 count 437 ); 438 439 return count; 440} 441 442bool 443pkcs11_management_id_get ( 444 const int index, 445 char ** id, 446 char **base64 447) { 448 pkcs11h_certificate_id_list_t id_list = NULL; 449 pkcs11h_certificate_id_list_t entry = NULL; 450#if 0 /* certificate_id seems to be unused -- JY */ 451 pkcs11h_certificate_id_t certificate_id = NULL; 452#endif 453 pkcs11h_certificate_t certificate = NULL; 454 CK_RV rv = CKR_OK; 455 unsigned char *certificate_blob = NULL; 456 size_t certificate_blob_size = 0; 457 size_t max; 458 char *internal_id = NULL; 459 char *internal_base64 = NULL; 460 int count = 0; 461 bool success = false; 462 463 ASSERT (id!=NULL); 464 ASSERT (base64!=NULL); 465 466 dmsg ( 467 D_PKCS11_DEBUG, 468 "PKCS#11: pkcs11_management_id_get - entered index=%d", 469 index 470 ); 471 472 *id = NULL; 473 *base64 = NULL; 474 475 if ( 476 (rv = pkcs11h_certificate_enumCertificateIds ( 477 PKCS11H_ENUM_METHOD_CACHE_EXIST, 478 NULL, 479 PKCS11H_PROMPT_MASK_ALLOW_ALL, 480 NULL, 481 &id_list 482 )) != CKR_OK 483 ) { 484 msg (M_WARN, "PKCS#11: Cannot get certificate list %ld-'%s'", rv, pkcs11h_getMessage (rv)); 485 goto cleanup; 486 } 487 488 entry = id_list; 489 count = 0; 490 while (entry != NULL && count != index) { 491 count++; 492 entry = entry->next; 493 } 494 495 if (entry == NULL) { 496 dmsg ( 497 D_PKCS11_DEBUG, 498 "PKCS#11: pkcs11_management_id_get - no certificate at index=%d", 499 index 500 ); 501 goto cleanup; 502 } 503 504 if ( 505 (rv = pkcs11h_certificate_serializeCertificateId ( 506 NULL, 507 &max, 508 entry->certificate_id 509 )) != CKR_OK 510 ) { 511 msg (M_WARN, "PKCS#11: Cannot serialize certificate id %ld-'%s'", rv, pkcs11h_getMessage (rv)); 512 goto cleanup; 513 } 514 515 if ((internal_id = (char *)malloc (max)) == NULL) { 516 msg (M_FATAL, "PKCS#11: Cannot allocate memory"); 517 goto cleanup; 518 } 519 520 if ( 521 (rv = pkcs11h_certificate_serializeCertificateId ( 522 internal_id, 523 &max, 524 entry->certificate_id 525 )) != CKR_OK 526 ) { 527 msg (M_WARN, "PKCS#11: Cannot serialize certificate id %ld-'%s'", rv, pkcs11h_getMessage (rv)); 528 goto cleanup; 529 } 530 531 if ( 532 (rv = pkcs11h_certificate_create ( 533 entry->certificate_id, 534 NULL, 535 PKCS11H_PROMPT_MASK_ALLOW_ALL, 536 PKCS11H_PIN_CACHE_INFINITE, 537 &certificate 538 )) != CKR_OK 539 ) { 540 msg (M_WARN, "PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage (rv)); 541 goto cleanup; 542 } 543 544 if ( 545 (rv = pkcs11h_certificate_getCertificateBlob ( 546 certificate, 547 NULL, 548 &certificate_blob_size 549 )) != CKR_OK 550 ) { 551 msg (M_WARN, "PKCS#11: Cannot get certificate blob %ld-'%s'", rv, pkcs11h_getMessage (rv)); 552 goto cleanup; 553 } 554 555 if ((certificate_blob = (unsigned char *)malloc (certificate_blob_size)) == NULL) { 556 msg (M_FATAL, "PKCS#11: Cannot allocate memory"); 557 goto cleanup; 558 } 559 560 if ( 561 (rv = pkcs11h_certificate_getCertificateBlob ( 562 certificate, 563 certificate_blob, 564 &certificate_blob_size 565 )) != CKR_OK 566 ) { 567 msg (M_WARN, "PKCS#11: Cannot get certificate blob %ld-'%s'", rv, pkcs11h_getMessage (rv)); 568 goto cleanup; 569 } 570 571 if (openvpn_base64_encode (certificate_blob, certificate_blob_size, &internal_base64) == -1) { 572 msg (M_WARN, "PKCS#11: Cannot encode certificate"); 573 goto cleanup; 574 } 575 576 *id = internal_id; 577 internal_id = NULL; 578 *base64 = internal_base64; 579 internal_base64 = NULL; 580 success = true; 581 582cleanup: 583 584 if (id_list != NULL) { 585 pkcs11h_certificate_freeCertificateIdList (id_list); 586 id_list = NULL; 587 } 588 589 if (internal_id != NULL) { 590 free (internal_id); 591 internal_id = NULL; 592 } 593 594 if (internal_base64 != NULL) { 595 free (internal_base64); 596 internal_base64 = NULL; 597 } 598 599 if (certificate_blob != NULL) { 600 free (certificate_blob); 601 certificate_blob = NULL; 602 } 603 604 dmsg ( 605 D_PKCS11_DEBUG, 606 "PKCS#11: pkcs11_management_id_get - return success=%d, id='%s'", 607 success ? 1 : 0, 608 *id 609 ); 610 611 return success; 612} 613 614int 615tls_ctx_use_pkcs11 ( 616 struct tls_root_ctx * const ssl_ctx, 617 bool pkcs11_id_management, 618 const char * const pkcs11_id 619) { 620 pkcs11h_certificate_id_t certificate_id = NULL; 621 pkcs11h_certificate_t certificate = NULL; 622 CK_RV rv = CKR_OK; 623 624 bool ok = false; 625 626 ASSERT (ssl_ctx!=NULL); 627 ASSERT (pkcs11_id_management || pkcs11_id!=NULL); 628 629 dmsg ( 630 D_PKCS11_DEBUG, 631 "PKCS#11: tls_ctx_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_id_management=%d, pkcs11_id='%s'", 632 (void *)ssl_ctx, 633 pkcs11_id_management ? 1 : 0, 634 pkcs11_id 635 ); 636 637 if (pkcs11_id_management) { 638 struct user_pass id_resp; 639 640 CLEAR (id_resp); 641 642 id_resp.defined = false; 643 id_resp.nocache = true; 644 openvpn_snprintf ( 645 id_resp.username, 646 sizeof (id_resp.username), 647 "Please specify PKCS#11 id to use" 648 ); 649 650 if ( 651 !get_user_pass ( 652 &id_resp, 653 NULL, 654 "pkcs11-id-request", 655 GET_USER_PASS_MANAGEMENT|GET_USER_PASS_NEED_STR|GET_USER_PASS_NOFATAL 656 ) 657 ) { 658 goto cleanup; 659 } 660 661 if ( 662 (rv = pkcs11h_certificate_deserializeCertificateId ( 663 &certificate_id, 664 id_resp.password 665 )) != CKR_OK 666 ) { 667 msg (M_WARN, "PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage (rv)); 668 goto cleanup; 669 } 670 } 671 else { 672 if ( 673 (rv = pkcs11h_certificate_deserializeCertificateId ( 674 &certificate_id, 675 pkcs11_id 676 )) != CKR_OK 677 ) { 678 msg (M_WARN, "PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage (rv)); 679 goto cleanup; 680 } 681 } 682 683 if ( 684 (rv = pkcs11h_certificate_create ( 685 certificate_id, 686 NULL, 687 PKCS11H_PROMPT_MASK_ALLOW_ALL, 688 PKCS11H_PIN_CACHE_INFINITE, 689 &certificate 690 )) != CKR_OK 691 ) { 692 msg (M_WARN, "PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage (rv)); 693 goto cleanup; 694 } 695 696 if ( 697 (pkcs11_init_tls_session ( 698 certificate, 699 ssl_ctx 700 )) 701 ) { 702 /* Handled by SSL context free */ 703 certificate = NULL; 704 goto cleanup; 705 } 706 707 /* Handled by SSL context free */ 708 certificate = NULL; 709 ok = true; 710 711cleanup: 712 if (certificate != NULL) { 713 pkcs11h_certificate_freeCertificate (certificate); 714 certificate = NULL; 715 } 716 717 if (certificate_id != NULL) { 718 pkcs11h_certificate_freeCertificateId (certificate_id); 719 certificate_id = NULL; 720 } 721 722 dmsg ( 723 D_PKCS11_DEBUG, 724 "PKCS#11: tls_ctx_use_pkcs11 - return ok=%d, rv=%ld", 725 ok ? 1 : 0, 726 rv 727 ); 728 729 return ok ? 1 : 0; 730} 731 732static 733PKCS11H_BOOL 734_pkcs11_openvpn_show_pkcs11_ids_pin_prompt ( 735 void * const global_data, 736 void * const user_data, 737 const pkcs11h_token_id_t token, 738 const unsigned retry, 739 char * const pin, 740 const size_t pin_max 741) { 742 struct gc_arena gc = gc_new (); 743 struct buffer pass_prompt = alloc_buf_gc (128, &gc); 744 745 (void)global_data; 746 (void)user_data; 747 (void)retry; 748 749 ASSERT (token!=NULL); 750 751 buf_printf (&pass_prompt, "Please enter '%s' token PIN or 'cancel': ", token->display); 752 753 if (!get_console_input (BSTR (&pass_prompt), false, pin, pin_max)) { 754 msg (M_FATAL, "Cannot read password from stdin"); 755 } 756 757 gc_free (&gc); 758 759 if (!strcmp (pin, "cancel")) { 760 return FALSE; 761 } 762 else { 763 return TRUE; 764 } 765} 766 767void 768show_pkcs11_ids ( 769 const char * const provider, 770 bool cert_private 771) { 772 struct gc_arena gc = gc_new(); 773 pkcs11h_certificate_id_list_t user_certificates = NULL; 774 pkcs11h_certificate_id_list_t current = NULL; 775 CK_RV rv = CKR_FUNCTION_FAILED; 776 777 if ((rv = pkcs11h_initialize ()) != CKR_OK) { 778 msg (M_FATAL, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage (rv)); 779 goto cleanup; 780 } 781 782 if ((rv = pkcs11h_setLogHook (_pkcs11_openvpn_log, NULL)) != CKR_OK) { 783 msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv)); 784 goto cleanup; 785 } 786 787 pkcs11h_setLogLevel (_pkcs11_msg_openvpn2pkcs11 (get_debug_level ())); 788 789 if ((rv = pkcs11h_setProtectedAuthentication (TRUE)) != CKR_OK) { 790 msg (M_FATAL, "PKCS#11: Cannot set protected authentication %ld-'%s'", rv, pkcs11h_getMessage (rv)); 791 goto cleanup; 792 } 793 794 if ((rv = pkcs11h_setPINPromptHook (_pkcs11_openvpn_show_pkcs11_ids_pin_prompt, NULL)) != CKR_OK) { 795 msg (M_FATAL, "PKCS#11: Cannot set PIN hook %ld-'%s'", rv, pkcs11h_getMessage (rv)); 796 goto cleanup; 797 } 798 799 if ( 800 (rv = pkcs11h_addProvider ( 801 provider, 802 provider, 803 TRUE, 804 0, 805 FALSE, 806 0, 807 cert_private ? TRUE : FALSE 808 )) != CKR_OK 809 ) { 810 msg (M_FATAL, "PKCS#11: Cannot add provider '%s' %ld-'%s'", provider, rv, pkcs11h_getMessage (rv)); 811 goto cleanup; 812 } 813 814 if ( 815 (rv = pkcs11h_certificate_enumCertificateIds ( 816 PKCS11H_ENUM_METHOD_CACHE_EXIST, 817 NULL, 818 PKCS11H_PROMPT_MASK_ALLOW_ALL, 819 NULL, 820 &user_certificates 821 )) != CKR_OK 822 ) { 823 msg (M_FATAL, "PKCS#11: Cannot enumerate certificates %ld-'%s'", rv, pkcs11h_getMessage (rv)); 824 goto cleanup; 825 } 826 827 msg ( 828 M_INFO|M_NOPREFIX|M_NOLF, 829 ( 830 "\n" 831 "The following objects are available for use.\n" 832 "Each object shown below may be used as parameter to\n" 833 "--pkcs11-id option please remember to use single quote mark.\n" 834 ) 835 ); 836 for (current = user_certificates;current != NULL; current = current->next) { 837 pkcs11h_certificate_t certificate = NULL; 838 char *dn = NULL; 839 char serial[1024] = {0}; 840 char *ser = NULL; 841 size_t ser_len = 0; 842 843 if ( 844 (rv = pkcs11h_certificate_serializeCertificateId ( 845 NULL, 846 &ser_len, 847 current->certificate_id 848 )) != CKR_OK 849 ) { 850 msg (M_FATAL, "PKCS#11: Cannot serialize certificate %ld-'%s'", rv, pkcs11h_getMessage (rv)); 851 goto cleanup1; 852 } 853 854 if ( 855 rv == CKR_OK && 856 (ser = (char *)malloc (ser_len)) == NULL 857 ) { 858 msg (M_FATAL, "PKCS#11: Cannot allocate memory"); 859 goto cleanup1; 860 } 861 862 if ( 863 (rv = pkcs11h_certificate_serializeCertificateId ( 864 ser, 865 &ser_len, 866 current->certificate_id 867 )) != CKR_OK 868 ) { 869 msg (M_FATAL, "PKCS#11: Cannot serialize certificate %ld-'%s'", rv, pkcs11h_getMessage (rv)); 870 goto cleanup1; 871 } 872 873 if ( 874 (rv = pkcs11h_certificate_create ( 875 current->certificate_id, 876 NULL, 877 PKCS11H_PROMPT_MASK_ALLOW_ALL, 878 PKCS11H_PIN_CACHE_INFINITE, 879 &certificate 880 )) 881 ) { 882 msg (M_FATAL, "PKCS#11: Cannot create certificate %ld-'%s'", rv, pkcs11h_getMessage (rv)); 883 goto cleanup1; 884 } 885 886 if ( 887 (dn = pkcs11_certificate_dn ( 888 certificate, 889 &gc 890 )) == NULL 891 ) { 892 goto cleanup1; 893 } 894 895 if ( 896 (pkcs11_certificate_serial ( 897 certificate, 898 serial, 899 sizeof(serial) 900 )) 901 ) { 902 goto cleanup1; 903 } 904 905 msg ( 906 M_INFO|M_NOPREFIX|M_NOLF, 907 ( 908 "\n" 909 "Certificate\n" 910 " DN: %s\n" 911 " Serial: %s\n" 912 " Serialized id: %s\n" 913 ), 914 dn, 915 serial, 916 ser 917 ); 918 919 cleanup1: 920 921 if (certificate != NULL) { 922 pkcs11h_certificate_freeCertificate (certificate); 923 certificate = NULL; 924 } 925 926 if (ser != NULL) { 927 free (ser); 928 ser = NULL; 929 } 930 } 931 932cleanup: 933 if (user_certificates != NULL) { 934 pkcs11h_certificate_freeCertificateIdList (user_certificates); 935 user_certificates = NULL; 936 } 937 938 pkcs11h_terminate (); 939 gc_free (&gc); 940} 941 942#else 943#ifdef _MSC_VER /* Dummy function needed to avoid empty file compiler warning in Microsoft VC */ 944static void dummy (void) {} 945#endif 946#endif /* ENABLE_PKCS11 */ 947