xref: /titanic_44/usr/src/uts/common/crypto/io/cryptoadm.c (revision 3c112a2b34403220c06c3e2fcac403358cfba168)
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  */
56 static int cryptoadm_attach(dev_info_t *, ddi_attach_cmd_t);
57 static int cryptoadm_detach(dev_info_t *, ddi_detach_cmd_t);
58 static int cryptoadm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
59 static int cryptoadm_open(dev_t *, int, int, cred_t *);
60 static int cryptoadm_close(dev_t, int, int, cred_t *);
61 static int cryptoadm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
62 
63 extern void audit_cryptoadm(int, char *, crypto_mech_name_t *, uint_t,
64     uint_t, uint32_t, int);
65 
66 /*
67  * Module linkage.
68  */
69 static 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 
90 static 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 
105 static struct modldrv modldrv = {
106 	&mod_driverops,					/* drv_modops */
107 	"Cryptographic Administrative Interface",	/* drv_linkinfo */
108 	&devops,
109 };
110 
111 static struct modlinkage modlinkage = {
112 	MODREV_1,		/* ml_rev */
113 	&modldrv,		/* ml_linkage */
114 	NULL
115 };
116 
117 static dev_info_t	*cryptoadm_dip = NULL;
118 
119 /*
120  * DDI entry points.
121  */
122 int
123 _init(void)
124 {
125 	return (mod_install(&modlinkage));
126 }
127 
128 int
129 _fini(void)
130 {
131 	return (mod_remove(&modlinkage));
132 }
133 
134 int
135 _info(struct modinfo *modinfop)
136 {
137 	return (mod_info(&modlinkage, modinfop));
138 }
139 
140 /* ARGSUSED */
141 static int
142 cryptoadm_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 
156 static int
157 cryptoadm_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 
181 static int
182 cryptoadm_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 */
194 static int
195 cryptoadm_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 */
212 static int
213 cryptoadm_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  */
222 static boolean_t
223 null_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 */
240 static int
241 get_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 */
298 static int
299 get_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 */
358 static int
359 get_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 */
429 static int
430 get_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 */
496 static int
497 load_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;
554 out:
555 	dev_disabled.dd_return_value = rv;
556 
557 	if (copyout(&dev_disabled, arg, sizeof (dev_disabled)) != 0) {
558 		error = EFAULT;
559 	}
560 out2:
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 */
572 static int
573 load_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;
632 out:
633 	soft_disabled.sd_return_value = rv;
634 
635 	if (copyout(&soft_disabled, arg, sizeof (soft_disabled)) != 0) {
636 		error = EFAULT;
637 	}
638 out2:
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 */
652 static int
653 load_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;
714 out:
715 	soft_config.sc_return_value = rv;
716 
717 	if (copyout(&soft_config, arg, sizeof (soft_config)) != 0) {
718 		error = EFAULT;
719 	}
720 out2:
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 */
732 static int
733 unload_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);
758 out:
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 	}
765 out2:
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 */
778 static int
779 load_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;
795 out:
796 	load_door.ld_return_value = rv;
797 
798 	if (copyout(&load_door, arg, sizeof (crypto_load_door_t)) != 0)
799 		error = EFAULT;
800 
801 out2:
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 */
820 static int
821 fips140_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 
881 static int
882 cryptoadm_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