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