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