xref: /titanic_51/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef.c (revision 6ea3c0609e50782557505b88bb391b786bca32c9)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5b8bf75cbSkrishna  * Common Development and Distribution License (the "License").
6b8bf75cbSkrishna  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22b5a2d845SHai-May Chao  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <fcntl.h>
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <strings.h>
307c478bd9Sstevel@tonic-gate #include <unistd.h>
317c478bd9Sstevel@tonic-gate #include <locale.h>
327c478bd9Sstevel@tonic-gate #include <libgen.h>
337c478bd9Sstevel@tonic-gate #include <sys/types.h>
347c478bd9Sstevel@tonic-gate #include <sys/stat.h>
357c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctladmin.h>
367c478bd9Sstevel@tonic-gate #include <signal.h>
377c478bd9Sstevel@tonic-gate #include <sys/crypto/elfsign.h>
387c478bd9Sstevel@tonic-gate #include "cryptoadm.h"
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate static int check_hardware_provider(char *, char *, int *, int *);
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /*
437c478bd9Sstevel@tonic-gate  * Display the mechanism list for a kernel software provider.
441b22764fSDaniel OpenSolaris Anderson  * This implements part of the "cryptoadm list -m" command.
451b22764fSDaniel OpenSolaris Anderson  *
46*d616ad8eSHai-May Chao  * Parameters phardlist and psoftlist are supplied by
47b5a2d845SHai-May Chao  * get_soft_info().
48b5a2d845SHai-May Chao  * If NULL, this function obtains it by calling getent_kef() and
49b5a2d845SHai-May Chao  * then get_kcfconf_info() via get_soft_info() internally.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate int
521b22764fSDaniel OpenSolaris Anderson list_mechlist_for_soft(char *provname,
53*d616ad8eSHai-May Chao     entrylist_t *phardlist, entrylist_t *psoftlist)
547c478bd9Sstevel@tonic-gate {
551b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*pmechlist = NULL;
567c478bd9Sstevel@tonic-gate 	int		rc;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	if (provname == NULL) {
597c478bd9Sstevel@tonic-gate 		return (FAILURE);
607c478bd9Sstevel@tonic-gate 	}
617c478bd9Sstevel@tonic-gate 
62*d616ad8eSHai-May Chao 	rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist);
637c478bd9Sstevel@tonic-gate 	if (rc == SUCCESS) {
647c478bd9Sstevel@tonic-gate 		(void) filter_mechlist(&pmechlist, RANDOM);
657c478bd9Sstevel@tonic-gate 		print_mechlist(provname, pmechlist);
667c478bd9Sstevel@tonic-gate 		free_mechlist(pmechlist);
677c478bd9Sstevel@tonic-gate 	} else {
687c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
697c478bd9Sstevel@tonic-gate 		    "failed to retrieve the mechanism list for %s."),
707c478bd9Sstevel@tonic-gate 		    provname);
717c478bd9Sstevel@tonic-gate 	}
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 	return (rc);
747c478bd9Sstevel@tonic-gate }
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate /*
777c478bd9Sstevel@tonic-gate  * Display the mechanism list for a kernel hardware provider.
781b22764fSDaniel OpenSolaris Anderson  * This implements part of the "cryptoadm list -m" command.
797c478bd9Sstevel@tonic-gate  */
807c478bd9Sstevel@tonic-gate int
817c478bd9Sstevel@tonic-gate list_mechlist_for_hard(char *provname)
827c478bd9Sstevel@tonic-gate {
831b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*pmechlist = NULL;
847c478bd9Sstevel@tonic-gate 	char		devname[MAXNAMELEN];
857c478bd9Sstevel@tonic-gate 	int		inst_num;
867c478bd9Sstevel@tonic-gate 	int		count;
877c478bd9Sstevel@tonic-gate 	int		rc = SUCCESS;
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	if (provname == NULL) {
907c478bd9Sstevel@tonic-gate 		return (FAILURE);
917c478bd9Sstevel@tonic-gate 	}
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	/*
947c478bd9Sstevel@tonic-gate 	 * Check if the provider is valid. If it is valid, get the number of
957c478bd9Sstevel@tonic-gate 	 * mechanisms also.
967c478bd9Sstevel@tonic-gate 	 */
977c478bd9Sstevel@tonic-gate 	if (check_hardware_provider(provname, devname, &inst_num, &count) ==
987c478bd9Sstevel@tonic-gate 	    FAILURE) {
997c478bd9Sstevel@tonic-gate 		return (FAILURE);
1007c478bd9Sstevel@tonic-gate 	}
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	/* Get the mechanism list for the kernel hardware provider */
1037c478bd9Sstevel@tonic-gate 	if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) ==
1047c478bd9Sstevel@tonic-gate 	    SUCCESS) {
1057c478bd9Sstevel@tonic-gate 		(void) filter_mechlist(&pmechlist, RANDOM);
1067c478bd9Sstevel@tonic-gate 		print_mechlist(provname, pmechlist);
1077c478bd9Sstevel@tonic-gate 		free_mechlist(pmechlist);
1087c478bd9Sstevel@tonic-gate 	}
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	return (rc);
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate /*
1157c478bd9Sstevel@tonic-gate  * Display the policy information for a kernel software provider.
1161b22764fSDaniel OpenSolaris Anderson  * This implements part of the "cryptoadm list -p" command.
1171b22764fSDaniel OpenSolaris Anderson  *
118*d616ad8eSHai-May Chao  * Parameters phardlist and psoftlist are supplied by
119b5a2d845SHai-May Chao  * getent_kef().
120b5a2d845SHai-May Chao  * If NULL, this function obtains it by calling get_kcfconf_info()
121b5a2d845SHai-May Chao  * via getent_kef() internally.
1227c478bd9Sstevel@tonic-gate  */
1237c478bd9Sstevel@tonic-gate int
1241b22764fSDaniel OpenSolaris Anderson list_policy_for_soft(char *provname,
125*d616ad8eSHai-May Chao     entrylist_t *phardlist, entrylist_t *psoftlist)
1267c478bd9Sstevel@tonic-gate {
1277c478bd9Sstevel@tonic-gate 	int		rc;
1287c478bd9Sstevel@tonic-gate 	entry_t		*pent = NULL;
1291b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*pmechlist = NULL;
1307c478bd9Sstevel@tonic-gate 	boolean_t	has_random = B_FALSE;
1317c478bd9Sstevel@tonic-gate 	boolean_t	has_mechs = B_FALSE;
1321b22764fSDaniel OpenSolaris Anderson 	boolean_t	in_kernel = B_FALSE;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	if (provname == NULL) {
1357c478bd9Sstevel@tonic-gate 		return (FAILURE);
1367c478bd9Sstevel@tonic-gate 	}
1377c478bd9Sstevel@tonic-gate 
1381b22764fSDaniel OpenSolaris Anderson 	if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
1391b22764fSDaniel OpenSolaris Anderson 		return (FAILURE);
1401b22764fSDaniel OpenSolaris Anderson 	} else if (in_kernel == B_FALSE) {
1417c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s does not exist."),
1427c478bd9Sstevel@tonic-gate 		    provname);
1437c478bd9Sstevel@tonic-gate 		return (FAILURE);
1447c478bd9Sstevel@tonic-gate 	}
145*d616ad8eSHai-May Chao 	pent = getent_kef(provname, phardlist, psoftlist);
1467c478bd9Sstevel@tonic-gate 
147*d616ad8eSHai-May Chao 	rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist);
1487c478bd9Sstevel@tonic-gate 	if (rc == SUCCESS) {
1497c478bd9Sstevel@tonic-gate 		has_random = filter_mechlist(&pmechlist, RANDOM);
1507c478bd9Sstevel@tonic-gate 		if (pmechlist != NULL) {
1517c478bd9Sstevel@tonic-gate 			has_mechs = B_TRUE;
1527c478bd9Sstevel@tonic-gate 			free_mechlist(pmechlist);
1537c478bd9Sstevel@tonic-gate 		}
1547c478bd9Sstevel@tonic-gate 	} else {
1557c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
1567c478bd9Sstevel@tonic-gate 		    "failed to retrieve the mechanism list for %s."),
1577c478bd9Sstevel@tonic-gate 		    provname);
1587c478bd9Sstevel@tonic-gate 		return (rc);
1597c478bd9Sstevel@tonic-gate 	}
1607c478bd9Sstevel@tonic-gate 
1611b22764fSDaniel OpenSolaris Anderson 	print_kef_policy(provname, pent, has_random, has_mechs);
1627c478bd9Sstevel@tonic-gate 	free_entry(pent);
1637c478bd9Sstevel@tonic-gate 	return (SUCCESS);
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate  * Display the policy information for a kernel hardware provider.
1701b22764fSDaniel OpenSolaris Anderson  * This implements part of the "cryptoadm list -p" command.
1711b22764fSDaniel OpenSolaris Anderson  *
172*d616ad8eSHai-May Chao  * Parameters phardlist and psoftlist are supplied by getent_kef().
173b5a2d845SHai-May Chao  * If NULL, this function obtains it by calling get_kcfconf_info() via
174b5a2d845SHai-May Chao  * getent_kef() internally.
175b5a2d845SHai-May Chao  * Parameter pdevlist is supplied by check_kernel_for_hard().
176b5a2d845SHai-May Chao  * If NULL, this function obtains it by calling get_dev_list() via
177b5a2d845SHai-May Chao  * check_kernel_for_hard() internally.
1787c478bd9Sstevel@tonic-gate  */
1797c478bd9Sstevel@tonic-gate int
1801b22764fSDaniel OpenSolaris Anderson list_policy_for_hard(char *provname,
1811b22764fSDaniel OpenSolaris Anderson 	entrylist_t *phardlist, entrylist_t *psoftlist,
182*d616ad8eSHai-May Chao 	crypto_get_dev_list_t *pdevlist)
1837c478bd9Sstevel@tonic-gate {
1841b22764fSDaniel OpenSolaris Anderson 	entry_t		*pent = NULL;
1851b22764fSDaniel OpenSolaris Anderson 	boolean_t	in_kernel;
1861b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*pmechlist = NULL;
1877c478bd9Sstevel@tonic-gate 	char		devname[MAXNAMELEN];
1887c478bd9Sstevel@tonic-gate 	int		inst_num;
1897c478bd9Sstevel@tonic-gate 	int		count;
1907c478bd9Sstevel@tonic-gate 	int		rc = SUCCESS;
1917c478bd9Sstevel@tonic-gate 	boolean_t	has_random = B_FALSE;
1927c478bd9Sstevel@tonic-gate 	boolean_t 	has_mechs = B_FALSE;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	if (provname == NULL) {
1957c478bd9Sstevel@tonic-gate 		return (FAILURE);
1967c478bd9Sstevel@tonic-gate 	}
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	/*
1997c478bd9Sstevel@tonic-gate 	 * Check if the provider is valid. If it is valid, get the number of
2007c478bd9Sstevel@tonic-gate 	 * mechanisms also.
2017c478bd9Sstevel@tonic-gate 	 */
2027c478bd9Sstevel@tonic-gate 	if (check_hardware_provider(provname, devname, &inst_num, &count) ==
2037c478bd9Sstevel@tonic-gate 	    FAILURE) {
2047c478bd9Sstevel@tonic-gate 		return (FAILURE);
2057c478bd9Sstevel@tonic-gate 	}
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	/* Get the mechanism list for the kernel hardware provider */
2087c478bd9Sstevel@tonic-gate 	if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) ==
2097c478bd9Sstevel@tonic-gate 	    SUCCESS) {
2107c478bd9Sstevel@tonic-gate 		has_random = filter_mechlist(&pmechlist, RANDOM);
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 		if (pmechlist != NULL) {
2137c478bd9Sstevel@tonic-gate 			has_mechs = B_TRUE;
2147c478bd9Sstevel@tonic-gate 			free_mechlist(pmechlist);
2157c478bd9Sstevel@tonic-gate 		}
2167c478bd9Sstevel@tonic-gate 	} else {
2177c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
2187c478bd9Sstevel@tonic-gate 		    "failed to retrieve the mechanism list for %s."),
2197c478bd9Sstevel@tonic-gate 		    devname);
2207c478bd9Sstevel@tonic-gate 		return (rc);
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	/*
2247c478bd9Sstevel@tonic-gate 	 * If the hardware provider has an entry in the kcf.conf file,
2257c478bd9Sstevel@tonic-gate 	 * some of its mechanisms must have been disabled.  Print out
2267c478bd9Sstevel@tonic-gate 	 * the disabled list from the config file entry.  Otherwise,
2277c478bd9Sstevel@tonic-gate 	 * if it is active, then all the mechanisms for it are enabled.
2287c478bd9Sstevel@tonic-gate 	 */
229*d616ad8eSHai-May Chao 	if ((pent = getent_kef(provname, phardlist, psoftlist)) != NULL) {
2301b22764fSDaniel OpenSolaris Anderson 		print_kef_policy(provname, pent, has_random, has_mechs);
2317c478bd9Sstevel@tonic-gate 		free_entry(pent);
2327c478bd9Sstevel@tonic-gate 		return (SUCCESS);
2337c478bd9Sstevel@tonic-gate 	} else {
2341b22764fSDaniel OpenSolaris Anderson 		if (check_kernel_for_hard(provname, pdevlist,
2351b22764fSDaniel OpenSolaris Anderson 		    &in_kernel) == FAILURE) {
2367c478bd9Sstevel@tonic-gate 			return (FAILURE);
2371b22764fSDaniel OpenSolaris Anderson 		} else if (in_kernel == B_TRUE) {
2387c478bd9Sstevel@tonic-gate 			(void) printf(gettext(
2397c478bd9Sstevel@tonic-gate 			    "%s: all mechanisms are enabled."), provname);
2407c478bd9Sstevel@tonic-gate 			if (has_random)
2417c478bd9Sstevel@tonic-gate 				/*
2420a85b835SDaniel Anderson 				 * TRANSLATION_NOTE
2437c478bd9Sstevel@tonic-gate 				 * "random" is a keyword and not to be
2447c478bd9Sstevel@tonic-gate 				 * translated.
2457c478bd9Sstevel@tonic-gate 				 */
2467c478bd9Sstevel@tonic-gate 				(void) printf(gettext(" %s is enabled.\n"),
2477c478bd9Sstevel@tonic-gate 				    "random");
2487c478bd9Sstevel@tonic-gate 			else
2497c478bd9Sstevel@tonic-gate 				(void) printf("\n");
2507c478bd9Sstevel@tonic-gate 			return (SUCCESS);
2517c478bd9Sstevel@tonic-gate 		} else {
2527c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_STDERR,
2537c478bd9Sstevel@tonic-gate 			    gettext("%s does not exist."), provname);
2547c478bd9Sstevel@tonic-gate 			return (FAILURE);
2557c478bd9Sstevel@tonic-gate 		}
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate }
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 
2601b22764fSDaniel OpenSolaris Anderson /*
2611b22764fSDaniel OpenSolaris Anderson  * Disable a kernel hardware provider.
2621b22764fSDaniel OpenSolaris Anderson  * This implements the "cryptoadm disable" command for
2631b22764fSDaniel OpenSolaris Anderson  * kernel hardware providers.
2641b22764fSDaniel OpenSolaris Anderson  */
2657c478bd9Sstevel@tonic-gate int
2667c478bd9Sstevel@tonic-gate disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag,
2677c478bd9Sstevel@tonic-gate     mechlist_t *dislist)
2687c478bd9Sstevel@tonic-gate {
2691b22764fSDaniel OpenSolaris Anderson 	crypto_load_dev_disabled_t	*pload_dev_dis = NULL;
2701b22764fSDaniel OpenSolaris Anderson 	mechlist_t			*infolist = NULL;
2711b22764fSDaniel OpenSolaris Anderson 	entry_t				*pent = NULL;
2727c478bd9Sstevel@tonic-gate 	boolean_t			new_dev_entry = B_FALSE;
2737c478bd9Sstevel@tonic-gate 	char				devname[MAXNAMELEN];
2747c478bd9Sstevel@tonic-gate 	int				inst_num;
2757c478bd9Sstevel@tonic-gate 	int				count;
2761b22764fSDaniel OpenSolaris Anderson 	int				fd = -1;
2777c478bd9Sstevel@tonic-gate 	int				rc = SUCCESS;
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	if (provname == NULL) {
2807c478bd9Sstevel@tonic-gate 		return (FAILURE);
2817c478bd9Sstevel@tonic-gate 	}
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	/*
2847c478bd9Sstevel@tonic-gate 	 * Check if the provider is valid. If it is valid, get the number of
2857c478bd9Sstevel@tonic-gate 	 * mechanisms also.
2867c478bd9Sstevel@tonic-gate 	 */
2877c478bd9Sstevel@tonic-gate 	if (check_hardware_provider(provname, devname, &inst_num, &count)
2887c478bd9Sstevel@tonic-gate 	    == FAILURE) {
2897c478bd9Sstevel@tonic-gate 		return (FAILURE);
2907c478bd9Sstevel@tonic-gate 	}
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	/* Get the mechanism list for the kernel hardware provider */
2937c478bd9Sstevel@tonic-gate 	if (get_dev_info(devname, inst_num, count, &infolist) == FAILURE) {
2947c478bd9Sstevel@tonic-gate 		return (FAILURE);
2957c478bd9Sstevel@tonic-gate 	}
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	/*
2987c478bd9Sstevel@tonic-gate 	 * Get the entry of this hardware provider from the config file.
2997c478bd9Sstevel@tonic-gate 	 * If there is no entry yet, create one for it.
3007c478bd9Sstevel@tonic-gate 	 */
301*d616ad8eSHai-May Chao 	if ((pent = getent_kef(provname, NULL, NULL)) == NULL) {
3021b22764fSDaniel OpenSolaris Anderson 		if ((pent = create_entry(provname)) == NULL) {
3037c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext("out of memory."));
3047c478bd9Sstevel@tonic-gate 			free_mechlist(infolist);
3057c478bd9Sstevel@tonic-gate 			return (FAILURE);
3067c478bd9Sstevel@tonic-gate 		}
3077c478bd9Sstevel@tonic-gate 		new_dev_entry = B_TRUE;
3087c478bd9Sstevel@tonic-gate 	}
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	/*
3117c478bd9Sstevel@tonic-gate 	 * kCF treats random as an internal mechanism. So, we need to
3127c478bd9Sstevel@tonic-gate 	 * filter it from the mechanism list here, if we are NOT disabling
3137c478bd9Sstevel@tonic-gate 	 * or enabling the random feature. Note that we map random feature at
3147c478bd9Sstevel@tonic-gate 	 * cryptoadm(1M) level to the "random" mechanism in kCF.
3157c478bd9Sstevel@tonic-gate 	 */
3167c478bd9Sstevel@tonic-gate 	if (!rndflag) {
317407eb7ccSmcpowers 		(void) filter_mechlist(&dislist, RANDOM);
3187c478bd9Sstevel@tonic-gate 	}
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	/* Calculate the new disabled list */
3217c478bd9Sstevel@tonic-gate 	if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) {
322407eb7ccSmcpowers 		free_mechlist(infolist);
3237c478bd9Sstevel@tonic-gate 		free_entry(pent);
3247c478bd9Sstevel@tonic-gate 		return (FAILURE);
3257c478bd9Sstevel@tonic-gate 	}
326407eb7ccSmcpowers 	free_mechlist(infolist);
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	/* If no mechanisms are to be disabled, return */
3297c478bd9Sstevel@tonic-gate 	if (pent->dis_count == 0) {
3307c478bd9Sstevel@tonic-gate 		free_entry(pent);
3317c478bd9Sstevel@tonic-gate 		return (SUCCESS);
3327c478bd9Sstevel@tonic-gate 	}
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	/* Update the config file with the new entry or the updated entry */
3357c478bd9Sstevel@tonic-gate 	if (new_dev_entry) {
3367c478bd9Sstevel@tonic-gate 		rc = update_kcfconf(pent, ADD_MODE);
3377c478bd9Sstevel@tonic-gate 	} else {
3387c478bd9Sstevel@tonic-gate 		rc = update_kcfconf(pent, MODIFY_MODE);
3397c478bd9Sstevel@tonic-gate 	}
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	if (rc == FAILURE) {
3427c478bd9Sstevel@tonic-gate 		free_entry(pent);
3437c478bd9Sstevel@tonic-gate 		return (FAILURE);
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	/* Inform kernel about the new disabled mechanism list */
3477c478bd9Sstevel@tonic-gate 	if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) {
3487c478bd9Sstevel@tonic-gate 		free_entry(pent);
3497c478bd9Sstevel@tonic-gate 		return (FAILURE);
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 	free_entry(pent);
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
3547c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
3557c478bd9Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
3567c478bd9Sstevel@tonic-gate 		free(pload_dev_dis);
3577c478bd9Sstevel@tonic-gate 		return (FAILURE);
3587c478bd9Sstevel@tonic-gate 	}
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) {
3617c478bd9Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: %s",
3627c478bd9Sstevel@tonic-gate 		    strerror(errno));
3637c478bd9Sstevel@tonic-gate 		free(pload_dev_dis);
3647c478bd9Sstevel@tonic-gate 		(void) close(fd);
3657c478bd9Sstevel@tonic-gate 		return (FAILURE);
3667c478bd9Sstevel@tonic-gate 	}
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
3697c478bd9Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl return_value = "
3707c478bd9Sstevel@tonic-gate 		    "%d", pload_dev_dis->dd_return_value);
3717c478bd9Sstevel@tonic-gate 		free(pload_dev_dis);
3727c478bd9Sstevel@tonic-gate 		(void) close(fd);
3737c478bd9Sstevel@tonic-gate 		return (FAILURE);
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	free(pload_dev_dis);
3777c478bd9Sstevel@tonic-gate 	(void) close(fd);
3787c478bd9Sstevel@tonic-gate 	return (SUCCESS);
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 
3821b22764fSDaniel OpenSolaris Anderson /*
3831b22764fSDaniel OpenSolaris Anderson  * Disable a kernel software provider.
3841b22764fSDaniel OpenSolaris Anderson  * This implements the "cryptoadm disable" command for
3851b22764fSDaniel OpenSolaris Anderson  * kernel software providers.
3861b22764fSDaniel OpenSolaris Anderson  */
3877c478bd9Sstevel@tonic-gate int
3887c478bd9Sstevel@tonic-gate disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag,
3897c478bd9Sstevel@tonic-gate     mechlist_t *dislist)
3907c478bd9Sstevel@tonic-gate {
3917c478bd9Sstevel@tonic-gate 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
3921b22764fSDaniel OpenSolaris Anderson 	mechlist_t			*infolist = NULL;
3931b22764fSDaniel OpenSolaris Anderson 	entry_t				*pent = NULL;
3941b22764fSDaniel OpenSolaris Anderson 	entrylist_t			*phardlist = NULL;
3951b22764fSDaniel OpenSolaris Anderson 	entrylist_t			*psoftlist = NULL;
3961b22764fSDaniel OpenSolaris Anderson 	boolean_t			in_kernel = B_FALSE;
3971b22764fSDaniel OpenSolaris Anderson 	int				fd = -1;
3981b22764fSDaniel OpenSolaris Anderson 	int				rc = SUCCESS;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	if (provname == NULL) {
4017c478bd9Sstevel@tonic-gate 		return (FAILURE);
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	/*
4057c478bd9Sstevel@tonic-gate 	 * Check if the kernel software provider is currently unloaded.
4067c478bd9Sstevel@tonic-gate 	 * If it is unloaded, return FAILURE, because the disable subcommand
4077c478bd9Sstevel@tonic-gate 	 * can not perform on inactive (unloaded) providers.
4087c478bd9Sstevel@tonic-gate 	 */
409*d616ad8eSHai-May Chao 	if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
4107c478bd9Sstevel@tonic-gate 		return (FAILURE);
4111b22764fSDaniel OpenSolaris Anderson 	} else if (in_kernel == B_FALSE) {
4127c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
4131b22764fSDaniel OpenSolaris Anderson 		    gettext("%s is not loaded or does not exist."),
4141b22764fSDaniel OpenSolaris Anderson 		    provname);
4157c478bd9Sstevel@tonic-gate 		return (FAILURE);
4167c478bd9Sstevel@tonic-gate 	}
4177c478bd9Sstevel@tonic-gate 
418*d616ad8eSHai-May Chao 	if (get_kcfconf_info(&phardlist, &psoftlist) == FAILURE) {
4191b22764fSDaniel OpenSolaris Anderson 		cryptoerror(LOG_ERR,
4201b22764fSDaniel OpenSolaris Anderson 		    "failed to retrieve the providers' "
4211b22764fSDaniel OpenSolaris Anderson 		    "information from the configuration file - %s.",
4221b22764fSDaniel OpenSolaris Anderson 		    _PATH_KCF_CONF);
4237c478bd9Sstevel@tonic-gate 		return (FAILURE);
4247c478bd9Sstevel@tonic-gate 	}
4257c478bd9Sstevel@tonic-gate 
4261b22764fSDaniel OpenSolaris Anderson 	/*
4271b22764fSDaniel OpenSolaris Anderson 	 * Get the entry of this provider from the kcf.conf file, if any.
4281b22764fSDaniel OpenSolaris Anderson 	 * Otherwise, create a new kcf.conf entry for writing back to the file.
4291b22764fSDaniel OpenSolaris Anderson 	 */
430*d616ad8eSHai-May Chao 	pent = getent_kef(provname, phardlist, psoftlist);
4311b22764fSDaniel OpenSolaris Anderson 	if (pent == NULL) { /* create a new entry */
4321b22764fSDaniel OpenSolaris Anderson 		pent = create_entry(provname);
4331b22764fSDaniel OpenSolaris Anderson 		if (pent == NULL) {
4341b22764fSDaniel OpenSolaris Anderson 			cryptodebug("out of memory.");
4351b22764fSDaniel OpenSolaris Anderson 			rc = FAILURE;
4361b22764fSDaniel OpenSolaris Anderson 			goto out;
4371b22764fSDaniel OpenSolaris Anderson 		}
4381b22764fSDaniel OpenSolaris Anderson 	}
4391b22764fSDaniel OpenSolaris Anderson 
4401b22764fSDaniel OpenSolaris Anderson 	/* Get the mechanism list for the software provider from the kernel */
441*d616ad8eSHai-May Chao 	if (get_soft_info(provname, &infolist, phardlist, psoftlist) ==
442*d616ad8eSHai-May Chao 	    FAILURE) {
4431b22764fSDaniel OpenSolaris Anderson 		rc = FAILURE;
4441b22764fSDaniel OpenSolaris Anderson 		goto out;
4451b22764fSDaniel OpenSolaris Anderson 	}
4461b22764fSDaniel OpenSolaris Anderson 
4471b22764fSDaniel OpenSolaris Anderson 	if ((infolist != NULL) && (infolist->name[0] != '\0')) {
4481b22764fSDaniel OpenSolaris Anderson 		/*
4491b22764fSDaniel OpenSolaris Anderson 		 * Replace the supportedlist from kcf.conf with possibly
4501b22764fSDaniel OpenSolaris Anderson 		 * more-up-to-date list from the kernel.  This is the case
4511b22764fSDaniel OpenSolaris Anderson 		 * for default software providers that had more mechanisms
4521b22764fSDaniel OpenSolaris Anderson 		 * added in the current version of the kernel.
4531b22764fSDaniel OpenSolaris Anderson 		 */
4541b22764fSDaniel OpenSolaris Anderson 		free_mechlist(pent->suplist);
4551b22764fSDaniel OpenSolaris Anderson 		pent->suplist = infolist;
4561b22764fSDaniel OpenSolaris Anderson 	}
4571b22764fSDaniel OpenSolaris Anderson 
4581b22764fSDaniel OpenSolaris Anderson 	/*
4591b22764fSDaniel OpenSolaris Anderson 	 * kCF treats random as an internal mechanism. So, we need to
4601b22764fSDaniel OpenSolaris Anderson 	 * filter it from the mechanism list here, if we are NOT disabling
4611b22764fSDaniel OpenSolaris Anderson 	 * or enabling the random feature. Note that we map random feature at
4621b22764fSDaniel OpenSolaris Anderson 	 * cryptoadm(1M) level to the "random" mechanism in kCF.
4631b22764fSDaniel OpenSolaris Anderson 	 */
4647c478bd9Sstevel@tonic-gate 	if (!rndflag) {
4657c478bd9Sstevel@tonic-gate 		(void) filter_mechlist(&infolist, RANDOM);
4667c478bd9Sstevel@tonic-gate 	}
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	/* Calculate the new disabled list */
4697c478bd9Sstevel@tonic-gate 	if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) {
4701b22764fSDaniel OpenSolaris Anderson 		rc = FAILURE;
4711b22764fSDaniel OpenSolaris Anderson 		goto out;
4727c478bd9Sstevel@tonic-gate 	}
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	/* Update the kcf.conf file with the updated entry */
4757c478bd9Sstevel@tonic-gate 	if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) {
4761b22764fSDaniel OpenSolaris Anderson 		rc = FAILURE;
4771b22764fSDaniel OpenSolaris Anderson 		goto out;
4787c478bd9Sstevel@tonic-gate 	}
4797c478bd9Sstevel@tonic-gate 
4801b22764fSDaniel OpenSolaris Anderson 	/* Setup argument to inform kernel about the new disabled list. */
4817c478bd9Sstevel@tonic-gate 	if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
4821b22764fSDaniel OpenSolaris Anderson 		rc = FAILURE;
4831b22764fSDaniel OpenSolaris Anderson 		goto out;
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
4877c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
4887c478bd9Sstevel@tonic-gate 		    gettext("failed to open %s for RW: %s"),
4897c478bd9Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
4901b22764fSDaniel OpenSolaris Anderson 		rc = FAILURE;
4911b22764fSDaniel OpenSolaris Anderson 		goto out;
4927c478bd9Sstevel@tonic-gate 	}
4937c478bd9Sstevel@tonic-gate 
4941b22764fSDaniel OpenSolaris Anderson 	/* Inform kernel about the new disabled list. */
4957c478bd9Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) {
4967c478bd9Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
4977c478bd9Sstevel@tonic-gate 		    strerror(errno));
4981b22764fSDaniel OpenSolaris Anderson 		rc = FAILURE;
4991b22764fSDaniel OpenSolaris Anderson 		goto out;
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
5037c478bd9Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
5047c478bd9Sstevel@tonic-gate 		    "%d", pload_soft_dis->sd_return_value);
5051b22764fSDaniel OpenSolaris Anderson 		rc = FAILURE;
5061b22764fSDaniel OpenSolaris Anderson 		goto out;
5077c478bd9Sstevel@tonic-gate 	}
5087c478bd9Sstevel@tonic-gate 
5091b22764fSDaniel OpenSolaris Anderson out:
5101b22764fSDaniel OpenSolaris Anderson 	free_entrylist(phardlist);
5111b22764fSDaniel OpenSolaris Anderson 	free_entrylist(psoftlist);
5121b22764fSDaniel OpenSolaris Anderson 	free_mechlist(infolist);
5131b22764fSDaniel OpenSolaris Anderson 	free_entry(pent);
5147c478bd9Sstevel@tonic-gate 	free(pload_soft_dis);
5151b22764fSDaniel OpenSolaris Anderson 	if (fd != -1)
5167c478bd9Sstevel@tonic-gate 		(void) close(fd);
5171b22764fSDaniel OpenSolaris Anderson 	return (rc);
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 
5211b22764fSDaniel OpenSolaris Anderson /*
5221b22764fSDaniel OpenSolaris Anderson  * Enable a kernel software or hardware provider.
5231b22764fSDaniel OpenSolaris Anderson  * This implements the "cryptoadm enable" command for kernel providers.
5241b22764fSDaniel OpenSolaris Anderson  */
5257c478bd9Sstevel@tonic-gate int
5267c478bd9Sstevel@tonic-gate enable_kef(char *provname, boolean_t rndflag, boolean_t allflag,
5277c478bd9Sstevel@tonic-gate     mechlist_t *mlist)
5287c478bd9Sstevel@tonic-gate {
5297c478bd9Sstevel@tonic-gate 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
5307c478bd9Sstevel@tonic-gate 	crypto_load_dev_disabled_t	*pload_dev_dis = NULL;
5311b22764fSDaniel OpenSolaris Anderson 	entry_t				*pent = NULL;
5327c478bd9Sstevel@tonic-gate 	boolean_t			redo_flag = B_FALSE;
5331b22764fSDaniel OpenSolaris Anderson 	boolean_t			in_kernel = B_FALSE;
5341b22764fSDaniel OpenSolaris Anderson 	int				fd = -1;
5357c478bd9Sstevel@tonic-gate 	int				rc = SUCCESS;
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 
5381b22764fSDaniel OpenSolaris Anderson 	/* Get the entry of this provider from the kcf.conf file, if any. */
539*d616ad8eSHai-May Chao 	pent = getent_kef(provname, NULL, NULL);
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	if (is_device(provname)) {
5427c478bd9Sstevel@tonic-gate 		if (pent == NULL) {
5437c478bd9Sstevel@tonic-gate 			/*
5447c478bd9Sstevel@tonic-gate 			 * This device doesn't have an entry in the config
5457c478bd9Sstevel@tonic-gate 			 * file, therefore nothing is disabled.
5467c478bd9Sstevel@tonic-gate 			 */
5477c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
5487c478bd9Sstevel@tonic-gate 			    "all mechanisms are enabled already for %s."),
5497c478bd9Sstevel@tonic-gate 			    provname);
5501b22764fSDaniel OpenSolaris Anderson 			free_entry(pent);
5517c478bd9Sstevel@tonic-gate 			return (SUCCESS);
5527c478bd9Sstevel@tonic-gate 		}
5537c478bd9Sstevel@tonic-gate 	} else { /* a software module */
5541b22764fSDaniel OpenSolaris Anderson 		if (check_kernel_for_soft(provname, NULL, &in_kernel) ==
5551b22764fSDaniel OpenSolaris Anderson 		    FAILURE) {
5561b22764fSDaniel OpenSolaris Anderson 			free_entry(pent);
5577c478bd9Sstevel@tonic-gate 			return (FAILURE);
5581b22764fSDaniel OpenSolaris Anderson 		} else if (in_kernel == B_FALSE) {
5591b22764fSDaniel OpenSolaris Anderson 			cryptoerror(LOG_STDERR, gettext("%s does not exist."),
5601b22764fSDaniel OpenSolaris Anderson 			    provname);
5611b22764fSDaniel OpenSolaris Anderson 			free_entry(pent);
5621b22764fSDaniel OpenSolaris Anderson 			return (FAILURE);
5631b22764fSDaniel OpenSolaris Anderson 		} else if ((pent == NULL) || (pent->dis_count == 0)) {
5647c478bd9Sstevel@tonic-gate 			/* nothing to be enabled. */
5657c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
5667c478bd9Sstevel@tonic-gate 			    "all mechanisms are enabled already for %s."),
5677c478bd9Sstevel@tonic-gate 			    provname);
5687c478bd9Sstevel@tonic-gate 			free_entry(pent);
5697c478bd9Sstevel@tonic-gate 			return (SUCCESS);
5707c478bd9Sstevel@tonic-gate 		}
5717c478bd9Sstevel@tonic-gate 	}
5727c478bd9Sstevel@tonic-gate 
5731b22764fSDaniel OpenSolaris Anderson 	/*
5741b22764fSDaniel OpenSolaris Anderson 	 * kCF treats random as an internal mechanism. So, we need to
5751b22764fSDaniel OpenSolaris Anderson 	 * filter it from the mechanism list here, if we are NOT disabling
5761b22764fSDaniel OpenSolaris Anderson 	 * or enabling the random feature. Note that we map random feature at
5771b22764fSDaniel OpenSolaris Anderson 	 * cryptoadm(1M) level to the "random" mechanism in kCF.
5781b22764fSDaniel OpenSolaris Anderson 	 */
5797c478bd9Sstevel@tonic-gate 	if (!rndflag) {
5807c478bd9Sstevel@tonic-gate 		redo_flag = filter_mechlist(&pent->dislist, RANDOM);
5817c478bd9Sstevel@tonic-gate 		if (redo_flag)
5827c478bd9Sstevel@tonic-gate 			pent->dis_count--;
5837c478bd9Sstevel@tonic-gate 	}
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 	/* Update the entry by enabling mechanisms for this provider */
5867c478bd9Sstevel@tonic-gate 	if ((rc = enable_mechs(&pent, allflag, mlist)) != SUCCESS) {
5877c478bd9Sstevel@tonic-gate 		free_entry(pent);
5887c478bd9Sstevel@tonic-gate 		return (rc);
5897c478bd9Sstevel@tonic-gate 	}
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 	if (redo_flag) {
5927c478bd9Sstevel@tonic-gate 		mechlist_t *tmp;
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 		if ((tmp = create_mech(RANDOM)) == NULL) {
5957c478bd9Sstevel@tonic-gate 			free_entry(pent);
5967c478bd9Sstevel@tonic-gate 			return (FAILURE);
5977c478bd9Sstevel@tonic-gate 		}
5987c478bd9Sstevel@tonic-gate 		tmp->next = pent->dislist;
5997c478bd9Sstevel@tonic-gate 		pent->dislist = tmp;
6007c478bd9Sstevel@tonic-gate 		pent->dis_count++;
6017c478bd9Sstevel@tonic-gate 	}
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 	/*
6047c478bd9Sstevel@tonic-gate 	 * Update the kcf.conf file with the updated entry.
6057c478bd9Sstevel@tonic-gate 	 * For a hardware provider, if there is no more disabled mechanism,
6061b22764fSDaniel OpenSolaris Anderson 	 * remove the entire kcf.conf entry.
6077c478bd9Sstevel@tonic-gate 	 */
6087c478bd9Sstevel@tonic-gate 	if (is_device(pent->name) && (pent->dis_count == 0)) {
6097c478bd9Sstevel@tonic-gate 		rc = update_kcfconf(pent, DELETE_MODE);
6107c478bd9Sstevel@tonic-gate 	} else {
6117c478bd9Sstevel@tonic-gate 		rc = update_kcfconf(pent, MODIFY_MODE);
6127c478bd9Sstevel@tonic-gate 	}
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	if (rc == FAILURE) {
6157c478bd9Sstevel@tonic-gate 		free_entry(pent);
6167c478bd9Sstevel@tonic-gate 		return (FAILURE);
6177c478bd9Sstevel@tonic-gate 	}
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 	/* Inform Kernel about the policy change */
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
6237c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
6247c478bd9Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
6251b22764fSDaniel OpenSolaris Anderson 		free_entry(pent);
6267c478bd9Sstevel@tonic-gate 		return (FAILURE);
6277c478bd9Sstevel@tonic-gate 	}
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	if (is_device(provname)) {
6307c478bd9Sstevel@tonic-gate 		/*  LOAD_DEV_DISABLED */
6317c478bd9Sstevel@tonic-gate 		if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) {
6321b22764fSDaniel OpenSolaris Anderson 			free_entry(pent);
6337c478bd9Sstevel@tonic-gate 			return (FAILURE);
6347c478bd9Sstevel@tonic-gate 		}
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) {
6377c478bd9Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: "
6387c478bd9Sstevel@tonic-gate 			    "%s", strerror(errno));
6391b22764fSDaniel OpenSolaris Anderson 			free_entry(pent);
6407c478bd9Sstevel@tonic-gate 			free(pload_dev_dis);
6417c478bd9Sstevel@tonic-gate 			(void) close(fd);
6427c478bd9Sstevel@tonic-gate 			return (FAILURE);
6437c478bd9Sstevel@tonic-gate 		}
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 		if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
6467c478bd9Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
6477c478bd9Sstevel@tonic-gate 			    "return_value = %d",
6487c478bd9Sstevel@tonic-gate 			    pload_dev_dis->dd_return_value);
6491b22764fSDaniel OpenSolaris Anderson 			free_entry(pent);
6507c478bd9Sstevel@tonic-gate 			free(pload_dev_dis);
6517c478bd9Sstevel@tonic-gate 			(void) close(fd);
6527c478bd9Sstevel@tonic-gate 			return (FAILURE);
6537c478bd9Sstevel@tonic-gate 		}
6547c478bd9Sstevel@tonic-gate 
6551b22764fSDaniel OpenSolaris Anderson 	} else { /* a software module */
6567c478bd9Sstevel@tonic-gate 		/* LOAD_SOFT_DISABLED */
6577c478bd9Sstevel@tonic-gate 		if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
6581b22764fSDaniel OpenSolaris Anderson 			free_entry(pent);
6597c478bd9Sstevel@tonic-gate 			return (FAILURE);
6607c478bd9Sstevel@tonic-gate 		}
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis)
6637c478bd9Sstevel@tonic-gate 		    == -1) {
6647c478bd9Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: "
6657c478bd9Sstevel@tonic-gate 			    "%s", strerror(errno));
6661b22764fSDaniel OpenSolaris Anderson 			free_entry(pent);
6677c478bd9Sstevel@tonic-gate 			free(pload_soft_dis);
6687c478bd9Sstevel@tonic-gate 			(void) close(fd);
6697c478bd9Sstevel@tonic-gate 			return (FAILURE);
6707c478bd9Sstevel@tonic-gate 		}
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 		if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
6737c478bd9Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
6747c478bd9Sstevel@tonic-gate 			    "return_value = %d",
6757c478bd9Sstevel@tonic-gate 			    pload_soft_dis->sd_return_value);
6761b22764fSDaniel OpenSolaris Anderson 			free_entry(pent);
6777c478bd9Sstevel@tonic-gate 			free(pload_soft_dis);
6787c478bd9Sstevel@tonic-gate 			(void) close(fd);
6797c478bd9Sstevel@tonic-gate 			return (FAILURE);
6807c478bd9Sstevel@tonic-gate 		}
6817c478bd9Sstevel@tonic-gate 	}
6827c478bd9Sstevel@tonic-gate 
6831b22764fSDaniel OpenSolaris Anderson 	free_entry(pent);
6841b22764fSDaniel OpenSolaris Anderson 	free(pload_soft_dis);
6857c478bd9Sstevel@tonic-gate 	(void) close(fd);
6867c478bd9Sstevel@tonic-gate 	return (SUCCESS);
6877c478bd9Sstevel@tonic-gate }
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate /*
6917c478bd9Sstevel@tonic-gate  * Install a software module with the specified mechanism list into the system.
6927c478bd9Sstevel@tonic-gate  * This routine adds an entry into the config file for this software module
6937c478bd9Sstevel@tonic-gate  * first, then makes a CRYPTO_LOAD_SOFT_CONFIG ioctl call to inform kernel
6947c478bd9Sstevel@tonic-gate  * about the new addition.
6957c478bd9Sstevel@tonic-gate  */
6967c478bd9Sstevel@tonic-gate int
6977c478bd9Sstevel@tonic-gate install_kef(char *provname, mechlist_t *mlist)
6987c478bd9Sstevel@tonic-gate {
6997c478bd9Sstevel@tonic-gate 	crypto_load_soft_config_t	*pload_soft_conf = NULL;
7007c478bd9Sstevel@tonic-gate 	boolean_t			found;
7011b22764fSDaniel OpenSolaris Anderson 	entry_t				*pent = NULL;
7021b22764fSDaniel OpenSolaris Anderson 	FILE				*pfile = NULL;
7031b22764fSDaniel OpenSolaris Anderson 	FILE				*pfile_tmp = NULL;
7047c478bd9Sstevel@tonic-gate 	char				tmpfile_name[MAXPATHLEN];
7057c478bd9Sstevel@tonic-gate 	char				*ptr;
7067c478bd9Sstevel@tonic-gate 	char				*str;
7077c478bd9Sstevel@tonic-gate 	char				*name;
7087c478bd9Sstevel@tonic-gate 	char				buffer[BUFSIZ];
7097c478bd9Sstevel@tonic-gate 	char				buffer2[BUFSIZ];
7107c478bd9Sstevel@tonic-gate 	int				found_count;
7111b22764fSDaniel OpenSolaris Anderson 	int				fd = -1;
7127c478bd9Sstevel@tonic-gate 	int				rc = SUCCESS;
7131b22764fSDaniel OpenSolaris Anderson 	int				err;
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	if ((provname == NULL) || (mlist == NULL)) {
7167c478bd9Sstevel@tonic-gate 		return (FAILURE);
7177c478bd9Sstevel@tonic-gate 	}
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 	/* Check if the provider already exists */
720*d616ad8eSHai-May Chao 	if ((pent = getent_kef(provname, NULL, NULL)) != NULL) {
7217c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s exists already."),
7227c478bd9Sstevel@tonic-gate 		    provname);
7237c478bd9Sstevel@tonic-gate 		free_entry(pent);
7247c478bd9Sstevel@tonic-gate 		return (FAILURE);
7257c478bd9Sstevel@tonic-gate 	}
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 	/* Create an entry with provname and mlist. */
7281b22764fSDaniel OpenSolaris Anderson 	if ((pent = create_entry(provname)) == NULL) {
7297c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("out of memory."));
7307c478bd9Sstevel@tonic-gate 		return (FAILURE);
7317c478bd9Sstevel@tonic-gate 	}
7327c478bd9Sstevel@tonic-gate 	pent->sup_count = get_mech_count(mlist);
7337c478bd9Sstevel@tonic-gate 	pent->suplist = mlist;
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 	/* Append an entry for this software module to the kcf.conf file. */
7367c478bd9Sstevel@tonic-gate 	if ((str = ent2str(pent)) == NULL) {
7377c478bd9Sstevel@tonic-gate 		free_entry(pent);
7387c478bd9Sstevel@tonic-gate 		return (FAILURE);
7397c478bd9Sstevel@tonic-gate 	}
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
7427c478bd9Sstevel@tonic-gate 		err = errno;
7437c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
7447c478bd9Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
7457c478bd9Sstevel@tonic-gate 		    strerror(err));
7467c478bd9Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
7477c478bd9Sstevel@tonic-gate 		free_entry(pent);
7487c478bd9Sstevel@tonic-gate 		return (FAILURE);
7497c478bd9Sstevel@tonic-gate 	}
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
7527c478bd9Sstevel@tonic-gate 		err = errno;
7537c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
7547c478bd9Sstevel@tonic-gate 		    gettext("failed to lock the configuration - %s"),
7557c478bd9Sstevel@tonic-gate 		    strerror(err));
7567c478bd9Sstevel@tonic-gate 		free_entry(pent);
7577c478bd9Sstevel@tonic-gate 		(void) fclose(pfile);
7587c478bd9Sstevel@tonic-gate 		return (FAILURE);
7597c478bd9Sstevel@tonic-gate 	}
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	/*
7627c478bd9Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory.
7637c478bd9Sstevel@tonic-gate 	 */
7647c478bd9Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
7657c478bd9Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
7667c478bd9Sstevel@tonic-gate 		err = errno;
7677c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
7687c478bd9Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
7697c478bd9Sstevel@tonic-gate 		    strerror(err));
7707c478bd9Sstevel@tonic-gate 		free_entry(pent);
7717c478bd9Sstevel@tonic-gate 		(void) fclose(pfile);
7727c478bd9Sstevel@tonic-gate 		return (FAILURE);
7737c478bd9Sstevel@tonic-gate 	}
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
7767c478bd9Sstevel@tonic-gate 		err = errno;
7777c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
7787c478bd9Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
7797c478bd9Sstevel@tonic-gate 		free_entry(pent);
7807c478bd9Sstevel@tonic-gate 		(void) fclose(pfile);
7817c478bd9Sstevel@tonic-gate 		return (FAILURE);
7827c478bd9Sstevel@tonic-gate 	}
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 	/*
7867c478bd9Sstevel@tonic-gate 	 * Loop thru the config file. If the provider was reserved within a
7877c478bd9Sstevel@tonic-gate 	 * package bracket, just uncomment it.  Otherwise, append it at
7887c478bd9Sstevel@tonic-gate 	 * the end.  The resulting file will be saved in the temp file first.
7897c478bd9Sstevel@tonic-gate 	 */
7907c478bd9Sstevel@tonic-gate 	found_count = 0;
7917c478bd9Sstevel@tonic-gate 	rc = SUCCESS;
7927c478bd9Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
7937c478bd9Sstevel@tonic-gate 		found = B_FALSE;
7947c478bd9Sstevel@tonic-gate 		if (buffer[0] == '#') {
7957c478bd9Sstevel@tonic-gate 			(void) strlcpy(buffer2, buffer, BUFSIZ);
7967c478bd9Sstevel@tonic-gate 			ptr = buffer2;
7977c478bd9Sstevel@tonic-gate 			ptr++;
7987c478bd9Sstevel@tonic-gate 			if ((name = strtok(ptr, SEP_COLON)) == NULL) {
7997c478bd9Sstevel@tonic-gate 				rc = FAILURE;
8007c478bd9Sstevel@tonic-gate 				break;
8017c478bd9Sstevel@tonic-gate 			} else if (strcmp(provname, name) == 0) {
8027c478bd9Sstevel@tonic-gate 				found = B_TRUE;
8037c478bd9Sstevel@tonic-gate 				found_count++;
8047c478bd9Sstevel@tonic-gate 			}
8057c478bd9Sstevel@tonic-gate 		}
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 		if (found == B_FALSE) {
8087c478bd9Sstevel@tonic-gate 			if (fputs(buffer, pfile_tmp) == EOF) {
8097c478bd9Sstevel@tonic-gate 				rc = FAILURE;
8107c478bd9Sstevel@tonic-gate 			}
8117c478bd9Sstevel@tonic-gate 		} else {
8127c478bd9Sstevel@tonic-gate 			if (found_count == 1) {
8137c478bd9Sstevel@tonic-gate 				if (fputs(str, pfile_tmp) == EOF) {
8147c478bd9Sstevel@tonic-gate 					rc = FAILURE;
8157c478bd9Sstevel@tonic-gate 				}
8167c478bd9Sstevel@tonic-gate 			} else {
8177c478bd9Sstevel@tonic-gate 				/*
8187c478bd9Sstevel@tonic-gate 				 * Found a second entry with #libname.
8191b22764fSDaniel OpenSolaris Anderson 				 * Should not happen. The kcf.conf file
8207c478bd9Sstevel@tonic-gate 				 * is corrupted. Give a warning and skip
8217c478bd9Sstevel@tonic-gate 				 * this entry.
8227c478bd9Sstevel@tonic-gate 				 */
8237c478bd9Sstevel@tonic-gate 				cryptoerror(LOG_STDERR, gettext(
8247c478bd9Sstevel@tonic-gate 				    "(Warning) Found an additional reserved "
8257c478bd9Sstevel@tonic-gate 				    "entry for %s."), provname);
8267c478bd9Sstevel@tonic-gate 			}
8277c478bd9Sstevel@tonic-gate 		}
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 		if (rc == FAILURE) {
8307c478bd9Sstevel@tonic-gate 			break;
8317c478bd9Sstevel@tonic-gate 		}
8327c478bd9Sstevel@tonic-gate 	}
8337c478bd9Sstevel@tonic-gate 	(void) fclose(pfile);
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 	if (rc == FAILURE) {
8367c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("write error."));
8377c478bd9Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
8387c478bd9Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
8397c478bd9Sstevel@tonic-gate 			err = errno;
8407c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
8417c478bd9Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"), tmpfile_name,
8427c478bd9Sstevel@tonic-gate 			    strerror(err));
8437c478bd9Sstevel@tonic-gate 		}
8447c478bd9Sstevel@tonic-gate 		free_entry(pent);
8457c478bd9Sstevel@tonic-gate 		return (FAILURE);
8467c478bd9Sstevel@tonic-gate 	}
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	if (found_count == 0) {
8497c478bd9Sstevel@tonic-gate 		/*
8507c478bd9Sstevel@tonic-gate 		 * This libname was not in package before, append it to the
8517c478bd9Sstevel@tonic-gate 		 * end of the temp file.
8527c478bd9Sstevel@tonic-gate 		 */
8537c478bd9Sstevel@tonic-gate 		if (fputs(str, pfile_tmp) == EOF) {
8547c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
8557c478bd9Sstevel@tonic-gate 			    "failed to write to %s: %s"), tmpfile_name,
8567c478bd9Sstevel@tonic-gate 			    strerror(errno));
8577c478bd9Sstevel@tonic-gate 			(void) fclose(pfile_tmp);
8587c478bd9Sstevel@tonic-gate 			if (unlink(tmpfile_name) != 0) {
8597c478bd9Sstevel@tonic-gate 				err = errno;
8607c478bd9Sstevel@tonic-gate 				cryptoerror(LOG_STDERR, gettext(
8617c478bd9Sstevel@tonic-gate 				    "(Warning) failed to remove %s: %s"),
8627c478bd9Sstevel@tonic-gate 				    tmpfile_name, strerror(err));
8637c478bd9Sstevel@tonic-gate 			}
8647c478bd9Sstevel@tonic-gate 			free_entry(pent);
8657c478bd9Sstevel@tonic-gate 			return (FAILURE);
8667c478bd9Sstevel@tonic-gate 		}
8677c478bd9Sstevel@tonic-gate 	}
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
8707c478bd9Sstevel@tonic-gate 		err = errno;
8717c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8727c478bd9Sstevel@tonic-gate 		    gettext("failed to close %s: %s"), tmpfile_name,
8737c478bd9Sstevel@tonic-gate 		    strerror(err));
8741b22764fSDaniel OpenSolaris Anderson 		free_entry(pent);
8757c478bd9Sstevel@tonic-gate 		return (FAILURE);
8767c478bd9Sstevel@tonic-gate 	}
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
8797c478bd9Sstevel@tonic-gate 		err = errno;
8807c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8817c478bd9Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
8827c478bd9Sstevel@tonic-gate 		    strerror(err));
8837c478bd9Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
8847c478bd9Sstevel@tonic-gate 		    _PATH_KCF_CONF, strerror(err));
8857c478bd9Sstevel@tonic-gate 		rc = FAILURE;
8867c478bd9Sstevel@tonic-gate 	} else if (chmod(_PATH_KCF_CONF,
8877c478bd9Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
8887c478bd9Sstevel@tonic-gate 		err = errno;
8897c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8907c478bd9Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
8917c478bd9Sstevel@tonic-gate 		    strerror(err));
8927c478bd9Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
8937c478bd9Sstevel@tonic-gate 		    strerror(err));
8947c478bd9Sstevel@tonic-gate 		rc = FAILURE;
8957c478bd9Sstevel@tonic-gate 	} else {
8967c478bd9Sstevel@tonic-gate 		rc = SUCCESS;
8977c478bd9Sstevel@tonic-gate 	}
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 	if (rc == FAILURE) {
9007c478bd9Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
9017c478bd9Sstevel@tonic-gate 			err = errno;
9027c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
9037c478bd9Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
9047c478bd9Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
9057c478bd9Sstevel@tonic-gate 		}
9061b22764fSDaniel OpenSolaris Anderson 		free_entry(pent);
9077c478bd9Sstevel@tonic-gate 		return (FAILURE);
9087c478bd9Sstevel@tonic-gate 	}
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 	/* Inform kernel of this new software module. */
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate 	if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
9147c478bd9Sstevel@tonic-gate 		free_entry(pent);
9157c478bd9Sstevel@tonic-gate 		return (FAILURE);
9167c478bd9Sstevel@tonic-gate 	}
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
9197c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
9207c478bd9Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
9217c478bd9Sstevel@tonic-gate 		free_entry(pent);
9227c478bd9Sstevel@tonic-gate 		free(pload_soft_conf);
9237c478bd9Sstevel@tonic-gate 		return (FAILURE);
9247c478bd9Sstevel@tonic-gate 	}
9257c478bd9Sstevel@tonic-gate 
9267c478bd9Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) {
9277c478bd9Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
9287c478bd9Sstevel@tonic-gate 		    strerror(errno));
9297c478bd9Sstevel@tonic-gate 		free_entry(pent);
9307c478bd9Sstevel@tonic-gate 		free(pload_soft_conf);
9317c478bd9Sstevel@tonic-gate 		(void) close(fd);
9327c478bd9Sstevel@tonic-gate 		return (FAILURE);
9337c478bd9Sstevel@tonic-gate 	}
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 	if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
9367c478bd9Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed, "
9377c478bd9Sstevel@tonic-gate 		    "return_value = %d", pload_soft_conf->sc_return_value);
9387c478bd9Sstevel@tonic-gate 		free_entry(pent);
9397c478bd9Sstevel@tonic-gate 		free(pload_soft_conf);
9407c478bd9Sstevel@tonic-gate 		(void) close(fd);
9417c478bd9Sstevel@tonic-gate 		return (FAILURE);
9427c478bd9Sstevel@tonic-gate 	}
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 	free_entry(pent);
9457c478bd9Sstevel@tonic-gate 	free(pload_soft_conf);
9467c478bd9Sstevel@tonic-gate 	(void) close(fd);
9477c478bd9Sstevel@tonic-gate 	return (SUCCESS);
9487c478bd9Sstevel@tonic-gate }
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate /*
9517c478bd9Sstevel@tonic-gate  * Uninstall the software module. This routine first unloads the software
9527c478bd9Sstevel@tonic-gate  * module with 3 ioctl calls, then deletes its entry from the config file.
9537c478bd9Sstevel@tonic-gate  * Removing an entry from the config file needs to be done last to ensure
9547c478bd9Sstevel@tonic-gate  * that there is still an entry if the earlier unload failed for any reason.
9557c478bd9Sstevel@tonic-gate  */
9567c478bd9Sstevel@tonic-gate int
9577c478bd9Sstevel@tonic-gate uninstall_kef(char *provname)
9587c478bd9Sstevel@tonic-gate {
9591b22764fSDaniel OpenSolaris Anderson 	entry_t		*pent = NULL;
9607c478bd9Sstevel@tonic-gate 	int		rc = SUCCESS;
9611b22764fSDaniel OpenSolaris Anderson 	boolean_t	in_kernel = B_FALSE;
9621b22764fSDaniel OpenSolaris Anderson 	boolean_t	in_kcfconf = B_FALSE;
9631b22764fSDaniel OpenSolaris Anderson 	int		fd = -1;
9641b22764fSDaniel OpenSolaris Anderson 	crypto_load_soft_config_t *pload_soft_conf = NULL;
9657c478bd9Sstevel@tonic-gate 
9661b22764fSDaniel OpenSolaris Anderson 	/* Check to see if the provider exists first. */
9671b22764fSDaniel OpenSolaris Anderson 	if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
9681b22764fSDaniel OpenSolaris Anderson 		return (FAILURE);
9691b22764fSDaniel OpenSolaris Anderson 	} else if (in_kernel == B_FALSE) {
9701b22764fSDaniel OpenSolaris Anderson 		cryptoerror(LOG_STDERR, gettext("%s does not exist."),
9711b22764fSDaniel OpenSolaris Anderson 		    provname);
9727c478bd9Sstevel@tonic-gate 		return (FAILURE);
9737c478bd9Sstevel@tonic-gate 	}
9747c478bd9Sstevel@tonic-gate 
9751b22764fSDaniel OpenSolaris Anderson 	/*
9761b22764fSDaniel OpenSolaris Anderson 	 * If it is loaded, unload it first.  This does 2 ioctl calls:
9771b22764fSDaniel OpenSolaris Anderson 	 * CRYPTO_UNLOAD_SOFT_MODULE and CRYPTO_LOAD_SOFT_DISABLED.
9781b22764fSDaniel OpenSolaris Anderson 	 */
9791b22764fSDaniel OpenSolaris Anderson 	if (unload_kef_soft(provname) == FAILURE) {
9801b22764fSDaniel OpenSolaris Anderson 		cryptoerror(LOG_STDERR,
9811b22764fSDaniel OpenSolaris Anderson 		    gettext("failed to unload %s during uninstall.\n"),
9821b22764fSDaniel OpenSolaris Anderson 		    provname);
9831b22764fSDaniel OpenSolaris Anderson 		return (FAILURE);
9841b22764fSDaniel OpenSolaris Anderson 	}
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 	/*
9871b22764fSDaniel OpenSolaris Anderson 	 * Inform kernel to remove the configuration of this software module.
9887c478bd9Sstevel@tonic-gate 	 */
9891b22764fSDaniel OpenSolaris Anderson 
9901b22764fSDaniel OpenSolaris Anderson 	/* Setup ioctl() parameter */
991*d616ad8eSHai-May Chao 	pent = getent_kef(provname, NULL, NULL);
9921b22764fSDaniel OpenSolaris Anderson 	if (pent != NULL) { /* in kcf.conf */
9931b22764fSDaniel OpenSolaris Anderson 		in_kcfconf = B_TRUE;
9941b22764fSDaniel OpenSolaris Anderson 		free_mechlist(pent->suplist);
9951b22764fSDaniel OpenSolaris Anderson 		pent->suplist = NULL;
9961b22764fSDaniel OpenSolaris Anderson 		pent->sup_count = 0;
9971b22764fSDaniel OpenSolaris Anderson 	} else if ((pent = create_entry(provname)) == NULL) {
9981b22764fSDaniel OpenSolaris Anderson 		cryptoerror(LOG_STDERR, gettext("out of memory."));
9991b22764fSDaniel OpenSolaris Anderson 		return (FAILURE);
10001b22764fSDaniel OpenSolaris Anderson 	}
10011b22764fSDaniel OpenSolaris Anderson 	if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
10027c478bd9Sstevel@tonic-gate 		free_entry(pent);
10037c478bd9Sstevel@tonic-gate 		return (FAILURE);
10047c478bd9Sstevel@tonic-gate 	}
10057c478bd9Sstevel@tonic-gate 
10061b22764fSDaniel OpenSolaris Anderson 	/* Open the /dev/cryptoadm device */
10071b22764fSDaniel OpenSolaris Anderson 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
10081b22764fSDaniel OpenSolaris Anderson 		int	err = errno;
10091b22764fSDaniel OpenSolaris Anderson 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
10101b22764fSDaniel OpenSolaris Anderson 		    ADMIN_IOCTL_DEVICE, strerror(err));
10111b22764fSDaniel OpenSolaris Anderson 		free_entry(pent);
10121b22764fSDaniel OpenSolaris Anderson 		free(pload_soft_conf);
10137c478bd9Sstevel@tonic-gate 		return (FAILURE);
10147c478bd9Sstevel@tonic-gate 	}
10157c478bd9Sstevel@tonic-gate 
10161b22764fSDaniel OpenSolaris Anderson 	if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG,
10171b22764fSDaniel OpenSolaris Anderson 	    pload_soft_conf) == -1) {
10181b22764fSDaniel OpenSolaris Anderson 		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
10191b22764fSDaniel OpenSolaris Anderson 		    strerror(errno));
10201b22764fSDaniel OpenSolaris Anderson 		free_entry(pent);
10211b22764fSDaniel OpenSolaris Anderson 		free(pload_soft_conf);
10221b22764fSDaniel OpenSolaris Anderson 		(void) close(fd);
10237c478bd9Sstevel@tonic-gate 		return (FAILURE);
10247c478bd9Sstevel@tonic-gate 	}
10257c478bd9Sstevel@tonic-gate 
10261b22764fSDaniel OpenSolaris Anderson 	if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
10271b22764fSDaniel OpenSolaris Anderson 		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl = return_value = %d",
10281b22764fSDaniel OpenSolaris Anderson 		    pload_soft_conf->sc_return_value);
10291b22764fSDaniel OpenSolaris Anderson 		free_entry(pent);
10301b22764fSDaniel OpenSolaris Anderson 		free(pload_soft_conf);
10311b22764fSDaniel OpenSolaris Anderson 		(void) close(fd);
10327c478bd9Sstevel@tonic-gate 		return (FAILURE);
10337c478bd9Sstevel@tonic-gate 	}
10347c478bd9Sstevel@tonic-gate 
10351b22764fSDaniel OpenSolaris Anderson 	/* ioctl cleanup */
10361b22764fSDaniel OpenSolaris Anderson 	free(pload_soft_conf);
10371b22764fSDaniel OpenSolaris Anderson 	(void) close(fd);
10381b22764fSDaniel OpenSolaris Anderson 
10391b22764fSDaniel OpenSolaris Anderson 
10401b22764fSDaniel OpenSolaris Anderson 	/* Finally, remove entry from kcf.conf, if present */
10411b22764fSDaniel OpenSolaris Anderson 	if (in_kcfconf && (pent != NULL)) {
10421b22764fSDaniel OpenSolaris Anderson 		rc = update_kcfconf(pent, DELETE_MODE);
10437c478bd9Sstevel@tonic-gate 	}
10447c478bd9Sstevel@tonic-gate 
10451b22764fSDaniel OpenSolaris Anderson 	free_entry(pent);
10467c478bd9Sstevel@tonic-gate 	return (rc);
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 
10501b22764fSDaniel OpenSolaris Anderson /*
10511b22764fSDaniel OpenSolaris Anderson  * Implement the "cryptoadm refresh" command for global zones.
10521b22764fSDaniel OpenSolaris Anderson  * That is, send the current contents of kcf.conf to the kernel via ioctl().
10531b22764fSDaniel OpenSolaris Anderson  */
10547c478bd9Sstevel@tonic-gate int
10557c478bd9Sstevel@tonic-gate refresh(void)
10567c478bd9Sstevel@tonic-gate {
10577c478bd9Sstevel@tonic-gate 	crypto_load_soft_config_t	*pload_soft_conf = NULL;
10587c478bd9Sstevel@tonic-gate 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
10597c478bd9Sstevel@tonic-gate 	crypto_load_dev_disabled_t	*pload_dev_dis = NULL;
10607c478bd9Sstevel@tonic-gate 	entrylist_t			*pdevlist = NULL;
10617c478bd9Sstevel@tonic-gate 	entrylist_t			*psoftlist = NULL;
10627c478bd9Sstevel@tonic-gate 	entrylist_t			*ptr;
10631b22764fSDaniel OpenSolaris Anderson 	int				fd = -1;
10647c478bd9Sstevel@tonic-gate 	int				rc = SUCCESS;
10651b22764fSDaniel OpenSolaris Anderson 	int				err;
10667c478bd9Sstevel@tonic-gate 
1067*d616ad8eSHai-May Chao 	if (get_kcfconf_info(&pdevlist, &psoftlist) == FAILURE) {
10687c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "failed to retrieve the providers' "
10697c478bd9Sstevel@tonic-gate 		    "information from the configuration file - %s.",
10707c478bd9Sstevel@tonic-gate 		    _PATH_KCF_CONF);
10717c478bd9Sstevel@tonic-gate 		return (FAILURE);
10727c478bd9Sstevel@tonic-gate 	}
10737c478bd9Sstevel@tonic-gate 
10747c478bd9Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
10757c478bd9Sstevel@tonic-gate 		err = errno;
10767c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
10777c478bd9Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(err));
10787c478bd9Sstevel@tonic-gate 		free(psoftlist);
10797c478bd9Sstevel@tonic-gate 		free(pdevlist);
10807c478bd9Sstevel@tonic-gate 		return (FAILURE);
10817c478bd9Sstevel@tonic-gate 	}
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 	/*
10841b22764fSDaniel OpenSolaris Anderson 	 * For each software provider module, pass two sets of information to
10851b22764fSDaniel OpenSolaris Anderson 	 * the kernel: the supported list and the disabled list.
10867c478bd9Sstevel@tonic-gate 	 */
10871b22764fSDaniel OpenSolaris Anderson 	for (ptr = psoftlist; ptr != NULL; ptr = ptr->next) {
10881b22764fSDaniel OpenSolaris Anderson 		entry_t		*pent = ptr->pent;
10891b22764fSDaniel OpenSolaris Anderson 
10907c478bd9Sstevel@tonic-gate 		/* load the supported list */
10911b22764fSDaniel OpenSolaris Anderson 		if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
10921b22764fSDaniel OpenSolaris Anderson 			cryptodebug("setup_soft_conf() failed");
10937c478bd9Sstevel@tonic-gate 			rc = FAILURE;
10947c478bd9Sstevel@tonic-gate 			break;
10957c478bd9Sstevel@tonic-gate 		}
10967c478bd9Sstevel@tonic-gate 
10971b22764fSDaniel OpenSolaris Anderson 		if (!pent->load) { /* unloaded--mark as loaded */
10981b22764fSDaniel OpenSolaris Anderson 			pent->load = B_TRUE;
10991b22764fSDaniel OpenSolaris Anderson 			rc = update_kcfconf(pent, MODIFY_MODE);
11001b22764fSDaniel OpenSolaris Anderson 			if (rc != SUCCESS) {
11011b22764fSDaniel OpenSolaris Anderson 				free(pload_soft_conf);
11021b22764fSDaniel OpenSolaris Anderson 				break;
11031b22764fSDaniel OpenSolaris Anderson 			}
11041b22764fSDaniel OpenSolaris Anderson 		}
11051b22764fSDaniel OpenSolaris Anderson 
11067c478bd9Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf)
11077c478bd9Sstevel@tonic-gate 		    == -1) {
11087c478bd9Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
11097c478bd9Sstevel@tonic-gate 			    strerror(errno));
11107c478bd9Sstevel@tonic-gate 			free(pload_soft_conf);
11117c478bd9Sstevel@tonic-gate 			rc = FAILURE;
11127c478bd9Sstevel@tonic-gate 			break;
11137c478bd9Sstevel@tonic-gate 		}
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 		if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
11167c478bd9Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl "
11177c478bd9Sstevel@tonic-gate 			    "return_value = %d",
11187c478bd9Sstevel@tonic-gate 			    pload_soft_conf->sc_return_value);
11197c478bd9Sstevel@tonic-gate 			free(pload_soft_conf);
11207c478bd9Sstevel@tonic-gate 			rc = FAILURE;
11217c478bd9Sstevel@tonic-gate 			break;
11227c478bd9Sstevel@tonic-gate 		}
11237c478bd9Sstevel@tonic-gate 
11241b22764fSDaniel OpenSolaris Anderson 		free(pload_soft_conf);
11251b22764fSDaniel OpenSolaris Anderson 
11267c478bd9Sstevel@tonic-gate 		/* load the disabled list */
11277c478bd9Sstevel@tonic-gate 		if (ptr->pent->dis_count != 0) {
11287c478bd9Sstevel@tonic-gate 			pload_soft_dis = setup_soft_dis(ptr->pent);
11297c478bd9Sstevel@tonic-gate 			if (pload_soft_dis == NULL) {
11301b22764fSDaniel OpenSolaris Anderson 				cryptodebug("setup_soft_dis() failed");
11311b22764fSDaniel OpenSolaris Anderson 				free(pload_soft_dis);
11327c478bd9Sstevel@tonic-gate 				rc = FAILURE;
11337c478bd9Sstevel@tonic-gate 				break;
11347c478bd9Sstevel@tonic-gate 			}
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate 			if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED,
11377c478bd9Sstevel@tonic-gate 			    pload_soft_dis) == -1) {
11387c478bd9Sstevel@tonic-gate 				cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
11397c478bd9Sstevel@tonic-gate 				    "failed: %s", strerror(errno));
11407c478bd9Sstevel@tonic-gate 				free(pload_soft_dis);
11417c478bd9Sstevel@tonic-gate 				rc = FAILURE;
11427c478bd9Sstevel@tonic-gate 				break;
11437c478bd9Sstevel@tonic-gate 			}
11447c478bd9Sstevel@tonic-gate 
11457c478bd9Sstevel@tonic-gate 			if (pload_soft_dis->sd_return_value !=
11467c478bd9Sstevel@tonic-gate 			    CRYPTO_SUCCESS) {
11477c478bd9Sstevel@tonic-gate 				cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
11487c478bd9Sstevel@tonic-gate 				    "return_value = %d",
11497c478bd9Sstevel@tonic-gate 				    pload_soft_dis->sd_return_value);
11507c478bd9Sstevel@tonic-gate 				free(pload_soft_dis);
11517c478bd9Sstevel@tonic-gate 				rc = FAILURE;
11527c478bd9Sstevel@tonic-gate 				break;
11537c478bd9Sstevel@tonic-gate 			}
11547c478bd9Sstevel@tonic-gate 			free(pload_soft_dis);
11557c478bd9Sstevel@tonic-gate 		}
11567c478bd9Sstevel@tonic-gate 	}
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate 	if (rc != SUCCESS) {
11597c478bd9Sstevel@tonic-gate 		(void) close(fd);
11607c478bd9Sstevel@tonic-gate 		return (rc);
11617c478bd9Sstevel@tonic-gate 	}
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 
11641b22764fSDaniel OpenSolaris Anderson 	/*
11651b22764fSDaniel OpenSolaris Anderson 	 * For each hardware provider module, pass the disabled list
11661b22764fSDaniel OpenSolaris Anderson 	 * information to the kernel.
11671b22764fSDaniel OpenSolaris Anderson 	 */
11681b22764fSDaniel OpenSolaris Anderson 	for (ptr = pdevlist; ptr != NULL; ptr = ptr->next) {
11697c478bd9Sstevel@tonic-gate 		/* load the disabled list */
11707c478bd9Sstevel@tonic-gate 		if (ptr->pent->dis_count != 0) {
11717c478bd9Sstevel@tonic-gate 			pload_dev_dis = setup_dev_dis(ptr->pent);
11727c478bd9Sstevel@tonic-gate 			if (pload_dev_dis == NULL) {
11737c478bd9Sstevel@tonic-gate 				rc = FAILURE;
11747c478bd9Sstevel@tonic-gate 				break;
11757c478bd9Sstevel@tonic-gate 			}
11767c478bd9Sstevel@tonic-gate 
11777c478bd9Sstevel@tonic-gate 			if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis)
11787c478bd9Sstevel@tonic-gate 			    == -1) {
11797c478bd9Sstevel@tonic-gate 				cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
11807c478bd9Sstevel@tonic-gate 				    "failed: %s", strerror(errno));
11817c478bd9Sstevel@tonic-gate 				free(pload_dev_dis);
11827c478bd9Sstevel@tonic-gate 				rc = FAILURE;
11837c478bd9Sstevel@tonic-gate 				break;
11847c478bd9Sstevel@tonic-gate 			}
11857c478bd9Sstevel@tonic-gate 
11867c478bd9Sstevel@tonic-gate 			if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
11877c478bd9Sstevel@tonic-gate 				cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
11887c478bd9Sstevel@tonic-gate 				    "return_value = %d",
11897c478bd9Sstevel@tonic-gate 				    pload_dev_dis->dd_return_value);
11907c478bd9Sstevel@tonic-gate 				free(pload_dev_dis);
11917c478bd9Sstevel@tonic-gate 				rc = FAILURE;
11927c478bd9Sstevel@tonic-gate 				break;
11937c478bd9Sstevel@tonic-gate 			}
11947c478bd9Sstevel@tonic-gate 			free(pload_dev_dis);
11957c478bd9Sstevel@tonic-gate 		}
11967c478bd9Sstevel@tonic-gate 	}
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate 	(void) close(fd);
11997c478bd9Sstevel@tonic-gate 	return (rc);
12007c478bd9Sstevel@tonic-gate }
12017c478bd9Sstevel@tonic-gate 
12027c478bd9Sstevel@tonic-gate /*
12037c478bd9Sstevel@tonic-gate  * Unload the kernel software provider. Before calling this function, the
12041b22764fSDaniel OpenSolaris Anderson  * caller should check to see if the provider is in the kernel.
12051b22764fSDaniel OpenSolaris Anderson  *
12061b22764fSDaniel OpenSolaris Anderson  * This routine makes 2 ioctl calls to remove it completely from the kernel:
12071b22764fSDaniel OpenSolaris Anderson  *	CRYPTO_UNLOAD_SOFT_MODULE - does a modunload of the KCF module
12081b22764fSDaniel OpenSolaris Anderson  *	CRYPTO_LOAD_SOFT_DISABLED - updates kernel disabled mechanism list
12091b22764fSDaniel OpenSolaris Anderson  *
12101b22764fSDaniel OpenSolaris Anderson  * This implements part of "cryptoadm unload" and "cryptoadm uninstall".
12117c478bd9Sstevel@tonic-gate  */
12127c478bd9Sstevel@tonic-gate int
12131b22764fSDaniel OpenSolaris Anderson unload_kef_soft(char *provname)
12147c478bd9Sstevel@tonic-gate {
12157c478bd9Sstevel@tonic-gate 	crypto_unload_soft_module_t	*punload_soft = NULL;
12167c478bd9Sstevel@tonic-gate 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
12177c478bd9Sstevel@tonic-gate 	entry_t				*pent = NULL;
12181b22764fSDaniel OpenSolaris Anderson 	int				fd = -1;
12191b22764fSDaniel OpenSolaris Anderson 	int				err;
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate 	if (provname == NULL) {
12227c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
12237c478bd9Sstevel@tonic-gate 		return (FAILURE);
12247c478bd9Sstevel@tonic-gate 	}
12257c478bd9Sstevel@tonic-gate 
1226*d616ad8eSHai-May Chao 	pent = getent_kef(provname, NULL, NULL);
12271b22764fSDaniel OpenSolaris Anderson 	if (pent == NULL) { /* not in kcf.conf */
1228b8bf75cbSkrishna 		/* Construct an entry using the provname */
12291b22764fSDaniel OpenSolaris Anderson 		pent = create_entry(provname);
1230b8bf75cbSkrishna 		if (pent == NULL) {
1231b8bf75cbSkrishna 			cryptoerror(LOG_STDERR, gettext("out of memory."));
1232b8bf75cbSkrishna 			return (FAILURE);
1233b8bf75cbSkrishna 		}
12347c478bd9Sstevel@tonic-gate 	}
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate 	/* Open the admin_ioctl_device */
12377c478bd9Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
12387c478bd9Sstevel@tonic-gate 		err = errno;
12397c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
12407c478bd9Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(err));
12411b22764fSDaniel OpenSolaris Anderson 		free_entry(pent);
12427c478bd9Sstevel@tonic-gate 		return (FAILURE);
12437c478bd9Sstevel@tonic-gate 	}
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate 	/* Inform kernel to unload this software module */
12467c478bd9Sstevel@tonic-gate 	if ((punload_soft = setup_unload_soft(pent)) == NULL) {
12471b22764fSDaniel OpenSolaris Anderson 		free_entry(pent);
12487c478bd9Sstevel@tonic-gate 		(void) close(fd);
12497c478bd9Sstevel@tonic-gate 		return (FAILURE);
12507c478bd9Sstevel@tonic-gate 	}
12517c478bd9Sstevel@tonic-gate 
12527c478bd9Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_UNLOAD_SOFT_MODULE, punload_soft) == -1) {
12537c478bd9Sstevel@tonic-gate 		cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s",
12547c478bd9Sstevel@tonic-gate 		    strerror(errno));
12557c478bd9Sstevel@tonic-gate 		free_entry(pent);
12567c478bd9Sstevel@tonic-gate 		free(punload_soft);
12577c478bd9Sstevel@tonic-gate 		(void) close(fd);
12587c478bd9Sstevel@tonic-gate 		return (FAILURE);
12597c478bd9Sstevel@tonic-gate 	}
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate 	if (punload_soft->sm_return_value != CRYPTO_SUCCESS) {
12627c478bd9Sstevel@tonic-gate 		cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl return_value = "
12637c478bd9Sstevel@tonic-gate 		    "%d", punload_soft->sm_return_value);
12647c478bd9Sstevel@tonic-gate 		/*
12650a85b835SDaniel Anderson 		 * If the return value is CRYPTO_UNKNOWN_PROVIDER, it means
12667c478bd9Sstevel@tonic-gate 		 * that the provider is not registered yet.  Should just
12677c478bd9Sstevel@tonic-gate 		 * continue.
12687c478bd9Sstevel@tonic-gate 		 */
12697c478bd9Sstevel@tonic-gate 		if (punload_soft->sm_return_value != CRYPTO_UNKNOWN_PROVIDER) {
12707c478bd9Sstevel@tonic-gate 			free_entry(pent);
12717c478bd9Sstevel@tonic-gate 			free(punload_soft);
12727c478bd9Sstevel@tonic-gate 			(void) close(fd);
12737c478bd9Sstevel@tonic-gate 			return (FAILURE);
12747c478bd9Sstevel@tonic-gate 		}
12757c478bd9Sstevel@tonic-gate 	}
12767c478bd9Sstevel@tonic-gate 
12777c478bd9Sstevel@tonic-gate 	free(punload_soft);
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate 	/* Inform kernel to remove the disabled entries if any */
12807c478bd9Sstevel@tonic-gate 	if (pent->dis_count == 0) {
12817c478bd9Sstevel@tonic-gate 		free_entry(pent);
12827c478bd9Sstevel@tonic-gate 		(void) close(fd);
12837c478bd9Sstevel@tonic-gate 		return (SUCCESS);
12847c478bd9Sstevel@tonic-gate 	} else {
12857c478bd9Sstevel@tonic-gate 		free_mechlist(pent->dislist);
12867c478bd9Sstevel@tonic-gate 		pent->dislist = NULL;
12877c478bd9Sstevel@tonic-gate 		pent->dis_count = 0;
12887c478bd9Sstevel@tonic-gate 	}
12897c478bd9Sstevel@tonic-gate 
12907c478bd9Sstevel@tonic-gate 	if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
12917c478bd9Sstevel@tonic-gate 		free_entry(pent);
12927c478bd9Sstevel@tonic-gate 		(void) close(fd);
12937c478bd9Sstevel@tonic-gate 		return (FAILURE);
12947c478bd9Sstevel@tonic-gate 	}
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate 	/* pent is no longer needed; free it */
12977c478bd9Sstevel@tonic-gate 	free_entry(pent);
12987c478bd9Sstevel@tonic-gate 
12997c478bd9Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) {
13007c478bd9Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
13017c478bd9Sstevel@tonic-gate 		    strerror(errno));
13027c478bd9Sstevel@tonic-gate 		free(pload_soft_dis);
13037c478bd9Sstevel@tonic-gate 		(void) close(fd);
13047c478bd9Sstevel@tonic-gate 		return (FAILURE);
13057c478bd9Sstevel@tonic-gate 	}
13067c478bd9Sstevel@tonic-gate 
13077c478bd9Sstevel@tonic-gate 	if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
13087c478bd9Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
13097c478bd9Sstevel@tonic-gate 		    "%d", pload_soft_dis->sd_return_value);
13107c478bd9Sstevel@tonic-gate 		free(pload_soft_dis);
13117c478bd9Sstevel@tonic-gate 		(void) close(fd);
13127c478bd9Sstevel@tonic-gate 		return (FAILURE);
13137c478bd9Sstevel@tonic-gate 	}
13147c478bd9Sstevel@tonic-gate 
13157c478bd9Sstevel@tonic-gate 	free(pload_soft_dis);
13167c478bd9Sstevel@tonic-gate 	(void) close(fd);
13177c478bd9Sstevel@tonic-gate 	return (SUCCESS);
13187c478bd9Sstevel@tonic-gate }
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate 
13217c478bd9Sstevel@tonic-gate /*
13227c478bd9Sstevel@tonic-gate  * Check if a hardware provider is valid.  If it is valid, returns its device
13237c478bd9Sstevel@tonic-gate  * name,  instance number and the number of mechanisms it supports.
13247c478bd9Sstevel@tonic-gate  */
13257c478bd9Sstevel@tonic-gate static int
13267c478bd9Sstevel@tonic-gate check_hardware_provider(char *provname, char *pname, int *pnum, int *pcount)
13277c478bd9Sstevel@tonic-gate {
13287c478bd9Sstevel@tonic-gate 	crypto_get_dev_list_t *dev_list = NULL;
13297c478bd9Sstevel@tonic-gate 	int	i;
13307c478bd9Sstevel@tonic-gate 
13317c478bd9Sstevel@tonic-gate 	if (provname == NULL) {
13327c478bd9Sstevel@tonic-gate 		return (FAILURE);
13337c478bd9Sstevel@tonic-gate 	}
13347c478bd9Sstevel@tonic-gate 
13357c478bd9Sstevel@tonic-gate 	/* First, get the device name and the instance number from provname */
13367c478bd9Sstevel@tonic-gate 	if (split_hw_provname(provname, pname, pnum) == FAILURE) {
13377c478bd9Sstevel@tonic-gate 		return (FAILURE);
13387c478bd9Sstevel@tonic-gate 	}
13397c478bd9Sstevel@tonic-gate 
13407c478bd9Sstevel@tonic-gate 	/*
13417c478bd9Sstevel@tonic-gate 	 * Get the complete device list from kernel and check if this provider
13427c478bd9Sstevel@tonic-gate 	 * is in the list.
13437c478bd9Sstevel@tonic-gate 	 */
13447c478bd9Sstevel@tonic-gate 	if (get_dev_list(&dev_list) == FAILURE) {
13457c478bd9Sstevel@tonic-gate 		return (FAILURE);
13467c478bd9Sstevel@tonic-gate 	}
13477c478bd9Sstevel@tonic-gate 
13487c478bd9Sstevel@tonic-gate 	for (i = 0; i < dev_list->dl_dev_count; i++) {
13497c478bd9Sstevel@tonic-gate 		if ((strcmp(dev_list->dl_devs[i].le_dev_name, pname) == 0) &&
13507c478bd9Sstevel@tonic-gate 		    (dev_list->dl_devs[i].le_dev_instance == *pnum)) {
13517c478bd9Sstevel@tonic-gate 			break;
13527c478bd9Sstevel@tonic-gate 		}
13537c478bd9Sstevel@tonic-gate 	}
13547c478bd9Sstevel@tonic-gate 
13557c478bd9Sstevel@tonic-gate 	if (i == dev_list->dl_dev_count) {
13567c478bd9Sstevel@tonic-gate 		/* didn't find this provider in the kernel device list */
13577c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s does not exist."),
13587c478bd9Sstevel@tonic-gate 		    provname);
13597c478bd9Sstevel@tonic-gate 		free(dev_list);
13607c478bd9Sstevel@tonic-gate 		return (FAILURE);
13617c478bd9Sstevel@tonic-gate 	}
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate 	/* This provider is valid.  Get its mechanism count */
13647c478bd9Sstevel@tonic-gate 	*pcount = dev_list->dl_devs[i].le_mechanism_count;
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 	free(dev_list);
13677c478bd9Sstevel@tonic-gate 	return (SUCCESS);
13687c478bd9Sstevel@tonic-gate }
1369