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