1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <fcntl.h>
30*0Sstevel@tonic-gate #include <stdio.h>
31*0Sstevel@tonic-gate #include <stdlib.h>
32*0Sstevel@tonic-gate #include <strings.h>
33*0Sstevel@tonic-gate #include <unistd.h>
34*0Sstevel@tonic-gate #include <locale.h>
35*0Sstevel@tonic-gate #include <libgen.h>
36*0Sstevel@tonic-gate #include <sys/types.h>
37*0Sstevel@tonic-gate #include <sys/stat.h>
38*0Sstevel@tonic-gate #include <sys/crypto/ioctladmin.h>
39*0Sstevel@tonic-gate #include <signal.h>
40*0Sstevel@tonic-gate #include <sys/crypto/elfsign.h>
41*0Sstevel@tonic-gate #include "cryptoadm.h"
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate static int err; /* to store the value of errno in case being overwritten */
44*0Sstevel@tonic-gate static int check_hardware_provider(char *, char *, int *, int *);
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate /*
47*0Sstevel@tonic-gate  * Display the mechanism list for a kernel software provider.
48*0Sstevel@tonic-gate  */
49*0Sstevel@tonic-gate int
50*0Sstevel@tonic-gate list_mechlist_for_soft(char *provname)
51*0Sstevel@tonic-gate {
52*0Sstevel@tonic-gate 	mechlist_t *pmechlist;
53*0Sstevel@tonic-gate 	int rc;
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate 	if (provname == NULL) {
56*0Sstevel@tonic-gate 		return (FAILURE);
57*0Sstevel@tonic-gate 	}
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate 	rc = get_soft_info(provname, &pmechlist);
60*0Sstevel@tonic-gate 	if (rc == SUCCESS) {
61*0Sstevel@tonic-gate 		(void) filter_mechlist(&pmechlist, RANDOM);
62*0Sstevel@tonic-gate 		print_mechlist(provname, pmechlist);
63*0Sstevel@tonic-gate 		free_mechlist(pmechlist);
64*0Sstevel@tonic-gate 	} else {
65*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
66*0Sstevel@tonic-gate 		    "failed to retrieve the mechanism list for %s."),
67*0Sstevel@tonic-gate 		    provname);
68*0Sstevel@tonic-gate 	}
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate 	return (rc);
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate }
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate /*
75*0Sstevel@tonic-gate  * Display the mechanism list for a kernel hardware provider.
76*0Sstevel@tonic-gate  */
77*0Sstevel@tonic-gate int
78*0Sstevel@tonic-gate list_mechlist_for_hard(char *provname)
79*0Sstevel@tonic-gate {
80*0Sstevel@tonic-gate 	mechlist_t *pmechlist;
81*0Sstevel@tonic-gate 	char	devname[MAXNAMELEN];
82*0Sstevel@tonic-gate 	int	inst_num;
83*0Sstevel@tonic-gate 	int	count;
84*0Sstevel@tonic-gate 	int rc = SUCCESS;
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate 	if (provname == NULL) {
87*0Sstevel@tonic-gate 		return (FAILURE);
88*0Sstevel@tonic-gate 	}
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate 	/*
91*0Sstevel@tonic-gate 	 * Check if the provider is valid. If it is valid, get the number of
92*0Sstevel@tonic-gate 	 * mechanisms also.
93*0Sstevel@tonic-gate 	 */
94*0Sstevel@tonic-gate 	if (check_hardware_provider(provname, devname, &inst_num, &count) ==
95*0Sstevel@tonic-gate 	    FAILURE) {
96*0Sstevel@tonic-gate 		return (FAILURE);
97*0Sstevel@tonic-gate 	}
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	/* Get the mechanism list for the kernel hardware provider */
100*0Sstevel@tonic-gate 	if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) ==
101*0Sstevel@tonic-gate 	    SUCCESS) {
102*0Sstevel@tonic-gate 		(void) filter_mechlist(&pmechlist, RANDOM);
103*0Sstevel@tonic-gate 		print_mechlist(provname, pmechlist);
104*0Sstevel@tonic-gate 		free_mechlist(pmechlist);
105*0Sstevel@tonic-gate 	}
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate 	return (rc);
108*0Sstevel@tonic-gate }
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate /*
112*0Sstevel@tonic-gate  * Display the policy information for a kernel software provider.
113*0Sstevel@tonic-gate  */
114*0Sstevel@tonic-gate int
115*0Sstevel@tonic-gate list_policy_for_soft(char *provname)
116*0Sstevel@tonic-gate {
117*0Sstevel@tonic-gate 	int rc;
118*0Sstevel@tonic-gate 	entry_t *pent = NULL;
119*0Sstevel@tonic-gate 	mechlist_t *pmechlist;
120*0Sstevel@tonic-gate 	boolean_t has_random = B_FALSE;
121*0Sstevel@tonic-gate 	boolean_t has_mechs = B_FALSE;
122*0Sstevel@tonic-gate 
123*0Sstevel@tonic-gate 	if (provname == NULL) {
124*0Sstevel@tonic-gate 		return (FAILURE);
125*0Sstevel@tonic-gate 	}
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) == NULL) {
128*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s does not exist."),
129*0Sstevel@tonic-gate 		    provname);
130*0Sstevel@tonic-gate 		return (FAILURE);
131*0Sstevel@tonic-gate 	}
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 	rc = get_soft_info(provname, &pmechlist);
134*0Sstevel@tonic-gate 	if (rc == SUCCESS) {
135*0Sstevel@tonic-gate 		has_random = filter_mechlist(&pmechlist, RANDOM);
136*0Sstevel@tonic-gate 		if (pmechlist != NULL) {
137*0Sstevel@tonic-gate 			has_mechs = B_TRUE;
138*0Sstevel@tonic-gate 			free_mechlist(pmechlist);
139*0Sstevel@tonic-gate 		}
140*0Sstevel@tonic-gate 	} else {
141*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
142*0Sstevel@tonic-gate 		    "failed to retrieve the mechanism list for %s."),
143*0Sstevel@tonic-gate 		    provname);
144*0Sstevel@tonic-gate 		return (rc);
145*0Sstevel@tonic-gate 	}
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate 	print_kef_policy(pent, has_random, has_mechs);
148*0Sstevel@tonic-gate 	free_entry(pent);
149*0Sstevel@tonic-gate 	return (SUCCESS);
150*0Sstevel@tonic-gate }
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate /*
155*0Sstevel@tonic-gate  * Display the policy information for a kernel hardware provider.
156*0Sstevel@tonic-gate  */
157*0Sstevel@tonic-gate int
158*0Sstevel@tonic-gate list_policy_for_hard(char *provname)
159*0Sstevel@tonic-gate {
160*0Sstevel@tonic-gate 	entry_t *pent;
161*0Sstevel@tonic-gate 	boolean_t is_active;
162*0Sstevel@tonic-gate 	mechlist_t *pmechlist;
163*0Sstevel@tonic-gate 	char	devname[MAXNAMELEN];
164*0Sstevel@tonic-gate 	int	inst_num;
165*0Sstevel@tonic-gate 	int	count;
166*0Sstevel@tonic-gate 	int rc = SUCCESS;
167*0Sstevel@tonic-gate 	boolean_t has_random = B_FALSE;
168*0Sstevel@tonic-gate 	boolean_t has_mechs = B_FALSE;
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 	if (provname == NULL) {
171*0Sstevel@tonic-gate 		return (FAILURE);
172*0Sstevel@tonic-gate 	}
173*0Sstevel@tonic-gate 
174*0Sstevel@tonic-gate 	/*
175*0Sstevel@tonic-gate 	 * Check if the provider is valid. If it is valid, get the number of
176*0Sstevel@tonic-gate 	 * mechanisms also.
177*0Sstevel@tonic-gate 	 */
178*0Sstevel@tonic-gate 	if (check_hardware_provider(provname, devname, &inst_num, &count) ==
179*0Sstevel@tonic-gate 	    FAILURE) {
180*0Sstevel@tonic-gate 		return (FAILURE);
181*0Sstevel@tonic-gate 	}
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 	/* Get the mechanism list for the kernel hardware provider */
184*0Sstevel@tonic-gate 	if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) ==
185*0Sstevel@tonic-gate 	    SUCCESS) {
186*0Sstevel@tonic-gate 		has_random = filter_mechlist(&pmechlist, RANDOM);
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 		if (pmechlist != NULL) {
189*0Sstevel@tonic-gate 			has_mechs = B_TRUE;
190*0Sstevel@tonic-gate 			free_mechlist(pmechlist);
191*0Sstevel@tonic-gate 		}
192*0Sstevel@tonic-gate 	} else {
193*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
194*0Sstevel@tonic-gate 		    "failed to retrieve the mechanism list for %s."),
195*0Sstevel@tonic-gate 		    devname);
196*0Sstevel@tonic-gate 		return (rc);
197*0Sstevel@tonic-gate 	}
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 	/*
200*0Sstevel@tonic-gate 	 * If the hardware provider has an entry in the kcf.conf file,
201*0Sstevel@tonic-gate 	 * some of its mechanisms must have been disabled.  Print out
202*0Sstevel@tonic-gate 	 * the disabled list from the config file entry.  Otherwise,
203*0Sstevel@tonic-gate 	 * if it is active, then all the mechanisms for it are enabled.
204*0Sstevel@tonic-gate 	 */
205*0Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) != NULL) {
206*0Sstevel@tonic-gate 		print_kef_policy(pent, has_random, has_mechs);
207*0Sstevel@tonic-gate 		free_entry(pent);
208*0Sstevel@tonic-gate 		return (SUCCESS);
209*0Sstevel@tonic-gate 	} else {
210*0Sstevel@tonic-gate 		if (check_active_for_hard(provname, &is_active) ==
211*0Sstevel@tonic-gate 		    FAILURE) {
212*0Sstevel@tonic-gate 			return (FAILURE);
213*0Sstevel@tonic-gate 		} else if (is_active == B_TRUE) {
214*0Sstevel@tonic-gate 			(void) printf(gettext(
215*0Sstevel@tonic-gate 			    "%s: all mechanisms are enabled."), provname);
216*0Sstevel@tonic-gate 			if (has_random)
217*0Sstevel@tonic-gate 				/*
218*0Sstevel@tonic-gate 				 * TRANSLATION_NOTE:
219*0Sstevel@tonic-gate 				 * "random" is a keyword and not to be
220*0Sstevel@tonic-gate 				 * translated.
221*0Sstevel@tonic-gate 				 */
222*0Sstevel@tonic-gate 				(void) printf(gettext(" %s is enabled.\n"),
223*0Sstevel@tonic-gate 				    "random");
224*0Sstevel@tonic-gate 			else
225*0Sstevel@tonic-gate 				(void) printf("\n");
226*0Sstevel@tonic-gate 			return (SUCCESS);
227*0Sstevel@tonic-gate 		} else {
228*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR,
229*0Sstevel@tonic-gate 			    gettext("%s does not exist."), provname);
230*0Sstevel@tonic-gate 			return (FAILURE);
231*0Sstevel@tonic-gate 		}
232*0Sstevel@tonic-gate 	}
233*0Sstevel@tonic-gate }
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate int
238*0Sstevel@tonic-gate disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag,
239*0Sstevel@tonic-gate     mechlist_t *dislist)
240*0Sstevel@tonic-gate {
241*0Sstevel@tonic-gate 	crypto_load_dev_disabled_t	*pload_dev_dis;
242*0Sstevel@tonic-gate 	mechlist_t 	*infolist;
243*0Sstevel@tonic-gate 	entry_t		*pent;
244*0Sstevel@tonic-gate 	boolean_t	new_dev_entry = B_FALSE;
245*0Sstevel@tonic-gate 	char	devname[MAXNAMELEN];
246*0Sstevel@tonic-gate 	int	inst_num;
247*0Sstevel@tonic-gate 	int	count;
248*0Sstevel@tonic-gate 	int	fd;
249*0Sstevel@tonic-gate 	int	rc = SUCCESS;
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 	if (provname == NULL) {
252*0Sstevel@tonic-gate 		return (FAILURE);
253*0Sstevel@tonic-gate 	}
254*0Sstevel@tonic-gate 
255*0Sstevel@tonic-gate 	/*
256*0Sstevel@tonic-gate 	 * Check if the provider is valid. If it is valid, get the number of
257*0Sstevel@tonic-gate 	 * mechanisms also.
258*0Sstevel@tonic-gate 	 */
259*0Sstevel@tonic-gate 	if (check_hardware_provider(provname, devname, &inst_num, &count)
260*0Sstevel@tonic-gate 	    == FAILURE) {
261*0Sstevel@tonic-gate 		return (FAILURE);
262*0Sstevel@tonic-gate 	}
263*0Sstevel@tonic-gate 
264*0Sstevel@tonic-gate 	/* Get the mechanism list for the kernel hardware provider */
265*0Sstevel@tonic-gate 	if (get_dev_info(devname, inst_num, count, &infolist) == FAILURE) {
266*0Sstevel@tonic-gate 		return (FAILURE);
267*0Sstevel@tonic-gate 	}
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 	/*
270*0Sstevel@tonic-gate 	 * Get the entry of this hardware provider from the config file.
271*0Sstevel@tonic-gate 	 * If there is no entry yet, create one for it.
272*0Sstevel@tonic-gate 	 */
273*0Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) == NULL) {
274*0Sstevel@tonic-gate 		if ((pent = malloc(sizeof (entry_t))) == NULL) {
275*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext("out of memory."));
276*0Sstevel@tonic-gate 			free_mechlist(infolist);
277*0Sstevel@tonic-gate 			return (FAILURE);
278*0Sstevel@tonic-gate 		}
279*0Sstevel@tonic-gate 		new_dev_entry = B_TRUE;
280*0Sstevel@tonic-gate 		(void) strlcpy(pent->name, provname, MAXNAMELEN);
281*0Sstevel@tonic-gate 		pent->suplist = NULL;
282*0Sstevel@tonic-gate 		pent->sup_count = 0;
283*0Sstevel@tonic-gate 		pent->dislist = NULL;
284*0Sstevel@tonic-gate 		pent->dis_count = 0;
285*0Sstevel@tonic-gate 	}
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate 	/*
288*0Sstevel@tonic-gate 	 * kCF treats random as an internal mechanism. So, we need to
289*0Sstevel@tonic-gate 	 * filter it from the mechanism list here, if we are NOT disabling
290*0Sstevel@tonic-gate 	 * or enabling the random feature. Note that we map random feature at
291*0Sstevel@tonic-gate 	 * cryptoadm(1M) level to the "random" mechanism in kCF.
292*0Sstevel@tonic-gate 	 */
293*0Sstevel@tonic-gate 	if (!rndflag) {
294*0Sstevel@tonic-gate 		(void) filter_mechlist(&infolist, RANDOM);
295*0Sstevel@tonic-gate 	}
296*0Sstevel@tonic-gate 
297*0Sstevel@tonic-gate 	/* Calculate the new disabled list */
298*0Sstevel@tonic-gate 	if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) {
299*0Sstevel@tonic-gate 		free_entry(pent);
300*0Sstevel@tonic-gate 		return (FAILURE);
301*0Sstevel@tonic-gate 	}
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 	/* If no mechanisms are to be disabled, return */
304*0Sstevel@tonic-gate 	if (pent->dis_count == 0) {
305*0Sstevel@tonic-gate 		free_entry(pent);
306*0Sstevel@tonic-gate 		return (SUCCESS);
307*0Sstevel@tonic-gate 	}
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 	/* Update the config file with the new entry or the updated entry */
310*0Sstevel@tonic-gate 	if (new_dev_entry) {
311*0Sstevel@tonic-gate 		rc = update_kcfconf(pent, ADD_MODE);
312*0Sstevel@tonic-gate 	} else {
313*0Sstevel@tonic-gate 		rc = update_kcfconf(pent, MODIFY_MODE);
314*0Sstevel@tonic-gate 	}
315*0Sstevel@tonic-gate 
316*0Sstevel@tonic-gate 	if (rc == FAILURE) {
317*0Sstevel@tonic-gate 		free_entry(pent);
318*0Sstevel@tonic-gate 		return (FAILURE);
319*0Sstevel@tonic-gate 	}
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate 	/* Inform kernel about the new disabled mechanism list */
322*0Sstevel@tonic-gate 	if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) {
323*0Sstevel@tonic-gate 		free_entry(pent);
324*0Sstevel@tonic-gate 		return (FAILURE);
325*0Sstevel@tonic-gate 	}
326*0Sstevel@tonic-gate 	free_entry(pent);
327*0Sstevel@tonic-gate 
328*0Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
329*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
330*0Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
331*0Sstevel@tonic-gate 		free(pload_dev_dis);
332*0Sstevel@tonic-gate 		return (FAILURE);
333*0Sstevel@tonic-gate 	}
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) {
336*0Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: %s",
337*0Sstevel@tonic-gate 		    strerror(errno));
338*0Sstevel@tonic-gate 		free(pload_dev_dis);
339*0Sstevel@tonic-gate 		(void) close(fd);
340*0Sstevel@tonic-gate 		return (FAILURE);
341*0Sstevel@tonic-gate 	}
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
344*0Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl return_value = "
345*0Sstevel@tonic-gate 		    "%d", pload_dev_dis->dd_return_value);
346*0Sstevel@tonic-gate 		free(pload_dev_dis);
347*0Sstevel@tonic-gate 		(void) close(fd);
348*0Sstevel@tonic-gate 		return (FAILURE);
349*0Sstevel@tonic-gate 	}
350*0Sstevel@tonic-gate 
351*0Sstevel@tonic-gate 	free(pload_dev_dis);
352*0Sstevel@tonic-gate 	(void) close(fd);
353*0Sstevel@tonic-gate 	return (SUCCESS);
354*0Sstevel@tonic-gate }
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate 
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate int
359*0Sstevel@tonic-gate disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag,
360*0Sstevel@tonic-gate     mechlist_t *dislist)
361*0Sstevel@tonic-gate {
362*0Sstevel@tonic-gate 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
363*0Sstevel@tonic-gate 	mechlist_t 	*infolist;
364*0Sstevel@tonic-gate 	entry_t		*pent;
365*0Sstevel@tonic-gate 	boolean_t	is_active;
366*0Sstevel@tonic-gate 	int	fd;
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 	if (provname == NULL) {
369*0Sstevel@tonic-gate 		return (FAILURE);
370*0Sstevel@tonic-gate 	}
371*0Sstevel@tonic-gate 
372*0Sstevel@tonic-gate 	/* Get the entry of this provider from the config file. */
373*0Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) == NULL) {
374*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
375*0Sstevel@tonic-gate 		    gettext("%s does not exist."), provname);
376*0Sstevel@tonic-gate 		return (FAILURE);
377*0Sstevel@tonic-gate 	}
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate 	/*
380*0Sstevel@tonic-gate 	 * Check if the kernel software provider is currently unloaded.
381*0Sstevel@tonic-gate 	 * If it is unloaded, return FAILURE, because the disable subcommand
382*0Sstevel@tonic-gate 	 * can not perform on inactive (unloaded) providers.
383*0Sstevel@tonic-gate 	 */
384*0Sstevel@tonic-gate 	if (check_active_for_soft(provname, &is_active) == FAILURE) {
385*0Sstevel@tonic-gate 		free_entry(pent);
386*0Sstevel@tonic-gate 		return (FAILURE);
387*0Sstevel@tonic-gate 	} else if (is_active == B_FALSE) {
388*0Sstevel@tonic-gate 		/*
389*0Sstevel@tonic-gate 		 * TRANSLATION_NOTE:
390*0Sstevel@tonic-gate 		 * "disable" is a keyword and not to be translated.
391*0Sstevel@tonic-gate 		 */
392*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
393*0Sstevel@tonic-gate 		    gettext("can not do %1$s on an unloaded "
394*0Sstevel@tonic-gate 		    "kernel software provider -- %2$s."), "disable", provname);
395*0Sstevel@tonic-gate 		free_entry(pent);
396*0Sstevel@tonic-gate 		return (FAILURE);
397*0Sstevel@tonic-gate 	}
398*0Sstevel@tonic-gate 
399*0Sstevel@tonic-gate 	/* Get the mechanism list for the software provider */
400*0Sstevel@tonic-gate 	if (get_soft_info(provname, &infolist) == FAILURE) {
401*0Sstevel@tonic-gate 		free(pent);
402*0Sstevel@tonic-gate 		return (FAILURE);
403*0Sstevel@tonic-gate 	}
404*0Sstevel@tonic-gate 
405*0Sstevel@tonic-gate 	/* See comments in disable_kef_hardware() */
406*0Sstevel@tonic-gate 	if (!rndflag) {
407*0Sstevel@tonic-gate 		(void) filter_mechlist(&infolist, RANDOM);
408*0Sstevel@tonic-gate 	}
409*0Sstevel@tonic-gate 
410*0Sstevel@tonic-gate 	/* Calculate the new disabled list */
411*0Sstevel@tonic-gate 	if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) {
412*0Sstevel@tonic-gate 		free_entry(pent);
413*0Sstevel@tonic-gate 		free_mechlist(infolist);
414*0Sstevel@tonic-gate 		return (FAILURE);
415*0Sstevel@tonic-gate 	}
416*0Sstevel@tonic-gate 
417*0Sstevel@tonic-gate 	/* infolist is no longer needed; free it */
418*0Sstevel@tonic-gate 	free_mechlist(infolist);
419*0Sstevel@tonic-gate 
420*0Sstevel@tonic-gate 	/* Update the kcf.conf file with the updated entry */
421*0Sstevel@tonic-gate 	if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) {
422*0Sstevel@tonic-gate 		free_entry(pent);
423*0Sstevel@tonic-gate 		return (FAILURE);
424*0Sstevel@tonic-gate 	}
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate 	/* Inform kernel about the new disabled list. */
427*0Sstevel@tonic-gate 	if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
428*0Sstevel@tonic-gate 		free_entry(pent);
429*0Sstevel@tonic-gate 		return (FAILURE);
430*0Sstevel@tonic-gate 	}
431*0Sstevel@tonic-gate 
432*0Sstevel@tonic-gate 	/* pent is no longer needed; free it. */
433*0Sstevel@tonic-gate 	free_entry(pent);
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
436*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
437*0Sstevel@tonic-gate 		    gettext("failed to open %s for RW: %s"),
438*0Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
439*0Sstevel@tonic-gate 		free(pload_soft_dis);
440*0Sstevel@tonic-gate 		return (FAILURE);
441*0Sstevel@tonic-gate 	}
442*0Sstevel@tonic-gate 
443*0Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) {
444*0Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
445*0Sstevel@tonic-gate 		    strerror(errno));
446*0Sstevel@tonic-gate 		free(pload_soft_dis);
447*0Sstevel@tonic-gate 		(void) close(fd);
448*0Sstevel@tonic-gate 		return (FAILURE);
449*0Sstevel@tonic-gate 	}
450*0Sstevel@tonic-gate 
451*0Sstevel@tonic-gate 	if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
452*0Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
453*0Sstevel@tonic-gate 		    "%d", pload_soft_dis->sd_return_value);
454*0Sstevel@tonic-gate 		free(pload_soft_dis);
455*0Sstevel@tonic-gate 		(void) close(fd);
456*0Sstevel@tonic-gate 		return (FAILURE);
457*0Sstevel@tonic-gate 	}
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 	free(pload_soft_dis);
460*0Sstevel@tonic-gate 	(void) close(fd);
461*0Sstevel@tonic-gate 	return (SUCCESS);
462*0Sstevel@tonic-gate }
463*0Sstevel@tonic-gate 
464*0Sstevel@tonic-gate 
465*0Sstevel@tonic-gate int
466*0Sstevel@tonic-gate enable_kef(char *provname, boolean_t rndflag, boolean_t allflag,
467*0Sstevel@tonic-gate     mechlist_t *mlist)
468*0Sstevel@tonic-gate {
469*0Sstevel@tonic-gate 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
470*0Sstevel@tonic-gate 	crypto_load_dev_disabled_t	*pload_dev_dis = NULL;
471*0Sstevel@tonic-gate 	entry_t		*pent;
472*0Sstevel@tonic-gate 	boolean_t redo_flag = B_FALSE;
473*0Sstevel@tonic-gate 	int	fd;
474*0Sstevel@tonic-gate 	int	rc = SUCCESS;
475*0Sstevel@tonic-gate 
476*0Sstevel@tonic-gate 
477*0Sstevel@tonic-gate 	/* Get the entry with the provider name from the kcf.conf file */
478*0Sstevel@tonic-gate 	pent = getent_kef(provname);
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate 	if (is_device(provname)) {
481*0Sstevel@tonic-gate 		if (pent == NULL) {
482*0Sstevel@tonic-gate 			/*
483*0Sstevel@tonic-gate 			 * This device doesn't have an entry in the config
484*0Sstevel@tonic-gate 			 * file, therefore nothing is disabled.
485*0Sstevel@tonic-gate 			 */
486*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
487*0Sstevel@tonic-gate 			    "all mechanisms are enabled already for %s."),
488*0Sstevel@tonic-gate 			    provname);
489*0Sstevel@tonic-gate 			return (SUCCESS);
490*0Sstevel@tonic-gate 		}
491*0Sstevel@tonic-gate 	} else { /* a software module */
492*0Sstevel@tonic-gate 		if (pent == NULL) {
493*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR,
494*0Sstevel@tonic-gate 			    gettext("%s does not exist."), provname);
495*0Sstevel@tonic-gate 			return (FAILURE);
496*0Sstevel@tonic-gate 		} else if (pent->dis_count == 0) {
497*0Sstevel@tonic-gate 			/* nothing to be enabled. */
498*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
499*0Sstevel@tonic-gate 			    "all mechanisms are enabled already for %s."),
500*0Sstevel@tonic-gate 			    provname);
501*0Sstevel@tonic-gate 			free_entry(pent);
502*0Sstevel@tonic-gate 			return (SUCCESS);
503*0Sstevel@tonic-gate 		}
504*0Sstevel@tonic-gate 	}
505*0Sstevel@tonic-gate 
506*0Sstevel@tonic-gate 	if (!rndflag) {
507*0Sstevel@tonic-gate 		/* See comments in disable_kef_hardware() */
508*0Sstevel@tonic-gate 		redo_flag = filter_mechlist(&pent->dislist, RANDOM);
509*0Sstevel@tonic-gate 		if (redo_flag)
510*0Sstevel@tonic-gate 			pent->dis_count--;
511*0Sstevel@tonic-gate 	}
512*0Sstevel@tonic-gate 
513*0Sstevel@tonic-gate 	/* Update the entry by enabling mechanisms for this provider */
514*0Sstevel@tonic-gate 	if ((rc = enable_mechs(&pent, allflag, mlist)) != SUCCESS) {
515*0Sstevel@tonic-gate 		free_entry(pent);
516*0Sstevel@tonic-gate 		return (rc);
517*0Sstevel@tonic-gate 	}
518*0Sstevel@tonic-gate 
519*0Sstevel@tonic-gate 	if (redo_flag) {
520*0Sstevel@tonic-gate 		mechlist_t *tmp;
521*0Sstevel@tonic-gate 
522*0Sstevel@tonic-gate 		if ((tmp = create_mech(RANDOM)) == NULL) {
523*0Sstevel@tonic-gate 			free_entry(pent);
524*0Sstevel@tonic-gate 			return (FAILURE);
525*0Sstevel@tonic-gate 		}
526*0Sstevel@tonic-gate 		tmp->next = pent->dislist;
527*0Sstevel@tonic-gate 		pent->dislist = tmp;
528*0Sstevel@tonic-gate 		pent->dis_count++;
529*0Sstevel@tonic-gate 	}
530*0Sstevel@tonic-gate 
531*0Sstevel@tonic-gate 	/*
532*0Sstevel@tonic-gate 	 * Update the kcf.conf file  with the updated entry.
533*0Sstevel@tonic-gate 	 * For a hardware provider, if there is no more disabled mechanism,
534*0Sstevel@tonic-gate 	 * the entire entry in the config file should be removed.
535*0Sstevel@tonic-gate 	 */
536*0Sstevel@tonic-gate 	if (is_device(pent->name) && (pent->dis_count == 0)) {
537*0Sstevel@tonic-gate 		rc = update_kcfconf(pent, DELETE_MODE);
538*0Sstevel@tonic-gate 	} else {
539*0Sstevel@tonic-gate 		rc = update_kcfconf(pent, MODIFY_MODE);
540*0Sstevel@tonic-gate 	}
541*0Sstevel@tonic-gate 
542*0Sstevel@tonic-gate 	if (rc == FAILURE) {
543*0Sstevel@tonic-gate 		free_entry(pent);
544*0Sstevel@tonic-gate 		return (FAILURE);
545*0Sstevel@tonic-gate 	}
546*0Sstevel@tonic-gate 
547*0Sstevel@tonic-gate 
548*0Sstevel@tonic-gate 	/* Inform Kernel about the policy change */
549*0Sstevel@tonic-gate 
550*0Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
551*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
552*0Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
553*0Sstevel@tonic-gate 		return (FAILURE);
554*0Sstevel@tonic-gate 	}
555*0Sstevel@tonic-gate 
556*0Sstevel@tonic-gate 	if (is_device(provname)) {
557*0Sstevel@tonic-gate 		/*  LOAD_DEV_DISABLED */
558*0Sstevel@tonic-gate 		if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) {
559*0Sstevel@tonic-gate 			return (FAILURE);
560*0Sstevel@tonic-gate 		}
561*0Sstevel@tonic-gate 
562*0Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) {
563*0Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: "
564*0Sstevel@tonic-gate 			    "%s", strerror(errno));
565*0Sstevel@tonic-gate 			free(pload_dev_dis);
566*0Sstevel@tonic-gate 			(void) close(fd);
567*0Sstevel@tonic-gate 			return (FAILURE);
568*0Sstevel@tonic-gate 		}
569*0Sstevel@tonic-gate 
570*0Sstevel@tonic-gate 		if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
571*0Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
572*0Sstevel@tonic-gate 			    "return_value = %d",
573*0Sstevel@tonic-gate 			    pload_dev_dis->dd_return_value);
574*0Sstevel@tonic-gate 			free(pload_dev_dis);
575*0Sstevel@tonic-gate 			(void) close(fd);
576*0Sstevel@tonic-gate 			return (FAILURE);
577*0Sstevel@tonic-gate 		}
578*0Sstevel@tonic-gate 
579*0Sstevel@tonic-gate 	} else {
580*0Sstevel@tonic-gate 		/* LOAD_SOFT_DISABLED */
581*0Sstevel@tonic-gate 		if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
582*0Sstevel@tonic-gate 			return (FAILURE);
583*0Sstevel@tonic-gate 		}
584*0Sstevel@tonic-gate 
585*0Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis)
586*0Sstevel@tonic-gate 		    == -1) {
587*0Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: "
588*0Sstevel@tonic-gate 			    "%s", strerror(errno));
589*0Sstevel@tonic-gate 			free(pload_soft_dis);
590*0Sstevel@tonic-gate 			(void) close(fd);
591*0Sstevel@tonic-gate 			return (FAILURE);
592*0Sstevel@tonic-gate 		}
593*0Sstevel@tonic-gate 
594*0Sstevel@tonic-gate 		if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
595*0Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
596*0Sstevel@tonic-gate 			    "return_value = %d",
597*0Sstevel@tonic-gate 			    pload_soft_dis->sd_return_value);
598*0Sstevel@tonic-gate 			free(pload_soft_dis);
599*0Sstevel@tonic-gate 			(void) close(fd);
600*0Sstevel@tonic-gate 			return (FAILURE);
601*0Sstevel@tonic-gate 		}
602*0Sstevel@tonic-gate 	}
603*0Sstevel@tonic-gate 
604*0Sstevel@tonic-gate 	(void) close(fd);
605*0Sstevel@tonic-gate 	return (SUCCESS);
606*0Sstevel@tonic-gate }
607*0Sstevel@tonic-gate 
608*0Sstevel@tonic-gate 
609*0Sstevel@tonic-gate /*
610*0Sstevel@tonic-gate  * Install a software module with the specified mechanism list into the system.
611*0Sstevel@tonic-gate  * This routine adds an entry into the config file for this software module
612*0Sstevel@tonic-gate  * first, then makes a CRYPTO_LOAD_SOFT_CONFIG ioctl call to inform kernel
613*0Sstevel@tonic-gate  * about the new addition.
614*0Sstevel@tonic-gate  */
615*0Sstevel@tonic-gate int
616*0Sstevel@tonic-gate install_kef(char *provname, mechlist_t *mlist)
617*0Sstevel@tonic-gate {
618*0Sstevel@tonic-gate 	crypto_load_soft_config_t	*pload_soft_conf = NULL;
619*0Sstevel@tonic-gate 	boolean_t	found;
620*0Sstevel@tonic-gate 	entry_t	*pent;
621*0Sstevel@tonic-gate 	FILE	*pfile;
622*0Sstevel@tonic-gate 	FILE	*pfile_tmp;
623*0Sstevel@tonic-gate 	char	tmpfile_name[MAXPATHLEN];
624*0Sstevel@tonic-gate 	char	*ptr;
625*0Sstevel@tonic-gate 	char	*str;
626*0Sstevel@tonic-gate 	char	*name;
627*0Sstevel@tonic-gate 	char	buffer[BUFSIZ];
628*0Sstevel@tonic-gate 	char	buffer2[BUFSIZ];
629*0Sstevel@tonic-gate 	int	found_count;
630*0Sstevel@tonic-gate 	int	fd;
631*0Sstevel@tonic-gate 	int	rc = SUCCESS;
632*0Sstevel@tonic-gate 
633*0Sstevel@tonic-gate 	if ((provname == NULL) || (mlist == NULL)) {
634*0Sstevel@tonic-gate 		return (FAILURE);
635*0Sstevel@tonic-gate 	}
636*0Sstevel@tonic-gate 
637*0Sstevel@tonic-gate 	/* Check if the provider already exists */
638*0Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) != NULL) {
639*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s exists already."),
640*0Sstevel@tonic-gate 		    provname);
641*0Sstevel@tonic-gate 		free_entry(pent);
642*0Sstevel@tonic-gate 		return (FAILURE);
643*0Sstevel@tonic-gate 	}
644*0Sstevel@tonic-gate 
645*0Sstevel@tonic-gate 	/* Create an entry with provname and mlist. */
646*0Sstevel@tonic-gate 	if ((pent = malloc(sizeof (entry_t))) == NULL) {
647*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("out of memory."));
648*0Sstevel@tonic-gate 		return (FAILURE);
649*0Sstevel@tonic-gate 	}
650*0Sstevel@tonic-gate 
651*0Sstevel@tonic-gate 	(void) strlcpy(pent->name, provname, MAXNAMELEN);
652*0Sstevel@tonic-gate 	pent->sup_count = get_mech_count(mlist);
653*0Sstevel@tonic-gate 	pent->suplist = mlist;
654*0Sstevel@tonic-gate 	pent->dis_count = 0;
655*0Sstevel@tonic-gate 	pent->dislist = NULL;
656*0Sstevel@tonic-gate 
657*0Sstevel@tonic-gate 	/* Append an entry for this software module to the kcf.conf file. */
658*0Sstevel@tonic-gate 	if ((str = ent2str(pent)) == NULL) {
659*0Sstevel@tonic-gate 		free_entry(pent);
660*0Sstevel@tonic-gate 		return (FAILURE);
661*0Sstevel@tonic-gate 	}
662*0Sstevel@tonic-gate 
663*0Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
664*0Sstevel@tonic-gate 		err = errno;
665*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
666*0Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
667*0Sstevel@tonic-gate 		    strerror(err));
668*0Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
669*0Sstevel@tonic-gate 		free_entry(pent);
670*0Sstevel@tonic-gate 		return (FAILURE);
671*0Sstevel@tonic-gate 	}
672*0Sstevel@tonic-gate 
673*0Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
674*0Sstevel@tonic-gate 		err = errno;
675*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
676*0Sstevel@tonic-gate 		    gettext("failed to lock the configuration - %s"),
677*0Sstevel@tonic-gate 		    strerror(err));
678*0Sstevel@tonic-gate 		free_entry(pent);
679*0Sstevel@tonic-gate 		(void) fclose(pfile);
680*0Sstevel@tonic-gate 		return (FAILURE);
681*0Sstevel@tonic-gate 	}
682*0Sstevel@tonic-gate 
683*0Sstevel@tonic-gate 	/*
684*0Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory.
685*0Sstevel@tonic-gate 	 */
686*0Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
687*0Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
688*0Sstevel@tonic-gate 		err = errno;
689*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
690*0Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
691*0Sstevel@tonic-gate 		    strerror(err));
692*0Sstevel@tonic-gate 		free_entry(pent);
693*0Sstevel@tonic-gate 		(void) fclose(pfile);
694*0Sstevel@tonic-gate 		return (FAILURE);
695*0Sstevel@tonic-gate 	}
696*0Sstevel@tonic-gate 
697*0Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
698*0Sstevel@tonic-gate 		err = errno;
699*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
700*0Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
701*0Sstevel@tonic-gate 		free_entry(pent);
702*0Sstevel@tonic-gate 		(void) fclose(pfile);
703*0Sstevel@tonic-gate 		return (FAILURE);
704*0Sstevel@tonic-gate 	}
705*0Sstevel@tonic-gate 
706*0Sstevel@tonic-gate 
707*0Sstevel@tonic-gate 	/*
708*0Sstevel@tonic-gate 	 * Loop thru the config file. If the provider was reserved within a
709*0Sstevel@tonic-gate 	 * package bracket, just uncomment it.  Otherwise, append it at
710*0Sstevel@tonic-gate 	 * the end.  The resulting file will be saved in the temp file first.
711*0Sstevel@tonic-gate 	 */
712*0Sstevel@tonic-gate 	found_count = 0;
713*0Sstevel@tonic-gate 	rc = SUCCESS;
714*0Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
715*0Sstevel@tonic-gate 		found = B_FALSE;
716*0Sstevel@tonic-gate 		if (buffer[0] == '#') {
717*0Sstevel@tonic-gate 			(void) strlcpy(buffer2, buffer, BUFSIZ);
718*0Sstevel@tonic-gate 			ptr = buffer2;
719*0Sstevel@tonic-gate 			ptr++;
720*0Sstevel@tonic-gate 			if ((name = strtok(ptr, SEP_COLON)) == NULL) {
721*0Sstevel@tonic-gate 				rc = FAILURE;
722*0Sstevel@tonic-gate 				break;
723*0Sstevel@tonic-gate 			} else if (strcmp(provname, name) == 0) {
724*0Sstevel@tonic-gate 				found = B_TRUE;
725*0Sstevel@tonic-gate 				found_count++;
726*0Sstevel@tonic-gate 			}
727*0Sstevel@tonic-gate 		}
728*0Sstevel@tonic-gate 
729*0Sstevel@tonic-gate 		if (found == B_FALSE) {
730*0Sstevel@tonic-gate 			if (fputs(buffer, pfile_tmp) == EOF) {
731*0Sstevel@tonic-gate 				rc = FAILURE;
732*0Sstevel@tonic-gate 			}
733*0Sstevel@tonic-gate 		} else {
734*0Sstevel@tonic-gate 			if (found_count == 1) {
735*0Sstevel@tonic-gate 				if (fputs(str, pfile_tmp) == EOF) {
736*0Sstevel@tonic-gate 					rc = FAILURE;
737*0Sstevel@tonic-gate 				}
738*0Sstevel@tonic-gate 			} else {
739*0Sstevel@tonic-gate 				/*
740*0Sstevel@tonic-gate 				 * Found a second entry with #libname.
741*0Sstevel@tonic-gate 				 * Should not happen. The kcf.conf ffile
742*0Sstevel@tonic-gate 				 * is corrupted. Give a warning and skip
743*0Sstevel@tonic-gate 				 * this entry.
744*0Sstevel@tonic-gate 				 */
745*0Sstevel@tonic-gate 				cryptoerror(LOG_STDERR, gettext(
746*0Sstevel@tonic-gate 				    "(Warning) Found an additional reserved "
747*0Sstevel@tonic-gate 				    "entry for %s."), provname);
748*0Sstevel@tonic-gate 			}
749*0Sstevel@tonic-gate 		}
750*0Sstevel@tonic-gate 
751*0Sstevel@tonic-gate 		if (rc == FAILURE) {
752*0Sstevel@tonic-gate 			break;
753*0Sstevel@tonic-gate 		}
754*0Sstevel@tonic-gate 	}
755*0Sstevel@tonic-gate 	(void) fclose(pfile);
756*0Sstevel@tonic-gate 
757*0Sstevel@tonic-gate 	if (rc == FAILURE) {
758*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("write error."));
759*0Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
760*0Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
761*0Sstevel@tonic-gate 			err = errno;
762*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
763*0Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"), tmpfile_name,
764*0Sstevel@tonic-gate 			    strerror(err));
765*0Sstevel@tonic-gate 		}
766*0Sstevel@tonic-gate 		free_entry(pent);
767*0Sstevel@tonic-gate 		return (FAILURE);
768*0Sstevel@tonic-gate 	}
769*0Sstevel@tonic-gate 
770*0Sstevel@tonic-gate 	if (found_count == 0) {
771*0Sstevel@tonic-gate 		/*
772*0Sstevel@tonic-gate 		 * This libname was not in package before, append it to the
773*0Sstevel@tonic-gate 		 * end of the temp file.
774*0Sstevel@tonic-gate 		 */
775*0Sstevel@tonic-gate 		if (fputs(str, pfile_tmp) == EOF) {
776*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
777*0Sstevel@tonic-gate 			    "failed to write to %s: %s"), tmpfile_name,
778*0Sstevel@tonic-gate 			    strerror(errno));
779*0Sstevel@tonic-gate 			(void) fclose(pfile_tmp);
780*0Sstevel@tonic-gate 			if (unlink(tmpfile_name) != 0) {
781*0Sstevel@tonic-gate 				err = errno;
782*0Sstevel@tonic-gate 				cryptoerror(LOG_STDERR, gettext(
783*0Sstevel@tonic-gate 				    "(Warning) failed to remove %s: %s"),
784*0Sstevel@tonic-gate 				    tmpfile_name, strerror(err));
785*0Sstevel@tonic-gate 			}
786*0Sstevel@tonic-gate 			free_entry(pent);
787*0Sstevel@tonic-gate 			return (FAILURE);
788*0Sstevel@tonic-gate 		}
789*0Sstevel@tonic-gate 	}
790*0Sstevel@tonic-gate 
791*0Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
792*0Sstevel@tonic-gate 		err = errno;
793*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
794*0Sstevel@tonic-gate 		    gettext("failed to close %s: %s"), tmpfile_name,
795*0Sstevel@tonic-gate 		    strerror(err));
796*0Sstevel@tonic-gate 		return (FAILURE);
797*0Sstevel@tonic-gate 	}
798*0Sstevel@tonic-gate 
799*0Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
800*0Sstevel@tonic-gate 		err = errno;
801*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
802*0Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
803*0Sstevel@tonic-gate 			strerror(err));
804*0Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
805*0Sstevel@tonic-gate 		    _PATH_KCF_CONF, strerror(err));
806*0Sstevel@tonic-gate 		rc = FAILURE;
807*0Sstevel@tonic-gate 	} else if (chmod(_PATH_KCF_CONF,
808*0Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
809*0Sstevel@tonic-gate 		err = errno;
810*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
811*0Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
812*0Sstevel@tonic-gate 		    strerror(err));
813*0Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
814*0Sstevel@tonic-gate 		    strerror(err));
815*0Sstevel@tonic-gate 		rc = FAILURE;
816*0Sstevel@tonic-gate 	} else {
817*0Sstevel@tonic-gate 		rc = SUCCESS;
818*0Sstevel@tonic-gate 	}
819*0Sstevel@tonic-gate 
820*0Sstevel@tonic-gate 	if (rc == FAILURE) {
821*0Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
822*0Sstevel@tonic-gate 			err = errno;
823*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
824*0Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
825*0Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
826*0Sstevel@tonic-gate 		}
827*0Sstevel@tonic-gate 		return (FAILURE);
828*0Sstevel@tonic-gate 	}
829*0Sstevel@tonic-gate 
830*0Sstevel@tonic-gate 
831*0Sstevel@tonic-gate 	/* Inform kernel of this new software module. */
832*0Sstevel@tonic-gate 
833*0Sstevel@tonic-gate 	if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
834*0Sstevel@tonic-gate 		free_entry(pent);
835*0Sstevel@tonic-gate 		return (FAILURE);
836*0Sstevel@tonic-gate 	}
837*0Sstevel@tonic-gate 
838*0Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
839*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
840*0Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
841*0Sstevel@tonic-gate 		free_entry(pent);
842*0Sstevel@tonic-gate 		free(pload_soft_conf);
843*0Sstevel@tonic-gate 		return (FAILURE);
844*0Sstevel@tonic-gate 	}
845*0Sstevel@tonic-gate 
846*0Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) {
847*0Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
848*0Sstevel@tonic-gate 		    strerror(errno));
849*0Sstevel@tonic-gate 		free_entry(pent);
850*0Sstevel@tonic-gate 		free(pload_soft_conf);
851*0Sstevel@tonic-gate 		(void) close(fd);
852*0Sstevel@tonic-gate 		return (FAILURE);
853*0Sstevel@tonic-gate 	}
854*0Sstevel@tonic-gate 
855*0Sstevel@tonic-gate 	if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
856*0Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed, "
857*0Sstevel@tonic-gate 		    "return_value = %d", pload_soft_conf->sc_return_value);
858*0Sstevel@tonic-gate 		free_entry(pent);
859*0Sstevel@tonic-gate 		free(pload_soft_conf);
860*0Sstevel@tonic-gate 		(void) close(fd);
861*0Sstevel@tonic-gate 		return (FAILURE);
862*0Sstevel@tonic-gate 	}
863*0Sstevel@tonic-gate 
864*0Sstevel@tonic-gate 	free_entry(pent);
865*0Sstevel@tonic-gate 	free(pload_soft_conf);
866*0Sstevel@tonic-gate 	(void) close(fd);
867*0Sstevel@tonic-gate 	return (SUCCESS);
868*0Sstevel@tonic-gate }
869*0Sstevel@tonic-gate 
870*0Sstevel@tonic-gate /*
871*0Sstevel@tonic-gate  * Uninstall the software module. This routine first unloads the software
872*0Sstevel@tonic-gate  * module with 3 ioctl calls, then deletes its entry from the config file.
873*0Sstevel@tonic-gate  * Removing an entry from the config file needs to be done last to ensure
874*0Sstevel@tonic-gate  * that there is still an entry if the earlier unload failed for any reason.
875*0Sstevel@tonic-gate  */
876*0Sstevel@tonic-gate int
877*0Sstevel@tonic-gate uninstall_kef(char *provname)
878*0Sstevel@tonic-gate {
879*0Sstevel@tonic-gate 	entry_t		*pent;
880*0Sstevel@tonic-gate 	boolean_t	is_active;
881*0Sstevel@tonic-gate 	boolean_t	in_package;
882*0Sstevel@tonic-gate 	boolean_t	found;
883*0Sstevel@tonic-gate 	FILE	*pfile;
884*0Sstevel@tonic-gate 	FILE	*pfile_tmp;
885*0Sstevel@tonic-gate 	char	tmpfile_name[MAXPATHLEN];
886*0Sstevel@tonic-gate 	char	*name;
887*0Sstevel@tonic-gate 	char	strbuf[BUFSIZ];
888*0Sstevel@tonic-gate 	char	buffer[BUFSIZ];
889*0Sstevel@tonic-gate 	char	buffer2[BUFSIZ];
890*0Sstevel@tonic-gate 	char	*str;
891*0Sstevel@tonic-gate 	int	len;
892*0Sstevel@tonic-gate 	int	rc = SUCCESS;
893*0Sstevel@tonic-gate 
894*0Sstevel@tonic-gate 
895*0Sstevel@tonic-gate 	/* Check if it is in the kcf.conf file first. */
896*0Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) == NULL) {
897*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
898*0Sstevel@tonic-gate 		    gettext("%s does not exist."), provname);
899*0Sstevel@tonic-gate 		return (FAILURE);
900*0Sstevel@tonic-gate 	}
901*0Sstevel@tonic-gate 
902*0Sstevel@tonic-gate 
903*0Sstevel@tonic-gate 	/*
904*0Sstevel@tonic-gate 	 * Get rid of the disabled list for the provider and get the converted
905*0Sstevel@tonic-gate 	 * string for the entry.  This is to prepare the string for a provider
906*0Sstevel@tonic-gate 	 * that is in a package.
907*0Sstevel@tonic-gate 	 */
908*0Sstevel@tonic-gate 	free_mechlist(pent->dislist);
909*0Sstevel@tonic-gate 	pent->dis_count = 0;
910*0Sstevel@tonic-gate 	pent->dislist = NULL;
911*0Sstevel@tonic-gate 	str = ent2str(pent);
912*0Sstevel@tonic-gate 	free_entry(pent);
913*0Sstevel@tonic-gate 	if (str == NULL) {
914*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
915*0Sstevel@tonic-gate 		return (FAILURE);
916*0Sstevel@tonic-gate 	}
917*0Sstevel@tonic-gate 	(void) snprintf(strbuf, sizeof (strbuf), "%s%s", "#", str);
918*0Sstevel@tonic-gate 	free(str);
919*0Sstevel@tonic-gate 
920*0Sstevel@tonic-gate 	/* If it is not loaded, unload it first  */
921*0Sstevel@tonic-gate 	if (check_active_for_soft(provname, &is_active) == FAILURE) {
922*0Sstevel@tonic-gate 		return (FAILURE);
923*0Sstevel@tonic-gate 	} else if ((is_active == B_TRUE) &&
924*0Sstevel@tonic-gate 	    (unload_kef_soft(provname) == FAILURE)) {
925*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
926*0Sstevel@tonic-gate 		    gettext("failed to uninstall %s.\n"), provname);
927*0Sstevel@tonic-gate 		return (FAILURE);
928*0Sstevel@tonic-gate 	}
929*0Sstevel@tonic-gate 
930*0Sstevel@tonic-gate 	/*
931*0Sstevel@tonic-gate 	 * Remove the entry from the config file.  If the provider to be
932*0Sstevel@tonic-gate 	 * uninstalled is in a package, just comment it off.
933*0Sstevel@tonic-gate 	 */
934*0Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
935*0Sstevel@tonic-gate 		err = errno;
936*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
937*0Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
938*0Sstevel@tonic-gate 		    strerror(err));
939*0Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
940*0Sstevel@tonic-gate 		return (FAILURE);
941*0Sstevel@tonic-gate 	}
942*0Sstevel@tonic-gate 
943*0Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
944*0Sstevel@tonic-gate 		err = errno;
945*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
946*0Sstevel@tonic-gate 		    gettext("failed to lock the configuration - %s"),
947*0Sstevel@tonic-gate 		    strerror(err));
948*0Sstevel@tonic-gate 		(void) fclose(pfile);
949*0Sstevel@tonic-gate 		return (FAILURE);
950*0Sstevel@tonic-gate 	}
951*0Sstevel@tonic-gate 
952*0Sstevel@tonic-gate 	/*
953*0Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory to save
954*0Sstevel@tonic-gate 	 * the new configuration file first.
955*0Sstevel@tonic-gate 	 */
956*0Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
957*0Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
958*0Sstevel@tonic-gate 		err = errno;
959*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
960*0Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
961*0Sstevel@tonic-gate 		    strerror(err));
962*0Sstevel@tonic-gate 		(void) fclose(pfile);
963*0Sstevel@tonic-gate 		return (FAILURE);
964*0Sstevel@tonic-gate 	}
965*0Sstevel@tonic-gate 
966*0Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
967*0Sstevel@tonic-gate 		err = errno;
968*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
969*0Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
970*0Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
971*0Sstevel@tonic-gate 			err = errno;
972*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
973*0Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"), tmpfile_name,
974*0Sstevel@tonic-gate 			    strerror(err));
975*0Sstevel@tonic-gate 		}
976*0Sstevel@tonic-gate 		(void) fclose(pfile);
977*0Sstevel@tonic-gate 		return (FAILURE);
978*0Sstevel@tonic-gate 	}
979*0Sstevel@tonic-gate 
980*0Sstevel@tonic-gate 	/*
981*0Sstevel@tonic-gate 	 * Loop thru the config file.  If the kernel software provider
982*0Sstevel@tonic-gate 	 * to be uninstalled is in a package, just comment it off.
983*0Sstevel@tonic-gate 	 */
984*0Sstevel@tonic-gate 	in_package = B_FALSE;
985*0Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
986*0Sstevel@tonic-gate 		found = B_FALSE;
987*0Sstevel@tonic-gate 		if (!(buffer[0] == ' ' || buffer[0] == '\n' ||
988*0Sstevel@tonic-gate 		    buffer[0] == '\t')) {
989*0Sstevel@tonic-gate 			if (strstr(buffer, " Start ") != NULL) {
990*0Sstevel@tonic-gate 				in_package = B_TRUE;
991*0Sstevel@tonic-gate 			} else if (strstr(buffer, " End ") != NULL) {
992*0Sstevel@tonic-gate 				in_package = B_FALSE;
993*0Sstevel@tonic-gate 			} else if (buffer[0] != '#') {
994*0Sstevel@tonic-gate 				(void) strlcpy(buffer2, buffer, BUFSIZ);
995*0Sstevel@tonic-gate 
996*0Sstevel@tonic-gate 				/* get rid of trailing '\n' */
997*0Sstevel@tonic-gate 				len = strlen(buffer2);
998*0Sstevel@tonic-gate 				if (buffer2[len-1] == '\n') {
999*0Sstevel@tonic-gate 					len--;
1000*0Sstevel@tonic-gate 				}
1001*0Sstevel@tonic-gate 				buffer2[len] = '\0';
1002*0Sstevel@tonic-gate 
1003*0Sstevel@tonic-gate 				if ((name = strtok(buffer2, SEP_COLON))
1004*0Sstevel@tonic-gate 				    == NULL) {
1005*0Sstevel@tonic-gate 					rc = FAILURE;
1006*0Sstevel@tonic-gate 					break;
1007*0Sstevel@tonic-gate 				} else if (strcmp(provname, name) == 0) {
1008*0Sstevel@tonic-gate 					found = B_TRUE;
1009*0Sstevel@tonic-gate 				}
1010*0Sstevel@tonic-gate 			}
1011*0Sstevel@tonic-gate 		}
1012*0Sstevel@tonic-gate 
1013*0Sstevel@tonic-gate 		if (found) {
1014*0Sstevel@tonic-gate 			if (in_package) {
1015*0Sstevel@tonic-gate 				if (fputs(strbuf, pfile_tmp) == EOF) {
1016*0Sstevel@tonic-gate 					rc = FAILURE;
1017*0Sstevel@tonic-gate 				}
1018*0Sstevel@tonic-gate 			}
1019*0Sstevel@tonic-gate 		} else {
1020*0Sstevel@tonic-gate 			if (fputs(buffer, pfile_tmp) == EOF) {
1021*0Sstevel@tonic-gate 				rc = FAILURE;
1022*0Sstevel@tonic-gate 			}
1023*0Sstevel@tonic-gate 		}
1024*0Sstevel@tonic-gate 
1025*0Sstevel@tonic-gate 		if (rc == FAILURE) {
1026*0Sstevel@tonic-gate 			break;
1027*0Sstevel@tonic-gate 		}
1028*0Sstevel@tonic-gate 	}
1029*0Sstevel@tonic-gate 
1030*0Sstevel@tonic-gate 	if (rc == FAILURE) {
1031*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("write error."));
1032*0Sstevel@tonic-gate 		(void) fclose(pfile);
1033*0Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
1034*0Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
1035*0Sstevel@tonic-gate 			err = errno;
1036*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
1037*0Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"), tmpfile_name,
1038*0Sstevel@tonic-gate 			    strerror(err));
1039*0Sstevel@tonic-gate 		}
1040*0Sstevel@tonic-gate 		return (FAILURE);
1041*0Sstevel@tonic-gate 	}
1042*0Sstevel@tonic-gate 
1043*0Sstevel@tonic-gate 	(void) fclose(pfile);
1044*0Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
1045*0Sstevel@tonic-gate 		err = errno;
1046*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
1047*0Sstevel@tonic-gate 		    gettext("failed to close %s: %s"), tmpfile_name,
1048*0Sstevel@tonic-gate 		    strerror(err));
1049*0Sstevel@tonic-gate 		return (FAILURE);
1050*0Sstevel@tonic-gate 	}
1051*0Sstevel@tonic-gate 
1052*0Sstevel@tonic-gate 	/* Now update the real config file */
1053*0Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
1054*0Sstevel@tonic-gate 		err = errno;
1055*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
1056*0Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
1057*0Sstevel@tonic-gate 		    strerror(err));
1058*0Sstevel@tonic-gate 		cryptodebug("failed to rename %1$s to %2$s: %3$s", tmpfile,
1059*0Sstevel@tonic-gate 		    _PATH_KCF_CONF, strerror(err));
1060*0Sstevel@tonic-gate 		rc = FAILURE;
1061*0Sstevel@tonic-gate 	} else if (chmod(_PATH_KCF_CONF,
1062*0Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
1063*0Sstevel@tonic-gate 		err = errno;
1064*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
1065*0Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
1066*0Sstevel@tonic-gate 		    strerror(err));
1067*0Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
1068*0Sstevel@tonic-gate 		    strerror(err));
1069*0Sstevel@tonic-gate 		rc = FAILURE;
1070*0Sstevel@tonic-gate 	} else {
1071*0Sstevel@tonic-gate 		rc = SUCCESS;
1072*0Sstevel@tonic-gate 	}
1073*0Sstevel@tonic-gate 
1074*0Sstevel@tonic-gate 	if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
1075*0Sstevel@tonic-gate 		err = errno;
1076*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
1077*0Sstevel@tonic-gate 		    "(Warning) failed to remove %s: %s"), tmpfile_name,
1078*0Sstevel@tonic-gate 		    strerror(err));
1079*0Sstevel@tonic-gate 	}
1080*0Sstevel@tonic-gate 
1081*0Sstevel@tonic-gate 	return (rc);
1082*0Sstevel@tonic-gate 
1083*0Sstevel@tonic-gate }
1084*0Sstevel@tonic-gate 
1085*0Sstevel@tonic-gate 
1086*0Sstevel@tonic-gate int
1087*0Sstevel@tonic-gate refresh(void)
1088*0Sstevel@tonic-gate {
1089*0Sstevel@tonic-gate 	crypto_get_soft_list_t		*psoftlist_kernel = NULL;
1090*0Sstevel@tonic-gate 	crypto_load_soft_config_t	*pload_soft_conf = NULL;
1091*0Sstevel@tonic-gate 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
1092*0Sstevel@tonic-gate 	crypto_load_dev_disabled_t	*pload_dev_dis = NULL;
1093*0Sstevel@tonic-gate 	entrylist_t	*pdevlist = NULL;
1094*0Sstevel@tonic-gate 	entrylist_t	*psoftlist = NULL;
1095*0Sstevel@tonic-gate 	entrylist_t	*ptr;
1096*0Sstevel@tonic-gate 	boolean_t	found;
1097*0Sstevel@tonic-gate 	char 	*psoftname;
1098*0Sstevel@tonic-gate 	int	fd;
1099*0Sstevel@tonic-gate 	int	rc = SUCCESS;
1100*0Sstevel@tonic-gate 	int	i;
1101*0Sstevel@tonic-gate 
1102*0Sstevel@tonic-gate 	if (get_soft_list(&psoftlist_kernel) == FAILURE) {
1103*0Sstevel@tonic-gate 		cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
1104*0Sstevel@tonic-gate 		    "software provider list from kernel."));
1105*0Sstevel@tonic-gate 		return (FAILURE);
1106*0Sstevel@tonic-gate 	}
1107*0Sstevel@tonic-gate 
1108*0Sstevel@tonic-gate 	if (get_kcfconf_info(&pdevlist, &psoftlist) == FAILURE) {
1109*0Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "failed to retrieve the providers' "
1110*0Sstevel@tonic-gate 		    "information from the configuration file - %s.",
1111*0Sstevel@tonic-gate 		    _PATH_KCF_CONF);
1112*0Sstevel@tonic-gate 		return (FAILURE);
1113*0Sstevel@tonic-gate 	}
1114*0Sstevel@tonic-gate 
1115*0Sstevel@tonic-gate 	/*
1116*0Sstevel@tonic-gate 	 * If a kernel software provider is in kernel, but it is not in the
1117*0Sstevel@tonic-gate 	 * kcf.conf file, it must have been pkgrm'ed and needs to be unloaded
1118*0Sstevel@tonic-gate 	 * now.
1119*0Sstevel@tonic-gate 	 */
1120*0Sstevel@tonic-gate 	if (psoftlist_kernel->sl_soft_count > 0) {
1121*0Sstevel@tonic-gate 		psoftname = psoftlist_kernel->sl_soft_names;
1122*0Sstevel@tonic-gate 		for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) {
1123*0Sstevel@tonic-gate 			ptr = psoftlist;
1124*0Sstevel@tonic-gate 			found = B_FALSE;
1125*0Sstevel@tonic-gate 			while (ptr != NULL) {
1126*0Sstevel@tonic-gate 				if (strcmp(psoftname, ptr->pent->name) == 0) {
1127*0Sstevel@tonic-gate 					found = B_TRUE;
1128*0Sstevel@tonic-gate 					break;
1129*0Sstevel@tonic-gate 				}
1130*0Sstevel@tonic-gate 				ptr = ptr->next;
1131*0Sstevel@tonic-gate 			}
1132*0Sstevel@tonic-gate 
1133*0Sstevel@tonic-gate 			if (!found) {
1134*0Sstevel@tonic-gate 				rc = unload_kef_soft(psoftname);
1135*0Sstevel@tonic-gate 				if (rc == FAILURE) {
1136*0Sstevel@tonic-gate 					cryptoerror(LOG_ERR, gettext(
1137*0Sstevel@tonic-gate 					    "WARNING - the provider %s is "
1138*0Sstevel@tonic-gate 					    "still in kernel."), psoftname);
1139*0Sstevel@tonic-gate 				}
1140*0Sstevel@tonic-gate 			}
1141*0Sstevel@tonic-gate 			psoftname = psoftname + strlen(psoftname) + 1;
1142*0Sstevel@tonic-gate 		}
1143*0Sstevel@tonic-gate 	}
1144*0Sstevel@tonic-gate 	free(psoftlist_kernel);
1145*0Sstevel@tonic-gate 
1146*0Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
1147*0Sstevel@tonic-gate 		err = errno;
1148*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
1149*0Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(err));
1150*0Sstevel@tonic-gate 		free(psoftlist);
1151*0Sstevel@tonic-gate 		free(pdevlist);
1152*0Sstevel@tonic-gate 		return (FAILURE);
1153*0Sstevel@tonic-gate 	}
1154*0Sstevel@tonic-gate 
1155*0Sstevel@tonic-gate 	/*
1156*0Sstevel@tonic-gate 	 * For each software module, pass two sets of information to kernel
1157*0Sstevel@tonic-gate 	 * - the supported list and the disabled list
1158*0Sstevel@tonic-gate 	 */
1159*0Sstevel@tonic-gate 	ptr = psoftlist;
1160*0Sstevel@tonic-gate 	while (ptr != NULL) {
1161*0Sstevel@tonic-gate 		/* load the supported list */
1162*0Sstevel@tonic-gate 		if ((pload_soft_conf = setup_soft_conf(ptr->pent)) == NULL) {
1163*0Sstevel@tonic-gate 			rc = FAILURE;
1164*0Sstevel@tonic-gate 			break;
1165*0Sstevel@tonic-gate 		}
1166*0Sstevel@tonic-gate 
1167*0Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf)
1168*0Sstevel@tonic-gate 		    == -1) {
1169*0Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
1170*0Sstevel@tonic-gate 			    strerror(errno));
1171*0Sstevel@tonic-gate 			free(pload_soft_conf);
1172*0Sstevel@tonic-gate 			rc = FAILURE;
1173*0Sstevel@tonic-gate 			break;
1174*0Sstevel@tonic-gate 		}
1175*0Sstevel@tonic-gate 
1176*0Sstevel@tonic-gate 		if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
1177*0Sstevel@tonic-gate 			cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl "
1178*0Sstevel@tonic-gate 			    "return_value = %d",
1179*0Sstevel@tonic-gate 			    pload_soft_conf->sc_return_value);
1180*0Sstevel@tonic-gate 			free(pload_soft_conf);
1181*0Sstevel@tonic-gate 			rc = FAILURE;
1182*0Sstevel@tonic-gate 			break;
1183*0Sstevel@tonic-gate 		}
1184*0Sstevel@tonic-gate 
1185*0Sstevel@tonic-gate 		/* load the disabled list */
1186*0Sstevel@tonic-gate 		if (ptr->pent->dis_count != 0) {
1187*0Sstevel@tonic-gate 			pload_soft_dis = setup_soft_dis(ptr->pent);
1188*0Sstevel@tonic-gate 			if (pload_soft_dis == NULL) {
1189*0Sstevel@tonic-gate 				rc = FAILURE;
1190*0Sstevel@tonic-gate 				break;
1191*0Sstevel@tonic-gate 			}
1192*0Sstevel@tonic-gate 
1193*0Sstevel@tonic-gate 			if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED,
1194*0Sstevel@tonic-gate 			    pload_soft_dis) == -1) {
1195*0Sstevel@tonic-gate 				cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
1196*0Sstevel@tonic-gate 				    "failed: %s", strerror(errno));
1197*0Sstevel@tonic-gate 				free(pload_soft_dis);
1198*0Sstevel@tonic-gate 				rc = FAILURE;
1199*0Sstevel@tonic-gate 				break;
1200*0Sstevel@tonic-gate 			}
1201*0Sstevel@tonic-gate 
1202*0Sstevel@tonic-gate 			if (pload_soft_dis->sd_return_value !=
1203*0Sstevel@tonic-gate 			    CRYPTO_SUCCESS) {
1204*0Sstevel@tonic-gate 				cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
1205*0Sstevel@tonic-gate 				    "return_value = %d",
1206*0Sstevel@tonic-gate 				    pload_soft_dis->sd_return_value);
1207*0Sstevel@tonic-gate 				free(pload_soft_dis);
1208*0Sstevel@tonic-gate 				rc = FAILURE;
1209*0Sstevel@tonic-gate 				break;
1210*0Sstevel@tonic-gate 			}
1211*0Sstevel@tonic-gate 			free(pload_soft_dis);
1212*0Sstevel@tonic-gate 		}
1213*0Sstevel@tonic-gate 
1214*0Sstevel@tonic-gate 		free(pload_soft_conf);
1215*0Sstevel@tonic-gate 		ptr = ptr->next;
1216*0Sstevel@tonic-gate 	}
1217*0Sstevel@tonic-gate 
1218*0Sstevel@tonic-gate 	if (rc != SUCCESS) {
1219*0Sstevel@tonic-gate 		(void) close(fd);
1220*0Sstevel@tonic-gate 		return (rc);
1221*0Sstevel@tonic-gate 	}
1222*0Sstevel@tonic-gate 
1223*0Sstevel@tonic-gate 
1224*0Sstevel@tonic-gate 	/* Pass the disabledlist information for Device to kernel */
1225*0Sstevel@tonic-gate 	ptr = pdevlist;
1226*0Sstevel@tonic-gate 	while (ptr != NULL) {
1227*0Sstevel@tonic-gate 		/* load the disabled list */
1228*0Sstevel@tonic-gate 		if (ptr->pent->dis_count != 0) {
1229*0Sstevel@tonic-gate 			pload_dev_dis = setup_dev_dis(ptr->pent);
1230*0Sstevel@tonic-gate 			if (pload_dev_dis == NULL) {
1231*0Sstevel@tonic-gate 				rc = FAILURE;
1232*0Sstevel@tonic-gate 				break;
1233*0Sstevel@tonic-gate 			}
1234*0Sstevel@tonic-gate 
1235*0Sstevel@tonic-gate 			if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis)
1236*0Sstevel@tonic-gate 			    == -1) {
1237*0Sstevel@tonic-gate 				cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
1238*0Sstevel@tonic-gate 				    "failed: %s", strerror(errno));
1239*0Sstevel@tonic-gate 				free(pload_dev_dis);
1240*0Sstevel@tonic-gate 				rc = FAILURE;
1241*0Sstevel@tonic-gate 				break;
1242*0Sstevel@tonic-gate 			}
1243*0Sstevel@tonic-gate 
1244*0Sstevel@tonic-gate 			if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
1245*0Sstevel@tonic-gate 				cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
1246*0Sstevel@tonic-gate 				    "return_value = %d",
1247*0Sstevel@tonic-gate 				    pload_dev_dis->dd_return_value);
1248*0Sstevel@tonic-gate 				free(pload_dev_dis);
1249*0Sstevel@tonic-gate 				rc = FAILURE;
1250*0Sstevel@tonic-gate 				break;
1251*0Sstevel@tonic-gate 			}
1252*0Sstevel@tonic-gate 			free(pload_dev_dis);
1253*0Sstevel@tonic-gate 		}
1254*0Sstevel@tonic-gate 
1255*0Sstevel@tonic-gate 		ptr = ptr->next;
1256*0Sstevel@tonic-gate 	}
1257*0Sstevel@tonic-gate 
1258*0Sstevel@tonic-gate 	(void) close(fd);
1259*0Sstevel@tonic-gate 	return (rc);
1260*0Sstevel@tonic-gate }
1261*0Sstevel@tonic-gate 
1262*0Sstevel@tonic-gate /*
1263*0Sstevel@tonic-gate  * Unload the kernel software provider. Before calling this function, the
1264*0Sstevel@tonic-gate  * caller should check if the provider is in the config file and if it
1265*0Sstevel@tonic-gate  * is kernel.  This routine makes 3 ioctl calls to remove it from kernel
1266*0Sstevel@tonic-gate  * completely.
1267*0Sstevel@tonic-gate  */
1268*0Sstevel@tonic-gate int
1269*0Sstevel@tonic-gate unload_kef_soft(char *provname)
1270*0Sstevel@tonic-gate {
1271*0Sstevel@tonic-gate 	crypto_unload_soft_module_t 	*punload_soft = NULL;
1272*0Sstevel@tonic-gate 	crypto_load_soft_config_t	*pload_soft_conf = NULL;
1273*0Sstevel@tonic-gate 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
1274*0Sstevel@tonic-gate 	entry_t	*pent = NULL;
1275*0Sstevel@tonic-gate 	int	fd;
1276*0Sstevel@tonic-gate 
1277*0Sstevel@tonic-gate 	if (provname == NULL) {
1278*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
1279*0Sstevel@tonic-gate 		return (FAILURE);
1280*0Sstevel@tonic-gate 	}
1281*0Sstevel@tonic-gate 
1282*0Sstevel@tonic-gate 	if ((pent = getent_kef(provname)) == NULL) {
1283*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s does not exist."),
1284*0Sstevel@tonic-gate 		    provname);
1285*0Sstevel@tonic-gate 		return (FAILURE);
1286*0Sstevel@tonic-gate 	}
1287*0Sstevel@tonic-gate 
1288*0Sstevel@tonic-gate 	/* Open the admin_ioctl_device */
1289*0Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
1290*0Sstevel@tonic-gate 		err = errno;
1291*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
1292*0Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(err));
1293*0Sstevel@tonic-gate 		return (FAILURE);
1294*0Sstevel@tonic-gate 	}
1295*0Sstevel@tonic-gate 
1296*0Sstevel@tonic-gate 	/* Inform kernel to unload this software module */
1297*0Sstevel@tonic-gate 	if ((punload_soft = setup_unload_soft(pent)) == NULL) {
1298*0Sstevel@tonic-gate 		(void) close(fd);
1299*0Sstevel@tonic-gate 		return (FAILURE);
1300*0Sstevel@tonic-gate 	}
1301*0Sstevel@tonic-gate 
1302*0Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_UNLOAD_SOFT_MODULE, punload_soft) == -1) {
1303*0Sstevel@tonic-gate 		cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s",
1304*0Sstevel@tonic-gate 		    strerror(errno));
1305*0Sstevel@tonic-gate 		free_entry(pent);
1306*0Sstevel@tonic-gate 		free(punload_soft);
1307*0Sstevel@tonic-gate 		(void) close(fd);
1308*0Sstevel@tonic-gate 		return (FAILURE);
1309*0Sstevel@tonic-gate 	}
1310*0Sstevel@tonic-gate 
1311*0Sstevel@tonic-gate 	if (punload_soft->sm_return_value != CRYPTO_SUCCESS) {
1312*0Sstevel@tonic-gate 		cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl return_value = "
1313*0Sstevel@tonic-gate 		    "%d", punload_soft->sm_return_value);
1314*0Sstevel@tonic-gate 		/*
1315*0Sstevel@tonic-gate 		 * If the return value is CRYPTO_UNKNOWN_PRIVDER, it means
1316*0Sstevel@tonic-gate 		 * that the provider is not registered yet.  Should just
1317*0Sstevel@tonic-gate 		 * continue.
1318*0Sstevel@tonic-gate 		 */
1319*0Sstevel@tonic-gate 		if (punload_soft->sm_return_value != CRYPTO_UNKNOWN_PROVIDER) {
1320*0Sstevel@tonic-gate 			free_entry(pent);
1321*0Sstevel@tonic-gate 			free(punload_soft);
1322*0Sstevel@tonic-gate 			(void) close(fd);
1323*0Sstevel@tonic-gate 			return (FAILURE);
1324*0Sstevel@tonic-gate 		}
1325*0Sstevel@tonic-gate 	}
1326*0Sstevel@tonic-gate 
1327*0Sstevel@tonic-gate 	free(punload_soft);
1328*0Sstevel@tonic-gate 
1329*0Sstevel@tonic-gate 	/*
1330*0Sstevel@tonic-gate 	 * Inform kernel to remove the configuration of this software
1331*0Sstevel@tonic-gate 	 * module.
1332*0Sstevel@tonic-gate 	 */
1333*0Sstevel@tonic-gate 	free_mechlist(pent->suplist);
1334*0Sstevel@tonic-gate 	pent->suplist = NULL;
1335*0Sstevel@tonic-gate 	pent->sup_count = 0;
1336*0Sstevel@tonic-gate 	if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
1337*0Sstevel@tonic-gate 		free_entry(pent);
1338*0Sstevel@tonic-gate 		(void) close(fd);
1339*0Sstevel@tonic-gate 		return (FAILURE);
1340*0Sstevel@tonic-gate 	}
1341*0Sstevel@tonic-gate 
1342*0Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) {
1343*0Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
1344*0Sstevel@tonic-gate 		    strerror(errno));
1345*0Sstevel@tonic-gate 		free_entry(pent);
1346*0Sstevel@tonic-gate 		free(pload_soft_conf);
1347*0Sstevel@tonic-gate 		(void) close(fd);
1348*0Sstevel@tonic-gate 		return (FAILURE);
1349*0Sstevel@tonic-gate 	}
1350*0Sstevel@tonic-gate 
1351*0Sstevel@tonic-gate 	if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
1352*0Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl return_value = "
1353*0Sstevel@tonic-gate 		    "%d", pload_soft_conf->sc_return_value);
1354*0Sstevel@tonic-gate 		free_entry(pent);
1355*0Sstevel@tonic-gate 		free(pload_soft_conf);
1356*0Sstevel@tonic-gate 		(void) close(fd);
1357*0Sstevel@tonic-gate 		return (FAILURE);
1358*0Sstevel@tonic-gate 	}
1359*0Sstevel@tonic-gate 
1360*0Sstevel@tonic-gate 	free(pload_soft_conf);
1361*0Sstevel@tonic-gate 
1362*0Sstevel@tonic-gate 	/* Inform kernel to remove the disabled entries if any */
1363*0Sstevel@tonic-gate 	if (pent->dis_count == 0) {
1364*0Sstevel@tonic-gate 		free_entry(pent);
1365*0Sstevel@tonic-gate 		(void) close(fd);
1366*0Sstevel@tonic-gate 		return (SUCCESS);
1367*0Sstevel@tonic-gate 	} else {
1368*0Sstevel@tonic-gate 		free_mechlist(pent->dislist);
1369*0Sstevel@tonic-gate 		pent->dislist = NULL;
1370*0Sstevel@tonic-gate 		pent->dis_count = 0;
1371*0Sstevel@tonic-gate 	}
1372*0Sstevel@tonic-gate 
1373*0Sstevel@tonic-gate 	if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
1374*0Sstevel@tonic-gate 		free_entry(pent);
1375*0Sstevel@tonic-gate 		(void) close(fd);
1376*0Sstevel@tonic-gate 		return (FAILURE);
1377*0Sstevel@tonic-gate 	}
1378*0Sstevel@tonic-gate 
1379*0Sstevel@tonic-gate 	/* pent is no longer needed; free it */
1380*0Sstevel@tonic-gate 	free_entry(pent);
1381*0Sstevel@tonic-gate 
1382*0Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) {
1383*0Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
1384*0Sstevel@tonic-gate 		    strerror(errno));
1385*0Sstevel@tonic-gate 		free(pload_soft_dis);
1386*0Sstevel@tonic-gate 		(void) close(fd);
1387*0Sstevel@tonic-gate 		return (FAILURE);
1388*0Sstevel@tonic-gate 	}
1389*0Sstevel@tonic-gate 
1390*0Sstevel@tonic-gate 	if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
1391*0Sstevel@tonic-gate 		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
1392*0Sstevel@tonic-gate 		    "%d", pload_soft_dis->sd_return_value);
1393*0Sstevel@tonic-gate 		free(pload_soft_dis);
1394*0Sstevel@tonic-gate 		(void) close(fd);
1395*0Sstevel@tonic-gate 		return (FAILURE);
1396*0Sstevel@tonic-gate 	}
1397*0Sstevel@tonic-gate 
1398*0Sstevel@tonic-gate 	free(pload_soft_dis);
1399*0Sstevel@tonic-gate 	(void) close(fd);
1400*0Sstevel@tonic-gate 	return (SUCCESS);
1401*0Sstevel@tonic-gate }
1402*0Sstevel@tonic-gate 
1403*0Sstevel@tonic-gate 
1404*0Sstevel@tonic-gate /*
1405*0Sstevel@tonic-gate  * Check if a hardware provider is valid.  If it is valid, returns its device
1406*0Sstevel@tonic-gate  * name,  instance number and the number of mechanisms it supports.
1407*0Sstevel@tonic-gate  */
1408*0Sstevel@tonic-gate static int
1409*0Sstevel@tonic-gate check_hardware_provider(char *provname, char *pname, int *pnum, int *pcount)
1410*0Sstevel@tonic-gate {
1411*0Sstevel@tonic-gate 	crypto_get_dev_list_t *dev_list = NULL;
1412*0Sstevel@tonic-gate 	int	i;
1413*0Sstevel@tonic-gate 
1414*0Sstevel@tonic-gate 	if (provname == NULL) {
1415*0Sstevel@tonic-gate 		return (FAILURE);
1416*0Sstevel@tonic-gate 	}
1417*0Sstevel@tonic-gate 
1418*0Sstevel@tonic-gate 	/* First, get the device name and the instance number from provname */
1419*0Sstevel@tonic-gate 	if (split_hw_provname(provname, pname, pnum) == FAILURE) {
1420*0Sstevel@tonic-gate 		return (FAILURE);
1421*0Sstevel@tonic-gate 	}
1422*0Sstevel@tonic-gate 
1423*0Sstevel@tonic-gate 	/*
1424*0Sstevel@tonic-gate 	 * Get the complete device list from kernel and check if this provider
1425*0Sstevel@tonic-gate 	 * is in the list.
1426*0Sstevel@tonic-gate 	 */
1427*0Sstevel@tonic-gate 	if (get_dev_list(&dev_list) == FAILURE) {
1428*0Sstevel@tonic-gate 		return (FAILURE);
1429*0Sstevel@tonic-gate 	}
1430*0Sstevel@tonic-gate 
1431*0Sstevel@tonic-gate 	for (i = 0; i < dev_list->dl_dev_count; i++) {
1432*0Sstevel@tonic-gate 		if ((strcmp(dev_list->dl_devs[i].le_dev_name, pname) == 0) &&
1433*0Sstevel@tonic-gate 		    (dev_list->dl_devs[i].le_dev_instance == *pnum)) {
1434*0Sstevel@tonic-gate 			break;
1435*0Sstevel@tonic-gate 		}
1436*0Sstevel@tonic-gate 	}
1437*0Sstevel@tonic-gate 
1438*0Sstevel@tonic-gate 	if (i == dev_list->dl_dev_count) {
1439*0Sstevel@tonic-gate 		/* didn't find this provider in the kernel device list */
1440*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s does not exist."),
1441*0Sstevel@tonic-gate 		    provname);
1442*0Sstevel@tonic-gate 		free(dev_list);
1443*0Sstevel@tonic-gate 		return (FAILURE);
1444*0Sstevel@tonic-gate 	}
1445*0Sstevel@tonic-gate 
1446*0Sstevel@tonic-gate 	/* This provider is valid.  Get its mechanism count */
1447*0Sstevel@tonic-gate 	*pcount = dev_list->dl_devs[i].le_mechanism_count;
1448*0Sstevel@tonic-gate 
1449*0Sstevel@tonic-gate 	free(dev_list);
1450*0Sstevel@tonic-gate 	return (SUCCESS);
1451*0Sstevel@tonic-gate }
1452