cryptoadm.c revision b5a2d8455dfa3190fc977c4bec53e91c99012767
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* The ioctl interface for administrative commands.
*/
#include <sys/types.h>
#include <sys/modctl.h>
#include <sys/conf.h>
#include <sys/stat.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/kmem.h>
#include <sys/errno.h>
#include <sys/ksynch.h>
#include <sys/file.h>
#include <sys/open.h>
#include <sys/cred.h>
#include <sys/model.h>
#include <sys/sysmacros.h>
#include <sys/crypto/common.h>
#include <sys/crypto/api.h>
#include <sys/crypto/impl.h>
#include <sys/crypto/sched_impl.h>
#include <sys/crypto/ioctladmin.h>
#include <c2/audit.h>
/*
* DDI entry points.
*/
static int cryptoadm_attach(dev_info_t *, ddi_attach_cmd_t);
static int cryptoadm_detach(dev_info_t *, ddi_detach_cmd_t);
static int cryptoadm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
static int cryptoadm_open(dev_t *, int, int, cred_t *);
static int cryptoadm_close(dev_t, int, int, cred_t *);
static int cryptoadm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
extern void audit_cryptoadm(int, char *, crypto_mech_name_t *, uint_t,
uint_t, uint32_t, int);
kmutex_t fips140_mode_lock;
extern uint32_t global_fips140_mode;
/*
* Module linkage.
*/
static struct cb_ops cbops = {
cryptoadm_open, /* cb_open */
cryptoadm_close, /* cb_close */
nodev, /* cb_strategy */
nodev, /* cb_print */
nodev, /* cb_dump */
nodev, /* cb_read */
nodev, /* cb_write */
cryptoadm_ioctl, /* cb_ioctl */
nodev, /* cb_devmap */
nodev, /* cb_mmap */
nodev, /* cb_segmap */
nochpoll, /* cb_chpoll */
ddi_prop_op, /* cb_prop_op */
NULL, /* cb_streamtab */
D_MP, /* cb_flag */
CB_REV, /* cb_rev */
nodev, /* cb_aread */
nodev, /* cb_awrite */
};
static struct dev_ops devops = {
DEVO_REV, /* devo_rev */
0, /* devo_refcnt */
cryptoadm_getinfo, /* devo_getinfo */
nulldev, /* devo_identify */
nulldev, /* devo_probe */
cryptoadm_attach, /* devo_attach */
cryptoadm_detach, /* devo_detach */
nodev, /* devo_reset */
&cbops, /* devo_cb_ops */
NULL, /* devo_bus_ops */
NULL, /* devo_power */
ddi_quiesce_not_needed, /* devo_quiesce */
};
static struct modldrv modldrv = {
&mod_driverops, /* drv_modops */
"Cryptographic Administrative Interface", /* drv_linkinfo */
&devops,
};
static struct modlinkage modlinkage = {
MODREV_1, /* ml_rev */
&modldrv, /* ml_linkage */
NULL
};
static dev_info_t *cryptoadm_dip = NULL;
/*
* DDI entry points.
*/
int
_init(void)
{
return (mod_install(&modlinkage));
}
int
_fini(void)
{
return (mod_remove(&modlinkage));
}
int
_info(struct modinfo *modinfop)
{
return (mod_info(&modlinkage, modinfop));
}
/* ARGSUSED */
static int
cryptoadm_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
{
switch (cmd) {
case DDI_INFO_DEVT2DEVINFO:
*result = (void *)cryptoadm_dip;
return (DDI_SUCCESS);
case DDI_INFO_DEVT2INSTANCE:
*result = (void *)0;
return (DDI_SUCCESS);
}
return (DDI_FAILURE);
}
static int
cryptoadm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
if (cmd != DDI_ATTACH) {
return (DDI_FAILURE);
}
if (ddi_get_instance(dip) != 0) {
/* we only allow instance 0 to attach */
return (DDI_FAILURE);
}
/* create the minor node */
if (ddi_create_minor_node(dip, "cryptoadm", S_IFCHR, 0,
DDI_PSEUDO, 0) != DDI_SUCCESS) {
cmn_err(CE_WARN, "cryptoadm: failed creating minor node");
ddi_remove_minor_node(dip, NULL);
return (DDI_FAILURE);
}
mutex_init(&fips140_mode_lock, NULL, MUTEX_DEFAULT, NULL);
cryptoadm_dip = dip;
return (DDI_SUCCESS);
}
static int
cryptoadm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
if (cmd != DDI_DETACH)
return (DDI_FAILURE);
cryptoadm_dip = NULL;
ddi_remove_minor_node(dip, NULL);
return (DDI_SUCCESS);
}
/* ARGSUSED */
static int
cryptoadm_open(dev_t *devp, int flag, int otyp, cred_t *credp)
{
if (otyp != OTYP_CHR || cryptoadm_dip == NULL)
return (ENXIO);
/* exclusive opens are not supported */
if (flag & FEXCL)
return (ENOTSUP);
*devp = makedevice(getmajor(*devp), 0);
kcf_sched_start();
return (0);
}
/* ARGSUSED */
static int
cryptoadm_close(dev_t dev, int flag, int otyp, cred_t *credp)
{
return (0);
}
/*
* Returns TRUE if array of size MAXNAMELEN contains a '\0'
* termination character, otherwise, it returns FALSE.
*/
static boolean_t
null_terminated(char *array)
{
int i;
for (i = 0; i < MAXNAMELEN; i++)
if (array[i] == '\0')
return (B_TRUE);
return (B_FALSE);
}
/*
* This ioctl returns an array of hardware providers. Each entry
* contains a device name, device instance, and number of
* supported mechanisms.
*/
/* ARGSUSED */
static int
get_dev_list(dev_t dev, caddr_t arg, int mode, int *rval)
{
crypto_get_dev_list_t dev_list;
crypto_dev_list_entry_t *entries;
size_t copyout_size;
uint_t count;
ulong_t offset;
if (copyin(arg, &dev_list, sizeof (dev_list)) != 0)
return (EFAULT);
/* get the list from the core module */
if (crypto_get_dev_list(&count, &entries) != 0) {
dev_list.dl_return_value = CRYPTO_FAILED;
if (copyout(&dev_list, arg, sizeof (dev_list)) != 0) {
return (EFAULT);
}
return (0);
}
/* check if buffer is too small */
if (count > dev_list.dl_dev_count) {
dev_list.dl_dev_count = count;
dev_list.dl_return_value = CRYPTO_BUFFER_TOO_SMALL;
crypto_free_dev_list(entries, count);
if (copyout(&dev_list, arg, sizeof (dev_list)) != 0) {
return (EFAULT);
}
return (0);
}
dev_list.dl_dev_count = count;
dev_list.dl_return_value = CRYPTO_SUCCESS;
copyout_size = count * sizeof (crypto_dev_list_entry_t);
/* copyout the first stuff */
if (copyout(&dev_list, arg, sizeof (dev_list)) != 0) {
crypto_free_dev_list(entries, count);
return (EFAULT);
}
/* copyout entries */
offset = offsetof(crypto_get_dev_list_t, dl_devs);
if (count > 0 && copyout(entries, arg + offset, copyout_size) != 0) {
crypto_free_dev_list(entries, count);
return (EFAULT);
}
crypto_free_dev_list(entries, count);
return (0);
}
/*
* This ioctl returns a buffer containing the null terminated names
* of software providers.
*/
/* ARGSUSED */
static int
get_soft_list(dev_t dev, caddr_t arg, int mode, int *rval)
{
STRUCT_DECL(crypto_get_soft_list, soft_list);
char *names;
size_t len;
uint_t count;
STRUCT_INIT(soft_list, mode);
if (copyin(arg, STRUCT_BUF(soft_list), STRUCT_SIZE(soft_list)) != 0)
return (EFAULT);
/* get the list from the core module */
if (crypto_get_soft_list(&count, &names, &len) != 0) {
STRUCT_FSET(soft_list, sl_return_value, CRYPTO_FAILED);
if (copyout(STRUCT_BUF(soft_list), arg,
STRUCT_SIZE(soft_list)) != 0) {
return (EFAULT);
}
return (0);
}
/* check if buffer is too small */
if (len > STRUCT_FGET(soft_list, sl_soft_len)) {
STRUCT_FSET(soft_list, sl_soft_count, count);
STRUCT_FSET(soft_list, sl_soft_len, len);
STRUCT_FSET(soft_list, sl_return_value,
CRYPTO_BUFFER_TOO_SMALL);
kmem_free(names, len);
if (copyout(STRUCT_BUF(soft_list), arg,
STRUCT_SIZE(soft_list)) != 0) {
return (EFAULT);
}
return (0);
}
STRUCT_FSET(soft_list, sl_soft_count, count);
STRUCT_FSET(soft_list, sl_soft_len, len);
STRUCT_FSET(soft_list, sl_return_value, CRYPTO_SUCCESS);
if (count > 0 && copyout(names,
STRUCT_FGETP(soft_list, sl_soft_names), len) != 0) {
kmem_free(names, len);
return (EFAULT);
}
kmem_free(names, len);
if (copyout(STRUCT_BUF(soft_list), arg, STRUCT_SIZE(soft_list)) != 0) {
return (EFAULT);
}
return (0);
}
/*
* This ioctl returns an array of mechanisms supported by the
* specified device.
*/
/* ARGSUSED */
static int
get_dev_info(dev_t dev, caddr_t arg, int mode, int *rval)
{
crypto_get_dev_info_t dev_info;
crypto_mech_name_t *entries;
size_t copyout_size;
uint_t count;
ulong_t offset;
char *dev_name;
int rv;
if (copyin(arg, &dev_info, sizeof (dev_info)) != 0)
return (EFAULT);
dev_name = dev_info.di_dev_name;
/* make sure the device name is null terminated */
if (!null_terminated(dev_name)) {
dev_info.di_return_value = CRYPTO_ARGUMENTS_BAD;
if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) {
return (EFAULT);
}
return (0);
}
/* get mechanism names from the core module */
if ((rv = crypto_get_dev_info(dev_name, dev_info.di_dev_instance,
&count, &entries)) != CRYPTO_SUCCESS) {
dev_info.di_return_value = rv;
if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) {
return (EFAULT);
}
return (0);
}
/* check if buffer is too small */
if (count > dev_info.di_count) {
dev_info.di_count = count;
dev_info.di_return_value = CRYPTO_BUFFER_TOO_SMALL;
crypto_free_mech_list(entries, count);
if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) {
return (EFAULT);
}
return (0);
}
dev_info.di_count = count;
dev_info.di_return_value = CRYPTO_SUCCESS;
copyout_size = count * sizeof (crypto_mech_name_t);
/* copyout the first stuff */
if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) {
crypto_free_mech_list(entries, count);
return (EFAULT);
}
/* copyout entries */
offset = offsetof(crypto_get_dev_info_t, di_list);
if (copyout(entries, arg + offset, copyout_size) != 0) {
crypto_free_mech_list(entries, count);
return (EFAULT);
}
crypto_free_mech_list(entries, count);
return (0);
}
/*
* This ioctl returns an array of mechanisms supported by the
* specified cryptographic module.
*/
/* ARGSUSED */
static int
get_soft_info(dev_t dev, caddr_t arg, int mode, int *rval)
{
crypto_get_soft_info_t soft_info;
crypto_mech_name_t *entries;
size_t copyout_size;
uint_t count;
ulong_t offset;
char *name;
if (copyin(arg, &soft_info, sizeof (soft_info)) != 0)
return (EFAULT);
name = soft_info.si_name;
/* make sure the provider name is null terminated */
if (!null_terminated(name)) {
soft_info.si_return_value = CRYPTO_ARGUMENTS_BAD;
if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) {
return (EFAULT);
}
return (0);
}
/* get mechanism names from the core module */
if (crypto_get_soft_info(name, &count, &entries) != 0) {
soft_info.si_return_value = CRYPTO_FAILED;
if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) {
return (EFAULT);
}
return (0);
}
/* check if buffer is too small */
if (count > soft_info.si_count) {
soft_info.si_count = count;
soft_info.si_return_value = CRYPTO_BUFFER_TOO_SMALL;
crypto_free_mech_list(entries, count);
if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) {
return (EFAULT);
}
return (0);
}
soft_info.si_count = count;
soft_info.si_return_value = CRYPTO_SUCCESS;
copyout_size = count * sizeof (crypto_mech_name_t);
/* copyout the first stuff */
if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) {
crypto_free_mech_list(entries, count);
return (EFAULT);
}
/* copyout entries */
offset = offsetof(crypto_get_soft_info_t, si_list);
if (copyout(entries, arg + offset, copyout_size) != 0) {
crypto_free_mech_list(entries, count);
return (EFAULT);
}
crypto_free_mech_list(entries, count);
return (0);
}
/*
* This ioctl disables mechanisms supported by the specified device.
*/
/* ARGSUSED */
static int
load_dev_disabled(dev_t dev, caddr_t arg, int mode, int *rval)
{
crypto_load_dev_disabled_t dev_disabled;
crypto_mech_name_t *entries;
size_t size;
ulong_t offset;
uint_t count;
uint_t instance;
char *dev_name;
uint32_t rv;
int error = 0;
if (copyin(arg, &dev_disabled, sizeof (dev_disabled)) != 0) {
error = EFAULT;
goto out2;
}
dev_name = dev_disabled.dd_dev_name;
/* make sure the device name is null terminated */
if (!null_terminated(dev_name)) {
rv = CRYPTO_ARGUMENTS_BAD;
goto out;
}
count = dev_disabled.dd_count;
instance = dev_disabled.dd_dev_instance;
if (count == 0) {
/* remove the entry */
if (crypto_load_dev_disabled(dev_name, instance, 0, NULL) != 0)
rv = CRYPTO_FAILED;
else
rv = CRYPTO_SUCCESS;
goto out;
}
if (count > KCF_MAXMECHS) {
rv = CRYPTO_ARGUMENTS_BAD;
goto out;
}
size = count * sizeof (crypto_mech_name_t);
entries = kmem_alloc(size, KM_SLEEP);
offset = offsetof(crypto_load_dev_disabled_t, dd_list);
if (copyin(arg + offset, entries, size) != 0) {
kmem_free(entries, size);
error = EFAULT;
goto out2;
}
/* 'entries' consumed (but not freed) by crypto_load_dev_disabled() */
if (crypto_load_dev_disabled(dev_name, instance, count, entries) != 0) {
kmem_free(entries, size);
rv = CRYPTO_FAILED;
goto out;
}
rv = CRYPTO_SUCCESS;
out:
dev_disabled.dd_return_value = rv;
if (copyout(&dev_disabled, arg, sizeof (dev_disabled)) != 0) {
error = EFAULT;
}
out2:
if (audit_active)
audit_cryptoadm(CRYPTO_LOAD_DEV_DISABLED, dev_name, entries,
count, instance, rv, error);
return (error);
}
/*
* This ioctl disables mechanisms supported by the specified
* cryptographic module.
*/
/* ARGSUSED */
static int
load_soft_disabled(dev_t dev, caddr_t arg, int mode, int *rval)
{
crypto_load_soft_disabled_t soft_disabled;
crypto_mech_name_t *entries;
size_t size;
uint_t count;
ulong_t offset;
char *name;
uint32_t rv;
int error = 0;
if (copyin(arg, &soft_disabled, sizeof (soft_disabled)) != 0) {
error = EFAULT;
goto out2;
}
name = soft_disabled.sd_name;
/* make sure the name is null terminated */
if (!null_terminated(name)) {
soft_disabled.sd_return_value = CRYPTO_ARGUMENTS_BAD;
if (copyout(&soft_disabled, arg, sizeof (soft_disabled)) != 0) {
return (EFAULT);
}
return (0);
}
count = soft_disabled.sd_count;
if (count == 0) {
/* remove the entry */
if (crypto_load_soft_disabled(name, 0, NULL) != 0) {
rv = CRYPTO_FAILED;
} else {
rv = CRYPTO_SUCCESS;
}
goto out;
}
if (count > KCF_MAXMECHS) {
rv = CRYPTO_ARGUMENTS_BAD;
goto out;
}
size = count * sizeof (crypto_mech_name_t);
entries = kmem_alloc(size, KM_SLEEP);
offset = offsetof(crypto_load_soft_disabled_t, sd_list);
if (copyin(arg + offset, entries, size) != 0) {
kmem_free(entries, size);
error = EFAULT;
goto out2;
}
/* 'entries' is consumed by crypto_load_soft_disabled() */
if (crypto_load_soft_disabled(name, count, entries) != 0) {
kmem_free(entries, size);
rv = CRYPTO_FAILED;
goto out;
}
rv = CRYPTO_SUCCESS;
out:
soft_disabled.sd_return_value = rv;
if (copyout(&soft_disabled, arg, sizeof (soft_disabled)) != 0) {
error = EFAULT;
}
out2:
if (audit_active)
audit_cryptoadm(CRYPTO_LOAD_SOFT_DISABLED, name, entries,
count, 0, rv, error);
return (error);
}
/*
* This ioctl loads the supported mechanisms of the specfied cryptographic
* module. This is so, at boot time, all software providers do not
* have to be opened in order to cause them to register their
* supported mechanisms.
*/
/* ARGSUSED */
static int
load_soft_config(dev_t dev, caddr_t arg, int mode, int *rval)
{
crypto_load_soft_config_t soft_config;
crypto_mech_name_t *entries;
size_t size;
uint_t count;
ulong_t offset;
char *name;
uint32_t rv;
int error = 0;
if (copyin(arg, &soft_config, sizeof (soft_config)) != 0) {
error = EFAULT;
goto out2;
}
name = soft_config.sc_name;
/* make sure the name is null terminated */
if (!null_terminated(name)) {
soft_config.sc_return_value = CRYPTO_ARGUMENTS_BAD;
if (copyout(&soft_config, arg, sizeof (soft_config)) != 0) {
return (EFAULT);
}
return (0);
}
count = soft_config.sc_count;
if (count == 0) {
if (crypto_load_soft_config(name, 0, NULL) != 0) {
rv = CRYPTO_FAILED;
} else {
rv = CRYPTO_SUCCESS;
}
goto out;
}
if (count > KCF_MAXMECHS) {
rv = CRYPTO_ARGUMENTS_BAD;
goto out;
}
size = count * sizeof (crypto_mech_name_t);
entries = kmem_alloc(size, KM_SLEEP);
offset = offsetof(crypto_load_soft_config_t, sc_list);
if (copyin(arg + offset, entries, size) != 0) {
kmem_free(entries, size);
error = EFAULT;
goto out2;
}
/*
* 'entries' is consumed (but not freed) by
* crypto_load_soft_config()
*/
if (crypto_load_soft_config(name, count, entries) != 0) {
kmem_free(entries, size);
rv = CRYPTO_FAILED;
goto out;
}
rv = CRYPTO_SUCCESS;
out:
soft_config.sc_return_value = rv;
if (copyout(&soft_config, arg, sizeof (soft_config)) != 0) {
error = EFAULT;
}
out2:
if (audit_active)
audit_cryptoadm(CRYPTO_LOAD_SOFT_CONFIG, name, entries, count,
0, rv, error);
return (error);
}
/*
* This ioctl unloads the specfied cryptographic module and removes
* its table of supported mechanisms.
*/
/* ARGSUSED */
static int
unload_soft_module(dev_t dev, caddr_t arg, int mode, int *rval)
{
crypto_unload_soft_module_t unload_soft_module;
char *name;
uint32_t rv;
int error = 0;
if (copyin(arg, &unload_soft_module,
sizeof (unload_soft_module)) != 0) {
error = EFAULT;
goto out2;
}
name = unload_soft_module.sm_name;
/* make sure the name is null terminated */
if (!null_terminated(name)) {
unload_soft_module.sm_return_value = CRYPTO_ARGUMENTS_BAD;
if (copyout(&unload_soft_module, arg,
sizeof (unload_soft_module)) != 0) {
return (EFAULT);
}
return (0);
}
rv = crypto_unload_soft_module(name);
out:
unload_soft_module.sm_return_value = rv;
if (copyout(&unload_soft_module, arg,
sizeof (unload_soft_module)) != 0) {
error = EFAULT;
}
out2:
if (audit_active)
audit_cryptoadm(CRYPTO_UNLOAD_SOFT_MODULE, name, NULL, 0, 0,
rv, error);
return (error);
}
/*
* This ioctl loads a door descriptor into the kernel. The descriptor
* is used for module verification.
*/
/* ARGSUSED */
static int
load_door(dev_t dev, caddr_t arg, int mode, int *rval)
{
crypto_load_door_t load_door;
uint32_t rv;
int error = 0;
if (copyin(arg, &load_door, sizeof (crypto_load_door_t)) != 0) {
error = EFAULT;
goto out2;
}
if (crypto_load_door(load_door.ld_did) != 0) {
rv = CRYPTO_FAILED;
goto out;
}
rv = CRYPTO_SUCCESS;
out:
load_door.ld_return_value = rv;
if (copyout(&load_door, arg, sizeof (crypto_load_door_t)) != 0)
error = EFAULT;
out2:
if (audit_active)
audit_cryptoadm(CRYPTO_LOAD_DOOR, NULL, NULL,
0, 0, rv, error);
return (error);
}
/*
* This function enables/disables FIPS140 mode or gets the current
* FIPS140 mode status.
*
* Enable or disable FIPS140 ioctl operation name:
* FIPS140_ENABLE or FIPS140_DISABLE
*
* Global fips140 mode status in kernel:
* FIPS140_MODE_ENABLED or FIPS140_MODE_DISABLED
*/
/* ARGSUSED */
static int
fips140_actions(dev_t dev, caddr_t arg, int mode, int *rval, int cmd)
{
crypto_fips140_t fips140_info;
uint32_t rv = CRYPTO_SUCCESS;
int error = 0;
if (copyin(arg, &fips140_info, sizeof (crypto_fips140_t)) != 0)
return (EFAULT);
switch (cmd) {
case CRYPTO_FIPS140_STATUS:
fips140_info.fips140_status = global_fips140_mode;
break;
case CRYPTO_FIPS140_SET:
mutex_enter(&fips140_mode_lock);
if (fips140_info.fips140_op == FIPS140_ENABLE)
global_fips140_mode = FIPS140_MODE_ENABLED;
else if (fips140_info.fips140_op == FIPS140_DISABLE)
global_fips140_mode = FIPS140_MODE_DISABLED;
else {
rv = CRYPTO_ARGUMENTS_BAD;
error = CRYPTO_FAILED;
}
mutex_exit(&fips140_mode_lock);
break;
}
fips140_info.fips140_return_value = rv;
if (copyout(&fips140_info, arg, sizeof (crypto_fips140_t)) != 0)
error = EFAULT;
return (error);
}
static int
cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
int *rval)
{
int error;
#define ARG ((caddr_t)arg)
switch (cmd) {
case CRYPTO_LOAD_DEV_DISABLED:
case CRYPTO_LOAD_SOFT_DISABLED:
case CRYPTO_LOAD_SOFT_CONFIG:
case CRYPTO_UNLOAD_SOFT_MODULE:
case CRYPTO_POOL_CREATE:
case CRYPTO_POOL_WAIT:
case CRYPTO_POOL_RUN:
case CRYPTO_LOAD_DOOR:
case CRYPTO_FIPS140_SET:
if ((error = drv_priv(c)) != 0)
return (error);
default:
break;
}
switch (cmd) {
case CRYPTO_GET_DEV_LIST:
return (get_dev_list(dev, ARG, mode, rval));
case CRYPTO_GET_DEV_INFO:
return (get_dev_info(dev, ARG, mode, rval));
case CRYPTO_GET_SOFT_LIST:
return (get_soft_list(dev, ARG, mode, rval));
case CRYPTO_GET_SOFT_INFO:
return (get_soft_info(dev, ARG, mode, rval));
case CRYPTO_LOAD_DEV_DISABLED:
return (load_dev_disabled(dev, ARG, mode, rval));
case CRYPTO_LOAD_SOFT_DISABLED:
return (load_soft_disabled(dev, ARG, mode, rval));
case CRYPTO_LOAD_SOFT_CONFIG:
return (load_soft_config(dev, ARG, mode, rval));
case CRYPTO_UNLOAD_SOFT_MODULE:
return (unload_soft_module(dev, ARG, mode, rval));
case CRYPTO_POOL_CREATE:
/*
* The framework allocates and initializes the pool.
* So, this is a no op. We are keeping this ioctl around
* to be used for any future threadpool related work.
*/
if (audit_active)
audit_cryptoadm(CRYPTO_POOL_CREATE, NULL, NULL,
0, 0, 0, 0);
return (0);
case CRYPTO_POOL_WAIT: {
int nthrs = 0, err;
if ((err = kcf_svc_wait(&nthrs)) == 0) {
if (copyout((caddr_t)&nthrs, ARG, sizeof (int))
== -1)
err = EFAULT;
}
if (audit_active)
audit_cryptoadm(CRYPTO_POOL_WAIT, NULL, NULL,
0, 0, 0, err);
return (err);
}
case CRYPTO_POOL_RUN: {
int err;
err = kcf_svc_do_run();
if (audit_active)
audit_cryptoadm(CRYPTO_POOL_RUN, NULL, NULL,
0, 0, 0, err);
return (err);
}
case CRYPTO_LOAD_DOOR:
return (load_door(dev, ARG, mode, rval));
case CRYPTO_FIPS140_STATUS:
return (fips140_actions(dev, ARG, mode, rval, cmd));
case CRYPTO_FIPS140_SET: {
int err;
err = fips140_actions(dev, ARG, mode, rval, cmd);
if (audit_active)
audit_cryptoadm(CRYPTO_FIPS140_SET, NULL, NULL,
0, 0, 0, err);
return (err);
}
}
return (EINVAL);
}