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.
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.
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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * The ioctl interface for administrative commands.
31 #include <sys/types.h>
32 #include <sys/modctl.h>
36 #include <sys/sunddi.h>
38 #include <sys/errno.h>
39 #include <sys/ksynch.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>
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 *);
65 static struct cb_ops cbops
= {
66 cryptoadm_open
, /* cb_open */
67 cryptoadm_close
, /* cb_close */
68 nodev
, /* cb_strategy */
73 cryptoadm_ioctl
, /* cb_ioctl */
74 nodev
, /* cb_devmap */
76 nodev
, /* cb_segmap */
77 nochpoll
, /* cb_chpoll */
78 ddi_prop_op
, /* cb_prop_op */
79 NULL
, /* cb_streamtab */
83 nodev
, /* cb_awrite */
86 static struct dev_ops devops
= {
87 DEVO_REV
, /* devo_rev */
89 cryptoadm_getinfo
, /* devo_getinfo */
90 nulldev
, /* devo_identify */
91 nulldev
, /* devo_probe */
92 cryptoadm_attach
, /* devo_attach */
93 cryptoadm_detach
, /* devo_detach */
94 nodev
, /* devo_reset */
95 &cbops
, /* devo_cb_ops */
96 NULL
, /* devo_bus_ops */
97 NULL
, /* devo_power */
98 ddi_quiesce_not_needed
, /* devo_quiesce */
101 static struct modldrv modldrv
= {
102 &mod_driverops
, /* drv_modops */
103 "Cryptographic Administrative Interface", /* drv_linkinfo */
107 static struct modlinkage modlinkage
= {
108 MODREV_1
, /* ml_rev */
109 &modldrv
, /* ml_linkage */
113 static dev_info_t
*cryptoadm_dip
= NULL
;
121 return (mod_install(&modlinkage
));
127 return (mod_remove(&modlinkage
));
131 _info(struct modinfo
*modinfop
)
133 return (mod_info(&modlinkage
, modinfop
));
138 cryptoadm_getinfo(dev_info_t
*dip
, ddi_info_cmd_t cmd
, void *arg
, void **result
)
141 case DDI_INFO_DEVT2DEVINFO
:
142 *result
= (void *)cryptoadm_dip
;
143 return (DDI_SUCCESS
);
145 case DDI_INFO_DEVT2INSTANCE
:
147 return (DDI_SUCCESS
);
149 return (DDI_FAILURE
);
153 cryptoadm_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
155 if (cmd
!= DDI_ATTACH
) {
156 return (DDI_FAILURE
);
158 if (ddi_get_instance(dip
) != 0) {
159 /* we only allow instance 0 to attach */
160 return (DDI_FAILURE
);
163 /* create the minor node */
164 if (ddi_create_minor_node(dip
, "cryptoadm", S_IFCHR
, 0,
165 DDI_PSEUDO
, 0) != DDI_SUCCESS
) {
166 cmn_err(CE_WARN
, "cryptoadm: failed creating minor node");
167 ddi_remove_minor_node(dip
, NULL
);
168 return (DDI_FAILURE
);
173 return (DDI_SUCCESS
);
177 cryptoadm_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
179 if (cmd
!= DDI_DETACH
)
180 return (DDI_FAILURE
);
182 cryptoadm_dip
= NULL
;
183 ddi_remove_minor_node(dip
, NULL
);
185 return (DDI_SUCCESS
);
190 cryptoadm_open(dev_t
*devp
, int flag
, int otyp
, cred_t
*credp
)
192 if (otyp
!= OTYP_CHR
|| cryptoadm_dip
== NULL
)
195 /* exclusive opens are not supported */
199 *devp
= makedevice(getmajor(*devp
), 0);
208 cryptoadm_close(dev_t dev
, int flag
, int otyp
, cred_t
*credp
)
214 * Returns TRUE if array of size MAXNAMELEN contains a '\0'
215 * termination character, otherwise, it returns FALSE.
218 null_terminated(char *array
)
222 for (i
= 0; i
< MAXNAMELEN
; i
++)
223 if (array
[i
] == '\0')
230 * This ioctl returns an array of hardware providers. Each entry
231 * contains a device name, device instance, and number of
232 * supported mechanisms.
236 get_dev_list(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
238 crypto_get_dev_list_t dev_list
;
239 crypto_dev_list_entry_t
*entries
;
244 if (copyin(arg
, &dev_list
, sizeof (dev_list
)) != 0)
247 /* get the list from the core module */
248 if (crypto_get_dev_list(&count
, &entries
) != 0) {
249 dev_list
.dl_return_value
= CRYPTO_FAILED
;
250 if (copyout(&dev_list
, arg
, sizeof (dev_list
)) != 0) {
256 /* check if buffer is too small */
257 if (count
> dev_list
.dl_dev_count
) {
258 dev_list
.dl_dev_count
= count
;
259 dev_list
.dl_return_value
= CRYPTO_BUFFER_TOO_SMALL
;
260 crypto_free_dev_list(entries
, count
);
261 if (copyout(&dev_list
, arg
, sizeof (dev_list
)) != 0) {
267 dev_list
.dl_dev_count
= count
;
268 dev_list
.dl_return_value
= CRYPTO_SUCCESS
;
270 copyout_size
= count
* sizeof (crypto_dev_list_entry_t
);
272 /* copyout the first stuff */
273 if (copyout(&dev_list
, arg
, sizeof (dev_list
)) != 0) {
274 crypto_free_dev_list(entries
, count
);
278 /* copyout entries */
279 offset
= offsetof(crypto_get_dev_list_t
, dl_devs
);
280 if (count
> 0 && copyout(entries
, arg
+ offset
, copyout_size
) != 0) {
281 crypto_free_dev_list(entries
, count
);
284 crypto_free_dev_list(entries
, count
);
289 * This ioctl returns a buffer containing the null terminated names
290 * of software providers.
294 get_soft_list(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
296 STRUCT_DECL(crypto_get_soft_list
, soft_list
);
301 STRUCT_INIT(soft_list
, mode
);
303 if (copyin(arg
, STRUCT_BUF(soft_list
), STRUCT_SIZE(soft_list
)) != 0)
306 /* get the list from the core module */
307 if (crypto_get_soft_list(&count
, &names
, &len
) != 0) {
308 STRUCT_FSET(soft_list
, sl_return_value
, CRYPTO_FAILED
);
309 if (copyout(STRUCT_BUF(soft_list
), arg
,
310 STRUCT_SIZE(soft_list
)) != 0) {
316 /* check if buffer is too small */
317 if (len
> STRUCT_FGET(soft_list
, sl_soft_len
)) {
318 STRUCT_FSET(soft_list
, sl_soft_count
, count
);
319 STRUCT_FSET(soft_list
, sl_soft_len
, len
);
320 STRUCT_FSET(soft_list
, sl_return_value
,
321 CRYPTO_BUFFER_TOO_SMALL
);
322 kmem_free(names
, len
);
323 if (copyout(STRUCT_BUF(soft_list
), arg
,
324 STRUCT_SIZE(soft_list
)) != 0) {
330 STRUCT_FSET(soft_list
, sl_soft_count
, count
);
331 STRUCT_FSET(soft_list
, sl_soft_len
, len
);
332 STRUCT_FSET(soft_list
, sl_return_value
, CRYPTO_SUCCESS
);
334 if (count
> 0 && copyout(names
,
335 STRUCT_FGETP(soft_list
, sl_soft_names
), len
) != 0) {
336 kmem_free(names
, len
);
339 kmem_free(names
, len
);
341 if (copyout(STRUCT_BUF(soft_list
), arg
, STRUCT_SIZE(soft_list
)) != 0) {
349 * This ioctl returns an array of mechanisms supported by the
354 get_dev_info(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
356 crypto_get_dev_info_t dev_info
;
357 crypto_mech_name_t
*entries
;
364 if (copyin(arg
, &dev_info
, sizeof (dev_info
)) != 0)
367 dev_name
= dev_info
.di_dev_name
;
368 /* make sure the device name is null terminated */
369 if (!null_terminated(dev_name
)) {
370 dev_info
.di_return_value
= CRYPTO_ARGUMENTS_BAD
;
371 if (copyout(&dev_info
, arg
, sizeof (dev_info
)) != 0) {
377 /* get mechanism names from the core module */
378 if ((rv
= crypto_get_dev_info(dev_name
, dev_info
.di_dev_instance
,
379 &count
, &entries
)) != CRYPTO_SUCCESS
) {
380 dev_info
.di_return_value
= rv
;
381 if (copyout(&dev_info
, arg
, sizeof (dev_info
)) != 0) {
387 /* check if buffer is too small */
388 if (count
> dev_info
.di_count
) {
389 dev_info
.di_count
= count
;
390 dev_info
.di_return_value
= CRYPTO_BUFFER_TOO_SMALL
;
391 crypto_free_mech_list(entries
, count
);
392 if (copyout(&dev_info
, arg
, sizeof (dev_info
)) != 0) {
398 dev_info
.di_count
= count
;
399 dev_info
.di_return_value
= CRYPTO_SUCCESS
;
401 copyout_size
= count
* sizeof (crypto_mech_name_t
);
403 /* copyout the first stuff */
404 if (copyout(&dev_info
, arg
, sizeof (dev_info
)) != 0) {
405 crypto_free_mech_list(entries
, count
);
409 /* copyout entries */
410 offset
= offsetof(crypto_get_dev_info_t
, di_list
);
411 if (copyout(entries
, arg
+ offset
, copyout_size
) != 0) {
412 crypto_free_mech_list(entries
, count
);
415 crypto_free_mech_list(entries
, count
);
420 * This ioctl returns an array of mechanisms supported by the
421 * specified cryptographic module.
425 get_soft_info(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
427 crypto_get_soft_info_t soft_info
;
428 crypto_mech_name_t
*entries
;
434 if (copyin(arg
, &soft_info
, sizeof (soft_info
)) != 0)
437 name
= soft_info
.si_name
;
438 /* make sure the provider name is null terminated */
439 if (!null_terminated(name
)) {
440 soft_info
.si_return_value
= CRYPTO_ARGUMENTS_BAD
;
441 if (copyout(&soft_info
, arg
, sizeof (soft_info
)) != 0) {
447 /* get mechanism names from the core module */
448 if (crypto_get_soft_info(name
, &count
, &entries
) != 0) {
449 soft_info
.si_return_value
= CRYPTO_FAILED
;
450 if (copyout(&soft_info
, arg
, sizeof (soft_info
)) != 0) {
456 /* check if buffer is too small */
457 if (count
> soft_info
.si_count
) {
458 soft_info
.si_count
= count
;
459 soft_info
.si_return_value
= CRYPTO_BUFFER_TOO_SMALL
;
460 crypto_free_mech_list(entries
, count
);
461 if (copyout(&soft_info
, arg
, sizeof (soft_info
)) != 0) {
467 soft_info
.si_count
= count
;
468 soft_info
.si_return_value
= CRYPTO_SUCCESS
;
469 copyout_size
= count
* sizeof (crypto_mech_name_t
);
471 /* copyout the first stuff */
472 if (copyout(&soft_info
, arg
, sizeof (soft_info
)) != 0) {
473 crypto_free_mech_list(entries
, count
);
477 /* copyout entries */
478 offset
= offsetof(crypto_get_soft_info_t
, si_list
);
479 if (copyout(entries
, arg
+ offset
, copyout_size
) != 0) {
480 crypto_free_mech_list(entries
, count
);
483 crypto_free_mech_list(entries
, count
);
488 * This ioctl disables mechanisms supported by the specified device.
492 load_dev_disabled(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
494 crypto_load_dev_disabled_t dev_disabled
;
495 crypto_mech_name_t
*entries
;
504 if (copyin(arg
, &dev_disabled
, sizeof (dev_disabled
)) != 0) {
509 dev_name
= dev_disabled
.dd_dev_name
;
510 /* make sure the device name is null terminated */
511 if (!null_terminated(dev_name
)) {
512 rv
= CRYPTO_ARGUMENTS_BAD
;
516 count
= dev_disabled
.dd_count
;
517 instance
= dev_disabled
.dd_dev_instance
;
519 /* remove the entry */
520 if (crypto_load_dev_disabled(dev_name
, instance
, 0, NULL
) != 0)
527 if (count
> KCF_MAXMECHS
) {
528 rv
= CRYPTO_ARGUMENTS_BAD
;
532 size
= count
* sizeof (crypto_mech_name_t
);
533 entries
= kmem_alloc(size
, KM_SLEEP
);
535 offset
= offsetof(crypto_load_dev_disabled_t
, dd_list
);
536 if (copyin(arg
+ offset
, entries
, size
) != 0) {
537 kmem_free(entries
, size
);
542 /* 'entries' consumed (but not freed) by crypto_load_dev_disabled() */
543 if (crypto_load_dev_disabled(dev_name
, instance
, count
, entries
) != 0) {
544 kmem_free(entries
, size
);
550 dev_disabled
.dd_return_value
= rv
;
552 if (copyout(&dev_disabled
, arg
, sizeof (dev_disabled
)) != 0) {
560 * This ioctl disables mechanisms supported by the specified
561 * cryptographic module.
565 load_soft_disabled(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
567 crypto_load_soft_disabled_t soft_disabled
;
568 crypto_mech_name_t
*entries
;
576 if (copyin(arg
, &soft_disabled
, sizeof (soft_disabled
)) != 0) {
581 name
= soft_disabled
.sd_name
;
582 /* make sure the name is null terminated */
583 if (!null_terminated(name
)) {
584 soft_disabled
.sd_return_value
= CRYPTO_ARGUMENTS_BAD
;
585 if (copyout(&soft_disabled
, arg
, sizeof (soft_disabled
)) != 0) {
591 count
= soft_disabled
.sd_count
;
593 /* remove the entry */
594 if (crypto_load_soft_disabled(name
, 0, NULL
) != 0) {
602 if (count
> KCF_MAXMECHS
) {
603 rv
= CRYPTO_ARGUMENTS_BAD
;
607 size
= count
* sizeof (crypto_mech_name_t
);
608 entries
= kmem_alloc(size
, KM_SLEEP
);
610 offset
= offsetof(crypto_load_soft_disabled_t
, sd_list
);
611 if (copyin(arg
+ offset
, entries
, size
) != 0) {
612 kmem_free(entries
, size
);
617 /* 'entries' is consumed by crypto_load_soft_disabled() */
618 if (crypto_load_soft_disabled(name
, count
, entries
) != 0) {
619 kmem_free(entries
, size
);
625 soft_disabled
.sd_return_value
= rv
;
627 if (copyout(&soft_disabled
, arg
, sizeof (soft_disabled
)) != 0) {
635 * This ioctl loads the supported mechanisms of the specfied cryptographic
636 * module. This is so, at boot time, all software providers do not
637 * have to be opened in order to cause them to register their
638 * supported mechanisms.
642 load_soft_config(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
644 crypto_load_soft_config_t soft_config
;
645 crypto_mech_name_t
*entries
;
653 if (copyin(arg
, &soft_config
, sizeof (soft_config
)) != 0) {
658 name
= soft_config
.sc_name
;
659 /* make sure the name is null terminated */
660 if (!null_terminated(name
)) {
661 soft_config
.sc_return_value
= CRYPTO_ARGUMENTS_BAD
;
662 if (copyout(&soft_config
, arg
, sizeof (soft_config
)) != 0) {
668 count
= soft_config
.sc_count
;
670 if (crypto_load_soft_config(name
, 0, NULL
) != 0) {
678 if (count
> KCF_MAXMECHS
) {
679 rv
= CRYPTO_ARGUMENTS_BAD
;
683 size
= count
* sizeof (crypto_mech_name_t
);
684 entries
= kmem_alloc(size
, KM_SLEEP
);
686 offset
= offsetof(crypto_load_soft_config_t
, sc_list
);
687 if (copyin(arg
+ offset
, entries
, size
) != 0) {
688 kmem_free(entries
, size
);
694 * 'entries' is consumed (but not freed) by
695 * crypto_load_soft_config()
697 if (crypto_load_soft_config(name
, count
, entries
) != 0) {
698 kmem_free(entries
, size
);
704 soft_config
.sc_return_value
= rv
;
706 if (copyout(&soft_config
, arg
, sizeof (soft_config
)) != 0) {
714 * This ioctl unloads the specfied cryptographic module and removes
715 * its table of supported mechanisms.
719 unload_soft_module(dev_t dev
, caddr_t arg
, int mode
, int *rval
)
721 crypto_unload_soft_module_t unload_soft_module
;
726 if (copyin(arg
, &unload_soft_module
,
727 sizeof (unload_soft_module
)) != 0) {
732 name
= unload_soft_module
.sm_name
;
733 /* make sure the name is null terminated */
734 if (!null_terminated(name
)) {
735 unload_soft_module
.sm_return_value
= CRYPTO_ARGUMENTS_BAD
;
736 if (copyout(&unload_soft_module
, arg
,
737 sizeof (unload_soft_module
)) != 0) {
743 rv
= crypto_unload_soft_module(name
);
745 unload_soft_module
.sm_return_value
= rv
;
747 if (copyout(&unload_soft_module
, arg
,
748 sizeof (unload_soft_module
)) != 0) {
756 cryptoadm_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
, cred_t
*c
,
760 #define ARG ((caddr_t)arg)
763 case CRYPTO_LOAD_DEV_DISABLED
:
764 case CRYPTO_LOAD_SOFT_DISABLED
:
765 case CRYPTO_LOAD_SOFT_CONFIG
:
766 case CRYPTO_UNLOAD_SOFT_MODULE
:
767 case CRYPTO_LOAD_DOOR
:
768 case CRYPTO_FIPS140_SET
:
769 if ((error
= drv_priv(c
)) != 0)
776 case CRYPTO_GET_DEV_LIST
:
777 return (get_dev_list(dev
, ARG
, mode
, rval
));
779 case CRYPTO_GET_DEV_INFO
:
780 return (get_dev_info(dev
, ARG
, mode
, rval
));
782 case CRYPTO_GET_SOFT_LIST
:
783 return (get_soft_list(dev
, ARG
, mode
, rval
));
785 case CRYPTO_GET_SOFT_INFO
:
786 return (get_soft_info(dev
, ARG
, mode
, rval
));
788 case CRYPTO_LOAD_DEV_DISABLED
:
789 return (load_dev_disabled(dev
, ARG
, mode
, rval
));
791 case CRYPTO_LOAD_SOFT_DISABLED
:
792 return (load_soft_disabled(dev
, ARG
, mode
, rval
));
794 case CRYPTO_LOAD_SOFT_CONFIG
:
795 return (load_soft_config(dev
, ARG
, mode
, rval
));
797 case CRYPTO_UNLOAD_SOFT_MODULE
:
798 return (unload_soft_module(dev
, ARG
, mode
, rval
));