xref: /illumos-gate/usr/src/cmd/cmd-crypto/cryptoadm/cryptoadm.c (revision 74e7dc986c89efca1f2e4451c7a572e05e4a6e4f)
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
252  * - PROV_KEF_HARD if provname contains one slash only and the slash is not
253  *	the 1st character.
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 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 	 * [-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 		if (mflag || vflag) {
635 			if (vflag)
636 				(void) printf(gettext("Provider: %s\n"),
637 					prov->cp_name);
638 			switch (prov->cp_type) {
639 			case PROV_UEF_LIB:
640 				rc = list_mechlist_for_lib(prov->cp_name,
641 					mecharglist, NULL, B_FALSE,
642 					vflag, mflag);
643 				break;
644 			case PROV_KEF_SOFT:
645 				rc = list_mechlist_for_soft(prov->cp_name);
646 				break;
647 			case PROV_KEF_HARD:
648 				rc = list_mechlist_for_hard(prov->cp_name);
649 				break;
650 			default: /* should not come here */
651 				rc = FAILURE;
652 				break;
653 			}
654 		} else if (pflag) {
655 			switch (prov->cp_type) {
656 			case PROV_UEF_LIB:
657 				rc = list_policy_for_lib(prov->cp_name);
658 				break;
659 			case PROV_KEF_SOFT:
660 				if (getzoneid() == GLOBAL_ZONEID) {
661 					rc = list_policy_for_soft(
662 					    prov->cp_name);
663 				} else {
664 					/*
665 					 * TRANSLATION_NOTE
666 					 * "global" is keyword and not to
667 					 * be translated.
668 					 */
669 					cryptoerror(LOG_STDERR, gettext(
670 					    "policy information for kernel "
671 					    "providers is available "
672 					    "in the %s zone only"), "global");
673 					rc = FAILURE;
674 				}
675 				break;
676 			case PROV_KEF_HARD:
677 				if (getzoneid() == GLOBAL_ZONEID) {
678 					rc = list_policy_for_hard(
679 					    prov->cp_name);
680 				} else {
681 					/*
682 					 * TRANSLATION_NOTE
683 					 * "global" is keyword and not to
684 					 * be translated.
685 					 */
686 					cryptoerror(LOG_STDERR, gettext(
687 					    "policy information for kernel "
688 					    "providers is available "
689 					    "in the %s zone only"), "global");
690 					rc = FAILURE;
691 				}
692 
693 				break;
694 			default: /* should not come here */
695 				rc = FAILURE;
696 				break;
697 			}
698 		} else {
699 			/* error message */
700 			usage();
701 			rc = ERROR_USAGE;
702 		}
703 	}
704 
705 out:
706 	if (prov != NULL)
707 		free(prov);
708 
709 	if (mecharglist != NULL)
710 		free_mechlist(mecharglist);
711 	return (rc);
712 }
713 
714 
715 /*
716  * The top level function for the disable subcommand.
717  */
718 static int
719 do_disable(int argc, char **argv)
720 {
721 	cryptoadm_provider_t	*prov = NULL;
722 	int	rc = SUCCESS;
723 	boolean_t auto_key_migrate_flag = B_FALSE;
724 
725 	if ((argc < 3) || (argc > 5)) {
726 		usage();
727 		return (ERROR_USAGE);
728 	}
729 
730 	prov = get_provider(argc, argv);
731 	if (prov == NULL) {
732 		usage();
733 		return (ERROR_USAGE);
734 	}
735 	if (prov->cp_type == PROV_BADNAME) {
736 		return (FAILURE);
737 	}
738 
739 	if ((rc = process_feature_operands(argc, argv)) != SUCCESS) {
740 		goto out;
741 	}
742 
743 	/*
744 	 * If allflag or rndflag has already been set there is no reason to
745 	 * process mech=
746 	 */
747 	if (prov->cp_type == METASLOT) {
748 		if ((argc > 3) &&
749 		    (rc = process_metaslot_operands(argc, argv,
750 		    NULL, NULL, NULL, &auto_key_migrate_flag)) != SUCCESS) {
751 			usage();
752 			return (rc);
753 		}
754 	} else if (!allflag && !rndflag &&
755 		(rc = process_mech_operands(argc, argv, B_FALSE)) != SUCCESS) {
756 			return (rc);
757 	}
758 
759 	switch (prov->cp_type) {
760 	case METASLOT:
761 		rc = disable_metaslot(mecharglist, allflag,
762 		    auto_key_migrate_flag);
763 		break;
764 	case PROV_UEF_LIB:
765 		rc = disable_uef_lib(prov->cp_name, rndflag, allflag,
766 		    mecharglist);
767 		break;
768 	case PROV_KEF_SOFT:
769 		if (rndflag && !allflag) {
770 			if ((mecharglist = create_mech(RANDOM)) == NULL) {
771 				rc = FAILURE;
772 				break;
773 			}
774 		}
775 		if (getzoneid() == GLOBAL_ZONEID) {
776 			rc = disable_kef_software(prov->cp_name, rndflag,
777 			    allflag, mecharglist);
778 		} else {
779 			/*
780 			 * TRANSLATION_NOTE
781 			 * "disable" could be either a literal keyword
782 			 * and hence not to be translated, or a verb and
783 			 * translatable.  A choice was made to view it as
784 			 * a literal keyword.  "global" is keyword and not
785 			 * to be translated.
786 			 */
787 			cryptoerror(LOG_STDERR, gettext("%1$s for kernel "
788 			    "providers is supported in the %2$s zone only"),
789 			    "disable", "global");
790 			rc = FAILURE;
791 		}
792 		break;
793 	case PROV_KEF_HARD:
794 		if (rndflag && !allflag) {
795 			if ((mecharglist = create_mech(RANDOM)) == NULL) {
796 				rc = FAILURE;
797 				break;
798 			}
799 		}
800 		if (getzoneid() == GLOBAL_ZONEID) {
801 			rc = disable_kef_hardware(prov->cp_name, rndflag,
802 			    allflag, mecharglist);
803 		} else {
804 			/*
805 			 * TRANSLATION_NOTE
806 			 * "disable" could be either a literal keyword
807 			 * and hence not to be translated, or a verb and
808 			 * translatable.  A choice was made to view it as
809 			 * a literal keyword.  "global" is keyword and not
810 			 * to be translated.
811 			 */
812 			cryptoerror(LOG_STDERR, gettext("%1$s for kernel "
813 			    "providers is supported in the %2$s zone only"),
814 			    "disable", "global");
815 			rc = FAILURE;
816 		}
817 		break;
818 	default: /* should not come here */
819 		rc = FAILURE;
820 		break;
821 	}
822 
823 out:
824 	free(prov);
825 	if (mecharglist != NULL) {
826 		free_mechlist(mecharglist);
827 	}
828 	return (rc);
829 }
830 
831 
832 /*
833  * The top level function fo the enable subcommand.
834  */
835 static int
836 do_enable(int argc, char **argv)
837 {
838 	cryptoadm_provider_t 	*prov = NULL;
839 	int	rc = SUCCESS;
840 	char *alt_token = NULL, *alt_slot = NULL;
841 	boolean_t use_default = B_FALSE, auto_key_migrate_flag = B_FALSE;
842 
843 	if ((argc < 3) || (argc > 6)) {
844 		usage();
845 		return (ERROR_USAGE);
846 	}
847 
848 	prov = get_provider(argc, argv);
849 	if (prov == NULL) {
850 		usage();
851 		return (ERROR_USAGE);
852 	}
853 	if ((prov->cp_type != METASLOT) && (argc != 4)) {
854 		usage();
855 		return (ERROR_USAGE);
856 	}
857 	if (prov->cp_type == PROV_BADNAME) {
858 		rc = FAILURE;
859 		goto out;
860 	}
861 
862 
863 	if (prov->cp_type == METASLOT) {
864 		if ((rc = process_metaslot_operands(argc, argv, &alt_token,
865 		    &alt_slot, &use_default, &auto_key_migrate_flag))
866 		    != SUCCESS) {
867 			usage();
868 			goto out;
869 		}
870 		if ((alt_slot || alt_token) && use_default) {
871 			usage();
872 			rc = FAILURE;
873 			goto out;
874 		}
875 	} else {
876 		if ((rc = process_feature_operands(argc, argv)) != SUCCESS) {
877 			goto out;
878 		}
879 
880 		/*
881 		 * If allflag or rndflag has already been set there is
882 		 * no reason to process mech=
883 		 */
884 		if (!allflag && !rndflag &&
885 		    (rc = process_mech_operands(argc, argv, B_FALSE))
886 		    != SUCCESS) {
887 			goto out;
888 		}
889 	}
890 
891 	switch (prov->cp_type) {
892 	case METASLOT:
893 		rc = enable_metaslot(alt_token, alt_slot, use_default,
894 		    mecharglist, allflag, auto_key_migrate_flag);
895 		break;
896 	case PROV_UEF_LIB:
897 		rc = enable_uef_lib(prov->cp_name, rndflag, allflag,
898 		    mecharglist);
899 		break;
900 	case PROV_KEF_SOFT:
901 	case PROV_KEF_HARD:
902 		if (rndflag && !allflag) {
903 			if ((mecharglist = create_mech(RANDOM)) == NULL) {
904 				rc = FAILURE;
905 				break;
906 			}
907 		}
908 		if (getzoneid() == GLOBAL_ZONEID) {
909 			rc = enable_kef(prov->cp_name, rndflag, allflag,
910 			    mecharglist);
911 		} else {
912 			/*
913 			 * TRANSLATION_NOTE
914 			 * "enable" could be either a literal keyword
915 			 * and hence not to be translated, or a verb and
916 			 * translatable.  A choice was made to view it as
917 			 * a literal keyword.  "global" is keyword and not
918 			 * to be translated.
919 			 */
920 			cryptoerror(LOG_STDERR, gettext("%1$s for kernel "
921 			    "providers is supported in the %2$s zone only"),
922 			    "enable", "global");
923 			rc = FAILURE;
924 		}
925 		break;
926 	default: /* should not come here */
927 		rc = FAILURE;
928 		break;
929 	}
930 out:
931 	free(prov);
932 	if (mecharglist != NULL) {
933 		free_mechlist(mecharglist);
934 	}
935 	if (alt_token != NULL) {
936 		free(alt_token);
937 	}
938 	if (alt_slot != NULL) {
939 		free(alt_slot);
940 	}
941 	return (rc);
942 }
943 
944 
945 
946 /*
947  * The top level function fo the install subcommand.
948  */
949 static int
950 do_install(int argc, char **argv)
951 {
952 	cryptoadm_provider_t 	*prov = NULL;
953 	int	rc;
954 
955 	if (argc < 3) {
956 		usage();
957 		return (ERROR_USAGE);
958 	}
959 
960 	prov = get_provider(argc, argv);
961 	if (prov == NULL ||
962 	    prov->cp_type == PROV_BADNAME || prov->cp_type == PROV_KEF_HARD) {
963 		/*
964 		 * TRANSLATION_NOTE
965 		 * "install" could be either a literal keyword and hence
966 		 * not to be translated, or a verb and translatable.  A
967 		 * choice was made to view it as a literal keyword.
968 		 */
969 		cryptoerror(LOG_STDERR,
970 		    gettext("bad provider name for %s."), "install");
971 		rc = FAILURE;
972 		goto out;
973 	}
974 
975 	if (prov->cp_type == PROV_UEF_LIB) {
976 		rc = install_uef_lib(prov->cp_name);
977 		goto out;
978 	}
979 
980 	/* It is the PROV_KEF_SOFT type now  */
981 
982 	/* check if there are mechanism operands */
983 	if (argc < 4) {
984 		/*
985 		 * TRANSLATION_NOTE
986 		 * "mechanism" could be either a literal keyword and hence
987 		 * not to be translated, or a descriptive word and
988 		 * translatable.  A choice was made to view it as a literal
989 		 * keyword.
990 		 */
991 		cryptoerror(LOG_STDERR,
992 		    gettext("need %s operands for installing a"
993 		    " kernel software provider."), "mechanism");
994 		rc = ERROR_USAGE;
995 		goto out;
996 	}
997 
998 	if ((rc = process_mech_operands(argc, argv, B_FALSE)) != SUCCESS) {
999 		goto out;
1000 	}
1001 
1002 	if (allflag == B_TRUE) {
1003 		/*
1004 		 * TRANSLATION_NOTE
1005 		 * "all", "mechanism", and "install" are all keywords and
1006 		 * not to be translated.
1007 		 */
1008 		cryptoerror(LOG_STDERR,
1009 		    gettext("can not use the %1$s keyword for %2$s "
1010 		    "in the %3$s subcommand."), "all", "mechanism", "install");
1011 		rc = ERROR_USAGE;
1012 		goto out;
1013 	}
1014 
1015 	if (getzoneid() == GLOBAL_ZONEID) {
1016 		rc = install_kef(prov->cp_name, mecharglist);
1017 	} else {
1018 		/*
1019 		 * TRANSLATION_NOTE
1020 		 * "install" could be either a literal keyword and hence
1021 		 * not to be translated, or a verb and translatable.  A
1022 		 * choice was made to view it as a literal keyword.
1023 		 * "global" is keyword and not to be translated.
1024 		 */
1025 		cryptoerror(LOG_STDERR, gettext("%1$s for kernel providers "
1026 		    "is supported in the %2$s zone only"), "install", "global");
1027 		rc = FAILURE;
1028 	}
1029 out:
1030 	free(prov);
1031 	return (rc);
1032 }
1033 
1034 
1035 
1036 /*
1037  * The top level function for the uninstall subcommand.
1038  */
1039 static int
1040 do_uninstall(int argc, char **argv)
1041 {
1042 	cryptoadm_provider_t 	*prov = NULL;
1043 	int	rc = SUCCESS;
1044 
1045 	if (argc != 3) {
1046 		usage();
1047 		return (ERROR_USAGE);
1048 	}
1049 
1050 	prov = get_provider(argc, argv);
1051 	if (prov == NULL ||
1052 	    prov->cp_type == PROV_BADNAME || prov->cp_type == PROV_KEF_HARD) {
1053 		/*
1054 		 * TRANSLATION_NOTE
1055 		 * "uninstall" could be either a literal keyword and hence
1056 		 * not to be translated, or a verb and translatable.  A
1057 		 * choice was made to view it as a literal keyword.
1058 		 */
1059 		cryptoerror(LOG_STDERR,
1060 		    gettext("bad provider name for %s."), "uninstall");
1061 		free(prov);
1062 		return (FAILURE);
1063 	}
1064 
1065 	if (prov->cp_type == PROV_UEF_LIB) {
1066 		rc = uninstall_uef_lib(prov->cp_name);
1067 	} else if (prov->cp_type == PROV_KEF_SOFT) {
1068 		if (getzoneid() == GLOBAL_ZONEID) {
1069 			rc = uninstall_kef(prov->cp_name);
1070 		} else {
1071 			/*
1072 			 * TRANSLATION_NOTE
1073 			 * "uninstall" could be either a literal keyword and
1074 			 * hence not to be translated, or a verb and
1075 			 * translatable.  A choice was made to view it as a
1076 			 * literal keyword.  "global" is keyword and not to
1077 			 * be translated.
1078 			 */
1079 			cryptoerror(LOG_STDERR, gettext("%1$s for kernel "
1080 			    "providers is supported in the %2$s zone only"),
1081 			    "uninstall", "global");
1082 			rc = FAILURE;
1083 		}
1084 	}
1085 
1086 	free(prov);
1087 	return (rc);
1088 }
1089 
1090 
1091 /*
1092  * The top level function for the unload subcommand.
1093  */
1094 static int
1095 do_unload(int argc, char **argv)
1096 {
1097 	cryptoadm_provider_t 	*prov = NULL;
1098 	entry_t	*pent;
1099 	boolean_t	is_active;
1100 	int rc = SUCCESS;
1101 
1102 	if (argc != 3) {
1103 		usage();
1104 		return (ERROR_USAGE);
1105 	}
1106 
1107 	/* check if it is a kernel software provider */
1108 	prov = get_provider(argc, argv);
1109 	if (prov == NULL) {
1110 		cryptoerror(LOG_STDERR,
1111 		    gettext("unable to determine provider name."));
1112 		goto out;
1113 	}
1114 	if (prov->cp_type != PROV_KEF_SOFT) {
1115 		cryptoerror(LOG_STDERR,
1116 		    gettext("%s is not a valid kernel software provider."),
1117 		    prov->cp_name);
1118 		rc = FAILURE;
1119 		goto out;
1120 	}
1121 
1122 	if (getzoneid() != GLOBAL_ZONEID) {
1123 		/*
1124 		 * TRANSLATION_NOTE
1125 		 * "unload" could be either a literal keyword and hence
1126 		 * not to be translated, or a verb and translatable.
1127 		 * A choice was made to view it as a literal keyword.
1128 		 * "global" is keyword and not to be translated.
1129 		 */
1130 		cryptoerror(LOG_STDERR, gettext("%1$s for kernel providers "
1131 		    "is supported in the %2$s zone only"), "unload", "global");
1132 		rc = FAILURE;
1133 		goto out;
1134 	}
1135 
1136 	/* Check if it is in the kcf.conf file first */
1137 	if ((pent = getent_kef(prov->cp_name)) == NULL) {
1138 		cryptoerror(LOG_STDERR,
1139 		    gettext("provider %s does not exist."), prov->cp_name);
1140 		rc = FAILURE;
1141 		goto out;
1142 	}
1143 	free_entry(pent);
1144 
1145 	/* If it is unloaded already, return  */
1146 	if (check_active_for_soft(prov->cp_name, &is_active) == FAILURE) {
1147 		cryptodebug("internal error");
1148 		cryptoerror(LOG_STDERR,
1149 		    gettext("failed to unload %s."), prov->cp_name);
1150 		rc = FAILURE;
1151 		goto out;
1152 	}
1153 
1154 	if (is_active == B_FALSE) { /* unloaded already */
1155 		rc = SUCCESS;
1156 		goto out;
1157 	} else if (unload_kef_soft(prov->cp_name, B_TRUE) == FAILURE) {
1158 		cryptoerror(LOG_STDERR,
1159 		    gettext("failed to unload %s."), prov->cp_name);
1160 		rc = FAILURE;
1161 	} else {
1162 		rc = SUCCESS;
1163 	}
1164 out:
1165 	free(prov);
1166 	return (rc);
1167 }
1168 
1169 
1170 
1171 /*
1172  * The top level function for the refresh subcommand.
1173  */
1174 static int
1175 do_refresh(int argc)
1176 {
1177 	if (argc != 2) {
1178 		usage();
1179 		return (ERROR_USAGE);
1180 	}
1181 
1182 	/*
1183 	 * Note:  in non-global zone, this must silently return SUCCESS
1184 	 * due to integration with SMF, for "svcadm refresh cryptosvc"
1185 	 */
1186 	if (getzoneid() != GLOBAL_ZONEID)
1187 		return (SUCCESS);
1188 
1189 	return (refresh());
1190 }
1191 
1192 
1193 /*
1194  * The top level function for the start subcommand.
1195  */
1196 static int
1197 do_start(int argc)
1198 {
1199 	int ret;
1200 
1201 	if (argc != 2) {
1202 		usage();
1203 		return (ERROR_USAGE);
1204 	}
1205 
1206 	ret = do_refresh(argc);
1207 	if (ret != SUCCESS)
1208 		return (ret);
1209 
1210 	return (start_daemon());
1211 }
1212 
1213 /*
1214  * The top level function for the stop subcommand.
1215  */
1216 static int
1217 do_stop(int argc)
1218 {
1219 	if (argc != 2) {
1220 		usage();
1221 		return (ERROR_USAGE);
1222 	}
1223 
1224 	return (stop_daemon());
1225 }
1226 
1227 
1228 
1229 /*
1230  * List all the providers.
1231  */
1232 static int
1233 list_simple_for_all(boolean_t verbose)
1234 {
1235 	uentrylist_t	*pliblist;
1236 	uentrylist_t	*plibptr;
1237 	entrylist_t	*pdevlist_conf;
1238 	entrylist_t	*psoftlist_conf;
1239 	entrylist_t	*pdevlist_zone;
1240 	entrylist_t	*psoftlist_zone;
1241 	entrylist_t	*ptr;
1242 	crypto_get_dev_list_t	*pdevlist_kernel = NULL;
1243 	boolean_t	is_active;
1244 	int	ru = SUCCESS;
1245 	int	rs = SUCCESS;
1246 	int	rd = SUCCESS;
1247 	int	i;
1248 
1249 	/* get user-level providers */
1250 	(void) printf(gettext("\nUser-level providers:\n"));
1251 	if (get_pkcs11conf_info(&pliblist) != SUCCESS) {
1252 		cryptoerror(LOG_STDERR, gettext(
1253 		    "failed to retrieve the list of user-level providers."));
1254 		ru = FAILURE;
1255 	}
1256 	plibptr = pliblist;
1257 	while (plibptr != NULL) {
1258 		if (strcmp(plibptr->puent->name, METASLOT_KEYWORD) != 0) {
1259 			(void) printf(gettext("Provider: %s\n"),
1260 			    plibptr->puent->name);
1261 			if (verbose) {
1262 				(void) list_mechlist_for_lib(
1263 				    plibptr->puent->name, mecharglist, NULL,
1264 				    B_FALSE, verbose, B_FALSE);
1265 				(void) printf("\n");
1266 			}
1267 		}
1268 		plibptr = plibptr->next;
1269 	}
1270 	free_uentrylist(pliblist);
1271 
1272 	/* get kernel software providers */
1273 	(void) printf(gettext("\nKernel software providers:\n"));
1274 
1275 	if (getzoneid() == GLOBAL_ZONEID) {
1276 		/* use kcf.conf for kernel software providers in global zone */
1277 		pdevlist_conf = NULL;
1278 		psoftlist_conf = NULL;
1279 
1280 		if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) !=
1281 		    SUCCESS) {
1282 			cryptoerror(LOG_STDERR,
1283 			    gettext("failed to retrieve the "
1284 			    "list of kernel software providers.\n"));
1285 			rs = FAILURE;
1286 		}
1287 
1288 		ptr = psoftlist_conf;
1289 		while (ptr != NULL) {
1290 			if (check_active_for_soft(ptr->pent->name, &is_active)
1291 			    == FAILURE) {
1292 				rs = FAILURE;
1293 				cryptoerror(LOG_STDERR, gettext("failed to "
1294 				    "get the state of a kernel software "
1295 				    "providers.\n"));
1296 				break;
1297 			}
1298 
1299 			(void) printf("\t%s", ptr->pent->name);
1300 			if (is_active == B_FALSE) {
1301 				(void) printf(gettext(" (inactive)\n"));
1302 			} else {
1303 				(void) printf("\n");
1304 			}
1305 			ptr = ptr->next;
1306 		}
1307 
1308 		free_entrylist(pdevlist_conf);
1309 		free_entrylist(psoftlist_conf);
1310 	} else {
1311 		/* kcf.conf not there in non-global zone, use /dev/cryptoadm */
1312 		pdevlist_zone = NULL;
1313 		psoftlist_zone = NULL;
1314 
1315 		if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) !=
1316 		    SUCCESS) {
1317 			cryptoerror(LOG_STDERR,
1318 			    gettext("failed to retrieve the "
1319 			    "list of kernel software providers.\n"));
1320 			rs = FAILURE;
1321 		}
1322 
1323 		ptr = psoftlist_zone;
1324 		while (ptr != NULL) {
1325 			(void) printf("\t%s\n", ptr->pent->name);
1326 			ptr = ptr->next;
1327 		}
1328 
1329 		free_entrylist(pdevlist_zone);
1330 		free_entrylist(psoftlist_zone);
1331 	}
1332 
1333 	/* get kernel hardware providers */
1334 	(void) printf(gettext("\nKernel hardware providers:\n"));
1335 	if (get_dev_list(&pdevlist_kernel) == FAILURE) {
1336 		cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1337 		    "the list of kernel hardware providers.\n"));
1338 		rd = FAILURE;
1339 	} else {
1340 		for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
1341 			(void) printf("\t%s/%d\n",
1342 			    pdevlist_kernel->dl_devs[i].le_dev_name,
1343 			    pdevlist_kernel->dl_devs[i].le_dev_instance);
1344 		}
1345 	}
1346 	free(pdevlist_kernel);
1347 
1348 	if (ru == FAILURE || rs == FAILURE || rd == FAILURE) {
1349 		return (FAILURE);
1350 	} else {
1351 		return (SUCCESS);
1352 	}
1353 }
1354 
1355 
1356 
1357 /*
1358  * List all the providers. And for each provider, list the mechanism list.
1359  */
1360 static int
1361 list_mechlist_for_all(boolean_t verbose)
1362 {
1363 	crypto_get_dev_list_t	*pdevlist_kernel;
1364 	uentrylist_t	*pliblist;
1365 	uentrylist_t	*plibptr;
1366 	entrylist_t	*pdevlist_conf;
1367 	entrylist_t	*psoftlist_conf;
1368 	entrylist_t	*pdevlist_zone;
1369 	entrylist_t	*psoftlist_zone;
1370 	entrylist_t	*ptr;
1371 	mechlist_t	*pmechlist;
1372 	boolean_t	is_active;
1373 	char	provname[MAXNAMELEN];
1374 	char	devname[MAXNAMELEN];
1375 	int 	inst_num;
1376 	int	count;
1377 	int	i;
1378 	int	rv;
1379 	int	rc = SUCCESS;
1380 
1381 	/* get user-level providers */
1382 	(void) printf(gettext("\nUser-level providers:\n"));
1383 	/*
1384 	 * TRANSLATION_NOTE
1385 	 * Strictly for appearance's sake, this line should be as long as
1386 	 * the length of the translated text above.
1387 	 */
1388 	(void) printf(gettext("=====================\n"));
1389 	if (get_pkcs11conf_info(&pliblist) != SUCCESS) {
1390 		cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1391 		    "the list of user-level providers.\n"));
1392 		rc = FAILURE;
1393 	}
1394 
1395 	plibptr = pliblist;
1396 	while (plibptr != NULL) {
1397 		/* skip metaslot entry */
1398 		if (strcmp(plibptr->puent->name, METASLOT_KEYWORD) != 0) {
1399 			(void) printf(gettext("\nProvider: %s\n"),
1400 			    plibptr->puent->name);
1401 			rv = list_mechlist_for_lib(plibptr->puent->name,
1402 			    mecharglist, NULL, B_FALSE, verbose, B_TRUE);
1403 			if (rv == FAILURE) {
1404 				rc = FAILURE;
1405 			}
1406 		}
1407 		plibptr = plibptr->next;
1408 	}
1409 	free_uentrylist(pliblist);
1410 
1411 	/* get kernel software providers */
1412 	(void) printf(gettext("\nKernel software providers:\n"));
1413 	/*
1414 	 * TRANSLATION_NOTE
1415 	 * Strictly for appearance's sake, this line should be as long as
1416 	 * the length of the translated text above.
1417 	 */
1418 	(void) printf(gettext("==========================\n"));
1419 	if (getzoneid() == GLOBAL_ZONEID) {
1420 		/* use kcf.conf for kernel software providers in global zone */
1421 		pdevlist_conf = NULL;
1422 		psoftlist_conf = NULL;
1423 
1424 		if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) !=
1425 		    SUCCESS) {
1426 			cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1427 			    "the list of kernel software providers.\n"));
1428 			rc = FAILURE;
1429 		}
1430 
1431 		ptr = psoftlist_conf;
1432 		while (ptr != NULL) {
1433 			if (check_active_for_soft(ptr->pent->name, &is_active)
1434 			    == SUCCESS) {
1435 				if (is_active) {
1436 					rv = list_mechlist_for_soft(
1437 					    ptr->pent->name);
1438 					if (rv == FAILURE) {
1439 						rc = FAILURE;
1440 					}
1441 				} else {
1442 					(void) printf(gettext(
1443 					    "%s: (inactive)\n"),
1444 					    ptr->pent->name);
1445 				}
1446 			} else {
1447 				/* should not happen */
1448 				(void) printf(gettext(
1449 				    "%s: failed to get the mechanism list.\n"),
1450 				    ptr->pent->name);
1451 				rc = FAILURE;
1452 			}
1453 			ptr = ptr->next;
1454 		}
1455 
1456 		free_entrylist(pdevlist_conf);
1457 		free_entrylist(psoftlist_conf);
1458 	} else {
1459 		/* kcf.conf not there in non-global zone, use /dev/cryptoadm */
1460 		pdevlist_zone = NULL;
1461 		psoftlist_zone = NULL;
1462 
1463 		if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) !=
1464 		    SUCCESS) {
1465 			cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1466 			    "the list of kernel software providers.\n"));
1467 			rc = FAILURE;
1468 		}
1469 
1470 		ptr = psoftlist_zone;
1471 		while (ptr != NULL) {
1472 			rv = list_mechlist_for_soft(ptr->pent->name);
1473 			if (rv == FAILURE) {
1474 				(void) printf(gettext(
1475 				    "%s: failed to get the mechanism list.\n"),
1476 				    ptr->pent->name);
1477 				rc = FAILURE;
1478 			}
1479 			ptr = ptr->next;
1480 		}
1481 
1482 		free_entrylist(pdevlist_zone);
1483 		free_entrylist(psoftlist_zone);
1484 	}
1485 
1486 	/* Get kernel hardware providers and their mechanism lists */
1487 	(void) printf(gettext("\nKernel hardware providers:\n"));
1488 	/*
1489 	 * TRANSLATION_NOTE
1490 	 * Strictly for appearance's sake, this line should be as long as
1491 	 * the length of the translated text above.
1492 	 */
1493 	(void) printf(gettext("==========================\n"));
1494 	if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
1495 		cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1496 		    "the list of hardware providers.\n"));
1497 		return (FAILURE);
1498 	}
1499 
1500 	for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
1501 		(void) strlcpy(devname,
1502 		    pdevlist_kernel->dl_devs[i].le_dev_name, MAXNAMELEN);
1503 		inst_num = pdevlist_kernel->dl_devs[i].le_dev_instance;
1504 		count = pdevlist_kernel->dl_devs[i].le_mechanism_count;
1505 		(void) snprintf(provname, sizeof (provname), "%s/%d", devname,
1506 		    inst_num);
1507 		if (get_dev_info(devname, inst_num, count, &pmechlist) ==
1508 		    SUCCESS) {
1509 			(void) filter_mechlist(&pmechlist, RANDOM);
1510 			print_mechlist(provname, pmechlist);
1511 			free_mechlist(pmechlist);
1512 		} else {
1513 			(void) printf(gettext("%s: failed to get the mechanism"
1514 			    " list.\n"), provname);
1515 			rc = FAILURE;
1516 		}
1517 	}
1518 	free(pdevlist_kernel);
1519 	return (rc);
1520 }
1521 
1522 
1523 /*
1524  * List all the providers. And for each provider, list the policy information.
1525  */
1526 static int
1527 list_policy_for_all(void)
1528 {
1529 	crypto_get_dev_list_t	*pdevlist_kernel;
1530 	uentrylist_t	*pliblist;
1531 	uentrylist_t	*plibptr;
1532 	entrylist_t	*pdevlist_conf;
1533 	entrylist_t	*psoftlist_conf;
1534 	entrylist_t	*ptr;
1535 	entrylist_t	*phead;
1536 	boolean_t	found;
1537 	char	provname[MAXNAMELEN];
1538 	int	i;
1539 	int	rc = SUCCESS;
1540 
1541 	/* Get user-level providers */
1542 	(void) printf(gettext("\nUser-level providers:\n"));
1543 	/*
1544 	 * TRANSLATION_NOTE
1545 	 * Strictly for appearance's sake, this line should be as long as
1546 	 * the length of the translated text above.
1547 	 */
1548 	(void) printf(gettext("=====================\n"));
1549 	if (get_pkcs11conf_info(&pliblist) == FAILURE) {
1550 		cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1551 		    "the list of user-level providers.\n"));
1552 	} else {
1553 		plibptr = pliblist;
1554 		while (plibptr != NULL) {
1555 			/* skip metaslot entry */
1556 			if (strcmp(plibptr->puent->name,
1557 			    METASLOT_KEYWORD) != 0) {
1558 				if (print_uef_policy(plibptr->puent)
1559 				    == FAILURE) {
1560 					rc = FAILURE;
1561 				}
1562 			}
1563 			plibptr = plibptr->next;
1564 		}
1565 		free_uentrylist(pliblist);
1566 	}
1567 
1568 	/* kernel software providers */
1569 	(void) printf(gettext("\nKernel software providers:\n"));
1570 	/*
1571 	 * TRANSLATION_NOTE
1572 	 * Strictly for appearance's sake, this line should be as long as
1573 	 * the length of the translated text above.
1574 	 */
1575 	(void) printf(gettext("==========================\n"));
1576 
1577 	/* Get all entries from the kcf.conf file */
1578 	pdevlist_conf = NULL;
1579 	if (getzoneid() == GLOBAL_ZONEID) {
1580 		/* use kcf.conf for kernel software providers in global zone */
1581 		psoftlist_conf = NULL;
1582 
1583 		if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) ==
1584 		    FAILURE) {
1585 			cryptoerror(LOG_STDERR, gettext(
1586 			    "failed to retrieve the list of kernel "
1587 			    "providers.\n"));
1588 			return (FAILURE);
1589 		}
1590 
1591 		ptr = psoftlist_conf;
1592 		while (ptr != NULL) {
1593 			(void) list_policy_for_soft(ptr->pent->name);
1594 			ptr = ptr->next;
1595 		}
1596 
1597 		free_entrylist(psoftlist_conf);
1598 	} else {
1599 		/* kcf.conf not there in non-global zone, no policy info */
1600 
1601 		/*
1602 		 * TRANSLATION_NOTE
1603 		 * "global" is keyword and not to be translated.
1604 		 */
1605 		cryptoerror(LOG_STDERR, gettext(
1606 		    "policy information for kernel software providers is "
1607 		    "available in the %s zone only"), "global");
1608 	}
1609 
1610 	/* Kernel hardware providers */
1611 	(void) printf(gettext("\nKernel hardware providers:\n"));
1612 	/*
1613 	 * TRANSLATION_NOTE
1614 	 * Strictly for appearance's sake, this line should be as long as
1615 	 * the length of the translated text above.
1616 	 */
1617 	(void) printf(gettext("==========================\n"));
1618 
1619 	if (getzoneid() != GLOBAL_ZONEID) {
1620 		/*
1621 		 * TRANSLATION_NOTE
1622 		 * "global" is keyword and not to be translated.
1623 		 */
1624 		cryptoerror(LOG_STDERR, gettext(
1625 		    "policy information for kernel hardware providers is "
1626 		    "available in the %s zone only"), "global");
1627 		return (FAILURE);
1628 	}
1629 
1630 	/* Get the hardware provider list from kernel */
1631 	if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
1632 		cryptoerror(LOG_STDERR, gettext(
1633 		    "failed to retrieve the list of hardware providers.\n"));
1634 		free_entrylist(pdevlist_conf);
1635 		return (FAILURE);
1636 	}
1637 
1638 	/*
1639 	 * For each hardware provider from kernel, check if it has an entry
1640 	 * in the config file.  If it has an entry, print out the policy from
1641 	 * config file and remove the entry from the hardware provider list
1642 	 * of the config file.  If it does not have an entry in the config
1643 	 * file, no mechanisms of it have been disabled. But, we still call
1644 	 * list_policy_for_hard() to account for the "random" feature.
1645 	 */
1646 	for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
1647 		(void) snprintf(provname, sizeof (provname), "%s/%d",
1648 		    pdevlist_kernel->dl_devs[i].le_dev_name,
1649 		    pdevlist_kernel->dl_devs[i].le_dev_instance);
1650 		found = B_FALSE;
1651 		phead = ptr = pdevlist_conf;
1652 		while (!found && ptr) {
1653 			if (strcmp(ptr->pent->name, provname) == 0) {
1654 				found = B_TRUE;
1655 			} else {
1656 				phead = ptr;
1657 				ptr = ptr->next;
1658 			}
1659 		}
1660 
1661 		if (found) {
1662 			(void) list_policy_for_hard(ptr->pent->name);
1663 			if (phead == ptr) {
1664 				pdevlist_conf = pdevlist_conf->next;
1665 			} else {
1666 				phead->next = ptr->next;
1667 			}
1668 			free_entry(ptr->pent);
1669 			free(ptr);
1670 		} else {
1671 			(void) list_policy_for_hard(provname);
1672 		}
1673 	}
1674 
1675 	/*
1676 	 * If there are still entries left in the pdevlist_conf list from
1677 	 * the config file, these providers must have been detached.
1678 	 * Should print out their policy information also.
1679 	 */
1680 	ptr = pdevlist_conf;
1681 	while (ptr != NULL) {
1682 		print_kef_policy(ptr->pent, B_FALSE, B_TRUE);
1683 		ptr = ptr->next;
1684 	}
1685 
1686 	free_entrylist(pdevlist_conf);
1687 	free(pdevlist_kernel);
1688 
1689 	return (rc);
1690 }
1691