#include <cryptoutil.h>
#include <stdio.h>
#include <libintl.h>
#include <dlfcn.h>
#include <link.h>
#include <strings.h>
#include <security/cryptoki.h>
#include <cryptoutil.h>
#include "cryptoadm.h"
#define METASLOT_ID 0
int
list_metaslot_info(boolean_t show_mechs, boolean_t verbose,
mechlist_t *mechlist)
{
int rc = SUCCESS;
CK_RV rv;
CK_SLOT_INFO slot_info;
CK_TOKEN_INFO token_info;
CK_MECHANISM_TYPE_PTR pmech_list = NULL;
CK_ULONG mech_count;
int i;
CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR);
CK_FUNCTION_LIST_PTR funcs;
void *dldesc = NULL;
boolean_t lib_initialized = B_FALSE;
uentry_t *puent;
char buf[128];
if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) {
cryptoerror(LOG_STDERR,
gettext("metaslot entry doesn't exist."));
return (FAILURE);
}
(void) printf(gettext("System-wide Meta Slot Configuration:\n"));
(void) printf(gettext("------------------------------------\n"));
(void) printf(gettext("Status: %s\n"), puent->flag_metaslot_enabled ?
gettext("enabled") : gettext("disabled"));
(void) printf(gettext("Sensitive Token Object Automatic Migrate: %s\n"),
puent->flag_metaslot_auto_key_migrate ? gettext("enabled") :
gettext("disabled"));
bzero(buf, sizeof (buf));
if (memcmp(puent->metaslot_ks_slot, buf, SLOT_DESCRIPTION_SIZE) != 0) {
(void) printf(gettext("Persistent object store slot: %s\n"),
puent->metaslot_ks_slot);
}
if (memcmp(puent->metaslot_ks_token, buf, TOKEN_LABEL_SIZE) != 0) {
(void) printf(gettext("Persistent object store token: %s\n"),
puent->metaslot_ks_token);
}
if ((!verbose) && (!show_mechs)) {
return (SUCCESS);
}
if (verbose) {
(void) printf(gettext("\nDetailed Meta Slot Information:\n"));
(void) printf(gettext("-------------------------------\n"));
}
dldesc = dlopen(UEF_FRAME_LIB, RTLD_NOW);
if (dldesc == NULL) {
char *dl_error;
dl_error = dlerror();
cryptodebug("Cannot load PKCS#11 framework library. "
"dlerror:%s", dl_error);
return (FAILURE);
}
Tmp_C_GetFunctionList = (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList");
if (Tmp_C_GetFunctionList == NULL) {
cryptodebug("Cannot get the address of the C_GetFunctionList "
"from framework");
rc = FAILURE;
goto finish;
}
rv = Tmp_C_GetFunctionList(&funcs);
if (rv != CKR_OK) {
cryptodebug("failed to call C_GetFunctionList in "
"framework library");
rc = FAILURE;
goto finish;
}
rv = funcs->C_Initialize(NULL_PTR);
if (rv != CKR_OK) {
cryptodebug("C_Initialize failed with error code 0x%x\n", rv);
rc = FAILURE;
goto finish;
} else {
lib_initialized = B_TRUE;
}
rv = funcs->C_GetSlotInfo(METASLOT_ID, &slot_info);
if (rv == CKR_SLOT_ID_INVALID) {
(void) printf(gettext("actual status: disabled.\n"));
goto finish;
}
if (rv != CKR_OK) {
cryptodebug("C_GetSlotInfo failed with error "
"code 0x%x\n", rv);
rc = FAILURE;
goto finish;
}
if (!verbose) {
goto display_mechs;
}
(void) printf(gettext("actual status: enabled.\n"));
(void) printf(gettext("Description: %.64s\n"),
slot_info.slotDescription);
(void) printf(gettext("Token Present: %s\n"),
(slot_info.flags & CKF_TOKEN_PRESENT ?
gettext("True") : gettext("False")));
rv = funcs->C_GetTokenInfo(METASLOT_ID, &token_info);
if (rv != CKR_OK) {
cryptodebug("C_GetTokenInfo failed with error "
"code 0x%x\n", rv);
rc = FAILURE;
goto finish;
}
(void) printf(gettext("Token Label: %.32s\n"
"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"),
token_info.label,
token_info.manufacturerID,
token_info.model,
token_info.serialNumber,
token_info.hardwareVersion.major,
token_info.hardwareVersion.minor,
token_info.firmwareVersion.major,
token_info.firmwareVersion.minor,
token_info.utcTime,
token_info.ulMinPinLen,
token_info.ulMaxPinLen);
display_token_flags(token_info.flags);
if (!show_mechs) {
goto finish;
}
display_mechs:
if (mechlist == NULL) {
rv = funcs->C_GetMechanismList(METASLOT_ID, NULL_PTR,
&mech_count);
if (rv != CKR_OK) {
cryptodebug("C_GetMechanismList failed with error "
"code 0x%x\n", rv);
rc = FAILURE;
goto finish;
}
if (mech_count > 0) {
pmech_list = malloc(mech_count *
sizeof (CK_MECHANISM_TYPE));
if (pmech_list == NULL) {
cryptodebug("out of memory");
rc = FAILURE;
goto finish;
}
rv = funcs->C_GetMechanismList(METASLOT_ID, pmech_list,
&mech_count);
if (rv != CKR_OK) {
cryptodebug("C_GetMechanismList failed with "
"error code 0x%x\n", rv);
rc = FAILURE;
goto finish;
}
}
} else {
rc = convert_mechlist(&pmech_list, &mech_count, mechlist);
if (rc != SUCCESS) {
goto finish;
}
}
(void) printf(gettext("Mechanisms:\n"));
if (mech_count == 0) {
(void) printf(gettext("No mechanisms\n"));
goto finish;
}
if (verbose) {
display_verbose_mech_header();
}
for (i = 0; i < mech_count; i++) {
CK_MECHANISM_TYPE mech = pmech_list[i];
if (mech >= CKM_VENDOR_DEFINED) {
(void) printf("%#lx", mech);
} else {
(void) printf("%-29s", pkcs11_mech2str(mech));
}
if (verbose) {
CK_MECHANISM_INFO mech_info;
rv = funcs->C_GetMechanismInfo(METASLOT_ID,
mech, &mech_info);
if (rv != CKR_OK) {
cryptodebug("C_GetMechanismInfo failed with "
"error code 0x%x\n", rv);
rc = FAILURE;
goto finish;
}
display_mech_info(&mech_info);
}
(void) printf("\n");
}
finish:
if ((rc == FAILURE) && (show_mechs)) {
(void) printf(gettext(
"metaslot: failed to retrieve the mechanism list.\n"));
}
if (lib_initialized) {
(void) funcs->C_Finalize(NULL_PTR);
}
if (dldesc != NULL) {
(void) dlclose(dldesc);
}
if (pmech_list != NULL) {
(void) free(pmech_list);
}
return (rc);
}
int
list_metaslot_policy()
{
uentry_t *puent;
int rc;
if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) {
cryptoerror(LOG_STDERR,
gettext("metaslot entry doesn't exist."));
return (FAILURE);
}
rc = display_policy(puent);
(void) printf("\n");
free_uentry(puent);
return (rc);
}
int
disable_metaslot(mechlist_t *mechlist, boolean_t allflag,
boolean_t auto_key_migrate_flag)
{
uentry_t *puent;
int rc = SUCCESS;
if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) {
cryptoerror(LOG_STDERR,
gettext("metaslot entry doesn't exist."));
return (FAILURE);
}
if ((mechlist == NULL) && (!auto_key_migrate_flag) && (!allflag)) {
puent->flag_metaslot_enabled = B_FALSE;
goto write_to_file;
}
if (auto_key_migrate_flag) {
puent->flag_metaslot_auto_key_migrate = B_FALSE;
}
if ((mechlist == NULL) && (!allflag)) {
goto write_to_file;
}
if (allflag) {
free_umechlist(puent->policylist);
puent->policylist = NULL;
puent->count = 0;
puent->flag_enabledlist = B_TRUE;
rc = SUCCESS;
} else {
if (puent->flag_enabledlist == B_TRUE) {
rc = update_policylist(puent, mechlist, DELETE_MODE);
} else {
rc = update_policylist(puent, mechlist, ADD_MODE);
}
}
if (rc != SUCCESS) {
goto finish;
}
if ((puent->flag_enabledlist) && (puent->count == 0)) {
puent->flag_metaslot_enabled = B_FALSE;
}
write_to_file:
rc = update_pkcs11conf(puent);
finish:
free_uentry(puent);
return (rc);
}
int
enable_metaslot(char *token, char *slot, boolean_t use_default,
mechlist_t *mechlist, boolean_t allflag, boolean_t auto_key_migrate_flag)
{
uentry_t *puent;
int rc = SUCCESS;
if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) {
cryptoerror(LOG_STDERR,
gettext("metaslot entry doesn't exist."));
return (FAILURE);
}
puent->flag_metaslot_enabled = B_TRUE;
if (auto_key_migrate_flag) {
puent->flag_metaslot_auto_key_migrate = B_TRUE;
}
if (allflag) {
free_umechlist(puent->policylist);
puent->policylist = NULL;
puent->count = 0;
puent->flag_enabledlist = B_FALSE;
rc = SUCCESS;
} else {
if (mechlist) {
if (puent->flag_enabledlist == B_TRUE) {
rc = update_policylist(puent, mechlist,
ADD_MODE);
} else {
rc = update_policylist(puent, mechlist,
DELETE_MODE);
}
}
}
if (rc != SUCCESS) {
goto finish;
}
if (!use_default && !token && !slot) {
goto write_to_file;
}
(void) bzero((char *)puent->metaslot_ks_token, TOKEN_LABEL_SIZE);
(void) bzero((char *)puent->metaslot_ks_slot, SLOT_DESCRIPTION_SIZE);
if (use_default) {
(void) strlcpy((char *)puent->metaslot_ks_token,
SOFT_TOKEN_LABEL, TOKEN_LABEL_SIZE);
(void) strlcpy((char *)puent->metaslot_ks_slot,
SOFT_SLOT_DESCRIPTION, SLOT_DESCRIPTION_SIZE);
} else {
if (token) {
(void) strlcpy((char *)puent->metaslot_ks_token, token,
TOKEN_LABEL_SIZE);
}
if (slot) {
(void) strlcpy((char *)puent->metaslot_ks_slot, slot,
SLOT_DESCRIPTION_SIZE);
}
}
write_to_file:
rc = update_pkcs11conf(puent);
finish:
free_uentry(puent);
return (rc);
}