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