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