/*
* 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 2010 Nexenta Systems, Inc. All rights resrved.
*/
#include <cryptoutil.h>
#include <fcntl.h>
#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <dlfcn.h>
#include <link.h>
#include <security/cryptoki.h>
#include "cryptoadm.h"
{
if (flags & CKF_TOKEN_PRESENT)
(void) printf("CKF_TOKEN_PRESENT ");
if (flags & CKF_REMOVABLE_DEVICE)
(void) printf("CKF_REMOVABLE_DEVICE ");
if (flags & CKF_HW_SLOT)
(void) printf("CKF_HW_SLOT ");
(void) printf("\n");
}
void
{
(void) printf("CKF_RNG ");
if (flags & CKF_WRITE_PROTECTED)
(void) printf("CKF_WRITE_PROTECTED ");
if (flags & CKF_LOGIN_REQUIRED)
(void) printf("CKF_LOGIN_REQUIRED ");
if (flags & CKF_USER_PIN_INITIALIZED)
(void) printf("CKF_USER_PIN_INITIALIZED ");
if (flags & CKF_RESTORE_KEY_NOT_NEEDED)
(void) printf("CKF_RESTORE_KEY_NOT_NEEDED ");
if (flags & CKF_CLOCK_ON_TOKEN)
(void) printf("CKF_CLOCK_ON_TOKEN ");
(void) printf("CKF_PROTECTED_AUTHENTICATION_PATH ");
if (flags & CKF_DUAL_CRYPTO_OPERATIONS)
(void) printf("CKF_DUAL_CRYPTO_OPERATIONS ");
if (flags & CKF_TOKEN_INITIALIZED)
(void) printf("CKF_TOKEN_INITIALIZED ");
(void) printf("CKF_SECONDARY_AUTHENTICATION ");
if (flags & CKF_USER_PIN_COUNT_LOW)
(void) printf("CKF_USER_PIN_COUNT_LOW ");
if (flags & CKF_USER_PIN_FINAL_TRY)
(void) printf("CKF_USER_PIN_FINAL_TRY ");
if (flags & CKF_USER_PIN_LOCKED)
(void) printf("CKF_USER_PIN_LOCKED ");
if (flags & CKF_USER_PIN_TO_BE_CHANGED)
(void) printf("CKF_USER_PIN_TO_BE_CHANGED ");
if (flags & CKF_SO_PIN_COUNT_LOW)
(void) printf("CKF_SO_PIN_COUNT_LOW ");
if (flags & CKF_SO_PIN_FINAL_TRY)
(void) printf("CKF_SO_PIN_FINAL_TRY ");
if (flags & CKF_SO_PIN_LOCKED)
(void) printf("CKF_SO_PIN_LOCKED ");
if (flags & CKF_SO_PIN_TO_BE_CHANGED)
(void) printf("CKF_SO_PIN_TO_BE_CHANGED ");
if (flags & CKF_SO_PIN_TO_BE_CHANGED)
(void) printf("CKF_SO_PIN_TO_BE_CHANGED ");
(void) printf("\n");
}
void
{
(void) printf("%s %s %s %s %s %s %s %s %s %s %s %s "
"%s %s",
}
/*
* Converts the provided list of mechanism names in their string format to
* their corresponding PKCS#11 mechanism IDs.
*
* The list of mechanism names to be converted is provided in the
* "mlist" argument. The list of converted mechanism IDs is returned
* in the "pmech_list" argument.
*
* This function is called by list_metaslot_info() and
* list_mechlist_for_lib() functions.
*/
int
{
int i, n = 0;
mechlist_t *p = mlist;
while (p != NULL) {
p = p->next;
n++;
}
if (pmech_list == NULL) {
cryptodebug("out of memory");
return (FAILURE);
}
p = mlist;
for (i = 0; i < n; i++) {
free(*pmech_list);
return (FAILURE);
}
p = p->next;
}
*mech_count = n;
return (SUCCESS);
}
/*
* Display the mechanism list for a user-level library
*/
int
{
char *dl_error;
const char *mech_name;
char *isa;
int i, j;
/* should not happen */
cryptodebug("list_mechlist_for_lib() - libname is NULL.");
return (FAILURE);
}
/* Check if the library is in the pkcs11.conf file */
return (FAILURE);
}
/* Remove $ISA from the library name */
libname);
return (FAILURE);
}
*isa = '\000';
} else {
}
/*
* Open the provider. Use RTLD_NOW here, as a way to
* catch any providers with incomplete symbols that
* might otherwise cause problems during libpkcs11's
* execution.
*/
cryptodebug("Cannot load PKCS#11 library %s. dlerror: %s",
goto clean_exit;
}
/* Get the pointer to provider's C_GetFunctionList() */
if (Tmp_C_GetFunctionList == NULL) {
cryptodebug("Cannot get the address of the C_GetFunctionList "
"from %s", libname);
goto clean_exit;
}
/* Get the provider's function list */
cryptodebug("failed to call C_GetFunctionList from %s",
libname);
goto clean_exit;
}
/* Initialize this provider */
cryptodebug("failed to call C_Initialize from %s, "
goto clean_exit;
} else {
}
/*
* Find out how many slots this provider has, call with tokenPresent
* set to FALSE so all potential slots are returned.
*/
goto clean_exit;
} else if (slot_count == 0) {
if (!no_warn)
libname);
goto clean_exit;
}
/* Allocate memory for the slot list */
if (prov_slots == NULL) {
cryptodebug("out of memory.");
goto clean_exit;
}
/* Get the slot list from provider */
cryptodebug("failed to call C_GetSlotList() from %s.",
libname);
goto clean_exit;
}
if (verbose) {
}
/* Get the mechanism list for each slot */
for (i = 0; i < slot_count; i++) {
if (verbose)
/*
* TRANSLATION_NOTE
* In some languages, the # symbol should be
* converted to "no", an "n" followed by a
* superscript "o"..
*/
goto clean_exit;
} else
continue;
}
break;
}
if (verbose) {
"Manufacturer: %.32s\n"
"PKCS#11 Version: %d.%d\n"),
"Firmware Version: %d.%d\n"),
&tokeninfo);
cryptodebug("Failed to get "
"token info from %s", libname);
break;
}
"Manufacturer ID: %.32s\n"
"Model: %.16s\n"
"Serial Number: %.16s\n"
"Hardware Version: %d.%d\n"
"Firmware Version: %d.%d\n"
"UTC Time: %.16s\n"
"PIN Min Length: %d\n"
"PIN Max Length: %d\n"),
}
NULL_PTR, &mech_count);
"failed to call C_GetMechanismList() "
"from %s.", libname);
break;
}
if (mech_count == 0) {
/* no mechanisms in this slot */
continue;
}
sizeof (CK_MECHANISM_TYPE));
if (pmech_list == NULL) {
cryptodebug("out of memory");
break;
}
/* Get the actual mechanism list */
pmech_list, &mech_count);
"failed to call C_GetMechanismList() "
"from %s.", libname);
break;
}
} else {
/* use the mechanism list passed in */
goto clean_exit;
}
}
if (show_mechs)
if (verbose && show_mechs) {
}
/*
* Merge the current mechanism list into the returning
* mechanism list.
*/
for (j = 0; show_mechs && j < mech_count; j++) {
"failed to call "
"C_GetMechanismInfo() from %s.",
libname);
pmech_list = NULL;
break;
}
if (mech >= CKM_VENDOR_DEFINED) {
} else {
}
if (verbose) {
}
(void) printf("\n");
}
if (pmech_list)
break;
}
}
goto clean_exit;
}
"%s: failed to retrieve the mechanism list.\n"), libname);
}
if (lib_initialized) {
}
}
if (prov_slots != NULL) {
}
return (rc);
}
/*
* Display the mechanism policy for a user-level library
*/
int
{
int rc;
/* should not happen */
cryptodebug("list_policy_for_lib() - libname is NULL.");
return (FAILURE);
}
/* Get the library entry from the pkcs11.conf file */
return (FAILURE);
}
/* Print the policy for this library */
return (rc);
}
/*
* Disable mechanisms for a user-level library
*/
int
{
int rc;
/* should not happen */
cryptodebug("disable_uef_lib() - libname is NULL.");
return (FAILURE);
}
/* Get the provider entry from the pkcs11.conf file */
return (FAILURE);
}
/*
* Update the mechanism policy of this library entry, based on
* the current policy mode of the library and the mechanisms specified
* in CLI.
*/
if (allflag) {
/*
* If disabling all, just need to clean up the policylist and
* set the flag_enabledlist flag to be B_TRUE.
*/
/*
* The current default policy mode of this library
* is "all are disabled, except ...", so if a
* specified mechanism is in the exception list
* (the policylist), delete it from the policylist.
*/
} else {
/*
* The current default policy mode of this library
* is "all are enabled", so if a specified mechanism
* is not in the exception list (policylist), add
* it into the policylist.
*/
}
} else if (!rndflag) {
/* should not happen */
cryptodebug("disable_uef_lib() - wrong arguments.");
return (FAILURE);
}
if (rndflag)
return (FAILURE);
}
/* Update the pkcs11.conf file with the updated entry */
return (rc);
}
/*
* Enable disabled mechanisms for a user-level library.
*/
int
{
/* should not happen */
cryptodebug("enable_uef_lib() - libname is NULL.");
return (FAILURE);
}
/* Get the provider entry from the pkcs11.conf file */
return (FAILURE);
}
/*
* Update the mechanism policy of this library entry, based on
* the current policy mode of the library and the mechanisms
* specified in CLI.
*/
if (allflag) {
/*
* If enabling all, what needs to be done are cleaning up the
* policylist and setting the "flag_enabledlist" flag to
* B_FALSE.
*/
/*
* The current default policy mode of this library
* is "all are disabled, except ...", so if a
* specified mechanism is not in the exception list
* (policylist), add it.
*/
} else {
/*
* The current default policy mode of this library
* is "all are enabled, except", so if a specified
* mechanism is in the exception list (policylist),
* delete it.
*/
}
} else if (!rndflag) {
/* should not come here */
cryptodebug("enable_uef_lib() - wrong arguments.");
return (FAILURE);
}
if (rndflag)
return (FAILURE);
}
/* Update the pkcs11.conf file with the updated entry */
return (rc);
}
/*
* Install a user-level library.
*/
int
{
char *isa;
/* should not happen */
cryptodebug("install_uef_lib() - libname is NULL.");
return (FAILURE);
}
/* Check if the provider already exists in the framework */
libname);
return (FAILURE);
}
/*
* Check if the library exists in the system. if $ISA is in the
* path, only check the 32bit version.
*/
return (FAILURE);
}
*isa = '\000';
"/", isa);
} else {
}
/* Check if it is same as the framework library */
"The framework library %s can not be installed."),
libname);
return (FAILURE);
}
return (FAILURE);
}
/* Need to add "\n" to libname for adding into the config file */
"can not install %s; the name is too long."), libname);
return (FAILURE);
}
}
/*
* Uninstall a user-level library.
*/
int
{
char *name;
int len;
/* should not happen */
cryptodebug("uninstall_uef_lib() - libname is NULL.");
return (FAILURE);
}
/* Check if the provider exists */
return (FAILURE);
}
/* Open the pkcs11.conf file and lock it */
gettext("failed to update the configuration - %s"),
return (FAILURE);
}
gettext("failed to lock the configuration - %s"),
return (FAILURE);
}
/*
* the new configuration file first.
*/
gettext("failed to create a temporary file - %s"),
return (FAILURE);
}
if (unlink(tmpfile_name) != 0) {
"(Warning) failed to remove %s: %s"),
}
return (FAILURE);
}
/*
* Loop thru the config file. If the library to be uninstalled
* is in a package, just comment it off.
*/
buffer[0] == '\t')) {
in_package = B_TRUE;
} else if (buffer[0] != '#') {
/* get rid of trailing '\n' */
len--;
}
== NULL) {
break;
}
}
}
if (found) {
if (in_package) {
}
}
} else {
}
}
break;
}
}
if (unlink(tmpfile_name) != 0) {
"(Warning) failed to remove %s: %s"),
}
return (FAILURE);
}
gettext("failed to close a temporary file - %s"),
return (FAILURE);
}
/* Now update the real config file */
gettext("failed to update the configuration - %s"),
} else if (chmod(_PATH_PKCS11_CONF,
gettext("failed to update the configuration - %s"),
} else {
}
"(Warning) failed to remove %s: %s"),
}
return (rc);
}
int
{
const char *mech_name;
return (SUCCESS);
}
(void) printf(".");
} else {
if (mech_id & CKO_VENDOR_DEFINED) {
/* vendor defined mechanism */
} else {
if (mech_id >= CKM_VENDOR_DEFINED) {
} else {
mech_id);
return (FAILURE);
}
}
}
(void) printf(".");
} else {
(void) printf(",");
}
}
}
} else { /* puent->flag_enabledlist == B_TRUE */
(void) printf(".");
} else {
if (mech_id & CKO_VENDOR_DEFINED) {
/* vendor defined mechanism */
} else {
return (FAILURE);
}
}
(void) printf(".");
} else {
(void) printf(",");
}
}
}
}
return (SUCCESS);
}
/*
* Print out the mechanism policy for a user-level provider pointed by puent.
*/
int
{
return (FAILURE);
}
return (FAILURE);
}
goto failed_exit;
}
/*
* TRANSLATION_NOTE
* "random" is a keyword and not to be translated.
*/
else {
/*
* TRANSLATION_NOTE
* "random" is a keyword and not to be translated.
*/
}
(void) printf("\n");
return (SUCCESS);
return (FAILURE);
}
/*
* Check if the mechanism is in the mechanism list.
*/
static boolean_t
{
return (B_FALSE);
}
break;
}
}
return (found);
}
/*
* Update the pkcs11.conf file with the updated entry.
*/
int
{
char *name;
char *str;
int len;
return (FAILURE);
}
/* Open the pkcs11.conf file */
gettext("failed to update the configuration - %s"),
return (FAILURE);
}
/* Lock the pkcs11.conf file */
gettext("failed to update the configuration - %s"),
return (FAILURE);
}
/*
* updated configuration file first.
*/
gettext("failed to create a temporary file - %s"),
return (FAILURE);
}
if (unlink(tmpfile_name) != 0) {
"(Warning) failed to remove %s: %s"),
}
return (FAILURE);
}
/*
* Loop thru entire pkcs11.conf file, update the entry to be
* updated and save the updated file to the temporary file first.
*/
/*
* Get the provider name from this line and check if
* this is the entry to be updated. Note: can not use
* "buffer" directly because strtok will change its
* value.
*/
/* get rid of trailing '\n' */
len--;
}
break;
}
}
if (found) {
/*
* This is the entry to be modified, get the updated
* string.
*/
break;
} else {
}
}
"failed to write to a temp file: %s."),
break;
}
}
if (unlink(tmpfile_name) != 0) {
"(Warning) failed to remove %s: %s"),
}
return (FAILURE);
}
return (FAILURE);
}
/* Copy the temporary file to the pkcs11.conf file */
gettext("failed to update the configuration - %s"),
} else if (chmod(_PATH_PKCS11_CONF,
gettext("failed to update the configuration - %s"),
} else {
}
"(Warning) failed to remove %s: %s"),
}
return (rc);
}
/*
* Convert an uentry to a character string
*/
static char *
{
char *buf;
return (NULL);
}
return (NULL);
}
/* convert the library name */
return (NULL);
}
/* convert the enabledlist or the disabledlist */
return (NULL);
}
return (NULL);
}
return (NULL);
}
>= BUFSIZ) {
return (NULL);
}
}
}
return (NULL);
}
return (NULL);
}
return (NULL);
}
>= BUFSIZ) {
return (NULL);
}
}
}
}
return (NULL);
}
return (NULL);
}
}
/* write the metaslot_status= value */
return (NULL);
}
return (NULL);
}
if (puent->flag_metaslot_enabled) {
return (NULL);
}
} else {
>= BUFSIZ) {
return (NULL);
}
}
if (!tok1_present) {
}
return (NULL);
}
return (NULL);
}
if (puent->flag_metaslot_auto_key_migrate) {
return (NULL);
}
} else {
return (NULL);
}
}
/* write metaslot_token= if specified */
TOKEN_LABEL_SIZE) != 0) {
/* write the metaslot_status= value */
return (NULL);
}
return (NULL);
}
>= BUFSIZ) {
return (NULL);
}
}
/* write metaslot_slot= if specified */
SLOT_DESCRIPTION_SIZE) != 0) {
/* write the metaslot_status= value */
return (NULL);
}
return (NULL);
}
>= BUFSIZ) {
return (NULL);
}
}
}
return (NULL);
}
return (buf);
}
/*
* This function updates the default policy mode and the policy exception list
* for a user-level provider based on the mechanism specified in the disable
* or enable subcommand and the update mode. This function is called by the
* enable_uef_lib() or disable_uef_lib().
*/
int
{
/* should not happen */
cryptodebug("update_policylist()- puent or marglist is NULL.");
return (FAILURE);
}
/* should not happen */
cryptodebug("update_policylist() - update_mode is incorrect.");
return (FAILURE);
}
/*
* For each mechanism operand, get its mechanism type first.
* If fails to get the mechanism type, the mechanism operand must be
* invalid, gives an warning and ignore it. Otherwise,
* - convert the mechanism type to the internal representation (hex)
* in the pkcs11.conf file
* - If update_mode == DELETE_MODE,
* If the mechanism is in the policy list, delete it.
* If the mechanism is not in the policy list, do nothing.
* - If update_mode == ADD_MODE,
* If the mechanism is not in the policy list, add it.
* If the mechanism is in the policy list already, do nothing.
*/
while (marglist) {
/*
* This mechanism is not a valid PKCS11 mechanism,
* give warning and ignore it.
*/
"(Warning) %s is not a valid PKCS#11 mechanism."),
} else {
(int)mech_type);
if (update_mode == DELETE_MODE) {
} else {
}
}
if (found) {
puent->policylist =
} else {
}
}
}
} else if (update_mode == ADD_MODE) {
if (!is_in_policylist(midname,
puent->policylist)) {
break;
}
}
}
}
}
return (rc);
}
/*
* Open a session to the given slot and check if we can do
* random numbers by asking for one byte.
*/
static boolean_t
{
return (B_FALSE);
/* We care only about the return value */
sizeof (test_byte));
/*
* These checks are purely to determine whether the slot can do
* random numbers. So, we don't check whether the routine
* succeeds. The reason we check for CKR_RANDOM_NO_RNG also is that
* this error effectively means CKR_FUNCTION_NOT_SUPPORTED.
*/
return (B_TRUE);
else
return (B_FALSE);
}
void
{
/*
* TRANSLATION_NOTE
* Strictly for appearance's sake, the first header line should be
* as long as the length of the translated text above. The format
* lengths should all match too.
*/
(void) printf("%28s ---- ---- "
"- - - - - - - - - - - - - -\n",
gettext("----------------------------"));
}