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