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