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