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