/*
* 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.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <locale.h>
#include <libgen.h>
#include <signal.h>
#include "cryptoadm.h"
static int check_hardware_provider(char *, char *, int *, int *);
/*
* Display the mechanism list for a kernel software provider.
* This implements part of the "cryptoadm list -m" command.
*
* Parameters phardlist and psoftlist are supplied by
* get_soft_info().
* If NULL, this function obtains it by calling getent_kef() and
* then get_kcfconf_info() via get_soft_info() internally.
*/
int
{
int rc;
return (FAILURE);
}
} else {
"failed to retrieve the mechanism list for %s."),
provname);
}
return (rc);
}
/*
* Display the mechanism list for a kernel hardware provider.
* This implements part of the "cryptoadm list -m" command.
*/
int
{
int inst_num;
int count;
return (FAILURE);
}
/*
* Check if the provider is valid. If it is valid, get the number of
* mechanisms also.
*/
FAILURE) {
return (FAILURE);
}
/* Get the mechanism list for the kernel hardware provider */
SUCCESS) {
}
return (rc);
}
/*
* Display the policy information for a kernel software provider.
* This implements part of the "cryptoadm list -p" command.
*
* Parameters phardlist and psoftlist are supplied by
* getent_kef().
* If NULL, this function obtains it by calling get_kcfconf_info()
* via getent_kef() internally.
*/
int
{
int rc;
return (FAILURE);
}
return (FAILURE);
provname);
return (FAILURE);
}
}
} else {
"failed to retrieve the mechanism list for %s."),
provname);
return (rc);
}
return (SUCCESS);
}
/*
* Display the policy information for a kernel hardware provider.
* This implements part of the "cryptoadm list -p" command.
*
* Parameters phardlist and psoftlist are supplied by getent_kef().
* If NULL, this function obtains it by calling get_kcfconf_info() via
* getent_kef() internally.
* Parameter pdevlist is supplied by check_kernel_for_hard().
* If NULL, this function obtains it by calling get_dev_list() via
* check_kernel_for_hard() internally.
*/
int
{
int inst_num;
int count;
return (FAILURE);
}
/*
* Check if the provider is valid. If it is valid, get the number of
* mechanisms also.
*/
FAILURE) {
return (FAILURE);
}
/* Get the mechanism list for the kernel hardware provider */
SUCCESS) {
}
} else {
"failed to retrieve the mechanism list for %s."),
devname);
return (rc);
}
/*
* If the hardware provider has an entry in the kcf.conf file,
* some of its mechanisms must have been disabled. Print out
* the disabled list from the config file entry. Otherwise,
* if it is active, then all the mechanisms for it are enabled.
*/
return (SUCCESS);
} else {
return (FAILURE);
"%s: all mechanisms are enabled."), provname);
if (has_random)
/*
* TRANSLATION_NOTE
* "random" is a keyword and not to be
* translated.
*/
"random");
else
(void) printf("\n");
return (SUCCESS);
} else {
return (FAILURE);
}
}
}
/*
* Disable a kernel hardware provider.
* This implements the "cryptoadm disable" command for
* kernel hardware providers.
*/
int
{
int inst_num;
int count;
return (FAILURE);
}
/*
* Check if the provider is valid. If it is valid, get the number of
* mechanisms also.
*/
== FAILURE) {
return (FAILURE);
}
/* Get the mechanism list for the kernel hardware provider */
return (FAILURE);
}
/*
* Get the entry of this hardware provider from the config file.
* If there is no entry yet, create one for it.
*/
return (FAILURE);
}
}
/*
* kCF treats random as an internal mechanism. So, we need to
* filter it from the mechanism list here, if we are NOT disabling
* or enabling the random feature. Note that we map random feature at
* cryptoadm(1M) level to the "random" mechanism in kCF.
*/
if (!rndflag) {
}
/* Calculate the new disabled list */
return (FAILURE);
}
/* If no mechanisms are to be disabled, return */
return (SUCCESS);
}
/* Update the config file with the new entry or the updated entry */
if (new_dev_entry) {
} else {
}
return (FAILURE);
}
/* Inform kernel about the new disabled mechanism list */
return (FAILURE);
}
return (FAILURE);
}
cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: %s",
return (FAILURE);
}
cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl return_value = "
return (FAILURE);
}
return (SUCCESS);
}
/*
* Disable a kernel software provider.
* This implements the "cryptoadm disable" command for
* kernel software providers.
*/
int
{
return (FAILURE);
}
/*
* Check if the kernel software provider is currently unloaded.
* If it is unloaded, return FAILURE, because the disable subcommand
* can not perform on inactive (unloaded) providers.
*/
return (FAILURE);
gettext("%s is not loaded or does not exist."),
provname);
return (FAILURE);
}
"failed to retrieve the providers' "
"information from the configuration file - %s.",
return (FAILURE);
}
/*
* Get the entry of this provider from the kcf.conf file, if any.
* Otherwise, create a new kcf.conf entry for writing back to the file.
*/
cryptodebug("out of memory.");
goto out;
}
}
/* Get the mechanism list for the software provider from the kernel */
FAILURE) {
goto out;
}
/*
* Replace the supportedlist from kcf.conf with possibly
* more-up-to-date list from the kernel. This is the case
* for default software providers that had more mechanisms
* added in the current version of the kernel.
*/
}
/*
* kCF treats random as an internal mechanism. So, we need to
* filter it from the mechanism list here, if we are NOT disabling
* or enabling the random feature. Note that we map random feature at
* cryptoadm(1M) level to the "random" mechanism in kCF.
*/
if (!rndflag) {
}
/* Calculate the new disabled list */
goto out;
}
/* Update the kcf.conf file with the updated entry */
goto out;
}
/* Setup argument to inform kernel about the new disabled list. */
goto out;
}
gettext("failed to open %s for RW: %s"),
goto out;
}
/* Inform kernel about the new disabled list. */
cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
goto out;
}
cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
goto out;
}
out:
if (fd != -1)
return (rc);
}
/*
* Enable a kernel software or hardware provider.
* This implements the "cryptoadm enable" command for kernel providers.
*/
int
{
/* Get the entry of this provider from the kcf.conf file, if any. */
/*
* This device doesn't have an entry in the config
* file, therefore nothing is disabled.
*/
"all mechanisms are enabled already for %s."),
provname);
return (SUCCESS);
}
} else { /* a software module */
FAILURE) {
return (FAILURE);
provname);
return (FAILURE);
/* nothing to be enabled. */
"all mechanisms are enabled already for %s."),
provname);
return (SUCCESS);
}
}
/*
* kCF treats random as an internal mechanism. So, we need to
* filter it from the mechanism list here, if we are NOT disabling
* or enabling the random feature. Note that we map random feature at
* cryptoadm(1M) level to the "random" mechanism in kCF.
*/
if (!rndflag) {
if (redo_flag)
}
/* Update the entry by enabling mechanisms for this provider */
return (rc);
}
if (redo_flag) {
return (FAILURE);
}
}
/*
* Update the kcf.conf file with the updated entry.
* For a hardware provider, if there is no more disabled mechanism,
* remove the entire kcf.conf entry.
*/
} else {
}
return (FAILURE);
}
/* Inform Kernel about the policy change */
return (FAILURE);
}
/* LOAD_DEV_DISABLED */
return (FAILURE);
}
cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: "
return (FAILURE);
}
cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
"return_value = %d",
return (FAILURE);
}
} else { /* a software module */
/* LOAD_SOFT_DISABLED */
return (FAILURE);
}
== -1) {
cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: "
return (FAILURE);
}
cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
"return_value = %d",
return (FAILURE);
}
}
return (SUCCESS);
}
/*
* Install a software module with the specified mechanism list into the system.
* This routine adds an entry into the config file for this software module
* first, then makes a CRYPTO_LOAD_SOFT_CONFIG ioctl call to inform kernel
* about the new addition.
*/
int
{
char *ptr;
char *str;
char *name;
int found_count;
int err;
return (FAILURE);
}
/* Check if the provider already exists */
provname);
return (FAILURE);
}
/* Create an entry with provname and mlist. */
return (FAILURE);
}
/* Append an entry for this software module to the kcf.conf file. */
return (FAILURE);
}
gettext("failed to update the configuration - %s"),
return (FAILURE);
}
gettext("failed to lock the configuration - %s"),
return (FAILURE);
}
/*
*/
gettext("failed to create a temporary file - %s"),
return (FAILURE);
}
return (FAILURE);
}
/*
* Loop thru the config file. If the provider was reserved within a
* package bracket, just uncomment it. Otherwise, append it at
* the end. The resulting file will be saved in the temp file first.
*/
found_count = 0;
if (buffer[0] == '#') {
ptr++;
break;
found_count++;
}
}
}
} else {
if (found_count == 1) {
}
} else {
/*
* Found a second entry with #libname.
* Should not happen. The kcf.conf file
* is corrupted. Give a warning and skip
* this entry.
*/
"(Warning) Found an additional reserved "
"entry for %s."), provname);
}
}
break;
}
}
if (unlink(tmpfile_name) != 0) {
"(Warning) failed to remove %s: %s"), tmpfile_name,
}
return (FAILURE);
}
if (found_count == 0) {
/*
* This libname was not in package before, append it to the
* end of the temp file.
*/
"failed to write to %s: %s"), tmpfile_name,
if (unlink(tmpfile_name) != 0) {
"(Warning) failed to remove %s: %s"),
}
return (FAILURE);
}
}
return (FAILURE);
}
gettext("failed to update the configuration - %s"),
} else if (chmod(_PATH_KCF_CONF,
gettext("failed to update the configuration - %s"),
} else {
}
if (unlink(tmpfile_name) != 0) {
"(Warning) failed to remove %s: %s"),
}
return (FAILURE);
}
/* Inform kernel of this new software module. */
return (FAILURE);
}
return (FAILURE);
}
cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
return (FAILURE);
}
cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed, "
return (FAILURE);
}
return (SUCCESS);
}
/*
* Uninstall the software module. This routine first unloads the software
* module with 3 ioctl calls, then deletes its entry from the config file.
* Removing an entry from the config file needs to be done last to ensure
* that there is still an entry if the earlier unload failed for any reason.
*/
int
{
/* Check to see if the provider exists first. */
return (FAILURE);
provname);
return (FAILURE);
}
/*
* If it is loaded, unload it first. This does 2 ioctl calls:
* CRYPTO_UNLOAD_SOFT_MODULE and CRYPTO_LOAD_SOFT_DISABLED.
*/
gettext("failed to unload %s during uninstall.\n"),
provname);
return (FAILURE);
}
/*
* Inform kernel to remove the configuration of this software module.
*/
/* Setup ioctl() parameter */
in_kcfconf = B_TRUE;
return (FAILURE);
}
return (FAILURE);
}
return (FAILURE);
}
pload_soft_conf) == -1) {
cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
return (FAILURE);
}
cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl = return_value = %d",
return (FAILURE);
}
/* ioctl cleanup */
/* Finally, remove entry from kcf.conf, if present */
}
return (rc);
}
/*
* Implement the "cryptoadm refresh" command for global zones.
* That is, send the current contents of kcf.conf to the kernel via ioctl().
*/
int
refresh(void)
{
int err;
"information from the configuration file - %s.",
return (FAILURE);
}
return (FAILURE);
}
/*
* For each software provider module, pass two sets of information to
* the kernel: the supported list and the disabled list.
*/
/* load the supported list */
cryptodebug("setup_soft_conf() failed");
break;
}
break;
}
}
== -1) {
cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
break;
}
cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl "
"return_value = %d",
break;
}
/* load the disabled list */
if (pload_soft_dis == NULL) {
cryptodebug("setup_soft_dis() failed");
break;
}
pload_soft_dis) == -1) {
cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
break;
}
if (pload_soft_dis->sd_return_value !=
cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
"return_value = %d",
break;
}
}
}
return (rc);
}
/*
* For each hardware provider module, pass the disabled list
* information to the kernel.
*/
/* load the disabled list */
if (pload_dev_dis == NULL) {
break;
}
== -1) {
cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
break;
}
cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
"return_value = %d",
break;
}
}
}
return (rc);
}
/*
* Unload the kernel software provider. Before calling this function, the
* caller should check to see if the provider is in the kernel.
*
* This routine makes 2 ioctl calls to remove it completely from the kernel:
* CRYPTO_UNLOAD_SOFT_MODULE - does a modunload of the KCF module
* CRYPTO_LOAD_SOFT_DISABLED - updates kernel disabled mechanism list
*
* This implements part of "cryptoadm unload" and "cryptoadm uninstall".
*/
int
{
int err;
return (FAILURE);
}
/* Construct an entry using the provname */
return (FAILURE);
}
}
/* Open the admin_ioctl_device */
return (FAILURE);
}
/* Inform kernel to unload this software module */
return (FAILURE);
}
cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s",
return (FAILURE);
}
cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl return_value = "
/*
* If the return value is CRYPTO_UNKNOWN_PROVIDER, it means
* that the provider is not registered yet. Should just
* continue.
*/
return (FAILURE);
}
}
/* Inform kernel to remove the disabled entries if any */
return (SUCCESS);
} else {
}
return (FAILURE);
}
/* pent is no longer needed; free it */
cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
return (FAILURE);
}
cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
return (FAILURE);
}
return (SUCCESS);
}
/*
* Check if a hardware provider is valid. If it is valid, returns its device
* name, instance number and the number of mechanisms it supports.
*/
static int
{
int i;
return (FAILURE);
}
/* First, get the device name and the instance number from provname */
return (FAILURE);
}
/*
* Get the complete device list from kernel and check if this provider
* is in the list.
*/
return (FAILURE);
}
for (i = 0; i < dev_list->dl_dev_count; i++) {
break;
}
}
if (i == dev_list->dl_dev_count) {
/* didn't find this provider in the kernel device list */
provname);
return (FAILURE);
}
/* This provider is valid. Get its mechanism count */
return (SUCCESS);
}