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