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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
33 #include <sys/types.h>
35 #include <sys/crypto/ioctladmin.h>
37 #include <sys/crypto/elfsign.h>
38 #include "cryptoadm.h"
40 static int check_hardware_provider(char *, char *, int *, int *);
43 * Display the mechanism list for a kernel software provider.
44 * This implements part of the "cryptoadm list -m" command.
46 * Parameters phardlist and psoftlist are supplied by
48 * If NULL, this function obtains it by calling getent_kef() and
49 * then get_kcfconf_info() via get_soft_info() internally.
52 list_mechlist_for_soft(char *provname
,
53 entrylist_t
*phardlist
, entrylist_t
*psoftlist
)
55 mechlist_t
*pmechlist
= NULL
;
58 if (provname
== NULL
) {
62 rc
= get_soft_info(provname
, &pmechlist
, phardlist
, psoftlist
);
64 (void) filter_mechlist(&pmechlist
, RANDOM
);
65 print_mechlist(provname
, pmechlist
);
66 free_mechlist(pmechlist
);
68 cryptoerror(LOG_STDERR
, gettext(
69 "failed to retrieve the mechanism list for %s."),
77 * Display the mechanism list for a kernel hardware provider.
78 * This implements part of the "cryptoadm list -m" command.
81 list_mechlist_for_hard(char *provname
)
83 mechlist_t
*pmechlist
= NULL
;
84 char devname
[MAXNAMELEN
];
89 if (provname
== NULL
) {
94 * Check if the provider is valid. If it is valid, get the number of
97 if (check_hardware_provider(provname
, devname
, &inst_num
, &count
) ==
102 /* Get the mechanism list for the kernel hardware provider */
103 if ((rc
= get_dev_info(devname
, inst_num
, count
, &pmechlist
)) ==
105 (void) filter_mechlist(&pmechlist
, RANDOM
);
106 print_mechlist(provname
, pmechlist
);
107 free_mechlist(pmechlist
);
115 * Display the policy information for a kernel software provider.
116 * This implements part of the "cryptoadm list -p" command.
118 * Parameters phardlist and psoftlist are supplied by
120 * If NULL, this function obtains it by calling get_kcfconf_info()
121 * via getent_kef() internally.
124 list_policy_for_soft(char *provname
,
125 entrylist_t
*phardlist
, entrylist_t
*psoftlist
)
128 entry_t
*pent
= NULL
;
129 mechlist_t
*pmechlist
= NULL
;
130 boolean_t has_random
= B_FALSE
;
131 boolean_t has_mechs
= B_FALSE
;
132 boolean_t in_kernel
= B_FALSE
;
134 if (provname
== NULL
) {
138 if (check_kernel_for_soft(provname
, NULL
, &in_kernel
) == FAILURE
) {
140 } else if (in_kernel
== B_FALSE
) {
141 cryptoerror(LOG_STDERR
, gettext("%s does not exist."),
145 pent
= getent_kef(provname
, phardlist
, psoftlist
);
147 rc
= get_soft_info(provname
, &pmechlist
, phardlist
, psoftlist
);
149 has_random
= filter_mechlist(&pmechlist
, RANDOM
);
150 if (pmechlist
!= NULL
) {
152 free_mechlist(pmechlist
);
155 cryptoerror(LOG_STDERR
, gettext(
156 "failed to retrieve the mechanism list for %s."),
161 print_kef_policy(provname
, pent
, has_random
, has_mechs
);
169 * Display the policy information for a kernel hardware provider.
170 * This implements part of the "cryptoadm list -p" command.
172 * Parameters phardlist and psoftlist are supplied by getent_kef().
173 * If NULL, this function obtains it by calling get_kcfconf_info() via
174 * getent_kef() internally.
175 * Parameter pdevlist is supplied by check_kernel_for_hard().
176 * If NULL, this function obtains it by calling get_dev_list() via
177 * check_kernel_for_hard() internally.
180 list_policy_for_hard(char *provname
,
181 entrylist_t
*phardlist
, entrylist_t
*psoftlist
,
182 crypto_get_dev_list_t
*pdevlist
)
184 entry_t
*pent
= NULL
;
186 mechlist_t
*pmechlist
= NULL
;
187 char devname
[MAXNAMELEN
];
191 boolean_t has_random
= B_FALSE
;
192 boolean_t has_mechs
= B_FALSE
;
194 if (provname
== NULL
) {
199 * Check if the provider is valid. If it is valid, get the number of
202 if (check_hardware_provider(provname
, devname
, &inst_num
, &count
) ==
207 /* Get the mechanism list for the kernel hardware provider */
208 if ((rc
= get_dev_info(devname
, inst_num
, count
, &pmechlist
)) ==
210 has_random
= filter_mechlist(&pmechlist
, RANDOM
);
212 if (pmechlist
!= NULL
) {
214 free_mechlist(pmechlist
);
217 cryptoerror(LOG_STDERR
, gettext(
218 "failed to retrieve the mechanism list for %s."),
224 * If the hardware provider has an entry in the kcf.conf file,
225 * some of its mechanisms must have been disabled. Print out
226 * the disabled list from the config file entry. Otherwise,
227 * if it is active, then all the mechanisms for it are enabled.
229 if ((pent
= getent_kef(provname
, phardlist
, psoftlist
)) != NULL
) {
230 print_kef_policy(provname
, pent
, has_random
, has_mechs
);
234 if (check_kernel_for_hard(provname
, pdevlist
,
235 &in_kernel
) == FAILURE
) {
237 } else if (in_kernel
== B_TRUE
) {
238 (void) printf(gettext(
239 "%s: all mechanisms are enabled."), provname
);
243 * "random" is a keyword and not to be
246 (void) printf(gettext(" %s is enabled.\n"),
252 cryptoerror(LOG_STDERR
,
253 gettext("%s does not exist."), provname
);
261 * Disable a kernel hardware provider.
262 * This implements the "cryptoadm disable" command for
263 * kernel hardware providers.
266 disable_kef_hardware(char *provname
, boolean_t rndflag
, boolean_t allflag
,
269 crypto_load_dev_disabled_t
*pload_dev_dis
= NULL
;
270 mechlist_t
*infolist
= NULL
;
271 entry_t
*pent
= NULL
;
272 boolean_t new_dev_entry
= B_FALSE
;
273 char devname
[MAXNAMELEN
];
279 if (provname
== NULL
) {
284 * Check if the provider is valid. If it is valid, get the number of
287 if (check_hardware_provider(provname
, devname
, &inst_num
, &count
)
292 /* Get the mechanism list for the kernel hardware provider */
293 if (get_dev_info(devname
, inst_num
, count
, &infolist
) == FAILURE
) {
298 * Get the entry of this hardware provider from the config file.
299 * If there is no entry yet, create one for it.
301 if ((pent
= getent_kef(provname
, NULL
, NULL
)) == NULL
) {
302 if ((pent
= create_entry(provname
)) == NULL
) {
303 cryptoerror(LOG_STDERR
, gettext("out of memory."));
304 free_mechlist(infolist
);
307 new_dev_entry
= B_TRUE
;
311 * kCF treats random as an internal mechanism. So, we need to
312 * filter it from the mechanism list here, if we are NOT disabling
313 * or enabling the random feature. Note that we map random feature at
314 * cryptoadm(1M) level to the "random" mechanism in kCF.
317 (void) filter_mechlist(&dislist
, RANDOM
);
320 /* Calculate the new disabled list */
321 if (disable_mechs(&pent
, infolist
, allflag
, dislist
) == FAILURE
) {
322 free_mechlist(infolist
);
326 free_mechlist(infolist
);
328 /* If no mechanisms are to be disabled, return */
329 if (pent
->dis_count
== 0) {
334 /* Update the config file with the new entry or the updated entry */
336 rc
= update_kcfconf(pent
, ADD_MODE
);
338 rc
= update_kcfconf(pent
, MODIFY_MODE
);
346 /* Inform kernel about the new disabled mechanism list */
347 if ((pload_dev_dis
= setup_dev_dis(pent
)) == NULL
) {
353 if ((fd
= open(ADMIN_IOCTL_DEVICE
, O_RDWR
)) == -1) {
354 cryptoerror(LOG_STDERR
, gettext("failed to open %s: %s"),
355 ADMIN_IOCTL_DEVICE
, strerror(errno
));
360 if (ioctl(fd
, CRYPTO_LOAD_DEV_DISABLED
, pload_dev_dis
) == -1) {
361 cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: %s",
368 if (pload_dev_dis
->dd_return_value
!= CRYPTO_SUCCESS
) {
369 cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl return_value = "
370 "%d", pload_dev_dis
->dd_return_value
);
383 * Disable a kernel software provider.
384 * This implements the "cryptoadm disable" command for
385 * kernel software providers.
388 disable_kef_software(char *provname
, boolean_t rndflag
, boolean_t allflag
,
391 crypto_load_soft_disabled_t
*pload_soft_dis
= NULL
;
392 mechlist_t
*infolist
= NULL
;
393 entry_t
*pent
= NULL
;
394 entrylist_t
*phardlist
= NULL
;
395 entrylist_t
*psoftlist
= NULL
;
396 boolean_t in_kernel
= B_FALSE
;
400 if (provname
== NULL
) {
405 * Check if the kernel software provider is currently unloaded.
406 * If it is unloaded, return FAILURE, because the disable subcommand
407 * can not perform on inactive (unloaded) providers.
409 if (check_kernel_for_soft(provname
, NULL
, &in_kernel
) == FAILURE
) {
411 } else if (in_kernel
== B_FALSE
) {
412 cryptoerror(LOG_STDERR
,
413 gettext("%s is not loaded or does not exist."),
418 if (get_kcfconf_info(&phardlist
, &psoftlist
) == FAILURE
) {
420 "failed to retrieve the providers' "
421 "information from the configuration file - %s.",
427 * Get the entry of this provider from the kcf.conf file, if any.
428 * Otherwise, create a new kcf.conf entry for writing back to the file.
430 pent
= getent_kef(provname
, phardlist
, psoftlist
);
431 if (pent
== NULL
) { /* create a new entry */
432 pent
= create_entry(provname
);
434 cryptodebug("out of memory.");
440 /* Get the mechanism list for the software provider from the kernel */
441 if (get_soft_info(provname
, &infolist
, phardlist
, psoftlist
) ==
447 if ((infolist
!= NULL
) && (infolist
->name
[0] != '\0')) {
449 * Replace the supportedlist from kcf.conf with possibly
450 * more-up-to-date list from the kernel. This is the case
451 * for default software providers that had more mechanisms
452 * added in the current version of the kernel.
454 free_mechlist(pent
->suplist
);
455 pent
->suplist
= infolist
;
459 * kCF treats random as an internal mechanism. So, we need to
460 * filter it from the mechanism list here, if we are NOT disabling
461 * or enabling the random feature. Note that we map random feature at
462 * cryptoadm(1M) level to the "random" mechanism in kCF.
465 (void) filter_mechlist(&infolist
, RANDOM
);
468 /* Calculate the new disabled list */
469 if (disable_mechs(&pent
, infolist
, allflag
, dislist
) == FAILURE
) {
474 /* Update the kcf.conf file with the updated entry */
475 if (update_kcfconf(pent
, MODIFY_MODE
) == FAILURE
) {
480 /* Setup argument to inform kernel about the new disabled list. */
481 if ((pload_soft_dis
= setup_soft_dis(pent
)) == NULL
) {
486 if ((fd
= open(ADMIN_IOCTL_DEVICE
, O_RDWR
)) == -1) {
487 cryptoerror(LOG_STDERR
,
488 gettext("failed to open %s for RW: %s"),
489 ADMIN_IOCTL_DEVICE
, strerror(errno
));
494 /* Inform kernel about the new disabled list. */
495 if (ioctl(fd
, CRYPTO_LOAD_SOFT_DISABLED
, pload_soft_dis
) == -1) {
496 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
502 if (pload_soft_dis
->sd_return_value
!= CRYPTO_SUCCESS
) {
503 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
504 "%d", pload_soft_dis
->sd_return_value
);
510 free_entrylist(phardlist
);
511 free_entrylist(psoftlist
);
512 free_mechlist(infolist
);
514 free(pload_soft_dis
);
522 * Enable a kernel software or hardware provider.
523 * This implements the "cryptoadm enable" command for kernel providers.
526 enable_kef(char *provname
, boolean_t rndflag
, boolean_t allflag
,
529 crypto_load_soft_disabled_t
*pload_soft_dis
= NULL
;
530 crypto_load_dev_disabled_t
*pload_dev_dis
= NULL
;
531 entry_t
*pent
= NULL
;
532 boolean_t redo_flag
= B_FALSE
;
533 boolean_t in_kernel
= B_FALSE
;
538 /* Get the entry of this provider from the kcf.conf file, if any. */
539 pent
= getent_kef(provname
, NULL
, NULL
);
541 if (is_device(provname
)) {
544 * This device doesn't have an entry in the config
545 * file, therefore nothing is disabled.
547 cryptoerror(LOG_STDERR
, gettext(
548 "all mechanisms are enabled already for %s."),
553 } else { /* a software module */
554 if (check_kernel_for_soft(provname
, NULL
, &in_kernel
) ==
558 } else if (in_kernel
== B_FALSE
) {
559 cryptoerror(LOG_STDERR
, gettext("%s does not exist."),
563 } else if ((pent
== NULL
) || (pent
->dis_count
== 0)) {
564 /* nothing to be enabled. */
565 cryptoerror(LOG_STDERR
, gettext(
566 "all mechanisms are enabled already for %s."),
574 * kCF treats random as an internal mechanism. So, we need to
575 * filter it from the mechanism list here, if we are NOT disabling
576 * or enabling the random feature. Note that we map random feature at
577 * cryptoadm(1M) level to the "random" mechanism in kCF.
580 redo_flag
= filter_mechlist(&pent
->dislist
, RANDOM
);
585 /* Update the entry by enabling mechanisms for this provider */
586 if ((rc
= enable_mechs(&pent
, allflag
, mlist
)) != SUCCESS
) {
594 if ((tmp
= create_mech(RANDOM
)) == NULL
) {
598 tmp
->next
= pent
->dislist
;
604 * Update the kcf.conf file with the updated entry.
605 * For a hardware provider, if there is no more disabled mechanism,
606 * remove the entire kcf.conf entry.
608 if (is_device(pent
->name
) && (pent
->dis_count
== 0)) {
609 rc
= update_kcfconf(pent
, DELETE_MODE
);
611 rc
= update_kcfconf(pent
, MODIFY_MODE
);
620 /* Inform Kernel about the policy change */
622 if ((fd
= open(ADMIN_IOCTL_DEVICE
, O_RDWR
)) == -1) {
623 cryptoerror(LOG_STDERR
, gettext("failed to open %s: %s"),
624 ADMIN_IOCTL_DEVICE
, strerror(errno
));
629 if (is_device(provname
)) {
630 /* LOAD_DEV_DISABLED */
631 if ((pload_dev_dis
= setup_dev_dis(pent
)) == NULL
) {
636 if (ioctl(fd
, CRYPTO_LOAD_DEV_DISABLED
, pload_dev_dis
) == -1) {
637 cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: "
638 "%s", strerror(errno
));
645 if (pload_dev_dis
->dd_return_value
!= CRYPTO_SUCCESS
) {
646 cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
648 pload_dev_dis
->dd_return_value
);
655 } else { /* a software module */
656 /* LOAD_SOFT_DISABLED */
657 if ((pload_soft_dis
= setup_soft_dis(pent
)) == NULL
) {
662 if (ioctl(fd
, CRYPTO_LOAD_SOFT_DISABLED
, pload_soft_dis
)
664 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: "
665 "%s", strerror(errno
));
667 free(pload_soft_dis
);
672 if (pload_soft_dis
->sd_return_value
!= CRYPTO_SUCCESS
) {
673 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
675 pload_soft_dis
->sd_return_value
);
677 free(pload_soft_dis
);
684 free(pload_soft_dis
);
691 * Install a software module with the specified mechanism list into the system.
692 * This routine adds an entry into the config file for this software module
693 * first, then makes a CRYPTO_LOAD_SOFT_CONFIG ioctl call to inform kernel
694 * about the new addition.
697 install_kef(char *provname
, mechlist_t
*mlist
)
699 crypto_load_soft_config_t
*pload_soft_conf
= NULL
;
701 entry_t
*pent
= NULL
;
703 FILE *pfile_tmp
= NULL
;
704 char tmpfile_name
[MAXPATHLEN
];
709 char buffer2
[BUFSIZ
];
715 if ((provname
== NULL
) || (mlist
== NULL
)) {
719 /* Check if the provider already exists */
720 if ((pent
= getent_kef(provname
, NULL
, NULL
)) != NULL
) {
721 cryptoerror(LOG_STDERR
, gettext("%s exists already."),
727 /* Create an entry with provname and mlist. */
728 if ((pent
= create_entry(provname
)) == NULL
) {
729 cryptoerror(LOG_STDERR
, gettext("out of memory."));
732 pent
->sup_count
= get_mech_count(mlist
);
733 pent
->suplist
= mlist
;
735 /* Append an entry for this software module to the kcf.conf file. */
736 if ((str
= ent2str(pent
)) == NULL
) {
741 if ((pfile
= fopen(_PATH_KCF_CONF
, "r+")) == NULL
) {
743 cryptoerror(LOG_STDERR
,
744 gettext("failed to update the configuration - %s"),
746 cryptodebug("failed to open %s for write.", _PATH_KCF_CONF
);
751 if (lockf(fileno(pfile
), F_TLOCK
, 0) == -1) {
753 cryptoerror(LOG_STDERR
,
754 gettext("failed to lock the configuration - %s"),
757 (void) fclose(pfile
);
762 * Create a temporary file in the /etc/crypto directory.
764 (void) strlcpy(tmpfile_name
, TMPFILE_TEMPLATE
, sizeof (tmpfile_name
));
765 if (mkstemp(tmpfile_name
) == -1) {
767 cryptoerror(LOG_STDERR
,
768 gettext("failed to create a temporary file - %s"),
771 (void) fclose(pfile
);
775 if ((pfile_tmp
= fopen(tmpfile_name
, "w")) == NULL
) {
777 cryptoerror(LOG_STDERR
, gettext("failed to open %s - %s"),
778 tmpfile_name
, strerror(err
));
780 (void) fclose(pfile
);
786 * Loop thru the config file. If the provider was reserved within a
787 * package bracket, just uncomment it. Otherwise, append it at
788 * the end. The resulting file will be saved in the temp file first.
792 while (fgets(buffer
, BUFSIZ
, pfile
) != NULL
) {
794 if (buffer
[0] == '#') {
795 (void) strlcpy(buffer2
, buffer
, BUFSIZ
);
798 if ((name
= strtok(ptr
, SEP_COLON
)) == NULL
) {
801 } else if (strcmp(provname
, name
) == 0) {
807 if (found
== B_FALSE
) {
808 if (fputs(buffer
, pfile_tmp
) == EOF
) {
812 if (found_count
== 1) {
813 if (fputs(str
, pfile_tmp
) == EOF
) {
818 * Found a second entry with #libname.
819 * Should not happen. The kcf.conf file
820 * is corrupted. Give a warning and skip
823 cryptoerror(LOG_STDERR
, gettext(
824 "(Warning) Found an additional reserved "
825 "entry for %s."), provname
);
833 (void) fclose(pfile
);
836 cryptoerror(LOG_STDERR
, gettext("write error."));
837 (void) fclose(pfile_tmp
);
838 if (unlink(tmpfile_name
) != 0) {
840 cryptoerror(LOG_STDERR
, gettext(
841 "(Warning) failed to remove %s: %s"), tmpfile_name
,
848 if (found_count
== 0) {
850 * This libname was not in package before, append it to the
851 * end of the temp file.
853 if (fputs(str
, pfile_tmp
) == EOF
) {
854 cryptoerror(LOG_STDERR
, gettext(
855 "failed to write to %s: %s"), tmpfile_name
,
857 (void) fclose(pfile_tmp
);
858 if (unlink(tmpfile_name
) != 0) {
860 cryptoerror(LOG_STDERR
, gettext(
861 "(Warning) failed to remove %s: %s"),
862 tmpfile_name
, strerror(err
));
869 if (fclose(pfile_tmp
) != 0) {
871 cryptoerror(LOG_STDERR
,
872 gettext("failed to close %s: %s"), tmpfile_name
,
878 if (rename(tmpfile_name
, _PATH_KCF_CONF
) == -1) {
880 cryptoerror(LOG_STDERR
,
881 gettext("failed to update the configuration - %s"),
883 cryptodebug("failed to rename %s to %s: %s", tmpfile_name
,
884 _PATH_KCF_CONF
, strerror(err
));
886 } else if (chmod(_PATH_KCF_CONF
,
887 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
) == -1) {
889 cryptoerror(LOG_STDERR
,
890 gettext("failed to update the configuration - %s"),
892 cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF
,
900 if (unlink(tmpfile_name
) != 0) {
902 cryptoerror(LOG_STDERR
, gettext(
903 "(Warning) failed to remove %s: %s"),
904 tmpfile_name
, strerror(err
));
911 /* Inform kernel of this new software module. */
913 if ((pload_soft_conf
= setup_soft_conf(pent
)) == NULL
) {
918 if ((fd
= open(ADMIN_IOCTL_DEVICE
, O_RDWR
)) == -1) {
919 cryptoerror(LOG_STDERR
, gettext("failed to open %s: %s"),
920 ADMIN_IOCTL_DEVICE
, strerror(errno
));
922 free(pload_soft_conf
);
926 if (ioctl(fd
, CRYPTO_LOAD_SOFT_CONFIG
, pload_soft_conf
) == -1) {
927 cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
930 free(pload_soft_conf
);
935 if (pload_soft_conf
->sc_return_value
!= CRYPTO_SUCCESS
) {
936 cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed, "
937 "return_value = %d", pload_soft_conf
->sc_return_value
);
939 free(pload_soft_conf
);
945 free(pload_soft_conf
);
951 * Uninstall the software module. This routine first unloads the software
952 * module with 3 ioctl calls, then deletes its entry from the config file.
953 * Removing an entry from the config file needs to be done last to ensure
954 * that there is still an entry if the earlier unload failed for any reason.
957 uninstall_kef(char *provname
)
959 entry_t
*pent
= NULL
;
961 boolean_t in_kernel
= B_FALSE
;
962 boolean_t in_kcfconf
= B_FALSE
;
964 crypto_load_soft_config_t
*pload_soft_conf
= NULL
;
966 /* Check to see if the provider exists first. */
967 if (check_kernel_for_soft(provname
, NULL
, &in_kernel
) == FAILURE
) {
969 } else if (in_kernel
== B_FALSE
) {
970 cryptoerror(LOG_STDERR
, gettext("%s does not exist."),
976 * If it is loaded, unload it first. This does 2 ioctl calls:
977 * CRYPTO_UNLOAD_SOFT_MODULE and CRYPTO_LOAD_SOFT_DISABLED.
979 if (unload_kef_soft(provname
) == FAILURE
) {
980 cryptoerror(LOG_STDERR
,
981 gettext("failed to unload %s during uninstall.\n"),
987 * Inform kernel to remove the configuration of this software module.
990 /* Setup ioctl() parameter */
991 pent
= getent_kef(provname
, NULL
, NULL
);
992 if (pent
!= NULL
) { /* in kcf.conf */
994 free_mechlist(pent
->suplist
);
995 pent
->suplist
= NULL
;
997 } else if ((pent
= create_entry(provname
)) == NULL
) {
998 cryptoerror(LOG_STDERR
, gettext("out of memory."));
1001 if ((pload_soft_conf
= setup_soft_conf(pent
)) == NULL
) {
1006 /* Open the /dev/cryptoadm device */
1007 if ((fd
= open(ADMIN_IOCTL_DEVICE
, O_RDWR
)) == -1) {
1009 cryptoerror(LOG_STDERR
, gettext("failed to open %s: %s"),
1010 ADMIN_IOCTL_DEVICE
, strerror(err
));
1012 free(pload_soft_conf
);
1016 if (ioctl(fd
, CRYPTO_LOAD_SOFT_CONFIG
,
1017 pload_soft_conf
) == -1) {
1018 cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
1021 free(pload_soft_conf
);
1026 if (pload_soft_conf
->sc_return_value
!= CRYPTO_SUCCESS
) {
1027 cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl = return_value = %d",
1028 pload_soft_conf
->sc_return_value
);
1030 free(pload_soft_conf
);
1036 free(pload_soft_conf
);
1040 /* Finally, remove entry from kcf.conf, if present */
1041 if (in_kcfconf
&& (pent
!= NULL
)) {
1042 rc
= update_kcfconf(pent
, DELETE_MODE
);
1051 * Implement the "cryptoadm refresh" command for global zones.
1052 * That is, send the current contents of kcf.conf to the kernel via ioctl().
1057 crypto_load_soft_config_t
*pload_soft_conf
= NULL
;
1058 crypto_load_soft_disabled_t
*pload_soft_dis
= NULL
;
1059 crypto_load_dev_disabled_t
*pload_dev_dis
= NULL
;
1060 entrylist_t
*pdevlist
= NULL
;
1061 entrylist_t
*psoftlist
= NULL
;
1067 if (get_kcfconf_info(&pdevlist
, &psoftlist
) == FAILURE
) {
1068 cryptoerror(LOG_ERR
, "failed to retrieve the providers' "
1069 "information from the configuration file - %s.",
1074 if ((fd
= open(ADMIN_IOCTL_DEVICE
, O_RDWR
)) == -1) {
1076 cryptoerror(LOG_STDERR
, gettext("failed to open %s: %s"),
1077 ADMIN_IOCTL_DEVICE
, strerror(err
));
1084 * For each software provider module, pass two sets of information to
1085 * the kernel: the supported list and the disabled list.
1087 for (ptr
= psoftlist
; ptr
!= NULL
; ptr
= ptr
->next
) {
1088 entry_t
*pent
= ptr
->pent
;
1090 /* load the supported list */
1091 if ((pload_soft_conf
= setup_soft_conf(pent
)) == NULL
) {
1092 cryptodebug("setup_soft_conf() failed");
1097 if (!pent
->load
) { /* unloaded--mark as loaded */
1098 pent
->load
= B_TRUE
;
1099 rc
= update_kcfconf(pent
, MODIFY_MODE
);
1100 if (rc
!= SUCCESS
) {
1101 free(pload_soft_conf
);
1106 if (ioctl(fd
, CRYPTO_LOAD_SOFT_CONFIG
, pload_soft_conf
)
1108 cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
1110 free(pload_soft_conf
);
1115 if (pload_soft_conf
->sc_return_value
!= CRYPTO_SUCCESS
) {
1116 cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl "
1117 "return_value = %d",
1118 pload_soft_conf
->sc_return_value
);
1119 free(pload_soft_conf
);
1124 free(pload_soft_conf
);
1126 /* load the disabled list */
1127 if (ptr
->pent
->dis_count
!= 0) {
1128 pload_soft_dis
= setup_soft_dis(ptr
->pent
);
1129 if (pload_soft_dis
== NULL
) {
1130 cryptodebug("setup_soft_dis() failed");
1131 free(pload_soft_dis
);
1136 if (ioctl(fd
, CRYPTO_LOAD_SOFT_DISABLED
,
1137 pload_soft_dis
) == -1) {
1138 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
1139 "failed: %s", strerror(errno
));
1140 free(pload_soft_dis
);
1145 if (pload_soft_dis
->sd_return_value
!=
1147 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
1148 "return_value = %d",
1149 pload_soft_dis
->sd_return_value
);
1150 free(pload_soft_dis
);
1154 free(pload_soft_dis
);
1158 if (rc
!= SUCCESS
) {
1165 * For each hardware provider module, pass the disabled list
1166 * information to the kernel.
1168 for (ptr
= pdevlist
; ptr
!= NULL
; ptr
= ptr
->next
) {
1169 /* load the disabled list */
1170 if (ptr
->pent
->dis_count
!= 0) {
1171 pload_dev_dis
= setup_dev_dis(ptr
->pent
);
1172 if (pload_dev_dis
== NULL
) {
1177 if (ioctl(fd
, CRYPTO_LOAD_DEV_DISABLED
, pload_dev_dis
)
1179 cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
1180 "failed: %s", strerror(errno
));
1181 free(pload_dev_dis
);
1186 if (pload_dev_dis
->dd_return_value
!= CRYPTO_SUCCESS
) {
1187 cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
1188 "return_value = %d",
1189 pload_dev_dis
->dd_return_value
);
1190 free(pload_dev_dis
);
1194 free(pload_dev_dis
);
1203 * Unload the kernel software provider. Before calling this function, the
1204 * caller should check to see if the provider is in the kernel.
1206 * This routine makes 2 ioctl calls to remove it completely from the kernel:
1207 * CRYPTO_UNLOAD_SOFT_MODULE - does a modunload of the KCF module
1208 * CRYPTO_LOAD_SOFT_DISABLED - updates kernel disabled mechanism list
1210 * This implements part of "cryptoadm unload" and "cryptoadm uninstall".
1213 unload_kef_soft(char *provname
)
1215 crypto_unload_soft_module_t
*punload_soft
= NULL
;
1216 crypto_load_soft_disabled_t
*pload_soft_dis
= NULL
;
1217 entry_t
*pent
= NULL
;
1221 if (provname
== NULL
) {
1222 cryptoerror(LOG_STDERR
, gettext("internal error."));
1226 pent
= getent_kef(provname
, NULL
, NULL
);
1227 if (pent
== NULL
) { /* not in kcf.conf */
1228 /* Construct an entry using the provname */
1229 pent
= create_entry(provname
);
1231 cryptoerror(LOG_STDERR
, gettext("out of memory."));
1236 /* Open the admin_ioctl_device */
1237 if ((fd
= open(ADMIN_IOCTL_DEVICE
, O_RDWR
)) == -1) {
1239 cryptoerror(LOG_STDERR
, gettext("failed to open %s: %s"),
1240 ADMIN_IOCTL_DEVICE
, strerror(err
));
1245 /* Inform kernel to unload this software module */
1246 if ((punload_soft
= setup_unload_soft(pent
)) == NULL
) {
1252 if (ioctl(fd
, CRYPTO_UNLOAD_SOFT_MODULE
, punload_soft
) == -1) {
1253 cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s",
1261 if (punload_soft
->sm_return_value
!= CRYPTO_SUCCESS
) {
1262 cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl return_value = "
1263 "%d", punload_soft
->sm_return_value
);
1265 * If the return value is CRYPTO_UNKNOWN_PROVIDER, it means
1266 * that the provider is not registered yet. Should just
1269 if (punload_soft
->sm_return_value
!= CRYPTO_UNKNOWN_PROVIDER
) {
1279 /* Inform kernel to remove the disabled entries if any */
1280 if (pent
->dis_count
== 0) {
1285 free_mechlist(pent
->dislist
);
1286 pent
->dislist
= NULL
;
1287 pent
->dis_count
= 0;
1290 if ((pload_soft_dis
= setup_soft_dis(pent
)) == NULL
) {
1296 /* pent is no longer needed; free it */
1299 if (ioctl(fd
, CRYPTO_LOAD_SOFT_DISABLED
, pload_soft_dis
) == -1) {
1300 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
1302 free(pload_soft_dis
);
1307 if (pload_soft_dis
->sd_return_value
!= CRYPTO_SUCCESS
) {
1308 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
1309 "%d", pload_soft_dis
->sd_return_value
);
1310 free(pload_soft_dis
);
1315 free(pload_soft_dis
);
1322 * Check if a hardware provider is valid. If it is valid, returns its device
1323 * name, instance number and the number of mechanisms it supports.
1326 check_hardware_provider(char *provname
, char *pname
, int *pnum
, int *pcount
)
1328 crypto_get_dev_list_t
*dev_list
= NULL
;
1331 if (provname
== NULL
) {
1335 /* First, get the device name and the instance number from provname */
1336 if (split_hw_provname(provname
, pname
, pnum
) == FAILURE
) {
1341 * Get the complete device list from kernel and check if this provider
1344 if (get_dev_list(&dev_list
) == FAILURE
) {
1348 for (i
= 0; i
< dev_list
->dl_dev_count
; i
++) {
1349 if ((strcmp(dev_list
->dl_devs
[i
].le_dev_name
, pname
) == 0) &&
1350 (dev_list
->dl_devs
[i
].le_dev_instance
== *pnum
)) {
1355 if (i
== dev_list
->dl_dev_count
) {
1356 /* didn't find this provider in the kernel device list */
1357 cryptoerror(LOG_STDERR
, gettext("%s does not exist."),
1363 /* This provider is valid. Get its mechanism count */
1364 *pcount
= dev_list
->dl_devs
[i
].le_mechanism_count
;