/* * 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 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Administration for metaslot * * All the "list" operations will call functions in libpkcs11.so * Normally, it doesn't make sense to call functions in libpkcs11.so directly * because libpkcs11.so depends on the configuration file (pkcs11.conf) the * cryptoadm command is trying to administer. However, since metaslot * is part of the framework, it is not possible to get information about * it without actually calling functions in libpkcs11.so. * * So, for the listing operation, which won't modify the value of pkcs11.conf * it is safe to call libpkcs11.so. * * For other operations that modifies the pkcs11.conf file, libpkcs11.so * will not be called. * */ #include #include #include #include #include #include #include #include #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]; /* * Display the system-wide metaslot settings as specified * in pkcs11.conf file. */ 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")); /* * TRANSLATION_NOTE: * Strictly for appearance's sake, this line should be as long as * the length of the translated text above. */ (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")); /* * TRANSLATION_NOTE: * Strictly for appearance's sake, this line should be as * long as the length of the translated text above. */ (void) printf(gettext("-------------------------------\n")); } /* * Need to actually make calls to libpkcs11.so to get * information about metaslot. */ 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); } /* Get the pointer to library's C_GetFunctionList() */ 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; } /* Get the provider's function list */ rv = Tmp_C_GetFunctionList(&funcs); if (rv != CKR_OK) { cryptodebug("failed to call C_GetFunctionList in " "framework library"); rc = FAILURE; goto finish; } /* Initialize this provider */ 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; } /* * We know for sure that metaslot is slot 0 in the framework, * so, we will do a C_GetSlotInfo() trying to see if it works. * If it fails with CKR_SLOT_ID_INVALID, we know that metaslot * is not really enabled. */ rv = funcs->C_GetSlotInfo(METASLOT_ID, &slot_info); if (rv == CKR_SLOT_ID_INVALID) { (void) printf(gettext("actual status: disabled.\n")); /* * Even if the -m and -v flag is supplied, there's nothing * interesting to display about metaslot since it is disabled, * so, just stop right here. */ 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) { /* should never be this case */ (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); } /* * disable metaslot and some of its configuration options * * If mechlist==NULL, and the other 2 flags are false, just disabled * the metaslot feature. * * mechlist: list of mechanisms to disable * allflag: if true, indicates all mechanisms should be disabled. * auto_key_migrate_flag: if true, indicates auto key migrate should be disabled */ 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)) { /* disable metaslot */ puent->flag_metaslot_enabled = B_FALSE; goto write_to_file; } if (auto_key_migrate_flag) { /* need to disable auto_key_migrate */ puent->flag_metaslot_auto_key_migrate = B_FALSE; } if ((mechlist == NULL) && (!allflag)) { goto write_to_file; } /* disable specified mechanisms */ 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) { /* * The current default policy mode * is "all are disabled, except ...", so if a * specified mechanism is in the exception list * (the policylist), delete it from the policylist. */ rc = update_policylist(puent, mechlist, DELETE_MODE); } 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. */ rc = update_policylist(puent, mechlist, ADD_MODE); } } if (rc != SUCCESS) { goto finish; } /* If all mechanisms are disabled, metaslot will be disabled as well */ 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); } /* * enable metaslot and some of its configuration options * * If mechlist==NULL, and the other flags are false, or not specified, * just enable the metaslot feature. * * token: if specified, indicate label of token to be used as keystore. * slot: if specified, indicate slot to be used as keystore. * use_default: if true, indicate to use the default keystore. It should * not be specified if either token or slot is specified. * mechlist: list of mechanisms to enable * allflag: if true, indicates all mechanisms should be enabled. * auto_key_migrate_flag: if true, indicates auto key migrate should be enabled */ 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) { /* need to enable auto_key_migrate */ puent->flag_metaslot_auto_key_migrate = B_TRUE; } if (allflag) { /* * If enabling all, what needs to be done are cleaning up the * policylist and setting the "flag_enabledlist" flag to * B_FALSE. */ 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) { /* * 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. */ rc = update_policylist(puent, mechlist, ADD_MODE); } 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. */ rc = update_policylist(puent, mechlist, DELETE_MODE); } } } if (rc != SUCCESS) { goto finish; } if (!use_default && !token && !slot) { /* no need to change metaslot keystore */ 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); }