cryptoadm.c revision 735564919188238196dbd0d320770dda59b38369
/*
* 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
* 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/sysmacros.h>
/*
* DDI entry points.
*/
/*
* Module linkage.
*/
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 */
};
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 */
};
&mod_driverops, /* drv_modops */
"Cryptographic Administrative Interface", /* drv_linkinfo */
&devops,
};
static struct modlinkage modlinkage = {
MODREV_1, /* ml_rev */
&modldrv, /* ml_linkage */
};
/*
* DDI entry points.
*/
int
_init(void)
{
return (mod_install(&modlinkage));
}
int
_fini(void)
{
return (mod_remove(&modlinkage));
}
int
{
}
/* ARGSUSED */
static int
{
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
{
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 */
DDI_PSEUDO, 0) != DDI_SUCCESS) {
return (DDI_FAILURE);
}
cryptoadm_dip = dip;
return (DDI_SUCCESS);
}
static int
{
if (cmd != DDI_DETACH)
return (DDI_FAILURE);
return (DDI_SUCCESS);
}
/* ARGSUSED */
static int
{
return (ENXIO);
/* exclusive opens are not supported */
return (ENOTSUP);
return (0);
}
/* ARGSUSED */
static int
{
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
{
return (EFAULT);
/* get the list from the core module */
return (EFAULT);
}
return (0);
}
/* check if buffer is too small */
return (EFAULT);
}
return (0);
}
/* copyout the first stuff */
return (EFAULT);
}
/* copyout entries */
return (EFAULT);
}
return (0);
}
/*
* This ioctl returns a buffer containing the null terminated names
* of software providers.
*/
/* ARGSUSED */
static int
{
char *names;
return (EFAULT);
/* get the list from the core module */
STRUCT_SIZE(soft_list)) != 0) {
return (EFAULT);
}
return (0);
}
/* check if buffer is too small */
STRUCT_SIZE(soft_list)) != 0) {
return (EFAULT);
}
return (0);
}
return (EFAULT);
}
return (EFAULT);
}
return (0);
}
/*
* This ioctl returns an array of mechanisms supported by the
* specified device.
*/
/* ARGSUSED */
static int
{
char *dev_name;
int rv;
return (EFAULT);
/* make sure the device name is null terminated */
if (!null_terminated(dev_name)) {
return (EFAULT);
}
return (0);
}
/* get mechanism names from the core module */
return (EFAULT);
}
return (0);
}
/* check if buffer is too small */
return (EFAULT);
}
return (0);
}
/* copyout the first stuff */
return (EFAULT);
}
/* copyout entries */
return (EFAULT);
}
return (0);
}
/*
* This ioctl returns an array of mechanisms supported by the
* specified cryptographic module.
*/
/* ARGSUSED */
static int
{
char *name;
return (EFAULT);
/* make sure the provider name is null terminated */
if (!null_terminated(name)) {
return (EFAULT);
}
return (0);
}
/* get mechanism names from the core module */
return (EFAULT);
}
return (0);
}
/* check if buffer is too small */
return (EFAULT);
}
return (0);
}
/* copyout the first stuff */
return (EFAULT);
}
/* copyout entries */
return (EFAULT);
}
return (0);
}
/*
* This ioctl disables mechanisms supported by the specified device.
*/
/* ARGSUSED */
static int
{
char *dev_name;
int error = 0;
goto out2;
}
/* make sure the device name is null terminated */
if (!null_terminated(dev_name)) {
goto out;
}
if (count == 0) {
/* remove the entry */
rv = CRYPTO_FAILED;
else
rv = CRYPTO_SUCCESS;
goto out;
}
if (count > KCF_MAXMECHS) {
goto out;
}
goto out2;
}
/* 'entries' consumed (but not freed) by crypto_load_dev_disabled() */
rv = CRYPTO_FAILED;
goto out;
}
rv = CRYPTO_SUCCESS;
out:
}
out2:
if (audit_active)
return (error);
}
/*
* This ioctl disables mechanisms supported by the specified
* cryptographic module.
*/
/* ARGSUSED */
static int
{
char *name;
int error = 0;
goto out2;
}
/* make sure the name is null terminated */
if (!null_terminated(name)) {
return (EFAULT);
}
return (0);
}
if (count == 0) {
/* remove the entry */
rv = CRYPTO_FAILED;
} else {
rv = CRYPTO_SUCCESS;
}
goto out;
}
if (count > KCF_MAXMECHS) {
goto out;
}
goto out2;
}
/* 'entries' is consumed by crypto_load_soft_disabled() */
rv = CRYPTO_FAILED;
goto out;
}
rv = CRYPTO_SUCCESS;
out:
}
out2:
if (audit_active)
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
{
char *name;
int error = 0;
goto out2;
}
/* make sure the name is null terminated */
if (!null_terminated(name)) {
return (EFAULT);
}
return (0);
}
if (count == 0) {
rv = CRYPTO_FAILED;
} else {
rv = CRYPTO_SUCCESS;
}
goto out;
}
if (count > KCF_MAXMECHS) {
goto out;
}
goto out2;
}
/*
* 'entries' is consumed (but not freed) by
* crypto_load_soft_config()
*/
rv = CRYPTO_FAILED;
goto out;
}
rv = CRYPTO_SUCCESS;
out:
}
out2:
if (audit_active)
return (error);
}
/*
* This ioctl unloads the specfied cryptographic module and removes
* its table of supported mechanisms.
*/
/* ARGSUSED */
static int
{
char *name;
int error = 0;
sizeof (unload_soft_module)) != 0) {
goto out2;
}
/* make sure the name is null terminated */
if (!null_terminated(name)) {
sizeof (unload_soft_module)) != 0) {
return (EFAULT);
}
return (0);
}
out:
sizeof (unload_soft_module)) != 0) {
}
out2:
if (audit_active)
return (error);
}
/*
* This ioctl loads a door descriptor into the kernel. The descriptor
* is used for module verification.
*/
/* ARGSUSED */
static int
{
int error = 0;
goto out2;
}
rv = CRYPTO_FAILED;
goto out;
}
rv = CRYPTO_SUCCESS;
out:
out2:
if (audit_active)
return (error);
}
/*
* FIPS 140 mode status.
*
* CRYPTO_FIPS140_STATUS: Returns back the value of global_fips140_mode.
* CRYPTO_FIPS140_SET: Recognizes 2 operations from userland:
* FIPS140_ENABLE or FIPS140_DISABLE. These can only be
* called when global_fips140_mode is FIPS140_MODE_UNSET
* as they are only operations that can be performed at
* bootup.
*/
/* ARGSUSED */
static int
{
int error = 0;
return (EFAULT);
switch (cmd) {
case CRYPTO_FIPS140_STATUS:
break;
case CRYPTO_FIPS140_SET:
/* If the mode has been determined, there is nothing to set */
/*
* If FIPS 140 is enabled, all approriate modules
* must be loaded and validated. This can be done in
* the background as the rest of the OS comes up.
*/
/*
* If FIPS 140 is not enabled, any modules that are
* waiting for validation must be released so they
* can be verified.
*/
kcf_activate();
}
break;
default:
}
return (error);
}
static int
int *rval)
{
int error;
switch (cmd) {
case CRYPTO_LOAD_DEV_DISABLED:
case CRYPTO_LOAD_SOFT_CONFIG:
case CRYPTO_POOL_CREATE:
case CRYPTO_POOL_WAIT:
case CRYPTO_POOL_RUN:
case CRYPTO_LOAD_DOOR:
case CRYPTO_FIPS140_SET:
return (error);
default:
break;
}
switch (cmd) {
case CRYPTO_GET_DEV_LIST:
case CRYPTO_GET_DEV_INFO:
case CRYPTO_GET_SOFT_LIST:
case CRYPTO_GET_SOFT_INFO:
case CRYPTO_LOAD_DEV_DISABLED:
case CRYPTO_LOAD_SOFT_CONFIG:
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)
0, 0, 0, 0);
return (0);
case CRYPTO_POOL_WAIT: {
== -1)
}
if (audit_active)
0, 0, 0, err);
return (err);
}
case CRYPTO_POOL_RUN: {
int err;
err = kcf_svc_do_run();
if (audit_active)
0, 0, 0, err);
return (err);
}
case CRYPTO_LOAD_DOOR:
case CRYPTO_FIPS140_STATUS:
case CRYPTO_FIPS140_SET: {
int err;
if (audit_active)
0, 0, 0, err);
return (err);
}
}
return (EINVAL);
}