1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 26 #include <fcntl.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <strings.h> 30 #include <unistd.h> 31 #include <locale.h> 32 #include <libgen.h> 33 #include <sys/types.h> 34 #include <zone.h> 35 #include <sys/crypto/ioctladmin.h> 36 #include <cryptoutil.h> 37 #include "cryptoadm.h" 38 39 #define REQ_ARG_CNT 2 40 41 /* subcommand index */ 42 enum subcommand_index { 43 CRYPTO_LIST, 44 CRYPTO_DISABLE, 45 CRYPTO_ENABLE, 46 CRYPTO_INSTALL, 47 CRYPTO_UNINSTALL, 48 CRYPTO_UNLOAD, 49 CRYPTO_REFRESH, 50 CRYPTO_START, 51 CRYPTO_STOP, 52 CRYPTO_HELP }; 53 54 /* 55 * TRANSLATION_NOTE 56 * Command keywords are not to be translated. 57 */ 58 static char *cmd_table[] = { 59 "list", 60 "disable", 61 "enable", 62 "install", 63 "uninstall", 64 "unload", 65 "refresh", 66 "start", 67 "stop", 68 "--help" }; 69 70 /* provider type */ 71 enum provider_type_index { 72 PROV_UEF_LIB, 73 PROV_KEF_SOFT, 74 PROV_KEF_HARD, 75 METASLOT, 76 PROV_BADNAME }; 77 78 typedef struct { 79 char cp_name[MAXPATHLEN]; 80 enum provider_type_index cp_type; 81 } cryptoadm_provider_t; 82 83 /* 84 * TRANSLATION_NOTE 85 * Operand keywords are not to be translated. 86 */ 87 static const char *KN_PROVIDER = "provider="; 88 static const char *KN_MECH = "mechanism="; 89 static const char *KN_ALL = "all"; 90 static const char *KN_TOKEN = "token="; 91 static const char *KN_SLOT = "slot="; 92 static const char *KN_DEFAULT_KS = "default-keystore"; 93 static const char *KN_AUTO_KEY_MIGRATE = "auto-key-migrate"; 94 95 /* static variables */ 96 static boolean_t allflag = B_FALSE; 97 static boolean_t rndflag = B_FALSE; 98 static mechlist_t *mecharglist = NULL; 99 100 /* static functions */ 101 static void usage(void); 102 static int get_provider_type(char *); 103 static int process_mech_operands(int, char **, boolean_t); 104 static int do_list(int, char **); 105 static int do_disable(int, char **); 106 static int do_enable(int, char **); 107 static int do_install(int, char **); 108 static int do_uninstall(int, char **); 109 static int do_unload(int, char **); 110 static int do_refresh(int); 111 static int do_start(int); 112 static int do_stop(int); 113 static int list_simple_for_all(boolean_t); 114 static int list_mechlist_for_all(boolean_t); 115 static int list_policy_for_all(void); 116 117 int 118 main(int argc, char *argv[]) 119 { 120 char *subcmd; 121 int cmdnum; 122 int cmd_index = 0; 123 int rc = SUCCESS; 124 125 (void) setlocale(LC_ALL, ""); 126 127 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 128 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 129 #endif 130 (void) textdomain(TEXT_DOMAIN); 131 132 cryptodebug_init(basename(argv[0])); 133 134 if (argc < REQ_ARG_CNT) { 135 usage(); 136 return (ERROR_USAGE); 137 } 138 139 /* get the subcommand index */ 140 cmd_index = 0; 141 subcmd = argv[1]; 142 cmdnum = sizeof (cmd_table)/sizeof (cmd_table[0]); 143 144 while ((cmd_index < cmdnum) && 145 (strcmp(subcmd, cmd_table[cmd_index]) != 0)) { 146 cmd_index++; 147 } 148 if (cmd_index >= cmdnum) { 149 usage(); 150 return (ERROR_USAGE); 151 } 152 153 /* do the subcommand */ 154 switch (cmd_index) { 155 case CRYPTO_LIST: 156 rc = do_list(argc, argv); 157 break; 158 case CRYPTO_DISABLE: 159 rc = do_disable(argc, argv); 160 break; 161 case CRYPTO_ENABLE: 162 rc = do_enable(argc, argv); 163 break; 164 case CRYPTO_INSTALL: 165 rc = do_install(argc, argv); 166 break; 167 case CRYPTO_UNINSTALL: 168 rc = do_uninstall(argc, argv); 169 break; 170 case CRYPTO_UNLOAD: 171 rc = do_unload(argc, argv); 172 break; 173 case CRYPTO_REFRESH: 174 rc = do_refresh(argc); 175 break; 176 case CRYPTO_START: 177 rc = do_start(argc); 178 break; 179 case CRYPTO_STOP: 180 rc = do_stop(argc); 181 break; 182 case CRYPTO_HELP: 183 usage(); 184 rc = SUCCESS; 185 break; 186 default: /* should not come here */ 187 usage(); 188 rc = ERROR_USAGE; 189 break; 190 } 191 return (rc); 192 } 193 194 195 static void 196 usage(void) 197 { 198 /* 199 * TRANSLATION_NOTE 200 * Command usage is not to be translated. Only the word "Usage:" 201 * along with localized expressions indicating what kind of value 202 * is expected for arguments. 203 */ 204 (void) fprintf(stderr, gettext("Usage:\n")); 205 (void) fprintf(stderr, 206 " cryptoadm list [-mpv] [provider=<%s> | metaslot]" 207 " [mechanism=<%s>]\n", 208 gettext("provider-name"), gettext("mechanism-list")); 209 (void) fprintf(stderr, 210 " cryptoadm list fips-140\n"); 211 (void) fprintf(stderr, 212 " cryptoadm disable provider=<%s>" 213 " mechanism=<%s> | random | all\n", 214 gettext("provider-name"), gettext("mechanism-list")); 215 (void) fprintf(stderr, 216 " cryptoadm disable metaslot" 217 " [auto-key-migrate] [mechanism=<%s>]\n", 218 gettext("mechanism-list")); 219 (void) fprintf(stderr, 220 " cryptoadm disable fips-140\n"); 221 (void) fprintf(stderr, 222 " cryptoadm enable provider=<%s>" 223 " mechanism=<%s> | random | all\n", 224 gettext("provider-name"), gettext("mechanism-list")); 225 (void) fprintf(stderr, 226 " cryptoadm enable metaslot [mechanism=<%s>]" 227 " [[token=<%s>] [slot=<%s>]" 228 " | [default-keystore]] | [auto-key-migrate]\n", 229 gettext("mechanism-list"), gettext("token-label"), 230 gettext("slot-description")); 231 (void) fprintf(stderr, 232 " cryptoadm enable fips-140\n"); 233 (void) fprintf(stderr, 234 " cryptoadm install provider=<%s>\n", 235 gettext("provider-name")); 236 (void) fprintf(stderr, 237 " cryptoadm install provider=<%s> [mechanism=<%s>]\n", 238 gettext("provider-name"), gettext("mechanism-list")); 239 (void) fprintf(stderr, 240 " cryptoadm uninstall provider=<%s>\n", 241 gettext("provider-name")); 242 (void) fprintf(stderr, 243 " cryptoadm unload provider=<%s>\n", 244 gettext("provider-name")); 245 (void) fprintf(stderr, 246 " cryptoadm refresh\n" 247 " cryptoadm start\n" 248 " cryptoadm stop\n" 249 " cryptoadm --help\n"); 250 } 251 252 253 /* 254 * Get the provider type. This function returns 255 * - PROV_UEF_LIB if provname contains an absolute path name 256 * - PROV_KEF_SOFT if provname is a base name only (e.g., "aes"). 257 * - PROV_KEF_HARD if provname contains one slash only and the slash is not 258 * the 1st character (e.g., "mca/0"). 259 * - PROV_BADNAME otherwise. 260 */ 261 static int 262 get_provider_type(char *provname) 263 { 264 char *pslash1; 265 char *pslash2; 266 267 if (provname == NULL) { 268 return (FAILURE); 269 } 270 271 if (provname[0] == '/') { 272 return (PROV_UEF_LIB); 273 } else if ((pslash1 = strchr(provname, SEP_SLASH)) == NULL) { 274 /* no slash */ 275 return (PROV_KEF_SOFT); 276 } else { 277 pslash2 = strrchr(provname, SEP_SLASH); 278 if (pslash1 == pslash2) { 279 return (PROV_KEF_HARD); 280 } else { 281 return (PROV_BADNAME); 282 } 283 } 284 } 285 286 /* 287 * Get the provider structure. This function returns NULL if no valid 288 * provider= is found in argv[], otherwise a cryptoadm_provider_t is returned. 289 * If provider= is found but has no argument, then a cryptoadm_provider_t 290 * with cp_type = PROV_BADNAME is returned. 291 */ 292 static cryptoadm_provider_t * 293 get_provider(int argc, char **argv) 294 { 295 int c = 0; 296 boolean_t found = B_FALSE; 297 cryptoadm_provider_t *provider = NULL; 298 char *provstr = NULL, *savstr; 299 boolean_t is_metaslot = B_FALSE; 300 301 while (!found && ++c < argc) { 302 if (strncmp(argv[c], METASLOT_KEYWORD, 303 strlen(METASLOT_KEYWORD)) == 0) { 304 is_metaslot = B_TRUE; 305 found = B_TRUE; 306 } else if (strncmp(argv[c], KN_PROVIDER, 307 strlen(KN_PROVIDER)) == 0 && 308 strlen(argv[c]) > strlen(KN_PROVIDER)) { 309 if ((provstr = strdup(argv[c])) == NULL) { 310 int err = errno; 311 /* 312 * TRANSLATION_NOTE 313 * "get_provider" is a function name and should 314 * not be translated. 315 */ 316 cryptoerror(LOG_STDERR, "get_provider: %s.", 317 strerror(err)); 318 return (NULL); 319 } 320 found = B_TRUE; 321 } 322 } 323 if (!found) 324 return (NULL); 325 326 provider = malloc(sizeof (cryptoadm_provider_t)); 327 if (provider == NULL) { 328 cryptoerror(LOG_STDERR, gettext("out of memory.")); 329 if (provstr) { 330 free(provstr); 331 } 332 return (NULL); 333 } 334 335 if (is_metaslot) { 336 (void) strlcpy(provider->cp_name, METASLOT_KEYWORD, 337 strlen(METASLOT_KEYWORD)); 338 provider->cp_type = METASLOT; 339 } else { 340 341 savstr = provstr; 342 (void) strtok(provstr, "="); 343 provstr = strtok(NULL, "="); 344 if (provstr == NULL) { 345 cryptoerror(LOG_STDERR, gettext("bad provider name.")); 346 provider->cp_type = PROV_BADNAME; 347 free(savstr); 348 return (provider); 349 } 350 351 (void) strlcpy(provider->cp_name, provstr, 352 sizeof (provider->cp_name)); 353 provider->cp_type = get_provider_type(provider->cp_name); 354 355 free(savstr); 356 } 357 return (provider); 358 } 359 360 /* 361 * Process the "feature" operands. 362 * 363 * "argc" and "argv" contain values specified on the command line. 364 * All other arguments are used for returning parsing results. 365 * If any of these arguments are NULL, that keyword is not expected, 366 * and FAILURE will be returned. 367 */ 368 static int 369 process_metaslot_operands(int argc, char **argv, char **meta_ks_token, 370 char **meta_ks_slot, boolean_t *use_default, 371 boolean_t *auto_key_migrate_flag) 372 { 373 int c = 2; 374 int rc = SUCCESS; 375 376 while (++c < argc) { 377 if ((strncmp(argv[c], KN_MECH, strlen(KN_MECH)) == 0) && 378 strlen(argv[c]) > strlen(KN_MECH)) { 379 380 /* process mechanism operands */ 381 if ((rc = process_mech_operands(argc, argv, B_TRUE)) 382 != SUCCESS) { 383 goto finish; 384 } 385 386 } else if ((strncmp(argv[c], KN_TOKEN, 387 strlen(KN_TOKEN)) == 0) && 388 strlen(argv[c]) > strlen(KN_TOKEN)) { 389 if ((meta_ks_token) && (strtok(argv[c], "=") != NULL)) { 390 char *tmp; 391 if ((tmp = strtok(NULL, "=")) != NULL) { 392 *meta_ks_token = strdup(tmp); 393 } else { 394 return (FAILURE); 395 } 396 } else { 397 return (FAILURE); 398 } 399 400 } else if ((strncmp(argv[c], KN_SLOT, 401 strlen(KN_SLOT)) == 0) && 402 strlen(argv[c]) > strlen(KN_SLOT)) { 403 404 if ((meta_ks_slot) && (strtok(argv[c], "=") != NULL)) { 405 char *tmp; 406 if ((tmp = strtok(NULL, "=")) != NULL) { 407 *meta_ks_slot = strdup(tmp); 408 } else { 409 return (FAILURE); 410 } 411 } else { 412 return (FAILURE); 413 } 414 415 } else if (strncmp(argv[c], KN_DEFAULT_KS, 416 strlen(KN_DEFAULT_KS)) == 0) { 417 418 if (use_default) { 419 *use_default = B_TRUE; 420 } else { 421 return (FAILURE); 422 } 423 } else if (strncmp(argv[c], KN_AUTO_KEY_MIGRATE, 424 strlen(KN_AUTO_KEY_MIGRATE)) == 0) { 425 426 if (auto_key_migrate_flag) { 427 *auto_key_migrate_flag = B_TRUE; 428 } else { 429 return (FAILURE); 430 } 431 } else { 432 return (FAILURE); 433 } 434 } 435 finish: 436 return (rc); 437 } 438 439 /* 440 * Process the "feature" operands. 441 */ 442 static int 443 process_feature_operands(int argc, char **argv) 444 { 445 int c = 2; 446 447 while (++c < argc) { 448 if (strcmp(argv[c], KN_ALL) == 0) { 449 allflag = B_TRUE; 450 rndflag = B_TRUE; /* all includes random also. */ 451 } else if (strcmp(argv[c], RANDOM) == 0) { 452 rndflag = B_TRUE; 453 } 454 } 455 return (SUCCESS); 456 } 457 458 /* 459 * Process the mechanism operands for the disable, enable and install 460 * subcommands. This function sets the static variable allflag to be B_TRUE 461 * if the keyword "all" is specified, otherwise builds a link list of the 462 * mechanism operands and save it in the static variable mecharglist. 463 * 464 * This function returns 465 * ERROR_USAGE: mechanism operand is missing. 466 * FAILURE: out of memory. 467 * SUCCESS: otherwise. 468 */ 469 static int 470 process_mech_operands(int argc, char **argv, boolean_t quiet) 471 { 472 mechlist_t *pmech; 473 mechlist_t *pcur = NULL; 474 mechlist_t *phead = NULL; 475 boolean_t found = B_FALSE; 476 char *mechliststr = NULL; 477 char *curmech = NULL; 478 int c = -1; 479 int rc = SUCCESS; 480 481 while (!found && ++c < argc) { 482 if ((strncmp(argv[c], KN_MECH, strlen(KN_MECH)) == 0) && 483 strlen(argv[c]) > strlen(KN_MECH)) { 484 found = B_TRUE; 485 } 486 } 487 if (!found) { 488 if (!quiet) 489 /* 490 * TRANSLATION_NOTE 491 * "mechanism" could be either a literal keyword 492 * and hence not to be translated, or a descriptive 493 * word and translatable. A choice was made to 494 * view it as a literal keyword. 495 */ 496 cryptoerror(LOG_STDERR, 497 gettext("the %s operand is missing.\n"), 498 "mechanism"); 499 return (ERROR_USAGE); 500 } 501 (void) strtok(argv[c], "="); 502 mechliststr = strtok(NULL, "="); 503 504 if (strcmp(mechliststr, "all") == 0) { 505 allflag = B_TRUE; 506 mecharglist = NULL; 507 return (SUCCESS); 508 } 509 510 curmech = strtok(mechliststr, ","); 511 do { 512 if ((pmech = create_mech(curmech)) == NULL) { 513 rc = FAILURE; 514 break; 515 } else { 516 if (phead == NULL) { 517 phead = pcur = pmech; 518 } else { 519 pcur->next = pmech; 520 pcur = pmech; 521 } 522 } 523 } while ((curmech = strtok(NULL, ",")) != NULL); 524 525 if (rc == FAILURE) { 526 cryptoerror(LOG_STDERR, gettext("out of memory.")); 527 free_mechlist(phead); 528 } else { 529 mecharglist = phead; 530 rc = SUCCESS; 531 } 532 return (rc); 533 } 534 535 536 537 /* 538 * The top level function for the "cryptoadm list" subcommand and options. 539 */ 540 static int 541 do_list(int argc, char **argv) 542 { 543 boolean_t mflag = B_FALSE; 544 boolean_t pflag = B_FALSE; 545 boolean_t vflag = B_FALSE; 546 char ch; 547 cryptoadm_provider_t *prov = NULL; 548 int rc = SUCCESS; 549 550 if ((argc == 3) && (strncmp(argv[2], FIPS_KEYWORD, 551 strlen(FIPS_KEYWORD))) == 0) { 552 int success_count = 0; 553 /* 554 * cryptoadm list fips-140 555 */ 556 rc = do_fips_actions(FIPS140_STATUS, NOT_REFRESH); 557 if (rc == SUCCESS) 558 success_count++; 559 (void) printf(gettext("\nKernel hardware providers:\n")); 560 (void) printf(gettext("=========================:\n")); 561 rc = do_fips_hw_actions(FIPS140_STATUS, HW_PROVIDER_NCP); 562 if (rc == SUCCESS) 563 success_count++; 564 rc = do_fips_hw_actions(FIPS140_STATUS, HW_PROVIDER_N2CP); 565 if (rc == SUCCESS) 566 success_count++; 567 rc = do_fips_hw_actions(FIPS140_STATUS, HW_PROVIDER_N2RNG); 568 if (rc == SUCCESS) 569 success_count++; 570 /* succeed to get status from config file? */ 571 return ((success_count > 0) ? SUCCESS: FAILURE); 572 } 573 574 argc -= 1; 575 argv += 1; 576 577 if (argc == 1) { 578 rc = list_simple_for_all(B_FALSE); 579 goto out; 580 } 581 582 /* 583 * cryptoadm list [-v] [-m] [-p] [provider=<>] [mechanism=<>] 584 */ 585 if (argc > 5) { 586 usage(); 587 return (rc); 588 } 589 590 while ((ch = getopt(argc, argv, "mpv")) != EOF) { 591 switch (ch) { 592 case 'm': 593 mflag = B_TRUE; 594 if (pflag) { 595 rc = ERROR_USAGE; 596 } 597 break; 598 case 'p': 599 pflag = B_TRUE; 600 if (mflag || vflag) { 601 rc = ERROR_USAGE; 602 } 603 break; 604 case 'v': 605 vflag = B_TRUE; 606 if (pflag) 607 rc = ERROR_USAGE; 608 break; 609 default: 610 rc = ERROR_USAGE; 611 break; 612 } 613 } 614 615 if (rc == ERROR_USAGE) { 616 usage(); 617 return (rc); 618 } 619 620 if ((rc = process_feature_operands(argc, argv)) != SUCCESS) { 621 goto out; 622 } 623 624 prov = get_provider(argc, argv); 625 626 if (mflag || vflag) { 627 if (argc > 0) { 628 rc = process_mech_operands(argc, argv, B_TRUE); 629 if (rc == FAILURE) 630 goto out; 631 /* "-m" is implied when a mechanism list is given */ 632 if (mecharglist != NULL || allflag) 633 mflag = B_TRUE; 634 } 635 } 636 637 if (prov == NULL) { 638 if (mflag) { 639 rc = list_mechlist_for_all(vflag); 640 } else if (pflag) { 641 rc = list_policy_for_all(); 642 } else if (vflag) { 643 rc = list_simple_for_all(vflag); 644 } 645 } else if (prov->cp_type == METASLOT) { 646 if ((!mflag) && (!vflag) && (!pflag)) { 647 /* no flag is specified, just list metaslot status */ 648 rc = list_metaslot_info(mflag, vflag, mecharglist); 649 } else if (mflag || vflag) { 650 rc = list_metaslot_info(mflag, vflag, mecharglist); 651 } else if (pflag) { 652 rc = list_metaslot_policy(); 653 } else { 654 /* error message */ 655 usage(); 656 rc = ERROR_USAGE; 657 } 658 } else if (prov->cp_type == PROV_BADNAME) { 659 usage(); 660 rc = ERROR_USAGE; 661 goto out; 662 } else { /* do the listing for a provider only */ 663 char *provname = prov->cp_name; 664 665 if (mflag || vflag) { 666 if (vflag) 667 (void) printf(gettext("Provider: %s\n"), 668 provname); 669 switch (prov->cp_type) { 670 case PROV_UEF_LIB: 671 rc = list_mechlist_for_lib(provname, 672 mecharglist, NULL, B_FALSE, vflag, mflag); 673 break; 674 case PROV_KEF_SOFT: 675 rc = list_mechlist_for_soft(provname, 676 NULL, NULL); 677 break; 678 case PROV_KEF_HARD: 679 rc = list_mechlist_for_hard(provname); 680 break; 681 default: /* should not come here */ 682 rc = FAILURE; 683 break; 684 } 685 } else if (pflag) { 686 switch (prov->cp_type) { 687 case PROV_UEF_LIB: 688 rc = list_policy_for_lib(provname); 689 break; 690 case PROV_KEF_SOFT: 691 if (getzoneid() == GLOBAL_ZONEID) { 692 rc = list_policy_for_soft(provname, 693 NULL, NULL); 694 } else { 695 /* 696 * TRANSLATION_NOTE 697 * "global" is keyword and not to 698 * be translated. 699 */ 700 cryptoerror(LOG_STDERR, gettext( 701 "policy information for kernel " 702 "providers is available " 703 "in the %s zone only"), "global"); 704 rc = FAILURE; 705 } 706 break; 707 case PROV_KEF_HARD: 708 if (getzoneid() == GLOBAL_ZONEID) { 709 rc = list_policy_for_hard( 710 provname, NULL, NULL, NULL); 711 } else { 712 /* 713 * TRANSLATION_NOTE 714 * "global" is keyword and not to 715 * be translated. 716 */ 717 cryptoerror(LOG_STDERR, gettext( 718 "policy information for kernel " 719 "providers is available " 720 "in the %s zone only"), "global"); 721 rc = FAILURE; 722 } 723 724 break; 725 default: /* should not come here */ 726 rc = FAILURE; 727 break; 728 } 729 } else { 730 /* error message */ 731 usage(); 732 rc = ERROR_USAGE; 733 } 734 } 735 736 out: 737 if (prov != NULL) 738 free(prov); 739 740 if (mecharglist != NULL) 741 free_mechlist(mecharglist); 742 return (rc); 743 } 744 745 746 /* 747 * The top level function for the "cryptoadm disable" subcommand. 748 */ 749 static int 750 do_disable(int argc, char **argv) 751 { 752 cryptoadm_provider_t *prov = NULL; 753 int rc = SUCCESS; 754 boolean_t auto_key_migrate_flag = B_FALSE; 755 756 if ((argc == 3) && (strncmp(argv[2], FIPS_KEYWORD, 757 strlen(FIPS_KEYWORD))) == 0) { 758 int success_count = 0; 759 /* 760 * cryptoadm disable fips-140 761 */ 762 rc = do_fips_actions(FIPS140_DISABLE, NOT_REFRESH); 763 if (rc == SUCCESS) 764 success_count++; 765 (void) printf(gettext("\nKernel hardware providers:\n")); 766 (void) printf(gettext("=========================:\n")); 767 rc = do_fips_hw_actions(FIPS140_DISABLE, HW_PROVIDER_NCP); 768 if (rc == SUCCESS) 769 success_count++; 770 rc = do_fips_hw_actions(FIPS140_DISABLE, HW_PROVIDER_N2CP); 771 if (rc == SUCCESS) 772 success_count++; 773 rc = do_fips_hw_actions(FIPS140_DISABLE, HW_PROVIDER_N2RNG); 774 if (rc == SUCCESS) 775 success_count++; 776 777 if (success_count > 0) { 778 (void) printf(gettext( 779 "\nThe FIPS-140 mode has changed.\n")); 780 (void) printf(gettext( 781 "The system will require a reboot.\n")); 782 return (SUCCESS); 783 } else { 784 return (FAILURE); 785 } 786 } 787 788 if ((argc < 3) || (argc > 5)) { 789 usage(); 790 return (ERROR_USAGE); 791 } 792 793 prov = get_provider(argc, argv); 794 if (prov == NULL) { 795 usage(); 796 return (ERROR_USAGE); 797 } 798 if (prov->cp_type == PROV_BADNAME) { 799 return (FAILURE); 800 } 801 802 if ((rc = process_feature_operands(argc, argv)) != SUCCESS) { 803 goto out; 804 } 805 806 /* 807 * If allflag or rndflag has already been set there is no reason to 808 * process mech= 809 */ 810 if (prov->cp_type == METASLOT) { 811 if ((argc > 3) && 812 (rc = process_metaslot_operands(argc, argv, 813 NULL, NULL, NULL, &auto_key_migrate_flag)) != SUCCESS) { 814 usage(); 815 return (rc); 816 } 817 } else if (!allflag && !rndflag && 818 (rc = process_mech_operands(argc, argv, B_FALSE)) != SUCCESS) { 819 return (rc); 820 } 821 822 switch (prov->cp_type) { 823 case METASLOT: 824 rc = disable_metaslot(mecharglist, allflag, 825 auto_key_migrate_flag); 826 break; 827 case PROV_UEF_LIB: 828 rc = disable_uef_lib(prov->cp_name, rndflag, allflag, 829 mecharglist); 830 break; 831 case PROV_KEF_SOFT: 832 if (rndflag && !allflag) { 833 if ((mecharglist = create_mech(RANDOM)) == NULL) { 834 rc = FAILURE; 835 break; 836 } 837 } 838 if (getzoneid() == GLOBAL_ZONEID) { 839 rc = disable_kef_software(prov->cp_name, rndflag, 840 allflag, mecharglist); 841 } else { 842 /* 843 * TRANSLATION_NOTE 844 * "disable" could be either a literal keyword 845 * and hence not to be translated, or a verb and 846 * translatable. A choice was made to view it as 847 * a literal keyword. "global" is keyword and not 848 * to be translated. 849 */ 850 cryptoerror(LOG_STDERR, gettext("%1$s for kernel " 851 "providers is supported in the %2$s zone only"), 852 "disable", "global"); 853 rc = FAILURE; 854 } 855 break; 856 case PROV_KEF_HARD: 857 if (rndflag && !allflag) { 858 if ((mecharglist = create_mech(RANDOM)) == NULL) { 859 rc = FAILURE; 860 break; 861 } 862 } 863 if (getzoneid() == GLOBAL_ZONEID) { 864 rc = disable_kef_hardware(prov->cp_name, rndflag, 865 allflag, mecharglist); 866 } else { 867 /* 868 * TRANSLATION_NOTE 869 * "disable" could be either a literal keyword 870 * and hence not to be translated, or a verb and 871 * translatable. A choice was made to view it as 872 * a literal keyword. "global" is keyword and not 873 * to be translated. 874 */ 875 cryptoerror(LOG_STDERR, gettext("%1$s for kernel " 876 "providers is supported in the %2$s zone only"), 877 "disable", "global"); 878 rc = FAILURE; 879 } 880 break; 881 default: /* should not come here */ 882 rc = FAILURE; 883 break; 884 } 885 886 out: 887 free(prov); 888 if (mecharglist != NULL) { 889 free_mechlist(mecharglist); 890 } 891 return (rc); 892 } 893 894 895 /* 896 * The top level function for the "cryptoadm enable" subcommand. 897 */ 898 static int 899 do_enable(int argc, char **argv) 900 { 901 cryptoadm_provider_t *prov = NULL; 902 int rc = SUCCESS; 903 char *alt_token = NULL, *alt_slot = NULL; 904 boolean_t use_default = B_FALSE; 905 boolean_t auto_key_migrate_flag = B_FALSE; 906 907 if ((argc == 3) && (strncmp(argv[2], FIPS_KEYWORD, 908 strlen(FIPS_KEYWORD))) == 0) { 909 int success_count = 0; 910 /* 911 * cryptoadm enable fips-140 912 */ 913 rc = do_fips_actions(FIPS140_ENABLE, NOT_REFRESH); 914 if (rc == SUCCESS) 915 success_count++; 916 (void) printf(gettext("\nKernel hardware providers:\n")); 917 (void) printf(gettext("=========================:\n")); 918 rc = do_fips_hw_actions(FIPS140_ENABLE, HW_PROVIDER_NCP); 919 if (rc == SUCCESS) 920 success_count++; 921 rc = do_fips_hw_actions(FIPS140_ENABLE, HW_PROVIDER_N2CP); 922 if (rc == SUCCESS) 923 success_count++; 924 rc = do_fips_hw_actions(FIPS140_ENABLE, HW_PROVIDER_N2RNG); 925 if (rc == SUCCESS) 926 success_count++; 927 928 if (success_count > 0) { 929 (void) printf(gettext( 930 "\nThe FIPS-140 mode has changed.\n")); 931 (void) printf(gettext( 932 "The system will require a reboot.\n")); 933 return (SUCCESS); 934 } else { 935 return (FAILURE); 936 } 937 } 938 939 if ((argc < 3) || (argc > 6)) { 940 usage(); 941 return (ERROR_USAGE); 942 } 943 944 prov = get_provider(argc, argv); 945 if (prov == NULL) { 946 usage(); 947 return (ERROR_USAGE); 948 } 949 if ((prov->cp_type != METASLOT) && (argc != 4)) { 950 usage(); 951 return (ERROR_USAGE); 952 } 953 if (prov->cp_type == PROV_BADNAME) { 954 rc = FAILURE; 955 goto out; 956 } 957 958 959 if (prov->cp_type == METASLOT) { 960 if ((rc = process_metaslot_operands(argc, argv, &alt_token, 961 &alt_slot, &use_default, &auto_key_migrate_flag)) 962 != SUCCESS) { 963 usage(); 964 goto out; 965 } 966 if ((alt_slot || alt_token) && use_default) { 967 usage(); 968 rc = FAILURE; 969 goto out; 970 } 971 } else { 972 if ((rc = process_feature_operands(argc, argv)) != SUCCESS) { 973 goto out; 974 } 975 976 /* 977 * If allflag or rndflag has already been set there is 978 * no reason to process mech= 979 */ 980 if (!allflag && !rndflag && 981 (rc = process_mech_operands(argc, argv, B_FALSE)) 982 != SUCCESS) { 983 goto out; 984 } 985 } 986 987 switch (prov->cp_type) { 988 case METASLOT: 989 rc = enable_metaslot(alt_token, alt_slot, use_default, 990 mecharglist, allflag, auto_key_migrate_flag); 991 break; 992 case PROV_UEF_LIB: 993 rc = enable_uef_lib(prov->cp_name, rndflag, allflag, 994 mecharglist); 995 break; 996 case PROV_KEF_SOFT: 997 case PROV_KEF_HARD: 998 if (rndflag && !allflag) { 999 if ((mecharglist = create_mech(RANDOM)) == NULL) { 1000 rc = FAILURE; 1001 break; 1002 } 1003 } 1004 if (getzoneid() == GLOBAL_ZONEID) { 1005 rc = enable_kef(prov->cp_name, rndflag, allflag, 1006 mecharglist); 1007 } else { 1008 /* 1009 * TRANSLATION_NOTE 1010 * "enable" could be either a literal keyword 1011 * and hence not to be translated, or a verb and 1012 * translatable. A choice was made to view it as 1013 * a literal keyword. "global" is keyword and not 1014 * to be translated. 1015 */ 1016 cryptoerror(LOG_STDERR, gettext("%1$s for kernel " 1017 "providers is supported in the %2$s zone only"), 1018 "enable", "global"); 1019 rc = FAILURE; 1020 } 1021 break; 1022 default: /* should not come here */ 1023 rc = FAILURE; 1024 break; 1025 } 1026 out: 1027 free(prov); 1028 if (mecharglist != NULL) { 1029 free_mechlist(mecharglist); 1030 } 1031 if (alt_token != NULL) { 1032 free(alt_token); 1033 } 1034 if (alt_slot != NULL) { 1035 free(alt_slot); 1036 } 1037 return (rc); 1038 } 1039 1040 1041 1042 /* 1043 * The top level function for the "cryptoadm install" subcommand. 1044 */ 1045 static int 1046 do_install(int argc, char **argv) 1047 { 1048 cryptoadm_provider_t *prov = NULL; 1049 int rc; 1050 1051 if (argc < 3) { 1052 usage(); 1053 return (ERROR_USAGE); 1054 } 1055 1056 prov = get_provider(argc, argv); 1057 if (prov == NULL || 1058 prov->cp_type == PROV_BADNAME || prov->cp_type == PROV_KEF_HARD) { 1059 /* 1060 * TRANSLATION_NOTE 1061 * "install" could be either a literal keyword and hence 1062 * not to be translated, or a verb and translatable. A 1063 * choice was made to view it as a literal keyword. 1064 */ 1065 cryptoerror(LOG_STDERR, 1066 gettext("bad provider name for %s."), "install"); 1067 rc = FAILURE; 1068 goto out; 1069 } 1070 1071 if (prov->cp_type == PROV_UEF_LIB) { 1072 rc = install_uef_lib(prov->cp_name); 1073 goto out; 1074 } 1075 1076 /* It is the PROV_KEF_SOFT type now */ 1077 1078 /* check if there are mechanism operands */ 1079 if (argc < 4) { 1080 /* 1081 * TRANSLATION_NOTE 1082 * "mechanism" could be either a literal keyword and hence 1083 * not to be translated, or a descriptive word and 1084 * translatable. A choice was made to view it as a literal 1085 * keyword. 1086 */ 1087 cryptoerror(LOG_STDERR, 1088 gettext("need %s operands for installing a" 1089 " kernel software provider."), "mechanism"); 1090 rc = ERROR_USAGE; 1091 goto out; 1092 } 1093 1094 if ((rc = process_mech_operands(argc, argv, B_FALSE)) != SUCCESS) { 1095 goto out; 1096 } 1097 1098 if (allflag == B_TRUE) { 1099 /* 1100 * TRANSLATION_NOTE 1101 * "all", "mechanism", and "install" are all keywords and 1102 * not to be translated. 1103 */ 1104 cryptoerror(LOG_STDERR, 1105 gettext("can not use the %1$s keyword for %2$s " 1106 "in the %3$s subcommand."), "all", "mechanism", "install"); 1107 rc = ERROR_USAGE; 1108 goto out; 1109 } 1110 1111 if (getzoneid() == GLOBAL_ZONEID) { 1112 rc = install_kef(prov->cp_name, mecharglist); 1113 } else { 1114 /* 1115 * TRANSLATION_NOTE 1116 * "install" could be either a literal keyword and hence 1117 * not to be translated, or a verb and translatable. A 1118 * choice was made to view it as a literal keyword. 1119 * "global" is keyword and not to be translated. 1120 */ 1121 cryptoerror(LOG_STDERR, gettext("%1$s for kernel providers " 1122 "is supported in the %2$s zone only"), "install", "global"); 1123 rc = FAILURE; 1124 } 1125 out: 1126 free(prov); 1127 return (rc); 1128 } 1129 1130 1131 1132 /* 1133 * The top level function for the "cryptoadm uninstall" subcommand. 1134 */ 1135 static int 1136 do_uninstall(int argc, char **argv) 1137 { 1138 cryptoadm_provider_t *prov = NULL; 1139 int rc = SUCCESS; 1140 1141 if (argc != 3) { 1142 usage(); 1143 return (ERROR_USAGE); 1144 } 1145 1146 prov = get_provider(argc, argv); 1147 if (prov == NULL || 1148 prov->cp_type == PROV_BADNAME || prov->cp_type == PROV_KEF_HARD) { 1149 /* 1150 * TRANSLATION_NOTE 1151 * "uninstall" could be either a literal keyword and hence 1152 * not to be translated, or a verb and translatable. A 1153 * choice was made to view it as a literal keyword. 1154 */ 1155 cryptoerror(LOG_STDERR, 1156 gettext("bad provider name for %s."), "uninstall"); 1157 free(prov); 1158 return (FAILURE); 1159 } 1160 1161 if (prov->cp_type == PROV_UEF_LIB) { 1162 rc = uninstall_uef_lib(prov->cp_name); 1163 1164 } else if (prov->cp_type == PROV_KEF_SOFT) { 1165 if (getzoneid() == GLOBAL_ZONEID) { 1166 /* unload and remove from kcf.conf */ 1167 rc = uninstall_kef(prov->cp_name); 1168 } else { 1169 /* 1170 * TRANSLATION_NOTE 1171 * "uninstall" could be either a literal keyword and 1172 * hence not to be translated, or a verb and 1173 * translatable. A choice was made to view it as a 1174 * literal keyword. "global" is keyword and not to 1175 * be translated. 1176 */ 1177 cryptoerror(LOG_STDERR, gettext("%1$s for kernel " 1178 "providers is supported in the %2$s zone only"), 1179 "uninstall", "global"); 1180 rc = FAILURE; 1181 } 1182 } 1183 1184 free(prov); 1185 return (rc); 1186 } 1187 1188 1189 /* 1190 * The top level function for the "cryptoadm unload" subcommand. 1191 */ 1192 static int 1193 do_unload(int argc, char **argv) 1194 { 1195 cryptoadm_provider_t *prov = NULL; 1196 entry_t *pent = NULL; 1197 boolean_t in_kernel = B_FALSE; 1198 int rc = SUCCESS; 1199 char *provname = NULL; 1200 1201 if (argc != 3) { 1202 usage(); 1203 return (ERROR_USAGE); 1204 } 1205 1206 /* check if it is a kernel software provider */ 1207 prov = get_provider(argc, argv); 1208 if (prov == NULL) { 1209 cryptoerror(LOG_STDERR, 1210 gettext("unable to determine provider name.")); 1211 goto out; 1212 } 1213 provname = prov->cp_name; 1214 if (prov->cp_type != PROV_KEF_SOFT) { 1215 cryptoerror(LOG_STDERR, 1216 gettext("%s is not a valid kernel software provider."), 1217 provname); 1218 rc = FAILURE; 1219 goto out; 1220 } 1221 1222 if (getzoneid() != GLOBAL_ZONEID) { 1223 /* 1224 * TRANSLATION_NOTE 1225 * "unload" could be either a literal keyword and hence 1226 * not to be translated, or a verb and translatable. 1227 * A choice was made to view it as a literal keyword. 1228 * "global" is keyword and not to be translated. 1229 */ 1230 cryptoerror(LOG_STDERR, gettext("%1$s for kernel providers " 1231 "is supported in the %2$s zone only"), "unload", "global"); 1232 rc = FAILURE; 1233 goto out; 1234 } 1235 1236 if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) { 1237 cryptodebug("internal error"); 1238 rc = FAILURE; 1239 goto out; 1240 } else if (in_kernel == B_FALSE) { 1241 cryptoerror(LOG_STDERR, 1242 gettext("provider %s is not loaded or does not exist."), 1243 provname); 1244 rc = FAILURE; 1245 goto out; 1246 } 1247 1248 /* Get kcf.conf entry. If none, build a new entry */ 1249 if ((pent = getent_kef(provname, NULL, NULL)) == NULL) { 1250 if ((pent = create_entry(provname)) == NULL) { 1251 cryptoerror(LOG_STDERR, gettext("out of memory.")); 1252 rc = FAILURE; 1253 goto out; 1254 } 1255 } 1256 1257 /* If it is unloaded already, return */ 1258 if (!pent->load) { /* unloaded already */ 1259 cryptoerror(LOG_STDERR, 1260 gettext("failed to unload %s."), provname); 1261 rc = FAILURE; 1262 goto out; 1263 } else if (unload_kef_soft(provname) != FAILURE) { 1264 /* Mark as unloaded in kcf.conf */ 1265 pent->load = B_FALSE; 1266 rc = update_kcfconf(pent, MODIFY_MODE); 1267 } else { 1268 cryptoerror(LOG_STDERR, 1269 gettext("failed to unload %s."), provname); 1270 rc = FAILURE; 1271 } 1272 out: 1273 free(prov); 1274 free_entry(pent); 1275 return (rc); 1276 } 1277 1278 1279 1280 /* 1281 * The top level function for the "cryptoadm refresh" subcommand. 1282 */ 1283 static int 1284 do_refresh(int argc) 1285 { 1286 if (argc != 2) { 1287 usage(); 1288 return (ERROR_USAGE); 1289 } 1290 1291 if (getzoneid() == GLOBAL_ZONEID) { 1292 return (refresh()); 1293 } else { /* non-global zone */ 1294 /* 1295 * Note: in non-global zone, this must silently return SUCCESS 1296 * due to integration with SMF, for "svcadm refresh cryptosvc" 1297 */ 1298 return (SUCCESS); 1299 } 1300 } 1301 1302 1303 /* 1304 * The top level function for the "cryptoadm start" subcommand. 1305 */ 1306 static int 1307 do_start(int argc) 1308 { 1309 int ret; 1310 1311 if (argc != 2) { 1312 usage(); 1313 return (ERROR_USAGE); 1314 } 1315 1316 ret = do_refresh(argc); 1317 if (ret != SUCCESS) 1318 return (ret); 1319 1320 return (start_daemon()); 1321 } 1322 1323 /* 1324 * The top level function for the "cryptoadm stop" subcommand. 1325 */ 1326 static int 1327 do_stop(int argc) 1328 { 1329 if (argc != 2) { 1330 usage(); 1331 return (ERROR_USAGE); 1332 } 1333 1334 return (stop_daemon()); 1335 } 1336 1337 1338 1339 /* 1340 * Print a list all the the providers. 1341 * Called for "cryptoadm list" or "cryptoadm list -v" (no -m or -p). 1342 */ 1343 static int 1344 list_simple_for_all(boolean_t verbose) 1345 { 1346 uentrylist_t *pliblist = NULL; 1347 uentrylist_t *plibptr = NULL; 1348 entry_t *pent = NULL; 1349 crypto_get_dev_list_t *pdevlist_kernel = NULL; 1350 int rc = SUCCESS; 1351 int i; 1352 1353 /* get user-level providers */ 1354 (void) printf(gettext("\nUser-level providers:\n")); 1355 if (get_pkcs11conf_info(&pliblist) != SUCCESS) { 1356 cryptoerror(LOG_STDERR, gettext( 1357 "failed to retrieve the list of user-level providers.")); 1358 rc = FAILURE; 1359 } 1360 1361 for (plibptr = pliblist; plibptr != NULL; plibptr = plibptr->next) { 1362 /* skip metaslot and fips-140 entry */ 1363 if ((strcmp(plibptr->puent->name, METASLOT_KEYWORD) != 0) && 1364 (strcmp(plibptr->puent->name, FIPS_KEYWORD) != 0)) { 1365 (void) printf(gettext("Provider: %s\n"), 1366 plibptr->puent->name); 1367 if (verbose) { 1368 (void) list_mechlist_for_lib( 1369 plibptr->puent->name, mecharglist, NULL, 1370 B_FALSE, verbose, B_FALSE); 1371 (void) printf("\n"); 1372 } 1373 } 1374 } 1375 free_uentrylist(pliblist); 1376 1377 /* get kernel software providers */ 1378 (void) printf(gettext("\nKernel software providers:\n")); 1379 1380 if (getzoneid() == GLOBAL_ZONEID) { 1381 /* get kernel software providers from kernel ioctl */ 1382 crypto_get_soft_list_t *psoftlist_kernel = NULL; 1383 uint_t sl_soft_count; 1384 char *psoftname; 1385 entrylist_t *pdevlist_conf = NULL; 1386 entrylist_t *psoftlist_conf = NULL; 1387 1388 if (get_soft_list(&psoftlist_kernel) == FAILURE) { 1389 cryptoerror(LOG_ERR, gettext("Failed to retrieve the " 1390 "software provider list from kernel.")); 1391 rc = FAILURE; 1392 } else { 1393 sl_soft_count = psoftlist_kernel->sl_soft_count; 1394 1395 if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) 1396 == FAILURE) { 1397 cryptoerror(LOG_ERR, 1398 "failed to retrieve the providers' " 1399 "information from file kcf.conf - %s.", 1400 _PATH_KCF_CONF); 1401 free(psoftlist_kernel); 1402 rc = FAILURE; 1403 } else { 1404 1405 for (i = 0, 1406 psoftname = psoftlist_kernel->sl_soft_names; 1407 i < sl_soft_count; 1408 ++i, psoftname += strlen(psoftname) + 1) { 1409 pent = getent_kef(psoftname, 1410 pdevlist_conf, psoftlist_conf); 1411 (void) printf("\t%s%s\n", psoftname, 1412 (pent == NULL) || (pent->load) ? 1413 "" : gettext(" (inactive)")); 1414 } 1415 free_entrylist(pdevlist_conf); 1416 free_entrylist(psoftlist_conf); 1417 } 1418 free(psoftlist_kernel); 1419 } 1420 1421 } else { 1422 /* kcf.conf not there in non-global zone, use /dev/cryptoadm */ 1423 entrylist_t *pdevlist_zone = NULL; 1424 entrylist_t *psoftlist_zone = NULL; 1425 entrylist_t *ptr; 1426 1427 if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) != 1428 SUCCESS) { 1429 cryptoerror(LOG_STDERR, 1430 gettext("failed to retrieve the " 1431 "list of kernel software providers.\n")); 1432 rc = FAILURE; 1433 } 1434 1435 ptr = psoftlist_zone; 1436 while (ptr != NULL) { 1437 (void) printf("\t%s\n", ptr->pent->name); 1438 ptr = ptr->next; 1439 } 1440 1441 free_entrylist(pdevlist_zone); 1442 free_entrylist(psoftlist_zone); 1443 } 1444 1445 /* get kernel hardware providers */ 1446 (void) printf(gettext("\nKernel hardware providers:\n")); 1447 if (get_dev_list(&pdevlist_kernel) == FAILURE) { 1448 cryptoerror(LOG_STDERR, gettext("failed to retrieve " 1449 "the list of kernel hardware providers.\n")); 1450 rc = FAILURE; 1451 } else { 1452 for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) { 1453 (void) printf("\t%s/%d\n", 1454 pdevlist_kernel->dl_devs[i].le_dev_name, 1455 pdevlist_kernel->dl_devs[i].le_dev_instance); 1456 } 1457 } 1458 free(pdevlist_kernel); 1459 1460 return (rc); 1461 } 1462 1463 1464 1465 /* 1466 * List all the providers. And for each provider, list the mechanism list. 1467 * Called for "cryptoadm list -m" or "cryptoadm list -mv" . 1468 */ 1469 static int 1470 list_mechlist_for_all(boolean_t verbose) 1471 { 1472 crypto_get_dev_list_t *pdevlist_kernel = NULL; 1473 uentrylist_t *pliblist = NULL; 1474 uentrylist_t *plibptr = NULL; 1475 entry_t *pent = NULL; 1476 mechlist_t *pmechlist = NULL; 1477 char provname[MAXNAMELEN]; 1478 char devname[MAXNAMELEN]; 1479 int inst_num; 1480 int count; 1481 int i; 1482 int rv; 1483 int rc = SUCCESS; 1484 1485 /* get user-level providers */ 1486 (void) printf(gettext("\nUser-level providers:\n")); 1487 /* 1488 * TRANSLATION_NOTE 1489 * Strictly for appearance's sake, this line should be as long as 1490 * the length of the translated text above. 1491 */ 1492 (void) printf(gettext("=====================\n")); 1493 if (get_pkcs11conf_info(&pliblist) != SUCCESS) { 1494 cryptoerror(LOG_STDERR, gettext("failed to retrieve " 1495 "the list of user-level providers.\n")); 1496 rc = FAILURE; 1497 } 1498 1499 plibptr = pliblist; 1500 while (plibptr != NULL) { 1501 /* skip metaslot and fips-140 entry */ 1502 if ((strcmp(plibptr->puent->name, METASLOT_KEYWORD) != 0) && 1503 (strcmp(plibptr->puent->name, FIPS_KEYWORD) != 0)) { 1504 (void) printf(gettext("\nProvider: %s\n"), 1505 plibptr->puent->name); 1506 rv = list_mechlist_for_lib(plibptr->puent->name, 1507 mecharglist, NULL, B_FALSE, verbose, B_TRUE); 1508 if (rv == FAILURE) { 1509 rc = FAILURE; 1510 } 1511 } 1512 plibptr = plibptr->next; 1513 } 1514 free_uentrylist(pliblist); 1515 1516 /* get kernel software providers */ 1517 (void) printf(gettext("\nKernel software providers:\n")); 1518 1519 /* 1520 * TRANSLATION_NOTE 1521 * Strictly for appearance's sake, this line should be as long as 1522 * the length of the translated text above. 1523 */ 1524 (void) printf(gettext("==========================\n")); 1525 if (getzoneid() == GLOBAL_ZONEID) { 1526 /* get kernel software providers from kernel ioctl */ 1527 crypto_get_soft_list_t *psoftlist_kernel = NULL; 1528 uint_t sl_soft_count; 1529 char *psoftname; 1530 int i; 1531 entrylist_t *pdevlist_conf = NULL; 1532 entrylist_t *psoftlist_conf = NULL; 1533 1534 if (get_soft_list(&psoftlist_kernel) == FAILURE) { 1535 cryptoerror(LOG_ERR, gettext("Failed to retrieve the " 1536 "software provider list from kernel.")); 1537 return (FAILURE); 1538 } 1539 sl_soft_count = psoftlist_kernel->sl_soft_count; 1540 1541 if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) 1542 == FAILURE) { 1543 cryptoerror(LOG_ERR, 1544 "failed to retrieve the providers' " 1545 "information from file kcf.conf - %s.", 1546 _PATH_KCF_CONF); 1547 free(psoftlist_kernel); 1548 return (FAILURE); 1549 } 1550 1551 for (i = 0, psoftname = psoftlist_kernel->sl_soft_names; 1552 i < sl_soft_count; 1553 ++i, psoftname += strlen(psoftname) + 1) { 1554 pent = getent_kef(psoftname, pdevlist_conf, 1555 psoftlist_conf); 1556 if ((pent == NULL) || (pent->load)) { 1557 rv = list_mechlist_for_soft(psoftname, 1558 NULL, NULL); 1559 if (rv == FAILURE) { 1560 rc = FAILURE; 1561 } 1562 } else { 1563 (void) printf(gettext("%s: (inactive)\n"), 1564 psoftname); 1565 } 1566 } 1567 1568 free(psoftlist_kernel); 1569 free_entrylist(pdevlist_conf); 1570 free_entrylist(psoftlist_conf); 1571 1572 } else { 1573 /* kcf.conf not there in non-global zone, use /dev/cryptoadm */ 1574 entrylist_t *pdevlist_zone = NULL; 1575 entrylist_t *psoftlist_zone = NULL; 1576 entrylist_t *ptr; 1577 1578 if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) != 1579 SUCCESS) { 1580 cryptoerror(LOG_STDERR, gettext("failed to retrieve " 1581 "the list of kernel software providers.\n")); 1582 rc = FAILURE; 1583 } 1584 1585 for (ptr = psoftlist_zone; ptr != NULL; ptr = ptr->next) { 1586 rv = list_mechlist_for_soft(ptr->pent->name, 1587 pdevlist_zone, psoftlist_zone); 1588 if (rv == FAILURE) { 1589 (void) printf(gettext( 1590 "%s: failed to get the mechanism list.\n"), 1591 ptr->pent->name); 1592 rc = FAILURE; 1593 } 1594 } 1595 1596 free_entrylist(pdevlist_zone); 1597 free_entrylist(psoftlist_zone); 1598 } 1599 1600 /* Get kernel hardware providers and their mechanism lists */ 1601 (void) printf(gettext("\nKernel hardware providers:\n")); 1602 /* 1603 * TRANSLATION_NOTE 1604 * Strictly for appearance's sake, this line should be as long as 1605 * the length of the translated text above. 1606 */ 1607 (void) printf(gettext("==========================\n")); 1608 if (get_dev_list(&pdevlist_kernel) != SUCCESS) { 1609 cryptoerror(LOG_STDERR, gettext("failed to retrieve " 1610 "the list of hardware providers.\n")); 1611 return (FAILURE); 1612 } 1613 1614 for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) { 1615 (void) strlcpy(devname, 1616 pdevlist_kernel->dl_devs[i].le_dev_name, MAXNAMELEN); 1617 inst_num = pdevlist_kernel->dl_devs[i].le_dev_instance; 1618 count = pdevlist_kernel->dl_devs[i].le_mechanism_count; 1619 (void) snprintf(provname, sizeof (provname), "%s/%d", devname, 1620 inst_num); 1621 if (get_dev_info(devname, inst_num, count, &pmechlist) == 1622 SUCCESS) { 1623 (void) filter_mechlist(&pmechlist, RANDOM); 1624 print_mechlist(provname, pmechlist); 1625 free_mechlist(pmechlist); 1626 } else { 1627 (void) printf(gettext("%s: failed to get the mechanism" 1628 " list.\n"), provname); 1629 rc = FAILURE; 1630 } 1631 } 1632 free(pdevlist_kernel); 1633 return (rc); 1634 } 1635 1636 1637 /* 1638 * List all the providers. And for each provider, list the policy information. 1639 * Called for "cryptoadm list -p". 1640 */ 1641 static int 1642 list_policy_for_all(void) 1643 { 1644 crypto_get_dev_list_t *pdevlist_kernel = NULL; 1645 uentrylist_t *pliblist = NULL; 1646 entrylist_t *pdevlist_conf = NULL; 1647 entrylist_t *psoftlist_conf = NULL; 1648 entrylist_t *ptr = NULL; 1649 entrylist_t *phead = NULL; 1650 boolean_t found = B_FALSE; 1651 char provname[MAXNAMELEN]; 1652 int i; 1653 int rc = SUCCESS; 1654 1655 /* Get user-level providers */ 1656 (void) printf(gettext("\nUser-level providers:\n")); 1657 /* 1658 * TRANSLATION_NOTE 1659 * Strictly for appearance's sake, this line should be as long as 1660 * the length of the translated text above. 1661 */ 1662 (void) printf(gettext("=====================\n")); 1663 if (get_pkcs11conf_info(&pliblist) == FAILURE) { 1664 cryptoerror(LOG_STDERR, gettext("failed to retrieve " 1665 "the list of user-level providers.\n")); 1666 rc = FAILURE; 1667 } else { 1668 uentrylist_t *plibptr = pliblist; 1669 1670 while (plibptr != NULL) { 1671 /* skip metaslot and fips-140 entry */ 1672 if ((strcmp(plibptr->puent->name, 1673 METASLOT_KEYWORD) != 0) && 1674 (strcmp(plibptr->puent->name, 1675 FIPS_KEYWORD) != 0)) { 1676 if (print_uef_policy(plibptr->puent) 1677 == FAILURE) { 1678 rc = FAILURE; 1679 } 1680 } 1681 plibptr = plibptr->next; 1682 } 1683 free_uentrylist(pliblist); 1684 } 1685 1686 /* kernel software providers */ 1687 (void) printf(gettext("\nKernel software providers:\n")); 1688 /* 1689 * TRANSLATION_NOTE 1690 * Strictly for appearance's sake, this line should be as long as 1691 * the length of the translated text above. 1692 */ 1693 (void) printf(gettext("==========================\n")); 1694 1695 /* Get all entries from the kernel */ 1696 if (getzoneid() == GLOBAL_ZONEID) { 1697 /* get kernel software providers from kernel ioctl */ 1698 crypto_get_soft_list_t *psoftlist_kernel = NULL; 1699 uint_t sl_soft_count; 1700 char *psoftname; 1701 int i; 1702 1703 if (get_soft_list(&psoftlist_kernel) == FAILURE) { 1704 cryptoerror(LOG_ERR, gettext("Failed to retrieve the " 1705 "software provider list from kernel.")); 1706 rc = FAILURE; 1707 } else { 1708 sl_soft_count = psoftlist_kernel->sl_soft_count; 1709 1710 for (i = 0, psoftname = psoftlist_kernel->sl_soft_names; 1711 i < sl_soft_count; 1712 ++i, psoftname += strlen(psoftname) + 1) { 1713 (void) list_policy_for_soft(psoftname, 1714 pdevlist_conf, psoftlist_conf); 1715 } 1716 free(psoftlist_kernel); 1717 } 1718 1719 } else { 1720 /* kcf.conf not there in non-global zone, no policy info */ 1721 1722 /* 1723 * TRANSLATION_NOTE 1724 * "global" is keyword and not to be translated. 1725 */ 1726 cryptoerror(LOG_STDERR, gettext( 1727 "policy information for kernel software providers is " 1728 "available in the %s zone only"), "global"); 1729 } 1730 1731 /* Kernel hardware providers */ 1732 (void) printf(gettext("\nKernel hardware providers:\n")); 1733 /* 1734 * TRANSLATION_NOTE 1735 * Strictly for appearance's sake, this line should be as long as 1736 * the length of the translated text above. 1737 */ 1738 (void) printf(gettext("==========================\n")); 1739 1740 if (getzoneid() != GLOBAL_ZONEID) { 1741 /* 1742 * TRANSLATION_NOTE 1743 * "global" is keyword and not to be translated. 1744 */ 1745 cryptoerror(LOG_STDERR, gettext( 1746 "policy information for kernel hardware providers is " 1747 "available in the %s zone only"), "global"); 1748 return (FAILURE); 1749 } 1750 1751 /* Get the hardware provider list from kernel */ 1752 if (get_dev_list(&pdevlist_kernel) != SUCCESS) { 1753 cryptoerror(LOG_STDERR, gettext( 1754 "failed to retrieve the list of hardware providers.\n")); 1755 return (FAILURE); 1756 } 1757 1758 if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) == FAILURE) { 1759 cryptoerror(LOG_ERR, "failed to retrieve the providers' " 1760 "information from file kcf.conf - %s.", 1761 _PATH_KCF_CONF); 1762 return (FAILURE); 1763 } 1764 1765 1766 /* 1767 * For each hardware provider from kernel, check if it has an entry 1768 * in the config file. If it has an entry, print out the policy from 1769 * config file and remove the entry from the hardware provider list 1770 * of the config file. If it does not have an entry in the config 1771 * file, no mechanisms of it have been disabled. But, we still call 1772 * list_policy_for_hard() to account for the "random" feature. 1773 */ 1774 for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) { 1775 (void) snprintf(provname, sizeof (provname), "%s/%d", 1776 pdevlist_kernel->dl_devs[i].le_dev_name, 1777 pdevlist_kernel->dl_devs[i].le_dev_instance); 1778 1779 found = B_FALSE; 1780 phead = ptr = pdevlist_conf; 1781 while (!found && ptr) { 1782 if (strcmp(ptr->pent->name, provname) == 0) { 1783 found = B_TRUE; 1784 } else { 1785 phead = ptr; 1786 ptr = ptr->next; 1787 } 1788 } 1789 1790 if (found) { 1791 (void) list_policy_for_hard(ptr->pent->name, 1792 pdevlist_conf, psoftlist_conf, pdevlist_kernel); 1793 if (phead == ptr) { 1794 pdevlist_conf = pdevlist_conf->next; 1795 } else { 1796 phead->next = ptr->next; 1797 } 1798 free_entry(ptr->pent); 1799 free(ptr); 1800 } else { 1801 (void) list_policy_for_hard(provname, pdevlist_conf, 1802 psoftlist_conf, pdevlist_kernel); 1803 } 1804 } 1805 1806 /* 1807 * If there are still entries left in the pdevlist_conf list from 1808 * the config file, these providers must have been detached. 1809 * Should print out their policy information also. 1810 */ 1811 for (ptr = pdevlist_conf; ptr != NULL; ptr = ptr->next) { 1812 print_kef_policy(ptr->pent->name, ptr->pent, B_FALSE, B_TRUE); 1813 } 1814 1815 free_entrylist(pdevlist_conf); 1816 free_entrylist(psoftlist_conf); 1817 free(pdevlist_kernel); 1818 1819 return (rc); 1820 } 1821