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
_init(void)123 _init(void)
124 {
125 return (mod_install(&modlinkage));
126 }
127
128 int
_fini(void)129 _fini(void)
130 {
131 return (mod_remove(&modlinkage));
132 }
133
134 int
_info(struct modinfo * modinfop)135 _info(struct modinfo *modinfop)
136 {
137 return (mod_info(&modlinkage, modinfop));
138 }
139
140 /* ARGSUSED */
141 static int
cryptoadm_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)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
cryptoadm_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)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
cryptoadm_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)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
cryptoadm_open(dev_t * devp,int flag,int otyp,cred_t * credp)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
cryptoadm_close(dev_t dev,int flag,int otyp,cred_t * credp)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
null_terminated(char * array)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
get_dev_list(dev_t dev,caddr_t arg,int mode,int * rval)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
get_soft_list(dev_t dev,caddr_t arg,int mode,int * rval)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
get_dev_info(dev_t dev,caddr_t arg,int mode,int * rval)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
get_soft_info(dev_t dev,caddr_t arg,int mode,int * rval)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
load_dev_disabled(dev_t dev,caddr_t arg,int mode,int * rval)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
load_soft_disabled(dev_t dev,caddr_t arg,int mode,int * rval)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
load_soft_config(dev_t dev,caddr_t arg,int mode,int * rval)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
unload_soft_module(dev_t dev,caddr_t arg,int mode,int * rval)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
load_door(dev_t dev,caddr_t arg,int mode,int * rval)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
fips140_actions(dev_t dev,caddr_t arg,int mode,int * rval,int cmd)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
cryptoadm_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * c,int * rval)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