10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51971Skrishna  * Common Development and Distribution License (the "License").
61971Skrishna  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
221971Skrishna  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <fcntl.h>
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <strings.h>
320Sstevel@tonic-gate #include <unistd.h>
330Sstevel@tonic-gate #include <locale.h>
340Sstevel@tonic-gate #include <libgen.h>
350Sstevel@tonic-gate #include <sys/types.h>
360Sstevel@tonic-gate #include <sys/stat.h>
370Sstevel@tonic-gate #include <sys/crypto/ioctladmin.h>
380Sstevel@tonic-gate #include <signal.h>
390Sstevel@tonic-gate #include <sys/crypto/elfsign.h>
400Sstevel@tonic-gate #include "cryptoadm.h"
410Sstevel@tonic-gate 
420Sstevel@tonic-gate static int err; /* to store the value of errno in case being overwritten */
430Sstevel@tonic-gate static int check_hardware_provider(char *, char *, int *, int *);
440Sstevel@tonic-gate 
450Sstevel@tonic-gate /*
460Sstevel@tonic-gate  * Display the mechanism list for a kernel software provider.
470Sstevel@tonic-gate  */
480Sstevel@tonic-gate int
490Sstevel@tonic-gate list_mechlist_for_soft(char *provname)
500Sstevel@tonic-gate {
510Sstevel@tonic-gate 	mechlist_t *pmechlist;
520Sstevel@tonic-gate 	int rc;
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	if (provname == NULL) {
550Sstevel@tonic-gate 		return (FAILURE);
560Sstevel@tonic-gate 	}
570Sstevel@tonic-gate 
580Sstevel@tonic-gate 	rc = get_soft_info(provname, &pmechlist);
590Sstevel@tonic-gate 	if (rc == SUCCESS) {
600Sstevel@tonic-gate 		(void) filter_mechlist(&pmechlist, RANDOM);
610Sstevel@tonic-gate 		print_mechlist(provname, pmechlist);
620Sstevel@tonic-gate 		free_mechlist(pmechlist);
630Sstevel@tonic-gate 	} else {
640Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
650Sstevel@tonic-gate 		    "failed to retrieve the mechanism list for %s."),
660Sstevel@tonic-gate 		    provname);
670Sstevel@tonic-gate 	}
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	return (rc);
700Sstevel@tonic-gate 
710Sstevel@tonic-gate }
720Sstevel@tonic-gate 
730Sstevel@tonic-gate /*
740Sstevel@tonic-gate  * Display the mechanism list for a kernel hardware provider.
750Sstevel@tonic-gate  */
760Sstevel@tonic-gate int
770Sstevel@tonic-gate list_mechlist_for_hard(char *provname)
780Sstevel@tonic-gate {
790Sstevel@tonic-gate 	mechlist_t *pmechlist;
800Sstevel@tonic-gate 	char	devname[MAXNAMELEN];
810Sstevel@tonic-gate 	int	inst_num;
820Sstevel@tonic-gate 	int	count;
830Sstevel@tonic-gate 	int rc = SUCCESS;
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 	if (provname == NULL) {
860Sstevel@tonic-gate 		return (FAILURE);
870Sstevel@tonic-gate 	}
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	/*
900Sstevel@tonic-gate 	 * Check if the provider is valid. If it is valid, get the number of
910Sstevel@tonic-gate 	 * mechanisms also.
920Sstevel@tonic-gate 	 */
930Sstevel@tonic-gate 	if (check_hardware_provider(provname, devname, &inst_num, &count) ==
940Sstevel@tonic-gate 	    FAILURE) {
950Sstevel@tonic-gate 		return (FAILURE);
960Sstevel@tonic-gate 	}
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 	/* Get the mechanism list for the kernel hardware provider */
990Sstevel@tonic-gate 	if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) ==
1000Sstevel@tonic-gate 	    SUCCESS) {
1010Sstevel@tonic-gate 		(void) filter_mechlist(&pmechlist, RANDOM);
1020Sstevel@tonic-gate 		print_mechlist(provname, pmechlist);
1030Sstevel@tonic-gate 		free_mechlist(pmechlist);
1040Sstevel@tonic-gate 	}
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	return (rc);
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate /*
1110Sstevel@tonic-gate  * Display the policy information for a kernel software provider.
1120Sstevel@tonic-gate  */
1130Sstevel@tonic-gate int
1140Sstevel@tonic-gate list_policy_for_soft(char *provname)
1150Sstevel@tonic-gate {
1160Sstevel@tonic-gate 	int rc;
1170Sstevel@tonic-gate 	entry_t *pent = NULL;
1180Sstevel@tonic-gate 	mechlist_t *pmechlist;
1190Sstevel@tonic-gate 	boolean_t has_random = B_FALSE;
1200Sstevel@tonic-gate 	boolean_t has_mechs = B_FALSE;
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate 	if (provname == NULL) {
1230Sstevel@tonic-gate 		return (FAILURE);
1240Sstevel@tonic-gate 	}
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) == NULL) {
1270Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s does not exist."),
1280Sstevel@tonic-gate 		    provname);
1290Sstevel@tonic-gate 		return (FAILURE);
1300Sstevel@tonic-gate 	}
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	rc = get_soft_info(provname, &pmechlist);
1330Sstevel@tonic-gate 	if (rc == SUCCESS) {
1340Sstevel@tonic-gate 		has_random = filter_mechlist(&pmechlist, RANDOM);
1350Sstevel@tonic-gate 		if (pmechlist != NULL) {
1360Sstevel@tonic-gate 			has_mechs = B_TRUE;
1370Sstevel@tonic-gate 			free_mechlist(pmechlist);
1380Sstevel@tonic-gate 		}
1390Sstevel@tonic-gate 	} else {
1400Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
1410Sstevel@tonic-gate 		    "failed to retrieve the mechanism list for %s."),
1420Sstevel@tonic-gate 		    provname);
1430Sstevel@tonic-gate 		return (rc);
1440Sstevel@tonic-gate 	}
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	print_kef_policy(pent, has_random, has_mechs);
1470Sstevel@tonic-gate 	free_entry(pent);
1480Sstevel@tonic-gate 	return (SUCCESS);
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate /*
1540Sstevel@tonic-gate  * Display the policy information for a kernel hardware provider.
1550Sstevel@tonic-gate  */
1560Sstevel@tonic-gate int
1570Sstevel@tonic-gate list_policy_for_hard(char *provname)
1580Sstevel@tonic-gate {
1590Sstevel@tonic-gate 	entry_t *pent;
1600Sstevel@tonic-gate 	boolean_t is_active;
1610Sstevel@tonic-gate 	mechlist_t *pmechlist;
1620Sstevel@tonic-gate 	char	devname[MAXNAMELEN];
1630Sstevel@tonic-gate 	int	inst_num;
1640Sstevel@tonic-gate 	int	count;
1650Sstevel@tonic-gate 	int rc = SUCCESS;
1660Sstevel@tonic-gate 	boolean_t has_random = B_FALSE;
1670Sstevel@tonic-gate 	boolean_t has_mechs = B_FALSE;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	if (provname == NULL) {
1700Sstevel@tonic-gate 		return (FAILURE);
1710Sstevel@tonic-gate 	}
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	/*
1740Sstevel@tonic-gate 	 * Check if the provider is valid. If it is valid, get the number of
1750Sstevel@tonic-gate 	 * mechanisms also.
1760Sstevel@tonic-gate 	 */
1770Sstevel@tonic-gate 	if (check_hardware_provider(provname, devname, &inst_num, &count) ==
1780Sstevel@tonic-gate 	    FAILURE) {
1790Sstevel@tonic-gate 		return (FAILURE);
1800Sstevel@tonic-gate 	}
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	/* Get the mechanism list for the kernel hardware provider */
1830Sstevel@tonic-gate 	if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) ==
1840Sstevel@tonic-gate 	    SUCCESS) {
1850Sstevel@tonic-gate 		has_random = filter_mechlist(&pmechlist, RANDOM);
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 		if (pmechlist != NULL) {
1880Sstevel@tonic-gate 			has_mechs = B_TRUE;
1890Sstevel@tonic-gate 			free_mechlist(pmechlist);
1900Sstevel@tonic-gate 		}
1910Sstevel@tonic-gate 	} else {
1920Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
1930Sstevel@tonic-gate 		    "failed to retrieve the mechanism list for %s."),
1940Sstevel@tonic-gate 		    devname);
1950Sstevel@tonic-gate 		return (rc);
1960Sstevel@tonic-gate 	}
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	/*
1990Sstevel@tonic-gate 	 * If the hardware provider has an entry in the kcf.conf file,
2000Sstevel@tonic-gate 	 * some of its mechanisms must have been disabled.  Print out
2010Sstevel@tonic-gate 	 * the disabled list from the config file entry.  Otherwise,
2020Sstevel@tonic-gate 	 * if it is active, then all the mechanisms for it are enabled.
2030Sstevel@tonic-gate 	 */
2040Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) != NULL) {
2050Sstevel@tonic-gate 		print_kef_policy(pent, has_random, has_mechs);
2060Sstevel@tonic-gate 		free_entry(pent);
2070Sstevel@tonic-gate 		return (SUCCESS);
2080Sstevel@tonic-gate 	} else {
2090Sstevel@tonic-gate 		if (check_active_for_hard(provname, &is_active) ==
2100Sstevel@tonic-gate 		    FAILURE) {
2110Sstevel@tonic-gate 			return (FAILURE);
2120Sstevel@tonic-gate 		} else if (is_active == B_TRUE) {
2130Sstevel@tonic-gate 			(void) printf(gettext(
2140Sstevel@tonic-gate 			    "%s: all mechanisms are enabled."), provname);
2150Sstevel@tonic-gate 			if (has_random)
2160Sstevel@tonic-gate 				/*
2170Sstevel@tonic-gate 				 * TRANSLATION_NOTE:
2180Sstevel@tonic-gate 				 * "random" is a keyword and not to be
2190Sstevel@tonic-gate 				 * translated.
2200Sstevel@tonic-gate 				 */
2210Sstevel@tonic-gate 				(void) printf(gettext(" %s is enabled.\n"),
2220Sstevel@tonic-gate 				    "random");
2230Sstevel@tonic-gate 			else
2240Sstevel@tonic-gate 				(void) printf("\n");
2250Sstevel@tonic-gate 			return (SUCCESS);
2260Sstevel@tonic-gate 		} else {
2270Sstevel@tonic-gate 			cryptoerror(LOG_STDERR,
2280Sstevel@tonic-gate 			    gettext("%s does not exist."), provname);
2290Sstevel@tonic-gate 			return (FAILURE);
2300Sstevel@tonic-gate 		}
2310Sstevel@tonic-gate 	}
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate int
2370Sstevel@tonic-gate disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag,
2380Sstevel@tonic-gate     mechlist_t *dislist)
2390Sstevel@tonic-gate {
2400Sstevel@tonic-gate 	crypto_load_dev_disabled_t	*pload_dev_dis;
2410Sstevel@tonic-gate 	mechlist_t 	*infolist;
2420Sstevel@tonic-gate 	entry_t		*pent;
2430Sstevel@tonic-gate 	boolean_t	new_dev_entry = B_FALSE;
2440Sstevel@tonic-gate 	char	devname[MAXNAMELEN];
2450Sstevel@tonic-gate 	int	inst_num;
2460Sstevel@tonic-gate 	int	count;
2470Sstevel@tonic-gate 	int	fd;
2480Sstevel@tonic-gate 	int	rc = SUCCESS;
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	if (provname == NULL) {
2510Sstevel@tonic-gate 		return (FAILURE);
2520Sstevel@tonic-gate 	}
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	/*
2550Sstevel@tonic-gate 	 * Check if the provider is valid. If it is valid, get the number of
2560Sstevel@tonic-gate 	 * mechanisms also.
2570Sstevel@tonic-gate 	 */
2580Sstevel@tonic-gate 	if (check_hardware_provider(provname, devname, &inst_num, &count)
2590Sstevel@tonic-gate 	    == FAILURE) {
2600Sstevel@tonic-gate 		return (FAILURE);
2610Sstevel@tonic-gate 	}
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	/* Get the mechanism list for the kernel hardware provider */
2640Sstevel@tonic-gate 	if (get_dev_info(devname, inst_num, count, &infolist) == FAILURE) {
2650Sstevel@tonic-gate 		return (FAILURE);
2660Sstevel@tonic-gate 	}
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	/*
2690Sstevel@tonic-gate 	 * Get the entry of this hardware provider from the config file.
2700Sstevel@tonic-gate 	 * If there is no entry yet, create one for it.
2710Sstevel@tonic-gate 	 */
2720Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) == NULL) {
2730Sstevel@tonic-gate 		if ((pent = malloc(sizeof (entry_t))) == NULL) {
2740Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext("out of memory."));
2750Sstevel@tonic-gate 			free_mechlist(infolist);
2760Sstevel@tonic-gate 			return (FAILURE);
2770Sstevel@tonic-gate 		}
2780Sstevel@tonic-gate 		new_dev_entry = B_TRUE;
2790Sstevel@tonic-gate 		(void) strlcpy(pent->name, provname, MAXNAMELEN);
2800Sstevel@tonic-gate 		pent->suplist = NULL;
2810Sstevel@tonic-gate 		pent->sup_count = 0;
2820Sstevel@tonic-gate 		pent->dislist = NULL;
2830Sstevel@tonic-gate 		pent->dis_count = 0;
2840Sstevel@tonic-gate 	}
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	/*
2870Sstevel@tonic-gate 	 * kCF treats random as an internal mechanism. So, we need to
2880Sstevel@tonic-gate 	 * filter it from the mechanism list here, if we are NOT disabling
2890Sstevel@tonic-gate 	 * or enabling the random feature. Note that we map random feature at
2900Sstevel@tonic-gate 	 * cryptoadm(1M) level to the "random" mechanism in kCF.
2910Sstevel@tonic-gate 	 */
2920Sstevel@tonic-gate 	if (!rndflag) {
293*2860Smcpowers 		(void) filter_mechlist(&dislist, RANDOM);
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	/* Calculate the new disabled list */
2970Sstevel@tonic-gate 	if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) {
298*2860Smcpowers 		free_mechlist(infolist);
2990Sstevel@tonic-gate 		free_entry(pent);
3000Sstevel@tonic-gate 		return (FAILURE);
3010Sstevel@tonic-gate 	}
302*2860Smcpowers 	free_mechlist(infolist);
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	/* If no mechanisms are to be disabled, return */
3050Sstevel@tonic-gate 	if (pent->dis_count == 0) {
3060Sstevel@tonic-gate 		free_entry(pent);
3070Sstevel@tonic-gate 		return (SUCCESS);
3080Sstevel@tonic-gate 	}
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	/* Update the config file with the new entry or the updated entry */
3110Sstevel@tonic-gate 	if (new_dev_entry) {
3120Sstevel@tonic-gate 		rc = update_kcfconf(pent, ADD_MODE);
3130Sstevel@tonic-gate 	} else {
3140Sstevel@tonic-gate 		rc = update_kcfconf(pent, MODIFY_MODE);
3150Sstevel@tonic-gate 	}
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 	if (rc == FAILURE) {
3180Sstevel@tonic-gate 		free_entry(pent);
3190Sstevel@tonic-gate 		return (FAILURE);
3200Sstevel@tonic-gate 	}
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	/* Inform kernel about the new disabled mechanism list */
3230Sstevel@tonic-gate 	if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) {
3240Sstevel@tonic-gate 		free_entry(pent);
3250Sstevel@tonic-gate 		return (FAILURE);
3260Sstevel@tonic-gate 	}
3270Sstevel@tonic-gate 	free_entry(pent);
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
3300Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
3310Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
3320Sstevel@tonic-gate 		free(pload_dev_dis);
3330Sstevel@tonic-gate 		return (FAILURE);
3340Sstevel@tonic-gate 	}
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) {
3370Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: %s",
3380Sstevel@tonic-gate 		    strerror(errno));
3390Sstevel@tonic-gate 		free(pload_dev_dis);
3400Sstevel@tonic-gate 		(void) close(fd);
3410Sstevel@tonic-gate 		return (FAILURE);
3420Sstevel@tonic-gate 	}
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
3450Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl return_value = "
3460Sstevel@tonic-gate 		    "%d", pload_dev_dis->dd_return_value);
3470Sstevel@tonic-gate 		free(pload_dev_dis);
3480Sstevel@tonic-gate 		(void) close(fd);
3490Sstevel@tonic-gate 		return (FAILURE);
3500Sstevel@tonic-gate 	}
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	free(pload_dev_dis);
3530Sstevel@tonic-gate 	(void) close(fd);
3540Sstevel@tonic-gate 	return (SUCCESS);
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate int
3600Sstevel@tonic-gate disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag,
3610Sstevel@tonic-gate     mechlist_t *dislist)
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
3640Sstevel@tonic-gate 	mechlist_t 	*infolist;
3650Sstevel@tonic-gate 	entry_t		*pent;
3660Sstevel@tonic-gate 	boolean_t	is_active;
3670Sstevel@tonic-gate 	int	fd;
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	if (provname == NULL) {
3700Sstevel@tonic-gate 		return (FAILURE);
3710Sstevel@tonic-gate 	}
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate 	/* Get the entry of this provider from the config file. */
3740Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) == NULL) {
3750Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
3760Sstevel@tonic-gate 		    gettext("%s does not exist."), provname);
3770Sstevel@tonic-gate 		return (FAILURE);
3780Sstevel@tonic-gate 	}
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	/*
3810Sstevel@tonic-gate 	 * Check if the kernel software provider is currently unloaded.
3820Sstevel@tonic-gate 	 * If it is unloaded, return FAILURE, because the disable subcommand
3830Sstevel@tonic-gate 	 * can not perform on inactive (unloaded) providers.
3840Sstevel@tonic-gate 	 */
3850Sstevel@tonic-gate 	if (check_active_for_soft(provname, &is_active) == FAILURE) {
3860Sstevel@tonic-gate 		free_entry(pent);
3870Sstevel@tonic-gate 		return (FAILURE);
3880Sstevel@tonic-gate 	} else if (is_active == B_FALSE) {
3890Sstevel@tonic-gate 		/*
3900Sstevel@tonic-gate 		 * TRANSLATION_NOTE:
3910Sstevel@tonic-gate 		 * "disable" is a keyword and not to be translated.
3920Sstevel@tonic-gate 		 */
3930Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
3940Sstevel@tonic-gate 		    gettext("can not do %1$s on an unloaded "
3950Sstevel@tonic-gate 		    "kernel software provider -- %2$s."), "disable", provname);
3960Sstevel@tonic-gate 		free_entry(pent);
3970Sstevel@tonic-gate 		return (FAILURE);
3980Sstevel@tonic-gate 	}
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	/* Get the mechanism list for the software provider */
4010Sstevel@tonic-gate 	if (get_soft_info(provname, &infolist) == FAILURE) {
4020Sstevel@tonic-gate 		free(pent);
4030Sstevel@tonic-gate 		return (FAILURE);
4040Sstevel@tonic-gate 	}
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	/* See comments in disable_kef_hardware() */
4070Sstevel@tonic-gate 	if (!rndflag) {
4080Sstevel@tonic-gate 		(void) filter_mechlist(&infolist, RANDOM);
4090Sstevel@tonic-gate 	}
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 	/* Calculate the new disabled list */
4120Sstevel@tonic-gate 	if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) {
4130Sstevel@tonic-gate 		free_entry(pent);
4140Sstevel@tonic-gate 		free_mechlist(infolist);
4150Sstevel@tonic-gate 		return (FAILURE);
4160Sstevel@tonic-gate 	}
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	/* infolist is no longer needed; free it */
4190Sstevel@tonic-gate 	free_mechlist(infolist);
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	/* Update the kcf.conf file with the updated entry */
4220Sstevel@tonic-gate 	if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) {
4230Sstevel@tonic-gate 		free_entry(pent);
4240Sstevel@tonic-gate 		return (FAILURE);
4250Sstevel@tonic-gate 	}
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate 	/* Inform kernel about the new disabled list. */
4280Sstevel@tonic-gate 	if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
4290Sstevel@tonic-gate 		free_entry(pent);
4300Sstevel@tonic-gate 		return (FAILURE);
4310Sstevel@tonic-gate 	}
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	/* pent is no longer needed; free it. */
4340Sstevel@tonic-gate 	free_entry(pent);
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
4370Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
4380Sstevel@tonic-gate 		    gettext("failed to open %s for RW: %s"),
4390Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
4400Sstevel@tonic-gate 		free(pload_soft_dis);
4410Sstevel@tonic-gate 		return (FAILURE);
4420Sstevel@tonic-gate 	}
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) {
4450Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
4460Sstevel@tonic-gate 		    strerror(errno));
4470Sstevel@tonic-gate 		free(pload_soft_dis);
4480Sstevel@tonic-gate 		(void) close(fd);
4490Sstevel@tonic-gate 		return (FAILURE);
4500Sstevel@tonic-gate 	}
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 	if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
4530Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
4540Sstevel@tonic-gate 		    "%d", pload_soft_dis->sd_return_value);
4550Sstevel@tonic-gate 		free(pload_soft_dis);
4560Sstevel@tonic-gate 		(void) close(fd);
4570Sstevel@tonic-gate 		return (FAILURE);
4580Sstevel@tonic-gate 	}
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	free(pload_soft_dis);
4610Sstevel@tonic-gate 	(void) close(fd);
4620Sstevel@tonic-gate 	return (SUCCESS);
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate int
4670Sstevel@tonic-gate enable_kef(char *provname, boolean_t rndflag, boolean_t allflag,
4680Sstevel@tonic-gate     mechlist_t *mlist)
4690Sstevel@tonic-gate {
4700Sstevel@tonic-gate 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
4710Sstevel@tonic-gate 	crypto_load_dev_disabled_t	*pload_dev_dis = NULL;
4720Sstevel@tonic-gate 	entry_t		*pent;
4730Sstevel@tonic-gate 	boolean_t redo_flag = B_FALSE;
4740Sstevel@tonic-gate 	int	fd;
4750Sstevel@tonic-gate 	int	rc = SUCCESS;
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	/* Get the entry with the provider name from the kcf.conf file */
4790Sstevel@tonic-gate 	pent = getent_kef(provname);
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	if (is_device(provname)) {
4820Sstevel@tonic-gate 		if (pent == NULL) {
4830Sstevel@tonic-gate 			/*
4840Sstevel@tonic-gate 			 * This device doesn't have an entry in the config
4850Sstevel@tonic-gate 			 * file, therefore nothing is disabled.
4860Sstevel@tonic-gate 			 */
4870Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
4880Sstevel@tonic-gate 			    "all mechanisms are enabled already for %s."),
4890Sstevel@tonic-gate 			    provname);
4900Sstevel@tonic-gate 			return (SUCCESS);
4910Sstevel@tonic-gate 		}
4920Sstevel@tonic-gate 	} else { /* a software module */
4930Sstevel@tonic-gate 		if (pent == NULL) {
4940Sstevel@tonic-gate 			cryptoerror(LOG_STDERR,
4950Sstevel@tonic-gate 			    gettext("%s does not exist."), provname);
4960Sstevel@tonic-gate 			return (FAILURE);
4970Sstevel@tonic-gate 		} else if (pent->dis_count == 0) {
4980Sstevel@tonic-gate 			/* nothing to be enabled. */
4990Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
5000Sstevel@tonic-gate 			    "all mechanisms are enabled already for %s."),
5010Sstevel@tonic-gate 			    provname);
5020Sstevel@tonic-gate 			free_entry(pent);
5030Sstevel@tonic-gate 			return (SUCCESS);
5040Sstevel@tonic-gate 		}
5050Sstevel@tonic-gate 	}
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 	if (!rndflag) {
5080Sstevel@tonic-gate 		/* See comments in disable_kef_hardware() */
5090Sstevel@tonic-gate 		redo_flag = filter_mechlist(&pent->dislist, RANDOM);
5100Sstevel@tonic-gate 		if (redo_flag)
5110Sstevel@tonic-gate 			pent->dis_count--;
5120Sstevel@tonic-gate 	}
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 	/* Update the entry by enabling mechanisms for this provider */
5150Sstevel@tonic-gate 	if ((rc = enable_mechs(&pent, allflag, mlist)) != SUCCESS) {
5160Sstevel@tonic-gate 		free_entry(pent);
5170Sstevel@tonic-gate 		return (rc);
5180Sstevel@tonic-gate 	}
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 	if (redo_flag) {
5210Sstevel@tonic-gate 		mechlist_t *tmp;
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 		if ((tmp = create_mech(RANDOM)) == NULL) {
5240Sstevel@tonic-gate 			free_entry(pent);
5250Sstevel@tonic-gate 			return (FAILURE);
5260Sstevel@tonic-gate 		}
5270Sstevel@tonic-gate 		tmp->next = pent->dislist;
5280Sstevel@tonic-gate 		pent->dislist = tmp;
5290Sstevel@tonic-gate 		pent->dis_count++;
5300Sstevel@tonic-gate 	}
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 	/*
5330Sstevel@tonic-gate 	 * Update the kcf.conf file  with the updated entry.
5340Sstevel@tonic-gate 	 * For a hardware provider, if there is no more disabled mechanism,
5350Sstevel@tonic-gate 	 * the entire entry in the config file should be removed.
5360Sstevel@tonic-gate 	 */
5370Sstevel@tonic-gate 	if (is_device(pent->name) && (pent->dis_count == 0)) {
5380Sstevel@tonic-gate 		rc = update_kcfconf(pent, DELETE_MODE);
5390Sstevel@tonic-gate 	} else {
5400Sstevel@tonic-gate 		rc = update_kcfconf(pent, MODIFY_MODE);
5410Sstevel@tonic-gate 	}
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 	if (rc == FAILURE) {
5440Sstevel@tonic-gate 		free_entry(pent);
5450Sstevel@tonic-gate 		return (FAILURE);
5460Sstevel@tonic-gate 	}
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate 	/* Inform Kernel about the policy change */
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
5520Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
5530Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
5540Sstevel@tonic-gate 		return (FAILURE);
5550Sstevel@tonic-gate 	}
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate 	if (is_device(provname)) {
5580Sstevel@tonic-gate 		/*  LOAD_DEV_DISABLED */
5590Sstevel@tonic-gate 		if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) {
5600Sstevel@tonic-gate 			return (FAILURE);
5610Sstevel@tonic-gate 		}
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) {
5640Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: "
5650Sstevel@tonic-gate 			    "%s", strerror(errno));
5660Sstevel@tonic-gate 			free(pload_dev_dis);
5670Sstevel@tonic-gate 			(void) close(fd);
5680Sstevel@tonic-gate 			return (FAILURE);
5690Sstevel@tonic-gate 		}
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 		if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
5720Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
5730Sstevel@tonic-gate 			    "return_value = %d",
5740Sstevel@tonic-gate 			    pload_dev_dis->dd_return_value);
5750Sstevel@tonic-gate 			free(pload_dev_dis);
5760Sstevel@tonic-gate 			(void) close(fd);
5770Sstevel@tonic-gate 			return (FAILURE);
5780Sstevel@tonic-gate 		}
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 	} else {
5810Sstevel@tonic-gate 		/* LOAD_SOFT_DISABLED */
5820Sstevel@tonic-gate 		if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
5830Sstevel@tonic-gate 			return (FAILURE);
5840Sstevel@tonic-gate 		}
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis)
5870Sstevel@tonic-gate 		    == -1) {
5880Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: "
5890Sstevel@tonic-gate 			    "%s", strerror(errno));
5900Sstevel@tonic-gate 			free(pload_soft_dis);
5910Sstevel@tonic-gate 			(void) close(fd);
5920Sstevel@tonic-gate 			return (FAILURE);
5930Sstevel@tonic-gate 		}
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 		if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
5960Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
5970Sstevel@tonic-gate 			    "return_value = %d",
5980Sstevel@tonic-gate 			    pload_soft_dis->sd_return_value);
5990Sstevel@tonic-gate 			free(pload_soft_dis);
6000Sstevel@tonic-gate 			(void) close(fd);
6010Sstevel@tonic-gate 			return (FAILURE);
6020Sstevel@tonic-gate 		}
6030Sstevel@tonic-gate 	}
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate 	(void) close(fd);
6060Sstevel@tonic-gate 	return (SUCCESS);
6070Sstevel@tonic-gate }
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate /*
6110Sstevel@tonic-gate  * Install a software module with the specified mechanism list into the system.
6120Sstevel@tonic-gate  * This routine adds an entry into the config file for this software module
6130Sstevel@tonic-gate  * first, then makes a CRYPTO_LOAD_SOFT_CONFIG ioctl call to inform kernel
6140Sstevel@tonic-gate  * about the new addition.
6150Sstevel@tonic-gate  */
6160Sstevel@tonic-gate int
6170Sstevel@tonic-gate install_kef(char *provname, mechlist_t *mlist)
6180Sstevel@tonic-gate {
6190Sstevel@tonic-gate 	crypto_load_soft_config_t	*pload_soft_conf = NULL;
6200Sstevel@tonic-gate 	boolean_t	found;
6210Sstevel@tonic-gate 	entry_t	*pent;
6220Sstevel@tonic-gate 	FILE	*pfile;
6230Sstevel@tonic-gate 	FILE	*pfile_tmp;
6240Sstevel@tonic-gate 	char	tmpfile_name[MAXPATHLEN];
6250Sstevel@tonic-gate 	char	*ptr;
6260Sstevel@tonic-gate 	char	*str;
6270Sstevel@tonic-gate 	char	*name;
6280Sstevel@tonic-gate 	char	buffer[BUFSIZ];
6290Sstevel@tonic-gate 	char	buffer2[BUFSIZ];
6300Sstevel@tonic-gate 	int	found_count;
6310Sstevel@tonic-gate 	int	fd;
6320Sstevel@tonic-gate 	int	rc = SUCCESS;
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 	if ((provname == NULL) || (mlist == NULL)) {
6350Sstevel@tonic-gate 		return (FAILURE);
6360Sstevel@tonic-gate 	}
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate 	/* Check if the provider already exists */
6390Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) != NULL) {
6400Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s exists already."),
6410Sstevel@tonic-gate 		    provname);
6420Sstevel@tonic-gate 		free_entry(pent);
6430Sstevel@tonic-gate 		return (FAILURE);
6440Sstevel@tonic-gate 	}
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 	/* Create an entry with provname and mlist. */
6470Sstevel@tonic-gate 	if ((pent = malloc(sizeof (entry_t))) == NULL) {
6480Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("out of memory."));
6490Sstevel@tonic-gate 		return (FAILURE);
6500Sstevel@tonic-gate 	}
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate 	(void) strlcpy(pent->name, provname, MAXNAMELEN);
6530Sstevel@tonic-gate 	pent->sup_count = get_mech_count(mlist);
6540Sstevel@tonic-gate 	pent->suplist = mlist;
6550Sstevel@tonic-gate 	pent->dis_count = 0;
6560Sstevel@tonic-gate 	pent->dislist = NULL;
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 	/* Append an entry for this software module to the kcf.conf file. */
6590Sstevel@tonic-gate 	if ((str = ent2str(pent)) == NULL) {
6600Sstevel@tonic-gate 		free_entry(pent);
6610Sstevel@tonic-gate 		return (FAILURE);
6620Sstevel@tonic-gate 	}
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
6650Sstevel@tonic-gate 		err = errno;
6660Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
6670Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
6680Sstevel@tonic-gate 		    strerror(err));
6690Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
6700Sstevel@tonic-gate 		free_entry(pent);
6710Sstevel@tonic-gate 		return (FAILURE);
6720Sstevel@tonic-gate 	}
6730Sstevel@tonic-gate 
6740Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
6750Sstevel@tonic-gate 		err = errno;
6760Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
6770Sstevel@tonic-gate 		    gettext("failed to lock the configuration - %s"),
6780Sstevel@tonic-gate 		    strerror(err));
6790Sstevel@tonic-gate 		free_entry(pent);
6800Sstevel@tonic-gate 		(void) fclose(pfile);
6810Sstevel@tonic-gate 		return (FAILURE);
6820Sstevel@tonic-gate 	}
6830Sstevel@tonic-gate 
6840Sstevel@tonic-gate 	/*
6850Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory.
6860Sstevel@tonic-gate 	 */
6870Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
6880Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
6890Sstevel@tonic-gate 		err = errno;
6900Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
6910Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
6920Sstevel@tonic-gate 		    strerror(err));
6930Sstevel@tonic-gate 		free_entry(pent);
6940Sstevel@tonic-gate 		(void) fclose(pfile);
6950Sstevel@tonic-gate 		return (FAILURE);
6960Sstevel@tonic-gate 	}
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
6990Sstevel@tonic-gate 		err = errno;
7000Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
7010Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
7020Sstevel@tonic-gate 		free_entry(pent);
7030Sstevel@tonic-gate 		(void) fclose(pfile);
7040Sstevel@tonic-gate 		return (FAILURE);
7050Sstevel@tonic-gate 	}
7060Sstevel@tonic-gate 
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 	/*
7090Sstevel@tonic-gate 	 * Loop thru the config file. If the provider was reserved within a
7100Sstevel@tonic-gate 	 * package bracket, just uncomment it.  Otherwise, append it at
7110Sstevel@tonic-gate 	 * the end.  The resulting file will be saved in the temp file first.
7120Sstevel@tonic-gate 	 */
7130Sstevel@tonic-gate 	found_count = 0;
7140Sstevel@tonic-gate 	rc = SUCCESS;
7150Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
7160Sstevel@tonic-gate 		found = B_FALSE;
7170Sstevel@tonic-gate 		if (buffer[0] == '#') {
7180Sstevel@tonic-gate 			(void) strlcpy(buffer2, buffer, BUFSIZ);
7190Sstevel@tonic-gate 			ptr = buffer2;
7200Sstevel@tonic-gate 			ptr++;
7210Sstevel@tonic-gate 			if ((name = strtok(ptr, SEP_COLON)) == NULL) {
7220Sstevel@tonic-gate 				rc = FAILURE;
7230Sstevel@tonic-gate 				break;
7240Sstevel@tonic-gate 			} else if (strcmp(provname, name) == 0) {
7250Sstevel@tonic-gate 				found = B_TRUE;
7260Sstevel@tonic-gate 				found_count++;
7270Sstevel@tonic-gate 			}
7280Sstevel@tonic-gate 		}
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 		if (found == B_FALSE) {
7310Sstevel@tonic-gate 			if (fputs(buffer, pfile_tmp) == EOF) {
7320Sstevel@tonic-gate 				rc = FAILURE;
7330Sstevel@tonic-gate 			}
7340Sstevel@tonic-gate 		} else {
7350Sstevel@tonic-gate 			if (found_count == 1) {
7360Sstevel@tonic-gate 				if (fputs(str, pfile_tmp) == EOF) {
7370Sstevel@tonic-gate 					rc = FAILURE;
7380Sstevel@tonic-gate 				}
7390Sstevel@tonic-gate 			} else {
7400Sstevel@tonic-gate 				/*
7410Sstevel@tonic-gate 				 * Found a second entry with #libname.
7420Sstevel@tonic-gate 				 * Should not happen. The kcf.conf ffile
7430Sstevel@tonic-gate 				 * is corrupted. Give a warning and skip
7440Sstevel@tonic-gate 				 * this entry.
7450Sstevel@tonic-gate 				 */
7460Sstevel@tonic-gate 				cryptoerror(LOG_STDERR, gettext(
7470Sstevel@tonic-gate 				    "(Warning) Found an additional reserved "
7480Sstevel@tonic-gate 				    "entry for %s."), provname);
7490Sstevel@tonic-gate 			}
7500Sstevel@tonic-gate 		}
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 		if (rc == FAILURE) {
7530Sstevel@tonic-gate 			break;
7540Sstevel@tonic-gate 		}
7550Sstevel@tonic-gate 	}
7560Sstevel@tonic-gate 	(void) fclose(pfile);
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 	if (rc == FAILURE) {
7590Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("write error."));
7600Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
7610Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
7620Sstevel@tonic-gate 			err = errno;
7630Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
7640Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"), tmpfile_name,
7650Sstevel@tonic-gate 			    strerror(err));
7660Sstevel@tonic-gate 		}
7670Sstevel@tonic-gate 		free_entry(pent);
7680Sstevel@tonic-gate 		return (FAILURE);
7690Sstevel@tonic-gate 	}
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate 	if (found_count == 0) {
7720Sstevel@tonic-gate 		/*
7730Sstevel@tonic-gate 		 * This libname was not in package before, append it to the
7740Sstevel@tonic-gate 		 * end of the temp file.
7750Sstevel@tonic-gate 		 */
7760Sstevel@tonic-gate 		if (fputs(str, pfile_tmp) == EOF) {
7770Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
7780Sstevel@tonic-gate 			    "failed to write to %s: %s"), tmpfile_name,
7790Sstevel@tonic-gate 			    strerror(errno));
7800Sstevel@tonic-gate 			(void) fclose(pfile_tmp);
7810Sstevel@tonic-gate 			if (unlink(tmpfile_name) != 0) {
7820Sstevel@tonic-gate 				err = errno;
7830Sstevel@tonic-gate 				cryptoerror(LOG_STDERR, gettext(
7840Sstevel@tonic-gate 				    "(Warning) failed to remove %s: %s"),
7850Sstevel@tonic-gate 				    tmpfile_name, strerror(err));
7860Sstevel@tonic-gate 			}
7870Sstevel@tonic-gate 			free_entry(pent);
7880Sstevel@tonic-gate 			return (FAILURE);
7890Sstevel@tonic-gate 		}
7900Sstevel@tonic-gate 	}
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
7930Sstevel@tonic-gate 		err = errno;
7940Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
7950Sstevel@tonic-gate 		    gettext("failed to close %s: %s"), tmpfile_name,
7960Sstevel@tonic-gate 		    strerror(err));
7970Sstevel@tonic-gate 		return (FAILURE);
7980Sstevel@tonic-gate 	}
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
8010Sstevel@tonic-gate 		err = errno;
8020Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8030Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
8040Sstevel@tonic-gate 			strerror(err));
8050Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
8060Sstevel@tonic-gate 		    _PATH_KCF_CONF, strerror(err));
8070Sstevel@tonic-gate 		rc = FAILURE;
8080Sstevel@tonic-gate 	} else if (chmod(_PATH_KCF_CONF,
8090Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
8100Sstevel@tonic-gate 		err = errno;
8110Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8120Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
8130Sstevel@tonic-gate 		    strerror(err));
8140Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
8150Sstevel@tonic-gate 		    strerror(err));
8160Sstevel@tonic-gate 		rc = FAILURE;
8170Sstevel@tonic-gate 	} else {
8180Sstevel@tonic-gate 		rc = SUCCESS;
8190Sstevel@tonic-gate 	}
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 	if (rc == FAILURE) {
8220Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
8230Sstevel@tonic-gate 			err = errno;
8240Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
8250Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
8260Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
8270Sstevel@tonic-gate 		}
8280Sstevel@tonic-gate 		return (FAILURE);
8290Sstevel@tonic-gate 	}
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate 
8320Sstevel@tonic-gate 	/* Inform kernel of this new software module. */
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 	if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
8350Sstevel@tonic-gate 		free_entry(pent);
8360Sstevel@tonic-gate 		return (FAILURE);
8370Sstevel@tonic-gate 	}
8380Sstevel@tonic-gate 
8390Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
8400Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
8410Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
8420Sstevel@tonic-gate 		free_entry(pent);
8430Sstevel@tonic-gate 		free(pload_soft_conf);
8440Sstevel@tonic-gate 		return (FAILURE);
8450Sstevel@tonic-gate 	}
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) {
8480Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
8490Sstevel@tonic-gate 		    strerror(errno));
8500Sstevel@tonic-gate 		free_entry(pent);
8510Sstevel@tonic-gate 		free(pload_soft_conf);
8520Sstevel@tonic-gate 		(void) close(fd);
8530Sstevel@tonic-gate 		return (FAILURE);
8540Sstevel@tonic-gate 	}
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 	if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
8570Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed, "
8580Sstevel@tonic-gate 		    "return_value = %d", pload_soft_conf->sc_return_value);
8590Sstevel@tonic-gate 		free_entry(pent);
8600Sstevel@tonic-gate 		free(pload_soft_conf);
8610Sstevel@tonic-gate 		(void) close(fd);
8620Sstevel@tonic-gate 		return (FAILURE);
8630Sstevel@tonic-gate 	}
8640Sstevel@tonic-gate 
8650Sstevel@tonic-gate 	free_entry(pent);
8660Sstevel@tonic-gate 	free(pload_soft_conf);
8670Sstevel@tonic-gate 	(void) close(fd);
8680Sstevel@tonic-gate 	return (SUCCESS);
8690Sstevel@tonic-gate }
8700Sstevel@tonic-gate 
8710Sstevel@tonic-gate /*
8720Sstevel@tonic-gate  * Uninstall the software module. This routine first unloads the software
8730Sstevel@tonic-gate  * module with 3 ioctl calls, then deletes its entry from the config file.
8740Sstevel@tonic-gate  * Removing an entry from the config file needs to be done last to ensure
8750Sstevel@tonic-gate  * that there is still an entry if the earlier unload failed for any reason.
8760Sstevel@tonic-gate  */
8770Sstevel@tonic-gate int
8780Sstevel@tonic-gate uninstall_kef(char *provname)
8790Sstevel@tonic-gate {
8800Sstevel@tonic-gate 	entry_t		*pent;
8810Sstevel@tonic-gate 	boolean_t	is_active;
8820Sstevel@tonic-gate 	boolean_t	in_package;
8830Sstevel@tonic-gate 	boolean_t	found;
8840Sstevel@tonic-gate 	FILE	*pfile;
8850Sstevel@tonic-gate 	FILE	*pfile_tmp;
8860Sstevel@tonic-gate 	char	tmpfile_name[MAXPATHLEN];
8870Sstevel@tonic-gate 	char	*name;
8880Sstevel@tonic-gate 	char	strbuf[BUFSIZ];
8890Sstevel@tonic-gate 	char	buffer[BUFSIZ];
8900Sstevel@tonic-gate 	char	buffer2[BUFSIZ];
8910Sstevel@tonic-gate 	char	*str;
8920Sstevel@tonic-gate 	int	len;
8930Sstevel@tonic-gate 	int	rc = SUCCESS;
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 
8960Sstevel@tonic-gate 	/* Check if it is in the kcf.conf file first. */
8970Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) == NULL) {
8980Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8990Sstevel@tonic-gate 		    gettext("%s does not exist."), provname);
9000Sstevel@tonic-gate 		return (FAILURE);
9010Sstevel@tonic-gate 	}
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 	/*
9050Sstevel@tonic-gate 	 * Get rid of the disabled list for the provider and get the converted
9060Sstevel@tonic-gate 	 * string for the entry.  This is to prepare the string for a provider
9070Sstevel@tonic-gate 	 * that is in a package.
9080Sstevel@tonic-gate 	 */
9090Sstevel@tonic-gate 	free_mechlist(pent->dislist);
9100Sstevel@tonic-gate 	pent->dis_count = 0;
9110Sstevel@tonic-gate 	pent->dislist = NULL;
9120Sstevel@tonic-gate 	str = ent2str(pent);
9130Sstevel@tonic-gate 	free_entry(pent);
9140Sstevel@tonic-gate 	if (str == NULL) {
9150Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
9160Sstevel@tonic-gate 		return (FAILURE);
9170Sstevel@tonic-gate 	}
9180Sstevel@tonic-gate 	(void) snprintf(strbuf, sizeof (strbuf), "%s%s", "#", str);
9190Sstevel@tonic-gate 	free(str);
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate 	/* If it is not loaded, unload it first  */
9220Sstevel@tonic-gate 	if (check_active_for_soft(provname, &is_active) == FAILURE) {
9230Sstevel@tonic-gate 		return (FAILURE);
9240Sstevel@tonic-gate 	} else if ((is_active == B_TRUE) &&
9251971Skrishna 	    (unload_kef_soft(provname, B_TRUE) == FAILURE)) {
9260Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9270Sstevel@tonic-gate 		    gettext("failed to uninstall %s.\n"), provname);
9280Sstevel@tonic-gate 		return (FAILURE);
9290Sstevel@tonic-gate 	}
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 	/*
9320Sstevel@tonic-gate 	 * Remove the entry from the config file.  If the provider to be
9330Sstevel@tonic-gate 	 * uninstalled is in a package, just comment it off.
9340Sstevel@tonic-gate 	 */
9350Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
9360Sstevel@tonic-gate 		err = errno;
9370Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9380Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
9390Sstevel@tonic-gate 		    strerror(err));
9400Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
9410Sstevel@tonic-gate 		return (FAILURE);
9420Sstevel@tonic-gate 	}
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
9450Sstevel@tonic-gate 		err = errno;
9460Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9470Sstevel@tonic-gate 		    gettext("failed to lock the configuration - %s"),
9480Sstevel@tonic-gate 		    strerror(err));
9490Sstevel@tonic-gate 		(void) fclose(pfile);
9500Sstevel@tonic-gate 		return (FAILURE);
9510Sstevel@tonic-gate 	}
9520Sstevel@tonic-gate 
9530Sstevel@tonic-gate 	/*
9540Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory to save
9550Sstevel@tonic-gate 	 * the new configuration file first.
9560Sstevel@tonic-gate 	 */
9570Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
9580Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
9590Sstevel@tonic-gate 		err = errno;
9600Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9610Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
9620Sstevel@tonic-gate 		    strerror(err));
9630Sstevel@tonic-gate 		(void) fclose(pfile);
9640Sstevel@tonic-gate 		return (FAILURE);
9650Sstevel@tonic-gate 	}
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
9680Sstevel@tonic-gate 		err = errno;
9690Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
9700Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
9710Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
9720Sstevel@tonic-gate 			err = errno;
9730Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
9740Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"), tmpfile_name,
9750Sstevel@tonic-gate 			    strerror(err));
9760Sstevel@tonic-gate 		}
9770Sstevel@tonic-gate 		(void) fclose(pfile);
9780Sstevel@tonic-gate 		return (FAILURE);
9790Sstevel@tonic-gate 	}
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate 	/*
9820Sstevel@tonic-gate 	 * Loop thru the config file.  If the kernel software provider
9830Sstevel@tonic-gate 	 * to be uninstalled is in a package, just comment it off.
9840Sstevel@tonic-gate 	 */
9850Sstevel@tonic-gate 	in_package = B_FALSE;
9860Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
9870Sstevel@tonic-gate 		found = B_FALSE;
9880Sstevel@tonic-gate 		if (!(buffer[0] == ' ' || buffer[0] == '\n' ||
9890Sstevel@tonic-gate 		    buffer[0] == '\t')) {
9900Sstevel@tonic-gate 			if (strstr(buffer, " Start ") != NULL) {
9910Sstevel@tonic-gate 				in_package = B_TRUE;
9920Sstevel@tonic-gate 			} else if (strstr(buffer, " End ") != NULL) {
9930Sstevel@tonic-gate 				in_package = B_FALSE;
9940Sstevel@tonic-gate 			} else if (buffer[0] != '#') {
9950Sstevel@tonic-gate 				(void) strlcpy(buffer2, buffer, BUFSIZ);
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate 				/* get rid of trailing '\n' */
9980Sstevel@tonic-gate 				len = strlen(buffer2);
9990Sstevel@tonic-gate 				if (buffer2[len-1] == '\n') {
10000Sstevel@tonic-gate 					len--;
10010Sstevel@tonic-gate 				}
10020Sstevel@tonic-gate 				buffer2[len] = '\0';
10030Sstevel@tonic-gate 
10040Sstevel@tonic-gate 				if ((name = strtok(buffer2, SEP_COLON))
10050Sstevel@tonic-gate 				    == NULL) {
10060Sstevel@tonic-gate 					rc = FAILURE;
10070Sstevel@tonic-gate 					break;
10080Sstevel@tonic-gate 				} else if (strcmp(provname, name) == 0) {
10090Sstevel@tonic-gate 					found = B_TRUE;
10100Sstevel@tonic-gate 				}
10110Sstevel@tonic-gate 			}
10120Sstevel@tonic-gate 		}
10130Sstevel@tonic-gate 
10140Sstevel@tonic-gate 		if (found) {
10150Sstevel@tonic-gate 			if (in_package) {
10160Sstevel@tonic-gate 				if (fputs(strbuf, pfile_tmp) == EOF) {
10170Sstevel@tonic-gate 					rc = FAILURE;
10180Sstevel@tonic-gate 				}
10190Sstevel@tonic-gate 			}
10200Sstevel@tonic-gate 		} else {
10210Sstevel@tonic-gate 			if (fputs(buffer, pfile_tmp) == EOF) {
10220Sstevel@tonic-gate 				rc = FAILURE;
10230Sstevel@tonic-gate 			}
10240Sstevel@tonic-gate 		}
10250Sstevel@tonic-gate 
10260Sstevel@tonic-gate 		if (rc == FAILURE) {
10270Sstevel@tonic-gate 			break;
10280Sstevel@tonic-gate 		}
10290Sstevel@tonic-gate 	}
10300Sstevel@tonic-gate 
10310Sstevel@tonic-gate 	if (rc == FAILURE) {
10320Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("write error."));
10330Sstevel@tonic-gate 		(void) fclose(pfile);
10340Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
10350Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
10360Sstevel@tonic-gate 			err = errno;
10370Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
10380Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"), tmpfile_name,
10390Sstevel@tonic-gate 			    strerror(err));
10400Sstevel@tonic-gate 		}
10410Sstevel@tonic-gate 		return (FAILURE);
10420Sstevel@tonic-gate 	}
10430Sstevel@tonic-gate 
10440Sstevel@tonic-gate 	(void) fclose(pfile);
10450Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
10460Sstevel@tonic-gate 		err = errno;
10470Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
10480Sstevel@tonic-gate 		    gettext("failed to close %s: %s"), tmpfile_name,
10490Sstevel@tonic-gate 		    strerror(err));
10500Sstevel@tonic-gate 		return (FAILURE);
10510Sstevel@tonic-gate 	}
10520Sstevel@tonic-gate 
10530Sstevel@tonic-gate 	/* Now update the real config file */
10540Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
10550Sstevel@tonic-gate 		err = errno;
10560Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
10570Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
10580Sstevel@tonic-gate 		    strerror(err));
10590Sstevel@tonic-gate 		cryptodebug("failed to rename %1$s to %2$s: %3$s", tmpfile,
10600Sstevel@tonic-gate 		    _PATH_KCF_CONF, strerror(err));
10610Sstevel@tonic-gate 		rc = FAILURE;
10620Sstevel@tonic-gate 	} else if (chmod(_PATH_KCF_CONF,
10630Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
10640Sstevel@tonic-gate 		err = errno;
10650Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
10660Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
10670Sstevel@tonic-gate 		    strerror(err));
10680Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
10690Sstevel@tonic-gate 		    strerror(err));
10700Sstevel@tonic-gate 		rc = FAILURE;
10710Sstevel@tonic-gate 	} else {
10720Sstevel@tonic-gate 		rc = SUCCESS;
10730Sstevel@tonic-gate 	}
10740Sstevel@tonic-gate 
10750Sstevel@tonic-gate 	if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
10760Sstevel@tonic-gate 		err = errno;
10770Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
10780Sstevel@tonic-gate 		    "(Warning) failed to remove %s: %s"), tmpfile_name,
10790Sstevel@tonic-gate 		    strerror(err));
10800Sstevel@tonic-gate 	}
10810Sstevel@tonic-gate 
10820Sstevel@tonic-gate 	return (rc);
10830Sstevel@tonic-gate 
10840Sstevel@tonic-gate }
10850Sstevel@tonic-gate 
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate int
10880Sstevel@tonic-gate refresh(void)
10890Sstevel@tonic-gate {
10900Sstevel@tonic-gate 	crypto_get_soft_list_t		*psoftlist_kernel = NULL;
10910Sstevel@tonic-gate 	crypto_load_soft_config_t	*pload_soft_conf = NULL;
10920Sstevel@tonic-gate 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
10930Sstevel@tonic-gate 	crypto_load_dev_disabled_t	*pload_dev_dis = NULL;
10940Sstevel@tonic-gate 	entrylist_t	*pdevlist = NULL;
10950Sstevel@tonic-gate 	entrylist_t	*psoftlist = NULL;
10960Sstevel@tonic-gate 	entrylist_t	*ptr;
10970Sstevel@tonic-gate 	boolean_t	found;
10980Sstevel@tonic-gate 	char 	*psoftname;
10990Sstevel@tonic-gate 	int	fd;
11000Sstevel@tonic-gate 	int	rc = SUCCESS;
11010Sstevel@tonic-gate 	int	i;
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	if (get_soft_list(&psoftlist_kernel) == FAILURE) {
11040Sstevel@tonic-gate 		cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
11050Sstevel@tonic-gate 		    "software provider list from kernel."));
11060Sstevel@tonic-gate 		return (FAILURE);
11070Sstevel@tonic-gate 	}
11080Sstevel@tonic-gate 
11090Sstevel@tonic-gate 	if (get_kcfconf_info(&pdevlist, &psoftlist) == FAILURE) {
11100Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "failed to retrieve the providers' "
11110Sstevel@tonic-gate 		    "information from the configuration file - %s.",
11120Sstevel@tonic-gate 		    _PATH_KCF_CONF);
11130Sstevel@tonic-gate 		return (FAILURE);
11140Sstevel@tonic-gate 	}
11150Sstevel@tonic-gate 
11160Sstevel@tonic-gate 	/*
11170Sstevel@tonic-gate 	 * If a kernel software provider is in kernel, but it is not in the
11180Sstevel@tonic-gate 	 * kcf.conf file, it must have been pkgrm'ed and needs to be unloaded
11190Sstevel@tonic-gate 	 * now.
11200Sstevel@tonic-gate 	 */
11210Sstevel@tonic-gate 	if (psoftlist_kernel->sl_soft_count > 0) {
11220Sstevel@tonic-gate 		psoftname = psoftlist_kernel->sl_soft_names;
11230Sstevel@tonic-gate 		for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) {
11240Sstevel@tonic-gate 			ptr = psoftlist;
11250Sstevel@tonic-gate 			found = B_FALSE;
11260Sstevel@tonic-gate 			while (ptr != NULL) {
11270Sstevel@tonic-gate 				if (strcmp(psoftname, ptr->pent->name) == 0) {
11280Sstevel@tonic-gate 					found = B_TRUE;
11290Sstevel@tonic-gate 					break;
11300Sstevel@tonic-gate 				}
11310Sstevel@tonic-gate 				ptr = ptr->next;
11320Sstevel@tonic-gate 			}
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate 			if (!found) {
11351971Skrishna 				rc = unload_kef_soft(psoftname, B_FALSE);
11360Sstevel@tonic-gate 				if (rc == FAILURE) {
11370Sstevel@tonic-gate 					cryptoerror(LOG_ERR, gettext(
11380Sstevel@tonic-gate 					    "WARNING - the provider %s is "
11390Sstevel@tonic-gate 					    "still in kernel."), psoftname);
11400Sstevel@tonic-gate 				}
11410Sstevel@tonic-gate 			}
11420Sstevel@tonic-gate 			psoftname = psoftname + strlen(psoftname) + 1;
11430Sstevel@tonic-gate 		}
11440Sstevel@tonic-gate 	}
11450Sstevel@tonic-gate 	free(psoftlist_kernel);
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
11480Sstevel@tonic-gate 		err = errno;
11490Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
11500Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(err));
11510Sstevel@tonic-gate 		free(psoftlist);
11520Sstevel@tonic-gate 		free(pdevlist);
11530Sstevel@tonic-gate 		return (FAILURE);
11540Sstevel@tonic-gate 	}
11550Sstevel@tonic-gate 
11560Sstevel@tonic-gate 	/*
11570Sstevel@tonic-gate 	 * For each software module, pass two sets of information to kernel
11580Sstevel@tonic-gate 	 * - the supported list and the disabled list
11590Sstevel@tonic-gate 	 */
11600Sstevel@tonic-gate 	ptr = psoftlist;
11610Sstevel@tonic-gate 	while (ptr != NULL) {
11620Sstevel@tonic-gate 		/* load the supported list */
11630Sstevel@tonic-gate 		if ((pload_soft_conf = setup_soft_conf(ptr->pent)) == NULL) {
11640Sstevel@tonic-gate 			rc = FAILURE;
11650Sstevel@tonic-gate 			break;
11660Sstevel@tonic-gate 		}
11670Sstevel@tonic-gate 
11680Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf)
11690Sstevel@tonic-gate 		    == -1) {
11700Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
11710Sstevel@tonic-gate 			    strerror(errno));
11720Sstevel@tonic-gate 			free(pload_soft_conf);
11730Sstevel@tonic-gate 			rc = FAILURE;
11740Sstevel@tonic-gate 			break;
11750Sstevel@tonic-gate 		}
11760Sstevel@tonic-gate 
11770Sstevel@tonic-gate 		if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
11780Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl "
11790Sstevel@tonic-gate 			    "return_value = %d",
11800Sstevel@tonic-gate 			    pload_soft_conf->sc_return_value);
11810Sstevel@tonic-gate 			free(pload_soft_conf);
11820Sstevel@tonic-gate 			rc = FAILURE;
11830Sstevel@tonic-gate 			break;
11840Sstevel@tonic-gate 		}
11850Sstevel@tonic-gate 
11860Sstevel@tonic-gate 		/* load the disabled list */
11870Sstevel@tonic-gate 		if (ptr->pent->dis_count != 0) {
11880Sstevel@tonic-gate 			pload_soft_dis = setup_soft_dis(ptr->pent);
11890Sstevel@tonic-gate 			if (pload_soft_dis == NULL) {
11900Sstevel@tonic-gate 				rc = FAILURE;
11910Sstevel@tonic-gate 				break;
11920Sstevel@tonic-gate 			}
11930Sstevel@tonic-gate 
11940Sstevel@tonic-gate 			if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED,
11950Sstevel@tonic-gate 			    pload_soft_dis) == -1) {
11960Sstevel@tonic-gate 				cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
11970Sstevel@tonic-gate 				    "failed: %s", strerror(errno));
11980Sstevel@tonic-gate 				free(pload_soft_dis);
11990Sstevel@tonic-gate 				rc = FAILURE;
12000Sstevel@tonic-gate 				break;
12010Sstevel@tonic-gate 			}
12020Sstevel@tonic-gate 
12030Sstevel@tonic-gate 			if (pload_soft_dis->sd_return_value !=
12040Sstevel@tonic-gate 			    CRYPTO_SUCCESS) {
12050Sstevel@tonic-gate 				cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
12060Sstevel@tonic-gate 				    "return_value = %d",
12070Sstevel@tonic-gate 				    pload_soft_dis->sd_return_value);
12080Sstevel@tonic-gate 				free(pload_soft_dis);
12090Sstevel@tonic-gate 				rc = FAILURE;
12100Sstevel@tonic-gate 				break;
12110Sstevel@tonic-gate 			}
12120Sstevel@tonic-gate 			free(pload_soft_dis);
12130Sstevel@tonic-gate 		}
12140Sstevel@tonic-gate 
12150Sstevel@tonic-gate 		free(pload_soft_conf);
12160Sstevel@tonic-gate 		ptr = ptr->next;
12170Sstevel@tonic-gate 	}
12180Sstevel@tonic-gate 
12190Sstevel@tonic-gate 	if (rc != SUCCESS) {
12200Sstevel@tonic-gate 		(void) close(fd);
12210Sstevel@tonic-gate 		return (rc);
12220Sstevel@tonic-gate 	}
12230Sstevel@tonic-gate 
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 	/* Pass the disabledlist information for Device to kernel */
12260Sstevel@tonic-gate 	ptr = pdevlist;
12270Sstevel@tonic-gate 	while (ptr != NULL) {
12280Sstevel@tonic-gate 		/* load the disabled list */
12290Sstevel@tonic-gate 		if (ptr->pent->dis_count != 0) {
12300Sstevel@tonic-gate 			pload_dev_dis = setup_dev_dis(ptr->pent);
12310Sstevel@tonic-gate 			if (pload_dev_dis == NULL) {
12320Sstevel@tonic-gate 				rc = FAILURE;
12330Sstevel@tonic-gate 				break;
12340Sstevel@tonic-gate 			}
12350Sstevel@tonic-gate 
12360Sstevel@tonic-gate 			if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis)
12370Sstevel@tonic-gate 			    == -1) {
12380Sstevel@tonic-gate 				cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
12390Sstevel@tonic-gate 				    "failed: %s", strerror(errno));
12400Sstevel@tonic-gate 				free(pload_dev_dis);
12410Sstevel@tonic-gate 				rc = FAILURE;
12420Sstevel@tonic-gate 				break;
12430Sstevel@tonic-gate 			}
12440Sstevel@tonic-gate 
12450Sstevel@tonic-gate 			if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
12460Sstevel@tonic-gate 				cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
12470Sstevel@tonic-gate 				    "return_value = %d",
12480Sstevel@tonic-gate 				    pload_dev_dis->dd_return_value);
12490Sstevel@tonic-gate 				free(pload_dev_dis);
12500Sstevel@tonic-gate 				rc = FAILURE;
12510Sstevel@tonic-gate 				break;
12520Sstevel@tonic-gate 			}
12530Sstevel@tonic-gate 			free(pload_dev_dis);
12540Sstevel@tonic-gate 		}
12550Sstevel@tonic-gate 
12560Sstevel@tonic-gate 		ptr = ptr->next;
12570Sstevel@tonic-gate 	}
12580Sstevel@tonic-gate 
12590Sstevel@tonic-gate 	(void) close(fd);
12600Sstevel@tonic-gate 	return (rc);
12610Sstevel@tonic-gate }
12620Sstevel@tonic-gate 
12630Sstevel@tonic-gate /*
12640Sstevel@tonic-gate  * Unload the kernel software provider. Before calling this function, the
12650Sstevel@tonic-gate  * caller should check if the provider is in the config file and if it
12661971Skrishna  * is kernel. This routine makes 3 ioctl calls to remove it from kernel
12671971Skrishna  * completely. The argument do_check set to B_FALSE means that the
12681971Skrishna  * caller knows the provider is not the config file and hence the check
12691971Skrishna  * is skipped.
12700Sstevel@tonic-gate  */
12710Sstevel@tonic-gate int
12721971Skrishna unload_kef_soft(char *provname, boolean_t do_check)
12730Sstevel@tonic-gate {
12740Sstevel@tonic-gate 	crypto_unload_soft_module_t 	*punload_soft = NULL;
12750Sstevel@tonic-gate 	crypto_load_soft_config_t	*pload_soft_conf = NULL;
12760Sstevel@tonic-gate 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
12770Sstevel@tonic-gate 	entry_t	*pent = NULL;
12780Sstevel@tonic-gate 	int	fd;
12790Sstevel@tonic-gate 
12800Sstevel@tonic-gate 	if (provname == NULL) {
12810Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
12820Sstevel@tonic-gate 		return (FAILURE);
12830Sstevel@tonic-gate 	}
12840Sstevel@tonic-gate 
12851971Skrishna 	if (!do_check) {
12861971Skrishna 		/* Construct an entry using the provname */
12871971Skrishna 		pent = calloc(1, sizeof (entry_t));
12881971Skrishna 		if (pent == NULL) {
12891971Skrishna 			cryptoerror(LOG_STDERR, gettext("out of memory."));
12901971Skrishna 			return (FAILURE);
12911971Skrishna 		}
12921971Skrishna 		(void) strlcpy(pent->name, provname, MAXNAMELEN);
12931971Skrishna 	} else if ((pent = getent_kef(provname)) == NULL) {
12940Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s does not exist."),
12950Sstevel@tonic-gate 		    provname);
12960Sstevel@tonic-gate 		return (FAILURE);
12970Sstevel@tonic-gate 	}
12980Sstevel@tonic-gate 
12990Sstevel@tonic-gate 	/* Open the admin_ioctl_device */
13000Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
13010Sstevel@tonic-gate 		err = errno;
13020Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
13030Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(err));
13040Sstevel@tonic-gate 		return (FAILURE);
13050Sstevel@tonic-gate 	}
13060Sstevel@tonic-gate 
13070Sstevel@tonic-gate 	/* Inform kernel to unload this software module */
13080Sstevel@tonic-gate 	if ((punload_soft = setup_unload_soft(pent)) == NULL) {
13090Sstevel@tonic-gate 		(void) close(fd);
13100Sstevel@tonic-gate 		return (FAILURE);
13110Sstevel@tonic-gate 	}
13120Sstevel@tonic-gate 
13130Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_UNLOAD_SOFT_MODULE, punload_soft) == -1) {
13140Sstevel@tonic-gate 		cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s",
13150Sstevel@tonic-gate 		    strerror(errno));
13160Sstevel@tonic-gate 		free_entry(pent);
13170Sstevel@tonic-gate 		free(punload_soft);
13180Sstevel@tonic-gate 		(void) close(fd);
13190Sstevel@tonic-gate 		return (FAILURE);
13200Sstevel@tonic-gate 	}
13210Sstevel@tonic-gate 
13220Sstevel@tonic-gate 	if (punload_soft->sm_return_value != CRYPTO_SUCCESS) {
13230Sstevel@tonic-gate 		cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl return_value = "
13240Sstevel@tonic-gate 		    "%d", punload_soft->sm_return_value);
13250Sstevel@tonic-gate 		/*
13260Sstevel@tonic-gate 		 * If the return value is CRYPTO_UNKNOWN_PRIVDER, it means
13270Sstevel@tonic-gate 		 * that the provider is not registered yet.  Should just
13280Sstevel@tonic-gate 		 * continue.
13290Sstevel@tonic-gate 		 */
13300Sstevel@tonic-gate 		if (punload_soft->sm_return_value != CRYPTO_UNKNOWN_PROVIDER) {
13310Sstevel@tonic-gate 			free_entry(pent);
13320Sstevel@tonic-gate 			free(punload_soft);
13330Sstevel@tonic-gate 			(void) close(fd);
13340Sstevel@tonic-gate 			return (FAILURE);
13350Sstevel@tonic-gate 		}
13360Sstevel@tonic-gate 	}
13370Sstevel@tonic-gate 
13380Sstevel@tonic-gate 	free(punload_soft);
13390Sstevel@tonic-gate 
13400Sstevel@tonic-gate 	/*
13410Sstevel@tonic-gate 	 * Inform kernel to remove the configuration of this software
13420Sstevel@tonic-gate 	 * module.
13430Sstevel@tonic-gate 	 */
13440Sstevel@tonic-gate 	free_mechlist(pent->suplist);
13450Sstevel@tonic-gate 	pent->suplist = NULL;
13460Sstevel@tonic-gate 	pent->sup_count = 0;
13470Sstevel@tonic-gate 	if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
13480Sstevel@tonic-gate 		free_entry(pent);
13490Sstevel@tonic-gate 		(void) close(fd);
13500Sstevel@tonic-gate 		return (FAILURE);
13510Sstevel@tonic-gate 	}
13520Sstevel@tonic-gate 
13530Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) {
13540Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
13550Sstevel@tonic-gate 		    strerror(errno));
13560Sstevel@tonic-gate 		free_entry(pent);
13570Sstevel@tonic-gate 		free(pload_soft_conf);
13580Sstevel@tonic-gate 		(void) close(fd);
13590Sstevel@tonic-gate 		return (FAILURE);
13600Sstevel@tonic-gate 	}
13610Sstevel@tonic-gate 
13620Sstevel@tonic-gate 	if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
13630Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl return_value = "
13640Sstevel@tonic-gate 		    "%d", pload_soft_conf->sc_return_value);
13650Sstevel@tonic-gate 		free_entry(pent);
13660Sstevel@tonic-gate 		free(pload_soft_conf);
13670Sstevel@tonic-gate 		(void) close(fd);
13680Sstevel@tonic-gate 		return (FAILURE);
13690Sstevel@tonic-gate 	}
13700Sstevel@tonic-gate 
13710Sstevel@tonic-gate 	free(pload_soft_conf);
13720Sstevel@tonic-gate 
13730Sstevel@tonic-gate 	/* Inform kernel to remove the disabled entries if any */
13740Sstevel@tonic-gate 	if (pent->dis_count == 0) {
13750Sstevel@tonic-gate 		free_entry(pent);
13760Sstevel@tonic-gate 		(void) close(fd);
13770Sstevel@tonic-gate 		return (SUCCESS);
13780Sstevel@tonic-gate 	} else {
13790Sstevel@tonic-gate 		free_mechlist(pent->dislist);
13800Sstevel@tonic-gate 		pent->dislist = NULL;
13810Sstevel@tonic-gate 		pent->dis_count = 0;
13820Sstevel@tonic-gate 	}
13830Sstevel@tonic-gate 
13840Sstevel@tonic-gate 	if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
13850Sstevel@tonic-gate 		free_entry(pent);
13860Sstevel@tonic-gate 		(void) close(fd);
13870Sstevel@tonic-gate 		return (FAILURE);
13880Sstevel@tonic-gate 	}
13890Sstevel@tonic-gate 
13900Sstevel@tonic-gate 	/* pent is no longer needed; free it */
13910Sstevel@tonic-gate 	free_entry(pent);
13920Sstevel@tonic-gate 
13930Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) {
13940Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
13950Sstevel@tonic-gate 		    strerror(errno));
13960Sstevel@tonic-gate 		free(pload_soft_dis);
13970Sstevel@tonic-gate 		(void) close(fd);
13980Sstevel@tonic-gate 		return (FAILURE);
13990Sstevel@tonic-gate 	}
14000Sstevel@tonic-gate 
14010Sstevel@tonic-gate 	if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
14020Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
14030Sstevel@tonic-gate 		    "%d", pload_soft_dis->sd_return_value);
14040Sstevel@tonic-gate 		free(pload_soft_dis);
14050Sstevel@tonic-gate 		(void) close(fd);
14060Sstevel@tonic-gate 		return (FAILURE);
14070Sstevel@tonic-gate 	}
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 	free(pload_soft_dis);
14100Sstevel@tonic-gate 	(void) close(fd);
14110Sstevel@tonic-gate 	return (SUCCESS);
14120Sstevel@tonic-gate }
14130Sstevel@tonic-gate 
14140Sstevel@tonic-gate 
14150Sstevel@tonic-gate /*
14160Sstevel@tonic-gate  * Check if a hardware provider is valid.  If it is valid, returns its device
14170Sstevel@tonic-gate  * name,  instance number and the number of mechanisms it supports.
14180Sstevel@tonic-gate  */
14190Sstevel@tonic-gate static int
14200Sstevel@tonic-gate check_hardware_provider(char *provname, char *pname, int *pnum, int *pcount)
14210Sstevel@tonic-gate {
14220Sstevel@tonic-gate 	crypto_get_dev_list_t *dev_list = NULL;
14230Sstevel@tonic-gate 	int	i;
14240Sstevel@tonic-gate 
14250Sstevel@tonic-gate 	if (provname == NULL) {
14260Sstevel@tonic-gate 		return (FAILURE);
14270Sstevel@tonic-gate 	}
14280Sstevel@tonic-gate 
14290Sstevel@tonic-gate 	/* First, get the device name and the instance number from provname */
14300Sstevel@tonic-gate 	if (split_hw_provname(provname, pname, pnum) == FAILURE) {
14310Sstevel@tonic-gate 		return (FAILURE);
14320Sstevel@tonic-gate 	}
14330Sstevel@tonic-gate 
14340Sstevel@tonic-gate 	/*
14350Sstevel@tonic-gate 	 * Get the complete device list from kernel and check if this provider
14360Sstevel@tonic-gate 	 * is in the list.
14370Sstevel@tonic-gate 	 */
14380Sstevel@tonic-gate 	if (get_dev_list(&dev_list) == FAILURE) {
14390Sstevel@tonic-gate 		return (FAILURE);
14400Sstevel@tonic-gate 	}
14410Sstevel@tonic-gate 
14420Sstevel@tonic-gate 	for (i = 0; i < dev_list->dl_dev_count; i++) {
14430Sstevel@tonic-gate 		if ((strcmp(dev_list->dl_devs[i].le_dev_name, pname) == 0) &&
14440Sstevel@tonic-gate 		    (dev_list->dl_devs[i].le_dev_instance == *pnum)) {
14450Sstevel@tonic-gate 			break;
14460Sstevel@tonic-gate 		}
14470Sstevel@tonic-gate 	}
14480Sstevel@tonic-gate 
14490Sstevel@tonic-gate 	if (i == dev_list->dl_dev_count) {
14500Sstevel@tonic-gate 		/* didn't find this provider in the kernel device list */
14510Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s does not exist."),
14520Sstevel@tonic-gate 		    provname);
14530Sstevel@tonic-gate 		free(dev_list);
14540Sstevel@tonic-gate 		return (FAILURE);
14550Sstevel@tonic-gate 	}
14560Sstevel@tonic-gate 
14570Sstevel@tonic-gate 	/* This provider is valid.  Get its mechanism count */
14580Sstevel@tonic-gate 	*pcount = dev_list->dl_devs[i].le_mechanism_count;
14590Sstevel@tonic-gate 
14600Sstevel@tonic-gate 	free(dev_list);
14610Sstevel@tonic-gate 	return (SUCCESS);
14620Sstevel@tonic-gate }
1463