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