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