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