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