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