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