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