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