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, 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, 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, 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)) == 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 		if (strcmp(plibptr->puent->name, METASLOT_KEYWORD) != 0) {
1303 			(void) printf(gettext("Provider: %s\n"),
1304 			    plibptr->puent->name);
1305 			if (verbose) {
1306 				(void) list_mechlist_for_lib(
1307 				    plibptr->puent->name, mecharglist, NULL,
1308 				    B_FALSE, verbose, B_FALSE);
1309 				(void) printf("\n");
1310 			}
1311 		}
1312 	}
1313 	free_uentrylist(pliblist);
1314 
1315 	/* get kernel software providers */
1316 	(void) printf(gettext("\nKernel software providers:\n"));
1317 
1318 	if (getzoneid() == GLOBAL_ZONEID) {
1319 		/* get kernel software providers from kernel ioctl */
1320 		crypto_get_soft_list_t		*psoftlist_kernel = NULL;
1321 		uint_t				sl_soft_count;
1322 		char				*psoftname;
1323 		entrylist_t			*pdevlist_conf = NULL;
1324 		entrylist_t			*psoftlist_conf = NULL;
1325 		entrylist_t			*pfipslist_conf = NULL;
1326 
1327 		if (get_soft_list(&psoftlist_kernel) == FAILURE) {
1328 			cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
1329 			    "software provider list from kernel."));
1330 			rc = FAILURE;
1331 		} else {
1332 			sl_soft_count = psoftlist_kernel->sl_soft_count;
1333 
1334 			if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf,
1335 			    &pfipslist_conf) == FAILURE) {
1336 				cryptoerror(LOG_ERR,
1337 				    "failed to retrieve the providers' "
1338 				    "information from file kcf.conf - %s.",
1339 				    _PATH_KCF_CONF);
1340 				free(psoftlist_kernel);
1341 				rc = FAILURE;
1342 			} else {
1343 
1344 				for (i = 0,
1345 				    psoftname = psoftlist_kernel->sl_soft_names;
1346 				    i < sl_soft_count;
1347 				    ++i, psoftname += strlen(psoftname) + 1) {
1348 					pent = getent_kef(psoftname,
1349 					    pdevlist_conf, psoftlist_conf,
1350 					    pfipslist_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 				free_entrylist(pfipslist_conf);
1358 			}
1359 			free(psoftlist_kernel);
1360 		}
1361 
1362 	} else {
1363 		/* kcf.conf not there in non-global zone, use /dev/cryptoadm */
1364 		entrylist_t	*pdevlist_zone = NULL;
1365 		entrylist_t	*psoftlist_zone = NULL;
1366 		entrylist_t	*ptr;
1367 
1368 		if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) !=
1369 		    SUCCESS) {
1370 			cryptoerror(LOG_STDERR,
1371 			    gettext("failed to retrieve the "
1372 			    "list of kernel software providers.\n"));
1373 			rc = FAILURE;
1374 		}
1375 
1376 		ptr = psoftlist_zone;
1377 		while (ptr != NULL) {
1378 			(void) printf("\t%s\n", ptr->pent->name);
1379 			ptr = ptr->next;
1380 		}
1381 
1382 		free_entrylist(pdevlist_zone);
1383 		free_entrylist(psoftlist_zone);
1384 	}
1385 
1386 	/* get kernel hardware providers */
1387 	(void) printf(gettext("\nKernel hardware providers:\n"));
1388 	if (get_dev_list(&pdevlist_kernel) == FAILURE) {
1389 		cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1390 		    "the list of kernel hardware providers.\n"));
1391 		rc = FAILURE;
1392 	} else {
1393 		for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
1394 			(void) printf("\t%s/%d\n",
1395 			    pdevlist_kernel->dl_devs[i].le_dev_name,
1396 			    pdevlist_kernel->dl_devs[i].le_dev_instance);
1397 		}
1398 	}
1399 	free(pdevlist_kernel);
1400 
1401 	return (rc);
1402 }
1403 
1404 
1405 
1406 /*
1407  * List all the providers. And for each provider, list the mechanism list.
1408  * Called for "cryptoadm list -m" or "cryptoadm list -mv" .
1409  */
1410 static int
1411 list_mechlist_for_all(boolean_t verbose)
1412 {
1413 	crypto_get_dev_list_t	*pdevlist_kernel = NULL;
1414 	uentrylist_t		*pliblist = NULL;
1415 	uentrylist_t		*plibptr = NULL;
1416 	entry_t			*pent = NULL;
1417 	mechlist_t		*pmechlist = NULL;
1418 	char			provname[MAXNAMELEN];
1419 	char			devname[MAXNAMELEN];
1420 	int			inst_num;
1421 	int			count;
1422 	int			i;
1423 	int			rv;
1424 	int			rc = SUCCESS;
1425 
1426 	/* get user-level providers */
1427 	(void) printf(gettext("\nUser-level providers:\n"));
1428 	/*
1429 	 * TRANSLATION_NOTE
1430 	 * Strictly for appearance's sake, this line should be as long as
1431 	 * the length of the translated text above.
1432 	 */
1433 	(void) printf(gettext("=====================\n"));
1434 	if (get_pkcs11conf_info(&pliblist) != SUCCESS) {
1435 		cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1436 		    "the list of user-level providers.\n"));
1437 		rc = FAILURE;
1438 	}
1439 
1440 	plibptr = pliblist;
1441 	while (plibptr != NULL) {
1442 		/* skip metaslot entry */
1443 		if (strcmp(plibptr->puent->name, METASLOT_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 		entrylist_t			*pfipslist_conf = NULL;
1474 
1475 		if (get_soft_list(&psoftlist_kernel) == FAILURE) {
1476 			cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
1477 			    "software provider list from kernel."));
1478 			return (FAILURE);
1479 		}
1480 		sl_soft_count = psoftlist_kernel->sl_soft_count;
1481 
1482 		if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf,
1483 		    &pfipslist_conf) == FAILURE) {
1484 			cryptoerror(LOG_ERR,
1485 			    "failed to retrieve the providers' "
1486 			    "information from file kcf.conf - %s.",
1487 			    _PATH_KCF_CONF);
1488 			free(psoftlist_kernel);
1489 			return (FAILURE);
1490 		}
1491 
1492 		for (i = 0, psoftname = psoftlist_kernel->sl_soft_names;
1493 		    i < sl_soft_count;
1494 		    ++i, psoftname += strlen(psoftname) + 1) {
1495 			pent = getent_kef(psoftname, pdevlist_conf,
1496 			    psoftlist_conf, pfipslist_conf);
1497 			if ((pent == NULL) || (pent->load)) {
1498 				rv = list_mechlist_for_soft(psoftname,
1499 				    NULL, NULL, NULL);
1500 				if (rv == FAILURE) {
1501 					rc = FAILURE;
1502 				}
1503 			} else {
1504 				(void) printf(gettext("%s: (inactive)\n"),
1505 				    psoftname);
1506 			}
1507 		}
1508 
1509 		free(psoftlist_kernel);
1510 		free_entrylist(pdevlist_conf);
1511 		free_entrylist(psoftlist_conf);
1512 		free_entrylist(pfipslist_conf);
1513 
1514 	} else {
1515 		/* kcf.conf not there in non-global zone, use /dev/cryptoadm */
1516 		entrylist_t	*pdevlist_zone = NULL;
1517 		entrylist_t	*psoftlist_zone = NULL;
1518 		entrylist_t	*pfipslist_zone = NULL;
1519 		entrylist_t	*ptr;
1520 
1521 		if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) !=
1522 		    SUCCESS) {
1523 			cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1524 			    "the list of kernel software providers.\n"));
1525 			rc = FAILURE;
1526 		}
1527 
1528 		for (ptr = psoftlist_zone; ptr != NULL; ptr = ptr->next) {
1529 			rv = list_mechlist_for_soft(ptr->pent->name,
1530 			    pdevlist_zone, psoftlist_zone, pfipslist_zone);
1531 			if (rv == FAILURE) {
1532 				(void) printf(gettext(
1533 				    "%s: failed to get the mechanism list.\n"),
1534 				    ptr->pent->name);
1535 				rc = FAILURE;
1536 			}
1537 		}
1538 
1539 		free_entrylist(pdevlist_zone);
1540 		free_entrylist(psoftlist_zone);
1541 	}
1542 
1543 	/* Get kernel hardware providers and their mechanism lists */
1544 	(void) printf(gettext("\nKernel hardware providers:\n"));
1545 	/*
1546 	 * TRANSLATION_NOTE
1547 	 * Strictly for appearance's sake, this line should be as long as
1548 	 * the length of the translated text above.
1549 	 */
1550 	(void) printf(gettext("==========================\n"));
1551 	if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
1552 		cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1553 		    "the list of hardware providers.\n"));
1554 		return (FAILURE);
1555 	}
1556 
1557 	for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
1558 		(void) strlcpy(devname,
1559 		    pdevlist_kernel->dl_devs[i].le_dev_name, MAXNAMELEN);
1560 		inst_num = pdevlist_kernel->dl_devs[i].le_dev_instance;
1561 		count = pdevlist_kernel->dl_devs[i].le_mechanism_count;
1562 		(void) snprintf(provname, sizeof (provname), "%s/%d", devname,
1563 		    inst_num);
1564 		if (get_dev_info(devname, inst_num, count, &pmechlist) ==
1565 		    SUCCESS) {
1566 			(void) filter_mechlist(&pmechlist, RANDOM);
1567 			print_mechlist(provname, pmechlist);
1568 			free_mechlist(pmechlist);
1569 		} else {
1570 			(void) printf(gettext("%s: failed to get the mechanism"
1571 			    " list.\n"), provname);
1572 			rc = FAILURE;
1573 		}
1574 	}
1575 	free(pdevlist_kernel);
1576 	return (rc);
1577 }
1578 
1579 
1580 /*
1581  * List all the providers. And for each provider, list the policy information.
1582  * Called for "cryptoadm list -p".
1583  */
1584 static int
1585 list_policy_for_all(void)
1586 {
1587 	crypto_get_dev_list_t	*pdevlist_kernel = NULL;
1588 	uentrylist_t		*pliblist = NULL;
1589 	entrylist_t		*pdevlist_conf = NULL;
1590 	entrylist_t		*psoftlist_conf = NULL;
1591 	entrylist_t		*pfipslist_conf = NULL;
1592 	entrylist_t		*ptr = NULL;
1593 	entrylist_t		*phead = NULL;
1594 	boolean_t		found = B_FALSE;
1595 	char			provname[MAXNAMELEN];
1596 	int			i;
1597 	int			rc = SUCCESS;
1598 
1599 	/* Get user-level providers */
1600 	(void) printf(gettext("\nUser-level providers:\n"));
1601 	/*
1602 	 * TRANSLATION_NOTE
1603 	 * Strictly for appearance's sake, this line should be as long as
1604 	 * the length of the translated text above.
1605 	 */
1606 	(void) printf(gettext("=====================\n"));
1607 	if (get_pkcs11conf_info(&pliblist) == FAILURE) {
1608 		cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1609 		    "the list of user-level providers.\n"));
1610 		rc = FAILURE;
1611 	} else {
1612 		uentrylist_t	*plibptr = pliblist;
1613 
1614 		while (plibptr != NULL) {
1615 			/* skip metaslot entry */
1616 			if (strcmp(plibptr->puent->name,
1617 			    METASLOT_KEYWORD) != 0) {
1618 				if (print_uef_policy(plibptr->puent)
1619 				    == FAILURE) {
1620 					rc = FAILURE;
1621 				}
1622 			}
1623 			plibptr = plibptr->next;
1624 		}
1625 		free_uentrylist(pliblist);
1626 	}
1627 
1628 	/* kernel software providers */
1629 	(void) printf(gettext("\nKernel software providers:\n"));
1630 	/*
1631 	 * TRANSLATION_NOTE
1632 	 * Strictly for appearance's sake, this line should be as long as
1633 	 * the length of the translated text above.
1634 	 */
1635 	(void) printf(gettext("==========================\n"));
1636 
1637 	/* Get all entries from the kernel */
1638 	if (getzoneid() == GLOBAL_ZONEID) {
1639 		/* get kernel software providers from kernel ioctl */
1640 		crypto_get_soft_list_t		*psoftlist_kernel = NULL;
1641 		uint_t				sl_soft_count;
1642 		char				*psoftname;
1643 		int				i;
1644 
1645 		if (get_soft_list(&psoftlist_kernel) == FAILURE) {
1646 			cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
1647 			    "software provider list from kernel."));
1648 			rc = FAILURE;
1649 		} else {
1650 			sl_soft_count = psoftlist_kernel->sl_soft_count;
1651 
1652 			for (i = 0, psoftname = psoftlist_kernel->sl_soft_names;
1653 			    i < sl_soft_count;
1654 			    ++i, psoftname += strlen(psoftname) + 1) {
1655 				(void) list_policy_for_soft(psoftname,
1656 				    pdevlist_conf, psoftlist_conf,
1657 				    pfipslist_conf);
1658 			}
1659 			free(psoftlist_kernel);
1660 		}
1661 
1662 	} else {
1663 		/* kcf.conf not there in non-global zone, no policy info */
1664 
1665 		/*
1666 		 * TRANSLATION_NOTE
1667 		 * "global" is keyword and not to be translated.
1668 		 */
1669 		cryptoerror(LOG_STDERR, gettext(
1670 		    "policy information for kernel software providers is "
1671 		    "available in the %s zone only"), "global");
1672 	}
1673 
1674 	/* Kernel hardware providers */
1675 	(void) printf(gettext("\nKernel hardware providers:\n"));
1676 	/*
1677 	 * TRANSLATION_NOTE
1678 	 * Strictly for appearance's sake, this line should be as long as
1679 	 * the length of the translated text above.
1680 	 */
1681 	(void) printf(gettext("==========================\n"));
1682 
1683 	if (getzoneid() != GLOBAL_ZONEID) {
1684 		/*
1685 		 * TRANSLATION_NOTE
1686 		 * "global" is keyword and not to be translated.
1687 		 */
1688 		cryptoerror(LOG_STDERR, gettext(
1689 		    "policy information for kernel hardware providers is "
1690 		    "available in the %s zone only"), "global");
1691 		return (FAILURE);
1692 	}
1693 
1694 	/* Get the hardware provider list from kernel */
1695 	if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
1696 		cryptoerror(LOG_STDERR, gettext(
1697 		    "failed to retrieve the list of hardware providers.\n"));
1698 		return (FAILURE);
1699 	}
1700 
1701 	if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf,
1702 	    &pfipslist_conf) == FAILURE) {
1703 		cryptoerror(LOG_ERR, "failed to retrieve the providers' "
1704 		    "information from file kcf.conf - %s.",
1705 		    _PATH_KCF_CONF);
1706 		return (FAILURE);
1707 	}
1708 
1709 
1710 	/*
1711 	 * For each hardware provider from kernel, check if it has an entry
1712 	 * in the config file.  If it has an entry, print out the policy from
1713 	 * config file and remove the entry from the hardware provider list
1714 	 * of the config file.  If it does not have an entry in the config
1715 	 * file, no mechanisms of it have been disabled. But, we still call
1716 	 * list_policy_for_hard() to account for the "random" feature.
1717 	 */
1718 	for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
1719 		(void) snprintf(provname, sizeof (provname), "%s/%d",
1720 		    pdevlist_kernel->dl_devs[i].le_dev_name,
1721 		    pdevlist_kernel->dl_devs[i].le_dev_instance);
1722 
1723 		found = B_FALSE;
1724 		phead = ptr = pdevlist_conf;
1725 		while (!found && ptr) {
1726 			if (strcmp(ptr->pent->name, provname) == 0) {
1727 				found = B_TRUE;
1728 			} else {
1729 				phead = ptr;
1730 				ptr = ptr->next;
1731 			}
1732 		}
1733 
1734 		if (found) {
1735 			(void) list_policy_for_hard(ptr->pent->name,
1736 			    pdevlist_conf, psoftlist_conf, pfipslist_conf,
1737 			    pdevlist_kernel);
1738 			if (phead == ptr) {
1739 				pdevlist_conf = pdevlist_conf->next;
1740 			} else {
1741 				phead->next = ptr->next;
1742 			}
1743 			free_entry(ptr->pent);
1744 			free(ptr);
1745 		} else {
1746 			(void) list_policy_for_hard(provname, pdevlist_conf,
1747 			    psoftlist_conf, pfipslist_conf, pdevlist_kernel);
1748 		}
1749 	}
1750 
1751 	/*
1752 	 * If there are still entries left in the pdevlist_conf list from
1753 	 * the config file, these providers must have been detached.
1754 	 * Should print out their policy information also.
1755 	 */
1756 	for (ptr = pdevlist_conf; ptr != NULL; ptr = ptr->next) {
1757 		print_kef_policy(ptr->pent->name, ptr->pent, B_FALSE, B_TRUE);
1758 	}
1759 
1760 	free_entrylist(pdevlist_conf);
1761 	free_entrylist(psoftlist_conf);
1762 	free_entrylist(pfipslist_conf);
1763 	free(pdevlist_kernel);
1764 
1765 	return (rc);
1766 }
1767