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 /*
30*0Sstevel@tonic-gate  * The ioctl interface for administrative commands.
31*0Sstevel@tonic-gate  */
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate #include <sys/types.h>
34*0Sstevel@tonic-gate #include <sys/modctl.h>
35*0Sstevel@tonic-gate #include <sys/conf.h>
36*0Sstevel@tonic-gate #include <sys/stat.h>
37*0Sstevel@tonic-gate #include <sys/ddi.h>
38*0Sstevel@tonic-gate #include <sys/sunddi.h>
39*0Sstevel@tonic-gate #include <sys/kmem.h>
40*0Sstevel@tonic-gate #include <sys/errno.h>
41*0Sstevel@tonic-gate #include <sys/ksynch.h>
42*0Sstevel@tonic-gate #include <sys/file.h>
43*0Sstevel@tonic-gate #include <sys/open.h>
44*0Sstevel@tonic-gate #include <sys/cred.h>
45*0Sstevel@tonic-gate #include <sys/model.h>
46*0Sstevel@tonic-gate #include <sys/sysmacros.h>
47*0Sstevel@tonic-gate #include <sys/crypto/common.h>
48*0Sstevel@tonic-gate #include <sys/crypto/api.h>
49*0Sstevel@tonic-gate #include <sys/crypto/impl.h>
50*0Sstevel@tonic-gate #include <sys/crypto/sched_impl.h>
51*0Sstevel@tonic-gate #include <sys/crypto/ioctladmin.h>
52*0Sstevel@tonic-gate #include <c2/audit.h>
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate /*
55*0Sstevel@tonic-gate  * DDI entry points.
56*0Sstevel@tonic-gate  */
57*0Sstevel@tonic-gate static int cryptoadm_attach(dev_info_t *, ddi_attach_cmd_t);
58*0Sstevel@tonic-gate static int cryptoadm_detach(dev_info_t *, ddi_detach_cmd_t);
59*0Sstevel@tonic-gate static int cryptoadm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
60*0Sstevel@tonic-gate static int cryptoadm_open(dev_t *, int, int, cred_t *);
61*0Sstevel@tonic-gate static int cryptoadm_close(dev_t, int, int, cred_t *);
62*0Sstevel@tonic-gate static int cryptoadm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate extern void audit_cryptoadm(int, char *, crypto_mech_name_t *, uint_t,
65*0Sstevel@tonic-gate     uint_t, uint32_t, int);
66*0Sstevel@tonic-gate /*
67*0Sstevel@tonic-gate  * Module linkage.
68*0Sstevel@tonic-gate  */
69*0Sstevel@tonic-gate static struct cb_ops cbops = {
70*0Sstevel@tonic-gate 	cryptoadm_open,		/* cb_open */
71*0Sstevel@tonic-gate 	cryptoadm_close,	/* cb_close */
72*0Sstevel@tonic-gate 	nodev,			/* cb_strategy */
73*0Sstevel@tonic-gate 	nodev,			/* cb_print */
74*0Sstevel@tonic-gate 	nodev,			/* cb_dump */
75*0Sstevel@tonic-gate 	nodev,			/* cb_read */
76*0Sstevel@tonic-gate 	nodev,			/* cb_write */
77*0Sstevel@tonic-gate 	cryptoadm_ioctl,	/* cb_ioctl */
78*0Sstevel@tonic-gate 	nodev,			/* cb_devmap */
79*0Sstevel@tonic-gate 	nodev,			/* cb_mmap */
80*0Sstevel@tonic-gate 	nodev,			/* cb_segmap */
81*0Sstevel@tonic-gate 	nochpoll,		/* cb_chpoll */
82*0Sstevel@tonic-gate 	ddi_prop_op,		/* cb_prop_op */
83*0Sstevel@tonic-gate 	NULL,			/* cb_streamtab */
84*0Sstevel@tonic-gate 	D_MP,			/* cb_flag */
85*0Sstevel@tonic-gate 	CB_REV,			/* cb_rev */
86*0Sstevel@tonic-gate 	nodev,			/* cb_aread */
87*0Sstevel@tonic-gate 	nodev,			/* cb_awrite */
88*0Sstevel@tonic-gate };
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate static struct dev_ops devops = {
91*0Sstevel@tonic-gate 	DEVO_REV,		/* devo_rev */
92*0Sstevel@tonic-gate 	0,			/* devo_refcnt */
93*0Sstevel@tonic-gate 	cryptoadm_getinfo,	/* devo_getinfo */
94*0Sstevel@tonic-gate 	nulldev,		/* devo_identify */
95*0Sstevel@tonic-gate 	nulldev,		/* devo_probe */
96*0Sstevel@tonic-gate 	cryptoadm_attach,	/* devo_attach */
97*0Sstevel@tonic-gate 	cryptoadm_detach,	/* devo_detach */
98*0Sstevel@tonic-gate 	nodev,			/* devo_reset */
99*0Sstevel@tonic-gate 	&cbops,			/* devo_cb_ops */
100*0Sstevel@tonic-gate 	NULL,			/* devo_bus_ops */
101*0Sstevel@tonic-gate 	NULL,			/* devo_power */
102*0Sstevel@tonic-gate };
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate static struct modldrv modldrv = {
105*0Sstevel@tonic-gate 	&mod_driverops,					/* drv_modops */
106*0Sstevel@tonic-gate 	"Cryptographic Administrative Interface v%I%",	/* drv_linkinfo */
107*0Sstevel@tonic-gate 	&devops,
108*0Sstevel@tonic-gate };
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate static struct modlinkage modlinkage = {
111*0Sstevel@tonic-gate 	MODREV_1,		/* ml_rev */
112*0Sstevel@tonic-gate 	&modldrv,		/* ml_linkage */
113*0Sstevel@tonic-gate 	NULL
114*0Sstevel@tonic-gate };
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate static dev_info_t	*cryptoadm_dip = NULL;
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate /*
119*0Sstevel@tonic-gate  * DDI entry points.
120*0Sstevel@tonic-gate  */
121*0Sstevel@tonic-gate int
122*0Sstevel@tonic-gate _init(void)
123*0Sstevel@tonic-gate {
124*0Sstevel@tonic-gate 	return (mod_install(&modlinkage));
125*0Sstevel@tonic-gate }
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate int
128*0Sstevel@tonic-gate _fini(void)
129*0Sstevel@tonic-gate {
130*0Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
131*0Sstevel@tonic-gate }
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate int
134*0Sstevel@tonic-gate _info(struct modinfo *modinfop)
135*0Sstevel@tonic-gate {
136*0Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
137*0Sstevel@tonic-gate }
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate /* ARGSUSED */
140*0Sstevel@tonic-gate static int
141*0Sstevel@tonic-gate cryptoadm_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
142*0Sstevel@tonic-gate {
143*0Sstevel@tonic-gate 	switch (cmd) {
144*0Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
145*0Sstevel@tonic-gate 		*result = (void *)cryptoadm_dip;
146*0Sstevel@tonic-gate 		return (DDI_SUCCESS);
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
149*0Sstevel@tonic-gate 		*result = (void *)0;
150*0Sstevel@tonic-gate 		return (DDI_SUCCESS);
151*0Sstevel@tonic-gate 	}
152*0Sstevel@tonic-gate 	return (DDI_FAILURE);
153*0Sstevel@tonic-gate }
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate static int
156*0Sstevel@tonic-gate cryptoadm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
157*0Sstevel@tonic-gate {
158*0Sstevel@tonic-gate 	if (cmd != DDI_ATTACH) {
159*0Sstevel@tonic-gate 		return (DDI_FAILURE);
160*0Sstevel@tonic-gate 	}
161*0Sstevel@tonic-gate 	if (ddi_get_instance(dip) != 0) {
162*0Sstevel@tonic-gate 		/* we only allow instance 0 to attach */
163*0Sstevel@tonic-gate 		return (DDI_FAILURE);
164*0Sstevel@tonic-gate 	}
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	/* create the minor node */
167*0Sstevel@tonic-gate 	if (ddi_create_minor_node(dip, "cryptoadm", S_IFCHR, 0,
168*0Sstevel@tonic-gate 	    DDI_PSEUDO, 0) != DDI_SUCCESS) {
169*0Sstevel@tonic-gate 		cmn_err(CE_WARN, "cryptoadm: failed creating minor node");
170*0Sstevel@tonic-gate 		ddi_remove_minor_node(dip, NULL);
171*0Sstevel@tonic-gate 		return (DDI_FAILURE);
172*0Sstevel@tonic-gate 	}
173*0Sstevel@tonic-gate 
174*0Sstevel@tonic-gate 	cryptoadm_dip = dip;
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
177*0Sstevel@tonic-gate }
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate static int
180*0Sstevel@tonic-gate cryptoadm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
181*0Sstevel@tonic-gate {
182*0Sstevel@tonic-gate 	if (cmd != DDI_DETACH)
183*0Sstevel@tonic-gate 		return (DDI_FAILURE);
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 	cryptoadm_dip = NULL;
186*0Sstevel@tonic-gate 	ddi_remove_minor_node(dip, NULL);
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
189*0Sstevel@tonic-gate }
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate /* ARGSUSED */
192*0Sstevel@tonic-gate static int
193*0Sstevel@tonic-gate cryptoadm_open(dev_t *devp, int flag, int otyp, cred_t *credp)
194*0Sstevel@tonic-gate {
195*0Sstevel@tonic-gate 	if (otyp != OTYP_CHR || cryptoadm_dip == NULL)
196*0Sstevel@tonic-gate 		return (ENXIO);
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 	/* exclusive opens are not supported */
199*0Sstevel@tonic-gate 	if (flag & FEXCL)
200*0Sstevel@tonic-gate 		return (ENOTSUP);
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate 	*devp = makedevice(getmajor(*devp), 0);
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate 	kcf_sched_start();
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate 	return (0);
207*0Sstevel@tonic-gate }
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate /* ARGSUSED */
210*0Sstevel@tonic-gate static int
211*0Sstevel@tonic-gate cryptoadm_close(dev_t dev, int flag, int otyp, cred_t *credp)
212*0Sstevel@tonic-gate {
213*0Sstevel@tonic-gate 	return (0);
214*0Sstevel@tonic-gate }
215*0Sstevel@tonic-gate 
216*0Sstevel@tonic-gate /*
217*0Sstevel@tonic-gate  * Returns TRUE if array of size MAXNAMELEN contains a '\0'
218*0Sstevel@tonic-gate  * termination character, otherwise, it returns FALSE.
219*0Sstevel@tonic-gate  */
220*0Sstevel@tonic-gate static boolean_t
221*0Sstevel@tonic-gate null_terminated(char *array)
222*0Sstevel@tonic-gate {
223*0Sstevel@tonic-gate 	int i;
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate 	for (i = 0; i < MAXNAMELEN; i++)
226*0Sstevel@tonic-gate 		if (array[i] == '\0')
227*0Sstevel@tonic-gate 			return (B_TRUE);
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	return (B_FALSE);
230*0Sstevel@tonic-gate }
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate /*
233*0Sstevel@tonic-gate  * This ioctl returns an array of hardware providers.  Each entry
234*0Sstevel@tonic-gate  * contains a device name, device instance, and number of
235*0Sstevel@tonic-gate  * supported mechanisms.
236*0Sstevel@tonic-gate  */
237*0Sstevel@tonic-gate /* ARGSUSED */
238*0Sstevel@tonic-gate static int
239*0Sstevel@tonic-gate get_dev_list(dev_t dev, caddr_t arg, int mode, int *rval)
240*0Sstevel@tonic-gate {
241*0Sstevel@tonic-gate 	crypto_get_dev_list_t dev_list;
242*0Sstevel@tonic-gate 	crypto_dev_list_entry_t *entries;
243*0Sstevel@tonic-gate 	size_t copyout_size;
244*0Sstevel@tonic-gate 	uint_t count;
245*0Sstevel@tonic-gate 	ulong_t offset;
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 	if (copyin(arg, &dev_list, sizeof (dev_list)) != 0)
248*0Sstevel@tonic-gate 		return (EFAULT);
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 	/* get the list from the core module */
251*0Sstevel@tonic-gate 	if (crypto_get_dev_list(&count, &entries) != 0) {
252*0Sstevel@tonic-gate 		dev_list.dl_return_value = CRYPTO_FAILED;
253*0Sstevel@tonic-gate 		if (copyout(&dev_list, arg, sizeof (dev_list)) != 0) {
254*0Sstevel@tonic-gate 			return (EFAULT);
255*0Sstevel@tonic-gate 		}
256*0Sstevel@tonic-gate 		return (0);
257*0Sstevel@tonic-gate 	}
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate 	/* check if buffer is too small */
260*0Sstevel@tonic-gate 	if (count > dev_list.dl_dev_count) {
261*0Sstevel@tonic-gate 		dev_list.dl_dev_count = count;
262*0Sstevel@tonic-gate 		dev_list.dl_return_value = CRYPTO_BUFFER_TOO_SMALL;
263*0Sstevel@tonic-gate 		crypto_free_dev_list(entries, count);
264*0Sstevel@tonic-gate 		if (copyout(&dev_list, arg, sizeof (dev_list)) != 0) {
265*0Sstevel@tonic-gate 			return (EFAULT);
266*0Sstevel@tonic-gate 		}
267*0Sstevel@tonic-gate 		return (0);
268*0Sstevel@tonic-gate 	}
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate 	dev_list.dl_dev_count = count;
271*0Sstevel@tonic-gate 	dev_list.dl_return_value = CRYPTO_SUCCESS;
272*0Sstevel@tonic-gate 
273*0Sstevel@tonic-gate 	copyout_size = count * sizeof (crypto_dev_list_entry_t);
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate 	/* copyout the first stuff */
276*0Sstevel@tonic-gate 	if (copyout(&dev_list, arg, sizeof (dev_list)) != 0) {
277*0Sstevel@tonic-gate 		crypto_free_dev_list(entries, count);
278*0Sstevel@tonic-gate 		return (EFAULT);
279*0Sstevel@tonic-gate 	}
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 	/* copyout entries */
282*0Sstevel@tonic-gate 	offset = offsetof(crypto_get_dev_list_t, dl_devs);
283*0Sstevel@tonic-gate 	if (count > 0 && copyout(entries, arg + offset, copyout_size) != 0) {
284*0Sstevel@tonic-gate 		crypto_free_dev_list(entries, count);
285*0Sstevel@tonic-gate 		return (EFAULT);
286*0Sstevel@tonic-gate 	}
287*0Sstevel@tonic-gate 	crypto_free_dev_list(entries, count);
288*0Sstevel@tonic-gate 	return (0);
289*0Sstevel@tonic-gate }
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate /*
292*0Sstevel@tonic-gate  * This ioctl returns a buffer containing the null terminated names
293*0Sstevel@tonic-gate  * of software providers.
294*0Sstevel@tonic-gate  */
295*0Sstevel@tonic-gate /* ARGSUSED */
296*0Sstevel@tonic-gate static int
297*0Sstevel@tonic-gate get_soft_list(dev_t dev, caddr_t arg, int mode, int *rval)
298*0Sstevel@tonic-gate {
299*0Sstevel@tonic-gate 	STRUCT_DECL(crypto_get_soft_list, soft_list);
300*0Sstevel@tonic-gate 	char *names;
301*0Sstevel@tonic-gate 	size_t len;
302*0Sstevel@tonic-gate 	uint_t count;
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate 	STRUCT_INIT(soft_list, mode);
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate 	if (copyin(arg, STRUCT_BUF(soft_list), STRUCT_SIZE(soft_list)) != 0)
307*0Sstevel@tonic-gate 		return (EFAULT);
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 	/* get the list from the core module */
310*0Sstevel@tonic-gate 	if (crypto_get_soft_list(&count, &names, &len) != 0) {
311*0Sstevel@tonic-gate 		STRUCT_FSET(soft_list, sl_return_value, CRYPTO_FAILED);
312*0Sstevel@tonic-gate 		if (copyout(STRUCT_BUF(soft_list), arg,
313*0Sstevel@tonic-gate 		    STRUCT_SIZE(soft_list)) != 0) {
314*0Sstevel@tonic-gate 			return (EFAULT);
315*0Sstevel@tonic-gate 		}
316*0Sstevel@tonic-gate 		return (0);
317*0Sstevel@tonic-gate 	}
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 	/* check if buffer is too small */
320*0Sstevel@tonic-gate 	if (len > STRUCT_FGET(soft_list, sl_soft_len)) {
321*0Sstevel@tonic-gate 		STRUCT_FSET(soft_list, sl_soft_count, count);
322*0Sstevel@tonic-gate 		STRUCT_FSET(soft_list, sl_soft_len, len);
323*0Sstevel@tonic-gate 		STRUCT_FSET(soft_list, sl_return_value,
324*0Sstevel@tonic-gate 		    CRYPTO_BUFFER_TOO_SMALL);
325*0Sstevel@tonic-gate 		kmem_free(names, len);
326*0Sstevel@tonic-gate 		if (copyout(STRUCT_BUF(soft_list), arg,
327*0Sstevel@tonic-gate 		    STRUCT_SIZE(soft_list)) != 0) {
328*0Sstevel@tonic-gate 			return (EFAULT);
329*0Sstevel@tonic-gate 		}
330*0Sstevel@tonic-gate 		return (0);
331*0Sstevel@tonic-gate 	}
332*0Sstevel@tonic-gate 
333*0Sstevel@tonic-gate 	STRUCT_FSET(soft_list, sl_soft_count, count);
334*0Sstevel@tonic-gate 	STRUCT_FSET(soft_list, sl_soft_len, len);
335*0Sstevel@tonic-gate 	STRUCT_FSET(soft_list, sl_return_value, CRYPTO_SUCCESS);
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate 	if (count > 0 && copyout(names,
338*0Sstevel@tonic-gate 	    STRUCT_FGETP(soft_list, sl_soft_names), len) != 0) {
339*0Sstevel@tonic-gate 		kmem_free(names, len);
340*0Sstevel@tonic-gate 		return (EFAULT);
341*0Sstevel@tonic-gate 	}
342*0Sstevel@tonic-gate 	kmem_free(names, len);
343*0Sstevel@tonic-gate 
344*0Sstevel@tonic-gate 	if (copyout(STRUCT_BUF(soft_list), arg, STRUCT_SIZE(soft_list)) != 0) {
345*0Sstevel@tonic-gate 		return (EFAULT);
346*0Sstevel@tonic-gate 	}
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	return (0);
349*0Sstevel@tonic-gate }
350*0Sstevel@tonic-gate 
351*0Sstevel@tonic-gate /*
352*0Sstevel@tonic-gate  * This ioctl returns an array of mechanisms supported by the
353*0Sstevel@tonic-gate  * specified device.
354*0Sstevel@tonic-gate  */
355*0Sstevel@tonic-gate /* ARGSUSED */
356*0Sstevel@tonic-gate static int
357*0Sstevel@tonic-gate get_dev_info(dev_t dev, caddr_t arg, int mode, int *rval)
358*0Sstevel@tonic-gate {
359*0Sstevel@tonic-gate 	crypto_get_dev_info_t dev_info;
360*0Sstevel@tonic-gate 	crypto_mech_name_t *entries;
361*0Sstevel@tonic-gate 	size_t copyout_size;
362*0Sstevel@tonic-gate 	uint_t count;
363*0Sstevel@tonic-gate 	ulong_t offset;
364*0Sstevel@tonic-gate 	char *dev_name;
365*0Sstevel@tonic-gate 	int rv;
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate 	if (copyin(arg, &dev_info, sizeof (dev_info)) != 0)
368*0Sstevel@tonic-gate 		return (EFAULT);
369*0Sstevel@tonic-gate 
370*0Sstevel@tonic-gate 	dev_name = dev_info.di_dev_name;
371*0Sstevel@tonic-gate 	/* make sure the device name is null terminated */
372*0Sstevel@tonic-gate 	if (!null_terminated(dev_name)) {
373*0Sstevel@tonic-gate 		dev_info.di_return_value = CRYPTO_ARGUMENTS_BAD;
374*0Sstevel@tonic-gate 		if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) {
375*0Sstevel@tonic-gate 			return (EFAULT);
376*0Sstevel@tonic-gate 		}
377*0Sstevel@tonic-gate 		return (0);
378*0Sstevel@tonic-gate 	}
379*0Sstevel@tonic-gate 
380*0Sstevel@tonic-gate 	/* get mechanism names from the core module */
381*0Sstevel@tonic-gate 	if ((rv = crypto_get_dev_info(dev_name, dev_info.di_dev_instance,
382*0Sstevel@tonic-gate 	    &count, &entries)) != CRYPTO_SUCCESS) {
383*0Sstevel@tonic-gate 		dev_info.di_return_value = rv;
384*0Sstevel@tonic-gate 		if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) {
385*0Sstevel@tonic-gate 			return (EFAULT);
386*0Sstevel@tonic-gate 		}
387*0Sstevel@tonic-gate 		return (0);
388*0Sstevel@tonic-gate 	}
389*0Sstevel@tonic-gate 
390*0Sstevel@tonic-gate 	/* check if buffer is too small */
391*0Sstevel@tonic-gate 	if (count > dev_info.di_count) {
392*0Sstevel@tonic-gate 		dev_info.di_count = count;
393*0Sstevel@tonic-gate 		dev_info.di_return_value = CRYPTO_BUFFER_TOO_SMALL;
394*0Sstevel@tonic-gate 		crypto_free_mech_list(entries, count);
395*0Sstevel@tonic-gate 		if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) {
396*0Sstevel@tonic-gate 			return (EFAULT);
397*0Sstevel@tonic-gate 		}
398*0Sstevel@tonic-gate 		return (0);
399*0Sstevel@tonic-gate 	}
400*0Sstevel@tonic-gate 
401*0Sstevel@tonic-gate 	dev_info.di_count = count;
402*0Sstevel@tonic-gate 	dev_info.di_return_value = CRYPTO_SUCCESS;
403*0Sstevel@tonic-gate 
404*0Sstevel@tonic-gate 	copyout_size = count * sizeof (crypto_mech_name_t);
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate 	/* copyout the first stuff */
407*0Sstevel@tonic-gate 	if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) {
408*0Sstevel@tonic-gate 		crypto_free_mech_list(entries, count);
409*0Sstevel@tonic-gate 		return (EFAULT);
410*0Sstevel@tonic-gate 	}
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 	/* copyout entries */
413*0Sstevel@tonic-gate 	offset = offsetof(crypto_get_dev_info_t, di_list);
414*0Sstevel@tonic-gate 	if (copyout(entries, arg + offset, copyout_size) != 0) {
415*0Sstevel@tonic-gate 		crypto_free_mech_list(entries, count);
416*0Sstevel@tonic-gate 		return (EFAULT);
417*0Sstevel@tonic-gate 	}
418*0Sstevel@tonic-gate 	crypto_free_mech_list(entries, count);
419*0Sstevel@tonic-gate 	return (0);
420*0Sstevel@tonic-gate }
421*0Sstevel@tonic-gate 
422*0Sstevel@tonic-gate /*
423*0Sstevel@tonic-gate  * This ioctl returns an array of mechanisms supported by the
424*0Sstevel@tonic-gate  * specified cryptographic module.
425*0Sstevel@tonic-gate  */
426*0Sstevel@tonic-gate /* ARGSUSED */
427*0Sstevel@tonic-gate static int
428*0Sstevel@tonic-gate get_soft_info(dev_t dev, caddr_t arg, int mode, int *rval)
429*0Sstevel@tonic-gate {
430*0Sstevel@tonic-gate 	crypto_get_soft_info_t soft_info;
431*0Sstevel@tonic-gate 	crypto_mech_name_t *entries;
432*0Sstevel@tonic-gate 	size_t copyout_size;
433*0Sstevel@tonic-gate 	uint_t count;
434*0Sstevel@tonic-gate 	ulong_t offset;
435*0Sstevel@tonic-gate 	char *name;
436*0Sstevel@tonic-gate 
437*0Sstevel@tonic-gate 	if (copyin(arg, &soft_info, sizeof (soft_info)) != 0)
438*0Sstevel@tonic-gate 		return (EFAULT);
439*0Sstevel@tonic-gate 
440*0Sstevel@tonic-gate 	name = soft_info.si_name;
441*0Sstevel@tonic-gate 	/* make sure the provider name is null terminated */
442*0Sstevel@tonic-gate 	if (!null_terminated(name)) {
443*0Sstevel@tonic-gate 		soft_info.si_return_value = CRYPTO_ARGUMENTS_BAD;
444*0Sstevel@tonic-gate 		if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) {
445*0Sstevel@tonic-gate 			return (EFAULT);
446*0Sstevel@tonic-gate 		}
447*0Sstevel@tonic-gate 		return (0);
448*0Sstevel@tonic-gate 	}
449*0Sstevel@tonic-gate 
450*0Sstevel@tonic-gate 	/* get mechanism names from the core module */
451*0Sstevel@tonic-gate 	if (crypto_get_soft_info(name, &count, &entries) != 0) {
452*0Sstevel@tonic-gate 		soft_info.si_return_value = CRYPTO_FAILED;
453*0Sstevel@tonic-gate 		if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) {
454*0Sstevel@tonic-gate 			return (EFAULT);
455*0Sstevel@tonic-gate 		}
456*0Sstevel@tonic-gate 		return (0);
457*0Sstevel@tonic-gate 	}
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 	/* check if buffer is too small */
460*0Sstevel@tonic-gate 	if (count > soft_info.si_count) {
461*0Sstevel@tonic-gate 		soft_info.si_count = count;
462*0Sstevel@tonic-gate 		soft_info.si_return_value = CRYPTO_BUFFER_TOO_SMALL;
463*0Sstevel@tonic-gate 		crypto_free_mech_list(entries, count);
464*0Sstevel@tonic-gate 		if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) {
465*0Sstevel@tonic-gate 			return (EFAULT);
466*0Sstevel@tonic-gate 		}
467*0Sstevel@tonic-gate 		return (0);
468*0Sstevel@tonic-gate 	}
469*0Sstevel@tonic-gate 
470*0Sstevel@tonic-gate 	soft_info.si_count = count;
471*0Sstevel@tonic-gate 	soft_info.si_return_value = CRYPTO_SUCCESS;
472*0Sstevel@tonic-gate 	copyout_size = count * sizeof (crypto_mech_name_t);
473*0Sstevel@tonic-gate 
474*0Sstevel@tonic-gate 	/* copyout the first stuff */
475*0Sstevel@tonic-gate 	if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) {
476*0Sstevel@tonic-gate 		crypto_free_mech_list(entries, count);
477*0Sstevel@tonic-gate 		return (EFAULT);
478*0Sstevel@tonic-gate 	}
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate 	/* copyout entries */
481*0Sstevel@tonic-gate 	offset = offsetof(crypto_get_soft_info_t, si_list);
482*0Sstevel@tonic-gate 	if (copyout(entries, arg + offset, copyout_size) != 0) {
483*0Sstevel@tonic-gate 		crypto_free_mech_list(entries, count);
484*0Sstevel@tonic-gate 		return (EFAULT);
485*0Sstevel@tonic-gate 	}
486*0Sstevel@tonic-gate 	crypto_free_mech_list(entries, count);
487*0Sstevel@tonic-gate 	return (0);
488*0Sstevel@tonic-gate }
489*0Sstevel@tonic-gate 
490*0Sstevel@tonic-gate /*
491*0Sstevel@tonic-gate  * This ioctl disables mechanisms supported by the specified device.
492*0Sstevel@tonic-gate  */
493*0Sstevel@tonic-gate /* ARGSUSED */
494*0Sstevel@tonic-gate static int
495*0Sstevel@tonic-gate load_dev_disabled(dev_t dev, caddr_t arg, int mode, int *rval)
496*0Sstevel@tonic-gate {
497*0Sstevel@tonic-gate 	crypto_load_dev_disabled_t dev_disabled;
498*0Sstevel@tonic-gate 	crypto_mech_name_t *entries;
499*0Sstevel@tonic-gate 	size_t size;
500*0Sstevel@tonic-gate 	ulong_t offset;
501*0Sstevel@tonic-gate 	uint_t count;
502*0Sstevel@tonic-gate 	uint_t instance;
503*0Sstevel@tonic-gate 	char *dev_name;
504*0Sstevel@tonic-gate 	uint32_t rv;
505*0Sstevel@tonic-gate 	int error = 0;
506*0Sstevel@tonic-gate 
507*0Sstevel@tonic-gate 	if (copyin(arg, &dev_disabled, sizeof (dev_disabled)) != 0) {
508*0Sstevel@tonic-gate 		error =  EFAULT;
509*0Sstevel@tonic-gate 		goto out2;
510*0Sstevel@tonic-gate 	}
511*0Sstevel@tonic-gate 
512*0Sstevel@tonic-gate 	dev_name = dev_disabled.dd_dev_name;
513*0Sstevel@tonic-gate 	/* make sure the device name is null terminated */
514*0Sstevel@tonic-gate 	if (!null_terminated(dev_name)) {
515*0Sstevel@tonic-gate 		rv = CRYPTO_ARGUMENTS_BAD;
516*0Sstevel@tonic-gate 		goto out;
517*0Sstevel@tonic-gate 	}
518*0Sstevel@tonic-gate 
519*0Sstevel@tonic-gate 	count = dev_disabled.dd_count;
520*0Sstevel@tonic-gate 	instance = dev_disabled.dd_dev_instance;
521*0Sstevel@tonic-gate 	if (count == 0) {
522*0Sstevel@tonic-gate 		/* remove the entry */
523*0Sstevel@tonic-gate 		if (crypto_load_dev_disabled(dev_name, instance, 0, NULL) != 0)
524*0Sstevel@tonic-gate 			rv = CRYPTO_FAILED;
525*0Sstevel@tonic-gate 		else
526*0Sstevel@tonic-gate 			rv = CRYPTO_SUCCESS;
527*0Sstevel@tonic-gate 		goto out;
528*0Sstevel@tonic-gate 	}
529*0Sstevel@tonic-gate 
530*0Sstevel@tonic-gate 	if (count > KCF_MAXMECHS) {
531*0Sstevel@tonic-gate 		rv = CRYPTO_ARGUMENTS_BAD;
532*0Sstevel@tonic-gate 		goto out;
533*0Sstevel@tonic-gate 	}
534*0Sstevel@tonic-gate 
535*0Sstevel@tonic-gate 	size = count * sizeof (crypto_mech_name_t);
536*0Sstevel@tonic-gate 	entries = kmem_alloc(size, KM_SLEEP);
537*0Sstevel@tonic-gate 
538*0Sstevel@tonic-gate 	offset = offsetof(crypto_load_dev_disabled_t, dd_list);
539*0Sstevel@tonic-gate 	if (copyin(arg + offset, entries, size) != 0) {
540*0Sstevel@tonic-gate 		kmem_free(entries, size);
541*0Sstevel@tonic-gate 		error = EFAULT;
542*0Sstevel@tonic-gate 		goto out2;
543*0Sstevel@tonic-gate 	}
544*0Sstevel@tonic-gate 
545*0Sstevel@tonic-gate 	/* 'entries' consumed (but not freed) by crypto_load_dev_disabled() */
546*0Sstevel@tonic-gate 	if (crypto_load_dev_disabled(dev_name, instance, count, entries) != 0) {
547*0Sstevel@tonic-gate 		kmem_free(entries, size);
548*0Sstevel@tonic-gate 		rv = CRYPTO_FAILED;
549*0Sstevel@tonic-gate 		goto out;
550*0Sstevel@tonic-gate 	}
551*0Sstevel@tonic-gate 	rv = CRYPTO_SUCCESS;
552*0Sstevel@tonic-gate out:
553*0Sstevel@tonic-gate 	dev_disabled.dd_return_value = rv;
554*0Sstevel@tonic-gate 
555*0Sstevel@tonic-gate 	if (copyout(&dev_disabled, arg, sizeof (dev_disabled)) != 0) {
556*0Sstevel@tonic-gate 		error = EFAULT;
557*0Sstevel@tonic-gate 	}
558*0Sstevel@tonic-gate out2:
559*0Sstevel@tonic-gate #ifdef C2_AUDIT
560*0Sstevel@tonic-gate 	if (audit_active)
561*0Sstevel@tonic-gate 		audit_cryptoadm(CRYPTO_LOAD_DEV_DISABLED, dev_name, entries,
562*0Sstevel@tonic-gate 		    count, instance, rv, error);
563*0Sstevel@tonic-gate #endif
564*0Sstevel@tonic-gate 	return (error);
565*0Sstevel@tonic-gate }
566*0Sstevel@tonic-gate 
567*0Sstevel@tonic-gate /*
568*0Sstevel@tonic-gate  * This ioctl disables mechanisms supported by the specified
569*0Sstevel@tonic-gate  * cryptographic module.
570*0Sstevel@tonic-gate  */
571*0Sstevel@tonic-gate /* ARGSUSED */
572*0Sstevel@tonic-gate static int
573*0Sstevel@tonic-gate load_soft_disabled(dev_t dev, caddr_t arg, int mode, int *rval)
574*0Sstevel@tonic-gate {
575*0Sstevel@tonic-gate 	crypto_load_soft_disabled_t soft_disabled;
576*0Sstevel@tonic-gate 	crypto_mech_name_t *entries;
577*0Sstevel@tonic-gate 	size_t size;
578*0Sstevel@tonic-gate 	uint_t count;
579*0Sstevel@tonic-gate 	ulong_t offset;
580*0Sstevel@tonic-gate 	char *name;
581*0Sstevel@tonic-gate 	uint32_t rv;
582*0Sstevel@tonic-gate 	int error = 0;
583*0Sstevel@tonic-gate 
584*0Sstevel@tonic-gate 	if (copyin(arg, &soft_disabled, sizeof (soft_disabled)) != 0) {
585*0Sstevel@tonic-gate 		error = EFAULT;
586*0Sstevel@tonic-gate 		goto out2;
587*0Sstevel@tonic-gate 	}
588*0Sstevel@tonic-gate 
589*0Sstevel@tonic-gate 	name = soft_disabled.sd_name;
590*0Sstevel@tonic-gate 	/* make sure the name is null terminated */
591*0Sstevel@tonic-gate 	if (!null_terminated(name)) {
592*0Sstevel@tonic-gate 		soft_disabled.sd_return_value = CRYPTO_ARGUMENTS_BAD;
593*0Sstevel@tonic-gate 		if (copyout(&soft_disabled, arg, sizeof (soft_disabled)) != 0) {
594*0Sstevel@tonic-gate 			return (EFAULT);
595*0Sstevel@tonic-gate 		}
596*0Sstevel@tonic-gate 		return (0);
597*0Sstevel@tonic-gate 	}
598*0Sstevel@tonic-gate 
599*0Sstevel@tonic-gate 	count = soft_disabled.sd_count;
600*0Sstevel@tonic-gate 	if (count == 0) {
601*0Sstevel@tonic-gate 		/* remove the entry */
602*0Sstevel@tonic-gate 		if (crypto_load_soft_disabled(name, 0, NULL) != 0) {
603*0Sstevel@tonic-gate 			rv = CRYPTO_FAILED;
604*0Sstevel@tonic-gate 		} else {
605*0Sstevel@tonic-gate 			rv = CRYPTO_SUCCESS;
606*0Sstevel@tonic-gate 		}
607*0Sstevel@tonic-gate 		goto out;
608*0Sstevel@tonic-gate 	}
609*0Sstevel@tonic-gate 
610*0Sstevel@tonic-gate 	if (count > KCF_MAXMECHS) {
611*0Sstevel@tonic-gate 		rv = CRYPTO_ARGUMENTS_BAD;
612*0Sstevel@tonic-gate 		goto out;
613*0Sstevel@tonic-gate 	}
614*0Sstevel@tonic-gate 
615*0Sstevel@tonic-gate 	size = count * sizeof (crypto_mech_name_t);
616*0Sstevel@tonic-gate 	entries = kmem_alloc(size, KM_SLEEP);
617*0Sstevel@tonic-gate 
618*0Sstevel@tonic-gate 	offset = offsetof(crypto_load_soft_disabled_t, sd_list);
619*0Sstevel@tonic-gate 	if (copyin(arg + offset, entries, size) != 0) {
620*0Sstevel@tonic-gate 		kmem_free(entries, size);
621*0Sstevel@tonic-gate 		error = EFAULT;
622*0Sstevel@tonic-gate 		goto out2;
623*0Sstevel@tonic-gate 	}
624*0Sstevel@tonic-gate 
625*0Sstevel@tonic-gate 	/* 'entries' is consumed by crypto_load_soft_disabled() */
626*0Sstevel@tonic-gate 	if (crypto_load_soft_disabled(name, count, entries) != 0) {
627*0Sstevel@tonic-gate 		kmem_free(entries, size);
628*0Sstevel@tonic-gate 		rv = CRYPTO_FAILED;
629*0Sstevel@tonic-gate 		goto out;
630*0Sstevel@tonic-gate 	}
631*0Sstevel@tonic-gate 	rv = CRYPTO_SUCCESS;
632*0Sstevel@tonic-gate out:
633*0Sstevel@tonic-gate 	soft_disabled.sd_return_value = rv;
634*0Sstevel@tonic-gate 
635*0Sstevel@tonic-gate 	if (copyout(&soft_disabled, arg, sizeof (soft_disabled)) != 0) {
636*0Sstevel@tonic-gate 		error = EFAULT;
637*0Sstevel@tonic-gate 	}
638*0Sstevel@tonic-gate out2:
639*0Sstevel@tonic-gate #ifdef C2_AUDIT
640*0Sstevel@tonic-gate 	if (audit_active)
641*0Sstevel@tonic-gate 		audit_cryptoadm(CRYPTO_LOAD_SOFT_DISABLED, name, entries,
642*0Sstevel@tonic-gate 		    count, 0, rv, error);
643*0Sstevel@tonic-gate #endif
644*0Sstevel@tonic-gate 	return (error);
645*0Sstevel@tonic-gate }
646*0Sstevel@tonic-gate 
647*0Sstevel@tonic-gate /*
648*0Sstevel@tonic-gate  * This ioctl loads the supported mechanisms of the specfied cryptographic
649*0Sstevel@tonic-gate  * module.  This is so, at boot time, all software providers do not
650*0Sstevel@tonic-gate  * have to be opened in order to cause them to register their
651*0Sstevel@tonic-gate  * supported mechanisms.
652*0Sstevel@tonic-gate  */
653*0Sstevel@tonic-gate /* ARGSUSED */
654*0Sstevel@tonic-gate static int
655*0Sstevel@tonic-gate load_soft_config(dev_t dev, caddr_t arg, int mode, int *rval)
656*0Sstevel@tonic-gate {
657*0Sstevel@tonic-gate 	crypto_load_soft_config_t soft_config;
658*0Sstevel@tonic-gate 	crypto_mech_name_t *entries;
659*0Sstevel@tonic-gate 	size_t size;
660*0Sstevel@tonic-gate 	uint_t count;
661*0Sstevel@tonic-gate 	ulong_t offset;
662*0Sstevel@tonic-gate 	char *name;
663*0Sstevel@tonic-gate 	uint32_t rv;
664*0Sstevel@tonic-gate 	int error = 0;
665*0Sstevel@tonic-gate 
666*0Sstevel@tonic-gate 	if (copyin(arg, &soft_config, sizeof (soft_config)) != 0) {
667*0Sstevel@tonic-gate 		error = EFAULT;
668*0Sstevel@tonic-gate 		goto out2;
669*0Sstevel@tonic-gate 	}
670*0Sstevel@tonic-gate 
671*0Sstevel@tonic-gate 	name = soft_config.sc_name;
672*0Sstevel@tonic-gate 	/* make sure the name is null terminated */
673*0Sstevel@tonic-gate 	if (!null_terminated(name)) {
674*0Sstevel@tonic-gate 		soft_config.sc_return_value = CRYPTO_ARGUMENTS_BAD;
675*0Sstevel@tonic-gate 		if (copyout(&soft_config, arg, sizeof (soft_config)) != 0) {
676*0Sstevel@tonic-gate 			return (EFAULT);
677*0Sstevel@tonic-gate 		}
678*0Sstevel@tonic-gate 		return (0);
679*0Sstevel@tonic-gate 	}
680*0Sstevel@tonic-gate 
681*0Sstevel@tonic-gate 	count = soft_config.sc_count;
682*0Sstevel@tonic-gate 	if (count == 0) {
683*0Sstevel@tonic-gate 		if (crypto_load_soft_config(name, 0, NULL) != 0) {
684*0Sstevel@tonic-gate 			rv = CRYPTO_FAILED;
685*0Sstevel@tonic-gate 		} else {
686*0Sstevel@tonic-gate 			rv = CRYPTO_SUCCESS;
687*0Sstevel@tonic-gate 		}
688*0Sstevel@tonic-gate 		goto out;
689*0Sstevel@tonic-gate 	}
690*0Sstevel@tonic-gate 
691*0Sstevel@tonic-gate 	if (count > KCF_MAXMECHS) {
692*0Sstevel@tonic-gate 		rv = CRYPTO_ARGUMENTS_BAD;
693*0Sstevel@tonic-gate 		goto out;
694*0Sstevel@tonic-gate 	}
695*0Sstevel@tonic-gate 
696*0Sstevel@tonic-gate 	size = count * sizeof (crypto_mech_name_t);
697*0Sstevel@tonic-gate 	entries = kmem_alloc(size, KM_SLEEP);
698*0Sstevel@tonic-gate 
699*0Sstevel@tonic-gate 	offset = offsetof(crypto_load_soft_config_t, sc_list);
700*0Sstevel@tonic-gate 	if (copyin(arg + offset, entries, size) != 0) {
701*0Sstevel@tonic-gate 		kmem_free(entries, size);
702*0Sstevel@tonic-gate 		error = EFAULT;
703*0Sstevel@tonic-gate 		goto out2;
704*0Sstevel@tonic-gate 	}
705*0Sstevel@tonic-gate 
706*0Sstevel@tonic-gate 	/*
707*0Sstevel@tonic-gate 	 * 'entries' is consumed (but not freed) by
708*0Sstevel@tonic-gate 	 * crypto_load_soft_config()
709*0Sstevel@tonic-gate 	 */
710*0Sstevel@tonic-gate 	if (crypto_load_soft_config(name, count, entries) != 0) {
711*0Sstevel@tonic-gate 		kmem_free(entries, size);
712*0Sstevel@tonic-gate 		rv = CRYPTO_FAILED;
713*0Sstevel@tonic-gate 		goto out;
714*0Sstevel@tonic-gate 	}
715*0Sstevel@tonic-gate 	rv = CRYPTO_SUCCESS;
716*0Sstevel@tonic-gate out:
717*0Sstevel@tonic-gate 	soft_config.sc_return_value = rv;
718*0Sstevel@tonic-gate 
719*0Sstevel@tonic-gate 	if (copyout(&soft_config, arg, sizeof (soft_config)) != 0) {
720*0Sstevel@tonic-gate 		error = EFAULT;
721*0Sstevel@tonic-gate 	}
722*0Sstevel@tonic-gate out2:
723*0Sstevel@tonic-gate #ifdef C2_AUDIT
724*0Sstevel@tonic-gate 	if (audit_active)
725*0Sstevel@tonic-gate 		audit_cryptoadm(CRYPTO_LOAD_SOFT_CONFIG, name, entries, count,
726*0Sstevel@tonic-gate 		    0, rv, error);
727*0Sstevel@tonic-gate #endif
728*0Sstevel@tonic-gate 	return (error);
729*0Sstevel@tonic-gate }
730*0Sstevel@tonic-gate 
731*0Sstevel@tonic-gate /*
732*0Sstevel@tonic-gate  * This ioctl unloads the specfied cryptographic module and removes
733*0Sstevel@tonic-gate  * its table of supported mechanisms.
734*0Sstevel@tonic-gate  */
735*0Sstevel@tonic-gate /* ARGSUSED */
736*0Sstevel@tonic-gate static int
737*0Sstevel@tonic-gate unload_soft_module(dev_t dev, caddr_t arg, int mode, int *rval)
738*0Sstevel@tonic-gate {
739*0Sstevel@tonic-gate 	crypto_unload_soft_module_t unload_soft_module;
740*0Sstevel@tonic-gate 	char *name;
741*0Sstevel@tonic-gate 	uint32_t rv;
742*0Sstevel@tonic-gate 	int error = 0;
743*0Sstevel@tonic-gate 
744*0Sstevel@tonic-gate 	if (copyin(arg, &unload_soft_module,
745*0Sstevel@tonic-gate 	    sizeof (unload_soft_module)) != 0) {
746*0Sstevel@tonic-gate 		error = EFAULT;
747*0Sstevel@tonic-gate 		goto out2;
748*0Sstevel@tonic-gate 	}
749*0Sstevel@tonic-gate 
750*0Sstevel@tonic-gate 	name = unload_soft_module.sm_name;
751*0Sstevel@tonic-gate 	/* make sure the name is null terminated */
752*0Sstevel@tonic-gate 	if (!null_terminated(name)) {
753*0Sstevel@tonic-gate 		unload_soft_module.sm_return_value = CRYPTO_ARGUMENTS_BAD;
754*0Sstevel@tonic-gate 		if (copyout(&unload_soft_module, arg,
755*0Sstevel@tonic-gate 		    sizeof (unload_soft_module)) != 0) {
756*0Sstevel@tonic-gate 			return (EFAULT);
757*0Sstevel@tonic-gate 		}
758*0Sstevel@tonic-gate 		return (0);
759*0Sstevel@tonic-gate 	}
760*0Sstevel@tonic-gate 
761*0Sstevel@tonic-gate 	rv = crypto_unload_soft_module(name);
762*0Sstevel@tonic-gate out:
763*0Sstevel@tonic-gate 	unload_soft_module.sm_return_value = rv;
764*0Sstevel@tonic-gate 
765*0Sstevel@tonic-gate 	if (copyout(&unload_soft_module, arg,
766*0Sstevel@tonic-gate 	    sizeof (unload_soft_module)) != 0) {
767*0Sstevel@tonic-gate 		error = EFAULT;
768*0Sstevel@tonic-gate 	}
769*0Sstevel@tonic-gate out2:
770*0Sstevel@tonic-gate #ifdef C2_AUDIT
771*0Sstevel@tonic-gate 	if (audit_active)
772*0Sstevel@tonic-gate 		audit_cryptoadm(CRYPTO_UNLOAD_SOFT_MODULE, name, NULL, 0, 0,
773*0Sstevel@tonic-gate 		    rv, error);
774*0Sstevel@tonic-gate #endif
775*0Sstevel@tonic-gate 
776*0Sstevel@tonic-gate 	return (error);
777*0Sstevel@tonic-gate }
778*0Sstevel@tonic-gate 
779*0Sstevel@tonic-gate /*
780*0Sstevel@tonic-gate  * This ioctl loads a door descriptor into the  kernel.  The descriptor
781*0Sstevel@tonic-gate  * is used for module verification.
782*0Sstevel@tonic-gate  */
783*0Sstevel@tonic-gate /* ARGSUSED */
784*0Sstevel@tonic-gate static int
785*0Sstevel@tonic-gate load_door(dev_t dev, caddr_t arg, int mode, int *rval)
786*0Sstevel@tonic-gate {
787*0Sstevel@tonic-gate 	crypto_load_door_t load_door;
788*0Sstevel@tonic-gate 	uint32_t rv;
789*0Sstevel@tonic-gate 	int error = 0;
790*0Sstevel@tonic-gate 
791*0Sstevel@tonic-gate 	if (copyin(arg, &load_door, sizeof (crypto_load_door_t)) != 0) {
792*0Sstevel@tonic-gate 		error = EFAULT;
793*0Sstevel@tonic-gate 		goto out2;
794*0Sstevel@tonic-gate 	}
795*0Sstevel@tonic-gate 
796*0Sstevel@tonic-gate 	if (crypto_load_door(load_door.ld_did) != 0) {
797*0Sstevel@tonic-gate 		rv = CRYPTO_FAILED;
798*0Sstevel@tonic-gate 		goto out;
799*0Sstevel@tonic-gate 	}
800*0Sstevel@tonic-gate 	rv = CRYPTO_SUCCESS;
801*0Sstevel@tonic-gate out:
802*0Sstevel@tonic-gate 	load_door.ld_return_value = rv;
803*0Sstevel@tonic-gate 
804*0Sstevel@tonic-gate 	if (copyout(&load_door, arg, sizeof (crypto_load_door_t)) != 0)
805*0Sstevel@tonic-gate 		error = EFAULT;
806*0Sstevel@tonic-gate 
807*0Sstevel@tonic-gate out2:
808*0Sstevel@tonic-gate #ifdef C2_AUDIT
809*0Sstevel@tonic-gate 	if (audit_active)
810*0Sstevel@tonic-gate 		audit_cryptoadm(CRYPTO_LOAD_DOOR, NULL, NULL,
811*0Sstevel@tonic-gate 		    0, 0, rv, error);
812*0Sstevel@tonic-gate #endif
813*0Sstevel@tonic-gate 	return (error);
814*0Sstevel@tonic-gate }
815*0Sstevel@tonic-gate 
816*0Sstevel@tonic-gate static int
817*0Sstevel@tonic-gate cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
818*0Sstevel@tonic-gate     int *rval)
819*0Sstevel@tonic-gate {
820*0Sstevel@tonic-gate 	int error;
821*0Sstevel@tonic-gate #define	ARG	((caddr_t)arg)
822*0Sstevel@tonic-gate 
823*0Sstevel@tonic-gate 	switch (cmd) {
824*0Sstevel@tonic-gate 	case CRYPTO_LOAD_DEV_DISABLED:
825*0Sstevel@tonic-gate 	case CRYPTO_LOAD_SOFT_DISABLED:
826*0Sstevel@tonic-gate 	case CRYPTO_LOAD_SOFT_CONFIG:
827*0Sstevel@tonic-gate 	case CRYPTO_UNLOAD_SOFT_MODULE:
828*0Sstevel@tonic-gate 	case CRYPTO_POOL_CREATE:
829*0Sstevel@tonic-gate 	case CRYPTO_POOL_WAIT:
830*0Sstevel@tonic-gate 	case CRYPTO_POOL_RUN:
831*0Sstevel@tonic-gate 	case CRYPTO_LOAD_DOOR:
832*0Sstevel@tonic-gate 		if ((error = drv_priv(c)) != 0)
833*0Sstevel@tonic-gate 			return (error);
834*0Sstevel@tonic-gate 	default:
835*0Sstevel@tonic-gate 		break;
836*0Sstevel@tonic-gate 	}
837*0Sstevel@tonic-gate 
838*0Sstevel@tonic-gate 	switch (cmd) {
839*0Sstevel@tonic-gate 	case CRYPTO_GET_DEV_LIST:
840*0Sstevel@tonic-gate 		return (get_dev_list(dev, ARG, mode, rval));
841*0Sstevel@tonic-gate 
842*0Sstevel@tonic-gate 	case CRYPTO_GET_DEV_INFO:
843*0Sstevel@tonic-gate 		return (get_dev_info(dev, ARG, mode, rval));
844*0Sstevel@tonic-gate 
845*0Sstevel@tonic-gate 	case CRYPTO_GET_SOFT_LIST:
846*0Sstevel@tonic-gate 		return (get_soft_list(dev, ARG, mode, rval));
847*0Sstevel@tonic-gate 
848*0Sstevel@tonic-gate 	case CRYPTO_GET_SOFT_INFO:
849*0Sstevel@tonic-gate 		return (get_soft_info(dev, ARG, mode, rval));
850*0Sstevel@tonic-gate 
851*0Sstevel@tonic-gate 	case CRYPTO_LOAD_DEV_DISABLED:
852*0Sstevel@tonic-gate 		return (load_dev_disabled(dev, ARG, mode, rval));
853*0Sstevel@tonic-gate 
854*0Sstevel@tonic-gate 	case CRYPTO_LOAD_SOFT_DISABLED:
855*0Sstevel@tonic-gate 		return (load_soft_disabled(dev, ARG, mode, rval));
856*0Sstevel@tonic-gate 
857*0Sstevel@tonic-gate 	case CRYPTO_LOAD_SOFT_CONFIG:
858*0Sstevel@tonic-gate 		return (load_soft_config(dev, ARG, mode, rval));
859*0Sstevel@tonic-gate 
860*0Sstevel@tonic-gate 	case CRYPTO_UNLOAD_SOFT_MODULE:
861*0Sstevel@tonic-gate 		return (unload_soft_module(dev, ARG, mode, rval));
862*0Sstevel@tonic-gate 
863*0Sstevel@tonic-gate 	case CRYPTO_POOL_CREATE:
864*0Sstevel@tonic-gate 		/*
865*0Sstevel@tonic-gate 		 * The framework allocates and initializes the pool.
866*0Sstevel@tonic-gate 		 * So, this is a no op. We are keeping this ioctl around
867*0Sstevel@tonic-gate 		 * to be used for any future threadpool related work.
868*0Sstevel@tonic-gate 		 */
869*0Sstevel@tonic-gate #ifdef C2_AUDIT
870*0Sstevel@tonic-gate 		if (audit_active)
871*0Sstevel@tonic-gate 			audit_cryptoadm(CRYPTO_POOL_CREATE, NULL, NULL,
872*0Sstevel@tonic-gate 			    0, 0, 0, 0);
873*0Sstevel@tonic-gate #endif
874*0Sstevel@tonic-gate 		return (0);
875*0Sstevel@tonic-gate 
876*0Sstevel@tonic-gate 	case CRYPTO_POOL_WAIT: {
877*0Sstevel@tonic-gate 		int nthrs = 0, err;
878*0Sstevel@tonic-gate 
879*0Sstevel@tonic-gate 		if ((err = kcf_svc_wait(&nthrs)) == 0) {
880*0Sstevel@tonic-gate 			if (copyout((caddr_t)&nthrs, ARG, sizeof (int))
881*0Sstevel@tonic-gate 			    == -1)
882*0Sstevel@tonic-gate 				err = EFAULT;
883*0Sstevel@tonic-gate 		}
884*0Sstevel@tonic-gate #ifdef C2_AUDIT
885*0Sstevel@tonic-gate 		if (audit_active)
886*0Sstevel@tonic-gate 			audit_cryptoadm(CRYPTO_POOL_WAIT, NULL, NULL,
887*0Sstevel@tonic-gate 			    0, 0, 0, err);
888*0Sstevel@tonic-gate #endif
889*0Sstevel@tonic-gate 		return (err);
890*0Sstevel@tonic-gate 	}
891*0Sstevel@tonic-gate 
892*0Sstevel@tonic-gate 	case CRYPTO_POOL_RUN: {
893*0Sstevel@tonic-gate 		int err;
894*0Sstevel@tonic-gate 
895*0Sstevel@tonic-gate 		err = kcf_svc_do_run();
896*0Sstevel@tonic-gate #ifdef C2_AUDIT
897*0Sstevel@tonic-gate 		if (audit_active)
898*0Sstevel@tonic-gate 			audit_cryptoadm(CRYPTO_POOL_RUN, NULL, NULL,
899*0Sstevel@tonic-gate 			    0, 0, 0, err);
900*0Sstevel@tonic-gate #endif
901*0Sstevel@tonic-gate 		return (err);
902*0Sstevel@tonic-gate 	}
903*0Sstevel@tonic-gate 
904*0Sstevel@tonic-gate 	case CRYPTO_LOAD_DOOR:
905*0Sstevel@tonic-gate 		return (load_door(dev, ARG, mode, rval));
906*0Sstevel@tonic-gate 	}
907*0Sstevel@tonic-gate 	return (EINVAL);
908*0Sstevel@tonic-gate }
909