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