Example #1
0
static int
gencert_pkcs11(KMF_HANDLE_T kmfhandle,
	char *token, char *subject, char *altname,
	KMF_GENERALNAMECHOICES alttype, int altcrit,
	char *certlabel, KMF_KEY_ALG keyAlg,
	KMF_ALGORITHM_INDEX sigAlg,
	int keylen, uint32_t ltime, KMF_BIGINT *serial,
	uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred,
	EKU_LIST *ekulist, KMF_OID *curveoid)
{
	KMF_RETURN kmfrv = KMF_OK;
	KMF_KEY_HANDLE pubk, prik;
	KMF_X509_CERTIFICATE signedCert;
	KMF_X509_NAME	certSubject;
	KMF_X509_NAME	certIssuer;
	KMF_DATA x509DER;
	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
	KMF_ATTRIBUTE attrlist[16];
	int numattr = 0;
	KMF_KEY_ALG keytype;
	uint32_t keylength;

	(void) memset(&signedCert, 0, sizeof (signedCert));
	(void) memset(&certSubject, 0, sizeof (certSubject));
	(void) memset(&certIssuer, 0, sizeof (certIssuer));
	(void) memset(&x509DER, 0, sizeof (x509DER));

	/* If the subject name cannot be parsed, flag it now and exit */
	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
		cryptoerror(LOG_STDERR,
		    gettext("Subject name cannot be parsed.\n"));
		return (PK_ERR_USAGE);
	}

	/* For a self-signed cert, the issuser and subject are the same */
	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
		cryptoerror(LOG_STDERR,
		    gettext("Subject name cannot be parsed.\n"));
		return (PK_ERR_USAGE);
	}

	keylength = keylen; /* bits */
	keytype = keyAlg;

	/* Select a PKCS11 token */
	kmfrv = select_token(kmfhandle, token, FALSE);
	if (kmfrv != KMF_OK) {
		return (kmfrv);
	}

	/*
	 * Share the "genkeypair" routine for creating the keypair.
	 */
	kmfrv = genkeypair_pkcs11(kmfhandle, token, certlabel,
	    keytype, keylength, tokencred, curveoid, &prik, &pubk);
	if (kmfrv != KMF_OK)
		return (kmfrv);

	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
	    "keypair");

	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");

	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
	    "serial number");

	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
	    "validity time");

	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
	    "signature algorithm");

	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
	    "subject name");

	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
	    "issuer name");

	if (altname != NULL)
		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
		    alttype, altname), "subjectAltName");

	if (kubits != 0)
		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
		    "KeyUsage");

	if (ekulist != NULL) {
		int i;
		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
			SET_VALUE(kmf_add_cert_eku(&signedCert,
			    &ekulist->ekulist[i], ekulist->critlist[i]),
			    "Extended Key Usage");
		}
	}

	/*
	 * Construct attributes for the kmf_sign_cert operation.
	 */
	numattr = 0;
	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
	    &kstype, sizeof (kstype));
	numattr++;

	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
	numattr++;

	/* cert data that is to be signed */
	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
	numattr++;

	/* output buffer for the signed cert */
	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
	    &x509DER, sizeof (KMF_DATA));
	numattr++;

	kmf_set_attr_at_index(attrlist, numattr, KMF_ALGORITHM_INDEX_ATTR,
	    &sigAlg, sizeof (sigAlg));
	numattr++;

	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
	    KMF_OK) {
		goto cleanup;
	}

	/*
	 * Store the cert in the DB.
	 */
	numattr = 0;
	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
	    &kstype, sizeof (kstype));
	numattr++;
	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
	    &x509DER, sizeof (KMF_DATA));
	numattr++;

	if (certlabel != NULL) {
		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
		    certlabel, strlen(certlabel));
		numattr++;
	}

	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);

cleanup:
	kmf_free_data(&x509DER);
	kmf_free_dn(&certSubject);
	kmf_free_dn(&certIssuer);

	/*
	 * If kmf_sign_cert or kmf_store_cert failed, then we need to clean up
	 * the key pair from the token.
	 */
	if (kmfrv != KMF_OK) {
		/* delete the public key */
		numattr = 0;
		kmf_set_attr_at_index(attrlist, numattr,
		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
		numattr++;

		kmf_set_attr_at_index(attrlist, numattr,
		    KMF_KEY_HANDLE_ATTR, &pubk, sizeof (KMF_KEY_HANDLE));
		numattr++;

		if (tokencred != NULL && tokencred->cred != NULL) {
			kmf_set_attr_at_index(attrlist, numattr,
			    KMF_CREDENTIAL_ATTR, tokencred,
			    sizeof (KMF_CREDENTIAL));
			numattr++;
		}

		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
		    attrlist);

		/* delete the private key */
		numattr = 0;
		kmf_set_attr_at_index(attrlist, numattr,
		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
		numattr++;

		kmf_set_attr_at_index(attrlist, numattr,
		    KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
		numattr++;

		if (tokencred != NULL && tokencred->cred != NULL) {
			kmf_set_attr_at_index(attrlist, numattr,
			    KMF_CREDENTIAL_ATTR, tokencred,
			    sizeof (KMF_CREDENTIAL));
			numattr++;
		}

		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
		    attrlist);
	}

	return (kmfrv);
}
Example #2
0
/*
 * The top level function for the "cryptoadm list" subcommand and options.
 */
static int
do_list(int argc, char **argv)
{
	boolean_t		mflag = B_FALSE;
	boolean_t		pflag = B_FALSE;
	boolean_t		vflag = B_FALSE;
	char			ch;
	cryptoadm_provider_t	*prov = NULL;
	int			rc = SUCCESS;

	if ((argc == 3) && (strncmp(argv[2], FIPS_KEYWORD,
	    strlen(FIPS_KEYWORD))) == 0) {
		/*
		 * cryptoadm list fips-140
		 */
		rc = do_fips_actions(FIPS140_STATUS, NOT_REFRESH);
		return (rc);
	}

	argc -= 1;
	argv += 1;

	if (argc == 1) {
		rc = list_simple_for_all(B_FALSE);
		goto out;
	}

	/*
	 * cryptoadm list [-v] [-m] [-p] [provider=<>] [mechanism=<>]
	 */
	if (argc > 5) {
		usage();
		return (rc);
	}

	while ((ch = getopt(argc, argv, "mpv")) != EOF) {
		switch (ch) {
		case 'm':
			mflag = B_TRUE;
			if (pflag) {
				rc = ERROR_USAGE;
			}
			break;
		case 'p':
			pflag = B_TRUE;
			if (mflag || vflag) {
				rc = ERROR_USAGE;
			}
			break;
		case 'v':
			vflag = B_TRUE;
			if (pflag)
				rc = ERROR_USAGE;
			break;
		default:
			rc = ERROR_USAGE;
			break;
		}
	}

	if (rc == ERROR_USAGE) {
		usage();
		return (rc);
	}

	if ((rc = process_feature_operands(argc, argv)) != SUCCESS) {
		goto out;
	}

	prov = get_provider(argc, argv);

	if (mflag || vflag) {
		if (argc > 0) {
			rc = process_mech_operands(argc, argv, B_TRUE);
			if (rc == FAILURE)
				goto out;
			/* "-m" is implied when a mechanism list is given */
			if (mecharglist != NULL || allflag)
				mflag = B_TRUE;
		}
	}

	if (prov == NULL) {
		if (mflag) {
			rc = list_mechlist_for_all(vflag);
		} else if (pflag) {
			rc = list_policy_for_all();
		} else if (vflag) {
			rc = list_simple_for_all(vflag);
		}
	} else if (prov->cp_type == METASLOT) {
		if ((!mflag) && (!vflag) && (!pflag)) {
			/* no flag is specified, just list metaslot status */
			rc = list_metaslot_info(mflag, vflag, mecharglist);
		} else if (mflag || vflag) {
			rc = list_metaslot_info(mflag, vflag, mecharglist);
		} else if (pflag) {
			rc = list_metaslot_policy();
		} else {
			/* error message */
			usage();
			rc = ERROR_USAGE;
		}
	} else if (prov->cp_type == PROV_BADNAME) {
		usage();
		rc = ERROR_USAGE;
		goto out;
	} else { /* do the listing for a provider only */
		char	*provname = prov->cp_name;

		if (mflag || vflag) {
			if (vflag)
				(void) printf(gettext("Provider: %s\n"),
				    provname);
			switch (prov->cp_type) {
			case PROV_UEF_LIB:
				rc = list_mechlist_for_lib(provname,
				    mecharglist, NULL, B_FALSE, vflag, mflag);
				break;
			case PROV_KEF_SOFT:
				rc = list_mechlist_for_soft(provname,
				    NULL, NULL);
				break;
			case PROV_KEF_HARD:
				rc = list_mechlist_for_hard(provname);
				break;
			default: /* should not come here */
				rc = FAILURE;
				break;
			}
		} else if (pflag) {
			switch (prov->cp_type) {
			case PROV_UEF_LIB:
				rc = list_policy_for_lib(provname);
				break;
			case PROV_KEF_SOFT:
				if (getzoneid() == GLOBAL_ZONEID) {
					rc = list_policy_for_soft(provname,
					    NULL, NULL);
				} else {
					/*
					 * TRANSLATION_NOTE
					 * "global" is keyword and not to
					 * be translated.
					 */
					cryptoerror(LOG_STDERR, gettext(
					    "policy information for kernel "
					    "providers is available "
					    "in the %s zone only"), "global");
					rc = FAILURE;
				}
				break;
			case PROV_KEF_HARD:
				if (getzoneid() == GLOBAL_ZONEID) {
					rc = list_policy_for_hard(
					    provname, NULL, NULL, NULL);
				} else {
					/*
					 * TRANSLATION_NOTE
					 * "global" is keyword and not to
					 * be translated.
					 */
					cryptoerror(LOG_STDERR, gettext(
					    "policy information for kernel "
					    "providers is available "
					    "in the %s zone only"), "global");
					rc = FAILURE;
				}

				break;
			default: /* should not come here */
				rc = FAILURE;
				break;
			}
		} else {
			/* error message */
			usage();
			rc = ERROR_USAGE;
		}
	}

out:
	if (prov != NULL)
		free(prov);

	if (mecharglist != NULL)
		free_mechlist(mecharglist);
	return (rc);
}
Example #3
0
/*
 * The top level function for the "cryptoadm install" subcommand.
 */
static int
do_install(int argc, char **argv)
{
	cryptoadm_provider_t	*prov = NULL;
	int	rc;

	if (argc < 3) {
		usage();
		return (ERROR_USAGE);
	}

	prov = get_provider(argc, argv);
	if (prov == NULL ||
	    prov->cp_type == PROV_BADNAME || prov->cp_type == PROV_KEF_HARD) {
		/*
		 * TRANSLATION_NOTE
		 * "install" could be either a literal keyword and hence
		 * not to be translated, or a verb and translatable.  A
		 * choice was made to view it as a literal keyword.
		 */
		cryptoerror(LOG_STDERR,
		    gettext("bad provider name for %s."), "install");
		rc = FAILURE;
		goto out;
	}

	if (prov->cp_type == PROV_UEF_LIB) {
		rc = install_uef_lib(prov->cp_name);
		goto out;
	}

	/* It is the PROV_KEF_SOFT type now  */

	/* check if there are mechanism operands */
	if (argc < 4) {
		/*
		 * TRANSLATION_NOTE
		 * "mechanism" could be either a literal keyword and hence
		 * not to be translated, or a descriptive word and
		 * translatable.  A choice was made to view it as a literal
		 * keyword.
		 */
		cryptoerror(LOG_STDERR,
		    gettext("need %s operands for installing a"
		    " kernel software provider."), "mechanism");
		rc = ERROR_USAGE;
		goto out;
	}

	if ((rc = process_mech_operands(argc, argv, B_FALSE)) != SUCCESS) {
		goto out;
	}

	if (allflag == B_TRUE) {
		/*
		 * TRANSLATION_NOTE
		 * "all", "mechanism", and "install" are all keywords and
		 * not to be translated.
		 */
		cryptoerror(LOG_STDERR,
		    gettext("can not use the %1$s keyword for %2$s "
		    "in the %3$s subcommand."), "all", "mechanism", "install");
		rc = ERROR_USAGE;
		goto out;
	}

	if (getzoneid() == GLOBAL_ZONEID) {
		rc = install_kef(prov->cp_name, mecharglist);
	} else {
		/*
		 * TRANSLATION_NOTE
		 * "install" could be either a literal keyword and hence
		 * not to be translated, or a verb and translatable.  A
		 * choice was made to view it as a literal keyword.
		 * "global" is keyword and not to be translated.
		 */
		cryptoerror(LOG_STDERR, gettext("%1$s for kernel providers "
		    "is supported in the %2$s zone only"), "install", "global");
		rc = FAILURE;
	}
out:
	free(prov);
	return (rc);
}
Example #4
0
/*
 * List all the providers. And for each provider, list the mechanism list.
 * Called for "cryptoadm list -m" or "cryptoadm list -mv" .
 */
static int
list_mechlist_for_all(boolean_t verbose)
{
	crypto_get_dev_list_t	*pdevlist_kernel = NULL;
	uentrylist_t		*pliblist = NULL;
	uentrylist_t		*plibptr = NULL;
	entry_t			*pent = NULL;
	mechlist_t		*pmechlist = NULL;
	char			provname[MAXNAMELEN];
	char			devname[MAXNAMELEN];
	int			inst_num;
	int			count;
	int			i;
	int			rv;
	int			rc = SUCCESS;

	/* get user-level providers */
	(void) printf(gettext("\nUser-level providers:\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"));
	if (get_pkcs11conf_info(&pliblist) != SUCCESS) {
		cryptoerror(LOG_STDERR, gettext("failed to retrieve "
		    "the list of user-level providers.\n"));
		rc = FAILURE;
	}

	plibptr = pliblist;
	while (plibptr != NULL) {
		/* skip metaslot and fips-140 entry */
		if ((strcmp(plibptr->puent->name, METASLOT_KEYWORD) != 0) &&
		    (strcmp(plibptr->puent->name, FIPS_KEYWORD) != 0)) {
			(void) printf(gettext("\nProvider: %s\n"),
			    plibptr->puent->name);
			rv = list_mechlist_for_lib(plibptr->puent->name,
			    mecharglist, NULL, B_FALSE, verbose, B_TRUE);
			if (rv == FAILURE) {
				rc = FAILURE;
			}
		}
		plibptr = plibptr->next;
	}
	free_uentrylist(pliblist);

	/* get kernel software providers */
	(void) printf(gettext("\nKernel software providers:\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"));
	if (getzoneid() == GLOBAL_ZONEID) {
		/* get kernel software providers from kernel ioctl */
		crypto_get_soft_list_t		*psoftlist_kernel = NULL;
		uint_t				sl_soft_count;
		char				*psoftname;
		int				i;
		entrylist_t			*pdevlist_conf = NULL;
		entrylist_t			*psoftlist_conf = NULL;

		if (get_soft_list(&psoftlist_kernel) == FAILURE) {
			cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
			    "software provider list from kernel."));
			return (FAILURE);
		}
		sl_soft_count = psoftlist_kernel->sl_soft_count;

		if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf)
		    == FAILURE) {
			cryptoerror(LOG_ERR,
			    "failed to retrieve the providers' "
			    "information from file kcf.conf - %s.",
			    _PATH_KCF_CONF);
			free(psoftlist_kernel);
			return (FAILURE);
		}

		for (i = 0, psoftname = psoftlist_kernel->sl_soft_names;
		    i < sl_soft_count;
		    ++i, psoftname += strlen(psoftname) + 1) {
			pent = getent_kef(psoftname, pdevlist_conf,
			    psoftlist_conf);
			if ((pent == NULL) || (pent->load)) {
				rv = list_mechlist_for_soft(psoftname,
				    NULL, NULL);
				if (rv == FAILURE) {
					rc = FAILURE;
				}
			} else {
				(void) printf(gettext("%s: (inactive)\n"),
				    psoftname);
			}
		}

		free(psoftlist_kernel);
		free_entrylist(pdevlist_conf);
		free_entrylist(psoftlist_conf);

	} else {
		/* kcf.conf not there in non-global zone, use /dev/cryptoadm */
		entrylist_t	*pdevlist_zone = NULL;
		entrylist_t	*psoftlist_zone = NULL;
		entrylist_t	*ptr;

		if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) !=
		    SUCCESS) {
			cryptoerror(LOG_STDERR, gettext("failed to retrieve "
			    "the list of kernel software providers.\n"));
			rc = FAILURE;
		}

		for (ptr = psoftlist_zone; ptr != NULL; ptr = ptr->next) {
			rv = list_mechlist_for_soft(ptr->pent->name,
			    pdevlist_zone, psoftlist_zone);
			if (rv == FAILURE) {
				(void) printf(gettext(
				    "%s: failed to get the mechanism list.\n"),
				    ptr->pent->name);
				rc = FAILURE;
			}
		}

		free_entrylist(pdevlist_zone);
		free_entrylist(psoftlist_zone);
	}

	/* Get kernel hardware providers and their mechanism lists */
	(void) printf(gettext("\nKernel hardware providers:\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"));
	if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
		cryptoerror(LOG_STDERR, gettext("failed to retrieve "
		    "the list of hardware providers.\n"));
		return (FAILURE);
	}

	for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
		(void) strlcpy(devname,
		    pdevlist_kernel->dl_devs[i].le_dev_name, MAXNAMELEN);
		inst_num = pdevlist_kernel->dl_devs[i].le_dev_instance;
		count = pdevlist_kernel->dl_devs[i].le_mechanism_count;
		(void) snprintf(provname, sizeof (provname), "%s/%d", devname,
		    inst_num);
		if (get_dev_info(devname, inst_num, count, &pmechlist) ==
		    SUCCESS) {
			(void) filter_mechlist(&pmechlist, RANDOM);
			print_mechlist(provname, pmechlist);
			free_mechlist(pmechlist);
		} else {
			(void) printf(gettext("%s: failed to get the mechanism"
			    " list.\n"), provname);
			rc = FAILURE;
		}
	}
	free(pdevlist_kernel);
	return (rc);
}
Example #5
0
/*
 * Get the provider structure.  This function returns NULL if no valid
 * provider= is found in argv[], otherwise a cryptoadm_provider_t is returned.
 * If provider= is found but has no argument, then a cryptoadm_provider_t
 * with cp_type = PROV_BADNAME is returned.
 */
static cryptoadm_provider_t *
get_provider(int argc, char **argv)
{
	int			c = 0;
	boolean_t		found = B_FALSE;
	cryptoadm_provider_t	*provider = NULL;
	char			*provstr = NULL, *savstr;
	boolean_t		is_metaslot = B_FALSE;

	while (!found && ++c < argc) {
		if (strncmp(argv[c], METASLOT_KEYWORD,
		    strlen(METASLOT_KEYWORD)) == 0) {
			is_metaslot = B_TRUE;
			found = B_TRUE;
		} else if (strncmp(argv[c], KN_PROVIDER,
		    strlen(KN_PROVIDER)) == 0 &&
		    strlen(argv[c]) > strlen(KN_PROVIDER)) {
			if ((provstr = strdup(argv[c])) == NULL) {
				int err = errno;
				/*
				 * TRANSLATION_NOTE
				 * "get_provider" is a function name and should
				 * not be translated.
				 */
				cryptoerror(LOG_STDERR, "get_provider: %s.",
				    strerror(err));
				return (NULL);
			}
			found = B_TRUE;
		}
	}
	if (!found)
		return (NULL);

	provider = malloc(sizeof (cryptoadm_provider_t));
	if (provider == NULL) {
		cryptoerror(LOG_STDERR, gettext("out of memory."));
		if (provstr) {
			free(provstr);
		}
		return (NULL);
	}

	if (is_metaslot) {
		(void) strlcpy(provider->cp_name, METASLOT_KEYWORD,
		    strlen(METASLOT_KEYWORD));
		provider->cp_type = METASLOT;
	} else {

		savstr = provstr;
		(void) strtok(provstr, "=");
		provstr = strtok(NULL, "=");
		if (provstr == NULL) {
			cryptoerror(LOG_STDERR, gettext("bad provider name."));
			provider->cp_type = PROV_BADNAME;
			free(savstr);
			return (provider);
		}

		(void) strlcpy(provider->cp_name, provstr,
		    sizeof (provider->cp_name));
		provider->cp_type = get_provider_type(provider->cp_name);

		free(savstr);
	}
	return (provider);
}
Example #6
0
/*
 * For each provider found in pkcs11.conf: expand $ISA if necessary,
 * verify the module is signed, load the provider, find all of its
 * slots, and store the function list and disabled policy.
 *
 * This function requires that the uentrylist_t and pkcs11_slottable_t
 * already have memory allocated, and that the uentrylist_t is already
 * populated with provider and policy information.
 *
 * pInitArgs can be set to NULL, but is normally the same value
 * the framework's C_Initialize() was called with.
 *
 * Unless metaslot is explicitly disabled, it is setup when all other
 * providers are loaded.
 */
CK_RV
pkcs11_slot_mapping(uentrylist_t *pplist, CK_VOID_PTR pInitArgs)
{
	CK_RV rv = CKR_OK;
	CK_RV prov_rv;			/* Provider's return code */
	CK_INFO prov_info;
	CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR);
	CK_FUNCTION_LIST_PTR prov_funcs = NULL; /* Provider's function list */
	CK_ULONG prov_slot_count; 		/* Number of slots */
	CK_SLOT_ID slot_id; 		/* slotID assigned for framework */
	CK_SLOT_ID_PTR prov_slots = NULL; 	/* Provider's slot list */
					/* Enabled or Disabled policy */
	CK_MECHANISM_TYPE_PTR prov_pol_mechs = NULL;

	void *dldesc = NULL;
	char *isa, *fullpath = NULL, *dl_error;
	uentrylist_t *phead;
	uint_t prov_count = 0;
	pkcs11_slot_t *cur_slot;
	CK_ULONG i;
	size_t len;
	uentry_t *metaslot_entry = NULL;
	/* number of slots in the framework, not including metaslot */
	uint_t slot_count = 0;

	ELFsign_status_t estatus = ELFSIGN_UNKNOWN;
	char *estatus_str = NULL;
	int kcfdfd = -1;
	door_arg_t	darg;
	kcf_door_arg_t *kda = NULL;
	kcf_door_arg_t *rkda = NULL;
	int r;

	phead = pplist;

	/* Loop through all of the provider listed in pkcs11.conf */
	while (phead != NULL) {
		if (!strcasecmp(phead->puent->name, "metaslot")) {
			/*
			 * Skip standard processing for metaslot
			 * entry since it is not an actual library
			 * that can be dlopened.
			 * It will be initialized later.
			 */
			if (metaslot_entry != NULL) {
				cryptoerror(LOG_ERR,
				    "libpkcs11: multiple entries for metaslot "
				    "detected.  All but the first entry will "
				    "be ignored");
			} else {
				metaslot_entry = phead->puent;
			}
			goto contparse;
		}

		/* Check for Instruction Set Architecture indicator */
		if ((isa = strstr(phead->puent->name, PKCS11_ISA)) != NULL) {
			/* Substitute the architecture dependent path */
			len = strlen(phead->puent->name) -
			    strlen(PKCS11_ISA) +
			    strlen(PKCS11_ISA_DIR) + 1;
			if ((fullpath = (char *)malloc(len)) == NULL) {
				cryptoerror(LOG_ERR,
				    "libpksc11: parsing %s, out of memory. "
				    "Cannot continue parsing.",
				    _PATH_PKCS11_CONF);
				rv = CKR_HOST_MEMORY;
				goto conferror;
			}
			*isa = '\000';
			isa += strlen(PKCS11_ISA);
			(void) snprintf(fullpath, len, "%s%s%s",
			    phead->puent->name, PKCS11_ISA_DIR, isa);
		} else if ((fullpath = strdup(phead->puent->name)) == 0) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: parsing %s, out of memory. "
			    "Cannot continue parsing.",
			    _PATH_PKCS11_CONF);
			rv = CKR_HOST_MEMORY;
			goto conferror;
		}

		/*
		 * Open the provider. Use RTLD_NOW to make sure we
		 * will not encounter symbol referencing errors later.
		 * Use RTLD_GROUP to limit the provider to it's own
		 * symbols, which prevents it from mistakenly accessing
		 * the framework's C_* functions.
		 */
		dldesc = dlopen(fullpath, RTLD_NOW|RTLD_GROUP);

		/*
		 * If we failed to load it, we will just skip this
		 * provider and move on to the next one.
		 */
		if (dldesc == NULL) {
			dl_error = dlerror();
			cryptoerror(LOG_ERR,
			    "libpkcs11: Cannot load PKCS#11 library %s.  "
			    "dlerror: %s. %s",
			    fullpath, dl_error != NULL ? dl_error : "Unknown",
			    conf_err);
			goto contparse;
		}

		/* Get the pointer to provider's C_GetFunctionList() */
		Tmp_C_GetFunctionList =
		    (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList");

		/*
		 * If we failed to get the pointer to C_GetFunctionList(),
		 * skip this provider and continue to the next one.
		 */
		if (Tmp_C_GetFunctionList == NULL) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Could not dlsym() C_GetFunctionList() "
			    "for %s. May not be a PKCS#11 library. %s",
			    fullpath, conf_err);
			(void) dlclose(dldesc);
			goto contparse;
		}


		/* Get the provider's function list */
		prov_rv = Tmp_C_GetFunctionList(&prov_funcs);

		/*
		 * If we failed to get the provider's function list,
		 * skip this provider and continue to the next one.
		 */
		if (prov_rv != CKR_OK) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Could not get function list for %s. "
			    "%s Error: %s.",
			    fullpath, conf_err, pkcs11_strerror(prov_rv));
			(void) dlclose(dldesc);
			goto contparse;
		}

		/* Initialize this provider */
		prov_rv = prov_funcs->C_Initialize(pInitArgs);

		/*
		 * If we failed to initialize this provider,
		 * skip this provider and continue to the next one.
		 */
		if ((prov_rv != CKR_OK) &&
		    (prov_rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Could not initialize %s. "
			    "%s Error: %s.",
			    fullpath, conf_err, pkcs11_strerror(prov_rv));
			(void) dlclose(dldesc);
			goto contparse;
		}

		/*
		 * Make sure this provider is implementing the same
		 * major version, and at least the same minor version
		 * that we are.
		 */
		prov_rv = prov_funcs->C_GetInfo(&prov_info);

		/*
		 * If we can't verify that we are implementing the
		 * same major version, or if it is definitely not the same
		 * version, we need to skip this provider.
		 */
		if ((prov_rv != CKR_OK) ||
		    (prov_info.cryptokiVersion.major !=
			CRYPTOKI_VERSION_MAJOR))  {
			if (prov_rv != CKR_OK) {
				cryptoerror(LOG_ERR,
				    "libpkcs11: Could not verify version of "
				    "%s. %s Error: %s.", fullpath,
				    conf_err, pkcs11_strerror(prov_rv));
			} else {
				cryptoerror(LOG_ERR,
				    "libpkcs11: Only CRYPTOKI major version "
				    "%d is supported.  %s is major "
				    "version %d. %s",
				    CRYPTOKI_VERSION_MAJOR, fullpath,
				    prov_info.cryptokiVersion.major, conf_err);
			}
			(void) prov_funcs->C_Finalize(NULL);
			(void) dlclose(dldesc);
			goto contparse;
		}

		/*
		 * Warn the administrator (at debug) that a provider with
		 * a significantly older or newer version of
		 * CRYPTOKI is being used.  It should not cause
		 * problems, but logging a warning makes it easier
		 * to debug later.
		 */
		if ((prov_info.cryptokiVersion.minor <
			CRYPTOKI_VERSION_WARN_MINOR) ||
		    (prov_info.cryptokiVersion.minor >
			CRYPTOKI_VERSION_MINOR)) {
			cryptoerror(LOG_DEBUG,
			    "libpkcs11: %s CRYPTOKI minor version, %d, may "
			    "not be compatible with minor version %d.",
			    fullpath, prov_info.cryptokiVersion.minor,
			    CRYPTOKI_VERSION_MINOR);
		}

		/*
		 * Find out how many slots this provider has,
		 * call with tokenPresent set to FALSE so all
		 * potential slots are returned.
		 */
		prov_rv = prov_funcs->C_GetSlotList(FALSE,
		    NULL, &prov_slot_count);

		/*
		 * If the call failed, or if no slots are returned,
		 * then skip this provider and continue to next one.
		 */
		if (prov_rv != CKR_OK) {
			cryptoerror(LOG_ERR,
			    "libpksc11: Could not get slot list from %s. "
			    "%s Error: %s.",
			    fullpath, conf_err, pkcs11_strerror(prov_rv));
			(void) prov_funcs->C_Finalize(NULL);
			(void) dlclose(dldesc);
			goto contparse;
		}

		if (prov_slot_count == 0) {
			cryptodebug("libpkcs11: No slots presented from %s. "
			    "Skipping this plug-in at this time.\n",
			    fullpath);
			(void) prov_funcs->C_Finalize(NULL);
			(void) dlclose(dldesc);
			goto contparse;
		}

		/*
		 * Verify that the module is signed correctly.
		 *
		 * NOTE: there is a potential race condition here,
		 * since the module is verified well after we have
		 * opened the provider via dlopen().  This could be
		 * resolved by a variant of dlopen() that would take a
		 * file descriptor as an argument and by changing the
		 * kcfd libelfsign door protocol to use and fd instead
		 * of a path - but that wouldn't work in the kernel case.
		 */
		while ((kcfdfd = open(_PATH_KCFD_DOOR, O_RDONLY)) == -1) {
			if (!(errno == EINTR || errno == EAGAIN))
				break;
		}
		if (kcfdfd == -1) {
			cryptoerror(LOG_ERR, "libpkcs11: open %s: %s",
				_PATH_KCFD_DOOR,
			    strerror(errno));
			goto verifycleanup;
		}

		/* Mark the door "close on exec" */
		(void) fcntl(kcfdfd, F_SETFD, FD_CLOEXEC);

		if ((kda = malloc(sizeof (kcf_door_arg_t))) == NULL) {
			cryptoerror(LOG_ERR, "libpkcs11: malloc of kda "
				"failed: %s", strerror(errno));
			goto verifycleanup;
		}
		kda->da_version = KCF_KCFD_VERSION1;
		kda->da_iskernel = B_FALSE;
		(void) strlcpy(kda->da_u.filename, fullpath,
		    strlen(fullpath) + 1);

		darg.data_ptr = (char *)kda;
		darg.data_size = sizeof (kcf_door_arg_t);
		darg.desc_ptr = NULL;
		darg.desc_num = 0;
		darg.rbuf = (char *)kda;
		darg.rsize = sizeof (kcf_door_arg_t);

		while ((r = door_call(kcfdfd, &darg)) != 0) {
			if (!(errno == EINTR || errno == EAGAIN))
				break;
		}

		if (r != 0) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Unable to contact kcfd: %s",
			    strerror(errno));
			goto verifycleanup;
		}

		/*LINTED*/
		rkda = (kcf_door_arg_t *)darg.rbuf;
		if (rkda->da_version != KCF_KCFD_VERSION1) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: kcfd and libelfsign versions "
			    "don't match: got %d expected %d",
			    rkda->da_version, KCF_KCFD_VERSION1);
			goto verifycleanup;
		}
		estatus = rkda->da_u.result.status;
verifycleanup:
		if (kcfdfd != -1) {
			(void) close(kcfdfd);
		}
		if (rkda != NULL && rkda != kda)
			(void) munmap((char *)rkda, darg.rsize);
		if (kda != NULL) {
			bzero(kda, sizeof (kda));
			free(kda);
			kda = NULL;
			rkda = NULL;	/* rkda is an alias of kda */
		}

		switch (estatus) {
		case ELFSIGN_SUCCESS:
		case ELFSIGN_RESTRICTED:
			break;
		case ELFSIGN_NOTSIGNED:
			estatus_str = strdup("not a signed provider.");
			break;
		case ELFSIGN_FAILED:
			estatus_str = strdup("signature verification failed.");
			break;
		default:
			estatus_str = strdup("unexpected failure in ELF "
			    "signature verification. "
			    "System may have been tampered with.");
		}
		if (estatus_str != NULL) {
			cryptoerror(LOG_ERR, "libpkcs11: %s %s %s",
			    fullpath, estatus_str ? estatus_str : "",
			    estatus == ELFSIGN_UNKNOWN ?
			    "Cannot continue parsing " _PATH_PKCS11_CONF:
			    conf_err);
			(void) prov_funcs->C_Finalize(NULL);
			(void) dlclose(dldesc);
			free(estatus_str);
			estatus_str = NULL;
			if (estatus == ELFSIGN_UNKNOWN) {
				prov_funcs = NULL;
				dldesc = NULL;
				rv = CKR_GENERAL_ERROR;
				goto conferror;
			}
			goto contparse;
		}

		/* Allocate memory for the slot list */
		prov_slots = calloc(prov_slot_count, sizeof (CK_SLOT_ID));

		if (prov_slots == NULL) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Could not allocate memory for "
			    "plug-in slots. Cannot continue parsing %s\n",
			    _PATH_PKCS11_CONF);
			rv = CKR_HOST_MEMORY;
			goto conferror;
		}

		/* Get slot list from provider */
		prov_rv = prov_funcs->C_GetSlotList(FALSE,
		    prov_slots, &prov_slot_count);

		/* if second call fails, drop this provider */
		if (prov_rv != CKR_OK) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Second call to C_GetSlotList() for %s "
			    "failed. %s Error: %s.",
			    fullpath, conf_err, pkcs11_strerror(prov_rv));
			(void) prov_funcs->C_Finalize(NULL);
			(void) dlclose(dldesc);
			goto contparse;
		}

		/*
		 * Parse the list of disabled or enabled mechanisms, will
		 * apply to each of the provider's slots.
		 */
		if (phead->puent->count > 0) {
			rv = pkcs11_mech_parse(phead->puent->policylist,
			    &prov_pol_mechs, phead->puent->count);

			if (rv == CKR_HOST_MEMORY) {
				cryptoerror(LOG_ERR,
				    "libpkcs11: Could not parse configuration,"
				    "out of memory. Cannot continue parsing "
				    "%s.", _PATH_PKCS11_CONF);
				goto conferror;
			} else if (rv == CKR_MECHANISM_INVALID) {
				/*
				 * Configuration file is corrupted for this
				 * provider.
				 */
				cryptoerror(LOG_ERR,
				    "libpkcs11: Policy invalid or corrupted "
				    "for %s. Use cryptoadm(1M) to fix "
				    "this. Skipping this plug-in.",
				    fullpath);
				(void) prov_funcs->C_Finalize(NULL);
				(void) dlclose(dldesc);
				goto contparse;
			}
		}

		/* Allocate memory in our slottable for these slots */
		rv = pkcs11_slottable_increase(prov_slot_count);

		/*
		 * If any error is returned, it will be memory related,
		 * so we need to abort the attempt at filling the
		 * slottable.
		 */
		if (rv != CKR_OK) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: slottable could not increase. "
			    "Cannot continue parsing %s.",
			    _PATH_PKCS11_CONF);
			goto conferror;
		}

		/* Configure information for each new slot */
		for (i = 0; i < prov_slot_count; i++) {
			/* allocate slot in framework */
			rv = pkcs11_slot_allocate(&slot_id);
			if (rv != CKR_OK) {
				cryptoerror(LOG_ERR,
				    "libpkcs11: Could not allocate "
				    "new slot.  Cannot continue parsing %s.",
				    _PATH_PKCS11_CONF);
				goto conferror;
			}
			slot_count++;
			cur_slot = slottable->st_slots[slot_id];
			(void) pthread_mutex_lock(&cur_slot->sl_mutex);
			cur_slot->sl_id = prov_slots[i];
			cur_slot->sl_func_list = prov_funcs;
			cur_slot->sl_enabledpol =
			    phead->puent->flag_enabledlist;
			cur_slot->sl_pol_mechs = prov_pol_mechs;
			cur_slot->sl_pol_count = phead->puent->count;
			cur_slot->sl_norandom = phead->puent->flag_norandom;
			cur_slot->sl_dldesc = dldesc;
			cur_slot->sl_prov_id = prov_count + 1;
			(void) pthread_mutex_unlock(&cur_slot->sl_mutex);
		}


		/* Set and reset values to process next provider */
		prov_count++;
contparse:
		prov_slot_count = 0;
		Tmp_C_GetFunctionList = NULL;
		prov_funcs = NULL;
		dldesc = NULL;
		if (fullpath != NULL) {
			free(fullpath);
			fullpath = NULL;
		}
		if (prov_slots != NULL) {
			free(prov_slots);
			prov_slots = NULL;
		}
		phead = phead->next;
	}

	if (slot_count == 0) {
		/*
		 * there's no other slot in the framework,
		 * there is nothing to do
		 */
		goto config_complete;
	}

	/* determine if metaslot should be enabled */

	/*
	 * Check to see if any environment variable is defined
	 * by the user for configuring metaslot.  Users'
	 * setting always take precedence over the system wide
	 * setting.  So, we will first check for any user's
	 * defined env variables before looking at the system-wide
	 * configuration.
	 */
	get_user_metaslot_config();

	/* no metaslot entry in /etc/crypto/pkcs11.conf */
	if (!metaslot_entry) {
		/*
		 * If user env variable indicates metaslot should be enabled,
		 * but there's no entry in /etc/crypto/pkcs11.conf for
		 * metaslot at all, will respect the user's defined value
		 */
		if ((metaslot_config.enabled_specified) &&
		    (metaslot_config.enabled)) {
			metaslot_enabled = B_TRUE;
		}
	} else {
		if (!metaslot_config.enabled_specified) {
			/*
			 * take system wide value if
			 * it is not specified by user
			 */
			metaslot_enabled
			    = metaslot_entry->flag_metaslot_enabled;
		} else {
			metaslot_enabled = metaslot_config.enabled;
		}
	}

	/*
	 *
	 * As long as the user or system configuration file does not
	 * disable metaslot, it will be enabled regardless of the
	 * number of slots plugged into the framework.  Therefore,
	 * metaslot is enabled even when there's only one slot
	 * plugged into the framework.  This is necessary for
	 * presenting a consistent token label view to applications.
	 *
	 * However, for the case where there is only 1 slot plugged into
	 * the framework, we can use "fastpath".
	 *
	 * "fastpath" will pass all of the application's requests
	 * directly to the underlying provider.  Only when policy is in
	 * effect will we need to keep slotID around.
	 *
	 * When metaslot is enabled, and fastpath is enabled,
	 * all the metaslot processing will be skipped.
	 * When there is only 1 slot, there's
	 * really not much metaslot can do in terms of combining functionality
	 * of different slots, and object migration.
	 *
	 */

	/* check to see if fastpath can be used */
	if (slottable->st_last == slottable->st_first) {

		cur_slot = slottable->st_slots[slottable->st_first];

		(void) pthread_mutex_lock(&cur_slot->sl_mutex);

		if ((cur_slot->sl_pol_count == 0) &&
		    (!cur_slot->sl_enabledpol) && (!cur_slot->sl_norandom)) {
			/* No policy is in effect, don't need slotid */
			fast_funcs = cur_slot->sl_func_list;
			purefastpath = B_TRUE;
		} else {
			fast_funcs = cur_slot->sl_func_list;
			fast_slot = slottable->st_first;
			policyfastpath = B_TRUE;
		}

		(void) pthread_mutex_unlock(&cur_slot->sl_mutex);
	}

	if ((purefastpath || policyfastpath) && (!metaslot_enabled)) {
		goto config_complete;
	}

	/*
	 * If we get here, there are more than 2 slots in the framework,
	 * we need to set up metaslot if it is enabled
	 */
	if (metaslot_enabled) {
		rv = setup_metaslot(metaslot_entry);
		if (rv != CKR_OK) {
			goto conferror;
		}
	}


config_complete:

	return (CKR_OK);

conferror:
	/*
	 * This cleanup code is only exercised when a major,
	 * unrecoverable error like "out of memory" occurs.
	 */
	if (prov_funcs != NULL) {
		(void) prov_funcs->C_Finalize(NULL);
	}
	if (dldesc != NULL) {
		(void) dlclose(dldesc);
	}
	if (fullpath != NULL) {
		free(fullpath);
		fullpath = NULL;
	}
	if (prov_slots != NULL) {
		free(prov_slots);
		prov_slots = NULL;
	}

	return (rv);
}
Example #7
0
/*
 * The top level function for the "cryptoadm unload" subcommand.
 */
static int
do_unload(int argc, char **argv)
{
	cryptoadm_provider_t	*prov = NULL;
	entry_t			*pent = NULL;
	boolean_t		in_kernel = B_FALSE;
	int			rc = SUCCESS;
	char			*provname = NULL;

	if (argc != 3) {
		usage();
		return (ERROR_USAGE);
	}

	/* check if it is a kernel software provider */
	prov = get_provider(argc, argv);
	if (prov == NULL) {
		cryptoerror(LOG_STDERR,
		    gettext("unable to determine provider name."));
		goto out;
	}
	provname = prov->cp_name;
	if (prov->cp_type != PROV_KEF_SOFT) {
		cryptoerror(LOG_STDERR,
		    gettext("%s is not a valid kernel software provider."),
		    provname);
		rc = FAILURE;
		goto out;
	}

	if (getzoneid() != GLOBAL_ZONEID) {
		/*
		 * TRANSLATION_NOTE
		 * "unload" could be either a literal keyword and hence
		 * not to be translated, or a verb and translatable.
		 * A choice was made to view it as a literal keyword.
		 * "global" is keyword and not to be translated.
		 */
		cryptoerror(LOG_STDERR, gettext("%1$s for kernel providers "
		    "is supported in the %2$s zone only"), "unload", "global");
		rc = FAILURE;
		goto out;
	}

	if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
		cryptodebug("internal error");
		rc = FAILURE;
		goto out;
	} else if (in_kernel == B_FALSE) {
		cryptoerror(LOG_STDERR,
		    gettext("provider %s is not loaded or does not exist."),
		    provname);
		rc = FAILURE;
		goto out;
	}

	/* Get kcf.conf entry.  If none, build a new entry */
	if ((pent = getent_kef(provname, NULL, NULL)) == NULL) {
		if ((pent = create_entry(provname)) == NULL) {
			cryptoerror(LOG_STDERR, gettext("out of memory."));
			rc = FAILURE;
			goto out;
		}
	}

	/* If it is unloaded already, return  */
	if (!pent->load) { /* unloaded already */
		cryptoerror(LOG_STDERR,
		    gettext("failed to unload %s."), provname);
		rc = FAILURE;
		goto out;
	} else if (unload_kef_soft(provname) != FAILURE) {
		/* Mark as unloaded in kcf.conf */
		pent->load = B_FALSE;
		rc = update_kcfconf(pent, MODIFY_MODE);
	} else {
		cryptoerror(LOG_STDERR,
		    gettext("failed to unload %s."), provname);
		rc = FAILURE;
	}
out:
	free(prov);
	free_entry(pent);
	return (rc);
}
Example #8
0
/*
 * 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
list_policy_for_hard(char *provname,
	entrylist_t *phardlist, entrylist_t *psoftlist,
	crypto_get_dev_list_t *pdevlist)
{
	entry_t		*pent = NULL;
	boolean_t	in_kernel;
	mechlist_t	*pmechlist = NULL;
	char		devname[MAXNAMELEN];
	int		inst_num;
	int		count;
	int		rc = SUCCESS;
	boolean_t	has_random = B_FALSE;
	boolean_t 	has_mechs = B_FALSE;

	if (provname == NULL) {
		return (FAILURE);
	}

	/*
	 * Check if the provider is valid. If it is valid, get the number of
	 * mechanisms also.
	 */
	if (check_hardware_provider(provname, devname, &inst_num, &count) ==
	    FAILURE) {
		return (FAILURE);
	}

	/* Get the mechanism list for the kernel hardware provider */
	if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) ==
	    SUCCESS) {
		has_random = filter_mechlist(&pmechlist, RANDOM);

		if (pmechlist != NULL) {
			has_mechs = B_TRUE;
			free_mechlist(pmechlist);
		}
	} else {
		cryptoerror(LOG_STDERR, gettext(
		    "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.
	 */
	if ((pent = getent_kef(provname, phardlist, psoftlist)) != NULL) {
		print_kef_policy(provname, pent, has_random, has_mechs);
		free_entry(pent);
		return (SUCCESS);
	} else {
		if (check_kernel_for_hard(provname, pdevlist,
		    &in_kernel) == FAILURE) {
			return (FAILURE);
		} else if (in_kernel == B_TRUE) {
			(void) printf(gettext(
			    "%s: all mechanisms are enabled."), provname);
			if (has_random)
				/*
				 * TRANSLATION_NOTE
				 * "random" is a keyword and not to be
				 * translated.
				 */
				(void) printf(gettext(" %s is enabled.\n"),
				    "random");
			else
				(void) printf("\n");
			return (SUCCESS);
		} else {
			cryptoerror(LOG_STDERR,
			    gettext("%s does not exist."), provname);
			return (FAILURE);
		}
	}
}
Example #9
0
/*
 * Disable a kernel hardware provider.
 * This implements the "cryptoadm disable" command for
 * kernel hardware providers.
 */
int
disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag,
    mechlist_t *dislist)
{
	crypto_load_dev_disabled_t	*pload_dev_dis = NULL;
	mechlist_t			*infolist = NULL;
	entry_t				*pent = NULL;
	boolean_t			new_dev_entry = B_FALSE;
	char				devname[MAXNAMELEN];
	int				inst_num;
	int				count;
	int				fd = -1;
	int				rc = SUCCESS;

	if (provname == NULL) {
		return (FAILURE);
	}

	/*
	 * Check if the provider is valid. If it is valid, get the number of
	 * mechanisms also.
	 */
	if (check_hardware_provider(provname, devname, &inst_num, &count)
	    == FAILURE) {
		return (FAILURE);
	}

	/* Get the mechanism list for the kernel hardware provider */
	if (get_dev_info(devname, inst_num, count, &infolist) == FAILURE) {
		return (FAILURE);
	}

	/*
	 * Get the entry of this hardware provider from the config file.
	 * If there is no entry yet, create one for it.
	 */
	if ((pent = getent_kef(provname, NULL, NULL)) == NULL) {
		if ((pent = create_entry(provname)) == NULL) {
			cryptoerror(LOG_STDERR, gettext("out of memory."));
			free_mechlist(infolist);
			return (FAILURE);
		}
		new_dev_entry = B_TRUE;
	}

	/*
	 * 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) {
		(void) filter_mechlist(&dislist, RANDOM);
	}

	/* Calculate the new disabled list */
	if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) {
		free_mechlist(infolist);
		free_entry(pent);
		return (FAILURE);
	}
	free_mechlist(infolist);

	/* If no mechanisms are to be disabled, return */
	if (pent->dis_count == 0) {
		free_entry(pent);
		return (SUCCESS);
	}

	/* Update the config file with the new entry or the updated entry */
	if (new_dev_entry) {
		rc = update_kcfconf(pent, ADD_MODE);
	} else {
		rc = update_kcfconf(pent, MODIFY_MODE);
	}

	if (rc == FAILURE) {
		free_entry(pent);
		return (FAILURE);
	}

	/* Inform kernel about the new disabled mechanism list */
	if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) {
		free_entry(pent);
		return (FAILURE);
	}
	free_entry(pent);

	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
		    ADMIN_IOCTL_DEVICE, strerror(errno));
		free(pload_dev_dis);
		return (FAILURE);
	}

	if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) {
		cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: %s",
		    strerror(errno));
		free(pload_dev_dis);
		(void) close(fd);
		return (FAILURE);
	}

	if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
		cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl return_value = "
		    "%d", pload_dev_dis->dd_return_value);
		free(pload_dev_dis);
		(void) close(fd);
		return (FAILURE);
	}

	free(pload_dev_dis);
	(void) close(fd);
	return (SUCCESS);
}
Example #10
0
/*
 * 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)
{
	crypto_load_soft_config_t	*pload_soft_conf = NULL;
	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
	crypto_load_dev_disabled_t	*pload_dev_dis = NULL;
	entrylist_t			*pdevlist = NULL;
	entrylist_t			*psoftlist = NULL;
	entrylist_t			*ptr;
	int				fd = -1;
	int				rc = SUCCESS;
	int				err;

	if (get_kcfconf_info(&pdevlist, &psoftlist) == FAILURE) {
		cryptoerror(LOG_ERR, "failed to retrieve the providers' "
		    "information from the configuration file - %s.",
		    _PATH_KCF_CONF);
		return (FAILURE);
	}

	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
		err = errno;
		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
		    ADMIN_IOCTL_DEVICE, strerror(err));
		free(psoftlist);
		free(pdevlist);
		return (FAILURE);
	}

	/*
	 * For each software provider module, pass two sets of information to
	 * the kernel: the supported list and the disabled list.
	 */
	for (ptr = psoftlist; ptr != NULL; ptr = ptr->next) {
		entry_t		*pent = ptr->pent;

		/* load the supported list */
		if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
			cryptodebug("setup_soft_conf() failed");
			rc = FAILURE;
			break;
		}

		if (!pent->load) { /* unloaded--mark as loaded */
			pent->load = B_TRUE;
			rc = update_kcfconf(pent, MODIFY_MODE);
			if (rc != SUCCESS) {
				free(pload_soft_conf);
				break;
			}
		}

		if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf)
		    == -1) {
			cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
			    strerror(errno));
			free(pload_soft_conf);
			rc = FAILURE;
			break;
		}

		if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
			cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl "
			    "return_value = %d",
			    pload_soft_conf->sc_return_value);
			free(pload_soft_conf);
			rc = FAILURE;
			break;
		}

		free(pload_soft_conf);

		/* load the disabled list */
		if (ptr->pent->dis_count != 0) {
			pload_soft_dis = setup_soft_dis(ptr->pent);
			if (pload_soft_dis == NULL) {
				cryptodebug("setup_soft_dis() failed");
				free(pload_soft_dis);
				rc = FAILURE;
				break;
			}

			if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED,
			    pload_soft_dis) == -1) {
				cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
				    "failed: %s", strerror(errno));
				free(pload_soft_dis);
				rc = FAILURE;
				break;
			}

			if (pload_soft_dis->sd_return_value !=
			    CRYPTO_SUCCESS) {
				cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
				    "return_value = %d",
				    pload_soft_dis->sd_return_value);
				free(pload_soft_dis);
				rc = FAILURE;
				break;
			}
			free(pload_soft_dis);
		}
	}

	if (rc != SUCCESS) {
		(void) close(fd);
		return (rc);
	}


	/*
	 * For each hardware provider module, pass the disabled list
	 * information to the kernel.
	 */
	for (ptr = pdevlist; ptr != NULL; ptr = ptr->next) {
		/* load the disabled list */
		if (ptr->pent->dis_count != 0) {
			pload_dev_dis = setup_dev_dis(ptr->pent);
			if (pload_dev_dis == NULL) {
				rc = FAILURE;
				break;
			}

			if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis)
			    == -1) {
				cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
				    "failed: %s", strerror(errno));
				free(pload_dev_dis);
				rc = FAILURE;
				break;
			}

			if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
				cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
				    "return_value = %d",
				    pload_dev_dis->dd_return_value);
				free(pload_dev_dis);
				rc = FAILURE;
				break;
			}
			free(pload_dev_dis);
		}
	}

	/*
	 * handle fips_status=enabled|disabled
	 */
	{
		int	pkcs11_fips_mode = 0;

		/* Get FIPS-140 status from pkcs11.conf */
		fips_status_pkcs11conf(&pkcs11_fips_mode);
		if (pkcs11_fips_mode == CRYPTO_FIPS_MODE_ENABLED) {
			rc = do_fips_actions(FIPS140_ENABLE, REFRESH);
		} else {
			rc = do_fips_actions(FIPS140_DISABLE, REFRESH);
		}
	}

	(void) close(fd);
	return (rc);
}
Example #11
0
/*
 * 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
unload_kef_soft(char *provname)
{
	crypto_unload_soft_module_t	*punload_soft = NULL;
	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
	entry_t				*pent = NULL;
	int				fd = -1;
	int				err;

	if (provname == NULL) {
		cryptoerror(LOG_STDERR, gettext("internal error."));
		return (FAILURE);
	}

	pent = getent_kef(provname, NULL, NULL);
	if (pent == NULL) { /* not in kcf.conf */
		/* Construct an entry using the provname */
		pent = create_entry(provname);
		if (pent == NULL) {
			cryptoerror(LOG_STDERR, gettext("out of memory."));
			return (FAILURE);
		}
	}

	/* Open the admin_ioctl_device */
	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
		err = errno;
		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
		    ADMIN_IOCTL_DEVICE, strerror(err));
		free_entry(pent);
		return (FAILURE);
	}

	/* Inform kernel to unload this software module */
	if ((punload_soft = setup_unload_soft(pent)) == NULL) {
		free_entry(pent);
		(void) close(fd);
		return (FAILURE);
	}

	if (ioctl(fd, CRYPTO_UNLOAD_SOFT_MODULE, punload_soft) == -1) {
		cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s",
		    strerror(errno));
		free_entry(pent);
		free(punload_soft);
		(void) close(fd);
		return (FAILURE);
	}

	if (punload_soft->sm_return_value != CRYPTO_SUCCESS) {
		cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl return_value = "
		    "%d", punload_soft->sm_return_value);
		/*
		 * If the return value is CRYPTO_UNKNOWN_PROVIDER, it means
		 * that the provider is not registered yet.  Should just
		 * continue.
		 */
		if (punload_soft->sm_return_value != CRYPTO_UNKNOWN_PROVIDER) {
			free_entry(pent);
			free(punload_soft);
			(void) close(fd);
			return (FAILURE);
		}
	}

	free(punload_soft);

	/* Inform kernel to remove the disabled entries if any */
	if (pent->dis_count == 0) {
		free_entry(pent);
		(void) close(fd);
		return (SUCCESS);
	} else {
		free_mechlist(pent->dislist);
		pent->dislist = NULL;
		pent->dis_count = 0;
	}

	if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
		free_entry(pent);
		(void) close(fd);
		return (FAILURE);
	}

	/* pent is no longer needed; free it */
	free_entry(pent);

	if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) {
		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
		    strerror(errno));
		free(pload_soft_dis);
		(void) close(fd);
		return (FAILURE);
	}

	if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
		    "%d", pload_soft_dis->sd_return_value);
		free(pload_soft_dis);
		(void) close(fd);
		return (FAILURE);
	}

	free(pload_soft_dis);
	(void) close(fd);
	return (SUCCESS);
}
Example #12
0
int
pk_gencsr(int argc, char *argv[])
{
	KMF_RETURN rv;
	int opt;
	extern int	optind_av;
	extern char	*optarg_av;
	KMF_KEYSTORE_TYPE kstype = 0;
	char *subject = NULL;
	char *tokenname = NULL;
	char *dir = NULL;
	char *prefix = NULL;
	int keylen = PK_DEFAULT_KEYLENGTH;
	char *certlabel = NULL;
	char *outcsr = NULL;
	char *outkey = NULL;
	char *format = NULL;
	char *altname = NULL;
	char *kustr = NULL;
	char *ekustr = NULL;
	char *hashname = NULL;
	uint16_t kubits = 0;
	char *keytype = PK_DEFAULT_KEYTYPE;
	KMF_HANDLE_T kmfhandle = NULL;
	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
	KMF_KEY_ALG keyAlg = KMF_RSA;
	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_SHA1WithRSA;
	boolean_t interactive = B_FALSE;
	char *subname = NULL;
	KMF_CREDENTIAL tokencred = {NULL, 0};
	KMF_GENERALNAMECHOICES alttype = 0;
	int altcrit = 0, kucrit = 0;
	EKU_LIST *ekulist = NULL;
	KMF_OID *curveoid = NULL; /* ECC */
	KMF_OID *hashoid = NULL;
	int y_flag = 0;

	while ((opt = getopt_av(argc, argv,
	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
	    "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)"
	    "y:(keylen)l:(label)c:(outcsr)e:(eku)C:(curve)"
	    "K:(outkey)F:(format)E(listcurves)h:(hash)")) != EOF) {

		switch (opt) {
			case 'A':
				altname = optarg_av;
				break;
			case 'i':
				if (interactive)
					return (PK_ERR_USAGE);
				else if (subject) {
					cryptoerror(LOG_STDERR,
					    gettext("Interactive (-i) and "
					    "subject options are mutually "
					    "exclusive.\n"));
					return (PK_ERR_USAGE);
				} else
					interactive = B_TRUE;
				break;
			case 'k':
				kstype = KS2Int(optarg_av);
				if (kstype == 0)
					return (PK_ERR_USAGE);
				break;
			case 's':
				if (subject)
					return (PK_ERR_USAGE);
				else if (interactive) {
					cryptoerror(LOG_STDERR,
					    gettext("Interactive (-i) and "
					    "subject options are mutually "
					    "exclusive.\n"));
					return (PK_ERR_USAGE);
				} else
					subject = optarg_av;
				break;
			case 'l':
			case 'n':
				if (certlabel)
					return (PK_ERR_USAGE);
				certlabel = optarg_av;
				break;
			case 'T':
				if (tokenname)
					return (PK_ERR_USAGE);
				tokenname = optarg_av;
				break;
			case 'd':
				dir = optarg_av;
				break;
			case 'p':
				if (prefix)
					return (PK_ERR_USAGE);
				prefix = optarg_av;
				break;
			case 't':
				keytype = optarg_av;
				break;
			case 'u':
				kustr = optarg_av;
				break;
			case 'y':
				if (sscanf(optarg_av, "%d",
				    &keylen) != 1) {
					cryptoerror(LOG_STDERR,
					    gettext("Unrecognized "
					    "key length (%s)\n"), optarg_av);
					return (PK_ERR_USAGE);
				}
				y_flag++;
				break;
			case 'c':
				if (outcsr)
					return (PK_ERR_USAGE);
				outcsr = optarg_av;
				break;
			case 'K':
				if (outkey)
					return (PK_ERR_USAGE);
				outkey = optarg_av;
				break;
			case 'F':
				if (format)
					return (PK_ERR_USAGE);
				format = optarg_av;
				break;
			case 'e':
				ekustr = optarg_av;
				break;
			case 'C':
				curveoid = ecc_name_to_oid(optarg_av);
				if (curveoid == NULL) {
					cryptoerror(LOG_STDERR,
					    gettext("Unrecognized ECC "
					    "curve.\n"));
					return (PK_ERR_USAGE);
				}
				break;
			case 'E':
				/*
				 * This argument is only to be used
				 * by itself, no other options should
				 * be present.
				 */
				if (argc != 2) {
					cryptoerror(LOG_STDERR,
					    gettext("listcurves has no other "
					    "options.\n"));
					return (PK_ERR_USAGE);
				}
				show_ecc_curves();
				return (0);
			case 'h':
				hashname = optarg_av;
				hashoid = ecc_name_to_oid(optarg_av);
				if (hashoid == NULL) {
					cryptoerror(LOG_STDERR,
					    gettext("Unrecognized hash.\n"));
					return (PK_ERR_USAGE);
				}
				break;
			default:
				cryptoerror(LOG_STDERR, gettext(
				    "unrecognized gencsr option '%s'\n"),
				    argv[optind_av]);
				return (PK_ERR_USAGE);
		}
	}
	/* No additional args allowed. */
	argc -= optind_av;
	argv += optind_av;
	if (argc) {
		return (PK_ERR_USAGE);
	}

	/* Assume keystore = PKCS#11 if not specified. */
	if (kstype == 0)
		kstype = KMF_KEYSTORE_PK11TOKEN;

	DIR_OPTION_CHECK(kstype, dir);

	if (EMPTYSTRING(outcsr) && interactive) {
		(void) get_filename("CSR", &outcsr);
	}
	if (EMPTYSTRING(outcsr)) {
		(void) printf(gettext("A filename must be specified to hold"
		    "the final certificate request data.\n"));
		return (PK_ERR_USAGE);
	}
	/*
	 * verify that the outcsr file does not already exist
	 * and that it can be created.
	 */
	rv = verify_file(outcsr);
	if (rv == KMF_ERR_OPEN_FILE) {
		cryptoerror(LOG_STDERR,
		    gettext("Warning: file \"%s\" exists, "
		    "will be overwritten."), outcsr);
		if (yesno(gettext("Continue with gencsr? "),
		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
			return (0);
		} else {
			/* remove the file */
			(void) unlink(outcsr);
		}
	} else if (rv != KMF_OK)  {
		cryptoerror(LOG_STDERR,
		    gettext("Warning: error accessing \"%s\""), outcsr);
		return (rv);
	}

	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
		if (EMPTYSTRING(certlabel) && interactive)
			(void) get_certlabel(&certlabel);

		if (EMPTYSTRING(certlabel)) {
			cryptoerror(LOG_STDERR, gettext("A label must be "
			    "specified to create a certificate request.\n"));
			return (PK_ERR_USAGE);
		}
	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
		if (EMPTYSTRING(outkey) && interactive)
			(void) get_filename("private key", &outkey);

		if (EMPTYSTRING(outkey)) {
			cryptoerror(LOG_STDERR, gettext("A key filename "
			    "must be specified to create a certificate "
			    "request.\n"));
			return (PK_ERR_USAGE);
		}
	}

	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
		cryptoerror(LOG_STDERR,
		    gettext("Error parsing format string (%s).\n"), format);
		return (PK_ERR_USAGE);
	}
	if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) {
		cryptoerror(LOG_STDERR,
		    gettext("CSR must be DER or PEM format.\n"));
		return (PK_ERR_USAGE);
	}

	/*
	 * Check the subject name.
	 * If interactive is true, get it now interactively.
	 */
	if (interactive) {
		if (get_subname(&subname) != KMF_OK) {
			cryptoerror(LOG_STDERR, gettext("Failed to get the "
			    "subject name interactively.\n"));
			return (PK_ERR_USAGE);
		}
	} else {
		if (EMPTYSTRING(subject)) {
			cryptoerror(LOG_STDERR, gettext("A subject name or "
			    "-i must be specified to create a certificate "
			    "request.\n"));
			return (PK_ERR_USAGE);
		} else {
			subname = strdup(subject);
			if (subname == NULL) {
				cryptoerror(LOG_STDERR,
				    gettext("Out of memory.\n"));
				return (PK_ERR_SYSTEM);
			}
		}
	}
	if (altname != NULL) {
		rv = verify_altname(altname, &alttype, &altcrit);
		if (rv != KMF_OK) {
			cryptoerror(LOG_STDERR, gettext("Subject AltName "
			    "must be specified as a name=value pair. "
			    "See the man page for details."));
			goto end;
		} else {
			/* advance the altname past the '=' sign */
			char *p = strchr(altname, '=');
			if (p != NULL)
				altname = p + 1;
		}
	}

	if (kustr != NULL) {
		rv = verify_keyusage(kustr, &kubits, &kucrit);
		if (rv != KMF_OK) {
			cryptoerror(LOG_STDERR, gettext("KeyUsage "
			    "must be specified as a comma-separated list. "
			    "See the man page for details."));
			goto end;
		}
	}
	if (ekustr != NULL) {
		rv = verify_ekunames(ekustr, &ekulist);
		if (rv != KMF_OK) {
			(void) fprintf(stderr, gettext("EKUs must "
			    "be specified as a comma-separated list. "
			    "See the man page for details.\n"));
			rv = PK_ERR_USAGE;
			goto end;
		}
	}
	if ((rv = Str2KeyType(keytype, hashoid, &keyAlg, &sigAlg)) != 0) {
		cryptoerror(LOG_STDERR,
		    gettext("Unsupported key/hash combination (%s/%s).\n"),
		    keytype, (hashname ? hashname : "none"));
		goto end;
	}
	if (curveoid != NULL && keyAlg != KMF_ECDSA) {
		cryptoerror(LOG_STDERR, gettext("EC curves are only "
		    "valid for EC keytypes.\n"));
		return (PK_ERR_USAGE);
	}
	if (keyAlg == KMF_ECDSA && curveoid == NULL) {
		cryptoerror(LOG_STDERR, gettext("A curve must be "
		    "specifed when using EC keys.\n"));
		return (PK_ERR_USAGE);
	}
	if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
		(void) fprintf(stderr, gettext("ECC certificates are"
		    "only supported with the pkcs11 and nss keystores\n"));
		rv = PK_ERR_USAGE;
		goto end;
	}

	/* Adjust default keylength for NSS and DSA */
	if (keyAlg == KMF_DSA && !y_flag && kstype == KMF_KEYSTORE_NSS)
		keylen = 1024;

	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
		if (tokenname == NULL || !strlen(tokenname)) {
			if (kstype == KMF_KEYSTORE_NSS) {
				tokenname = "internal";
			} else  {
				tokenname = PK_DEFAULT_PK11TOKEN;
			}
		}

		(void) get_token_password(kstype, tokenname, &tokencred);
	}

	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
		return (PK_ERR_USAGE);
	}


	if (kstype == KMF_KEYSTORE_NSS) {
		if (dir == NULL)
			dir = PK_DEFAULT_DIRECTORY;

		rv = gencsr_nss(kmfhandle,
		    tokenname, subname, altname, alttype, altcrit,
		    certlabel, dir, prefix,
		    keyAlg, keylen, kubits, kucrit,
		    fmt, outcsr, &tokencred, ekulist,
		    sigAlg, curveoid);

	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
		rv = gencsr_pkcs11(kmfhandle,
		    tokenname, subname, altname, alttype, altcrit,
		    certlabel, keyAlg, keylen,
		    kubits, kucrit, fmt, outcsr, &tokencred,
		    ekulist, sigAlg, curveoid);

	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
		rv = gencsr_file(kmfhandle,
		    keyAlg, keylen, fmt, subname, altname,
		    alttype, altcrit, kubits, kucrit,
		    outcsr, outkey, ekulist, sigAlg);
	}

end:
	if (rv != KMF_OK) {
		display_error(kmfhandle, rv,
		    gettext("Error creating CSR or keypair"));

		if (rv == KMF_ERR_RDN_PARSER) {
			cryptoerror(LOG_STDERR, gettext("subject or "
			    "issuer name must be in proper DN format.\n"));
		}
	}

	if (ekulist != NULL)
		free_eku_list(ekulist);

	if (subname)
		free(subname);

	if (tokencred.cred != NULL)
		free(tokencred.cred);

	(void) kmf_finalize(kmfhandle);
	if (rv != KMF_OK)
		return (PK_ERR_USAGE);

	return (0);
}
Example #13
0
static KMF_RETURN
gencsr_file(KMF_HANDLE_T kmfhandle,
	KMF_KEY_ALG keyAlg,
	int keylen, KMF_ENCODE_FORMAT fmt,
	char *subject, char *altname, KMF_GENERALNAMECHOICES alttype,
	int altcrit, uint16_t kubits, int kucrit,
	char *outcsr, char *outkey, EKU_LIST *ekulist,
	KMF_ALGORITHM_INDEX sigAlg)
{
	KMF_RETURN kmfrv;
	KMF_KEY_HANDLE pubk, prik;
	KMF_X509_NAME	csrSubject;
	KMF_CSR_DATA	csr;
	KMF_DATA signedCsr = {NULL, 0};
	char *fullcsrpath = NULL;
	char *fullkeypath = NULL;


	(void) memset(&csr, 0, sizeof (csr));
	(void) memset(&csrSubject, 0, sizeof (csrSubject));

	if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) {
		cryptoerror(LOG_STDERR,
		    gettext("No output file was specified for "
		    "the csr or key\n"));
		return (KMF_ERR_BAD_PARAMETER);
	}
	fullcsrpath = strdup(outcsr);
	if (verify_file(fullcsrpath)) {
		cryptoerror(LOG_STDERR,
		    gettext("Cannot write the indicated output "
		    "certificate file (%s).\n"), fullcsrpath);
		free(fullcsrpath);
		return (PK_ERR_USAGE);
	}

	/* If the subject name cannot be parsed, flag it now and exit */
	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
		return (kmfrv);
	}
	/*
	 * Share the "genkeypair" routine for creating the keypair.
	 */
	kmfrv = genkeypair_file(kmfhandle, keyAlg, keylen,
	    fmt, outkey, &prik, &pubk);
	if (kmfrv != KMF_OK)
		return (kmfrv);

	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
	    "SetCSRPubKey");

	SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion");

	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
	    "kmf_set_csr_subject");

	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");

	if (altname != NULL) {
		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
		    alttype), "kmf_set_csr_subject_altname");
	}
	if (kubits != NULL) {
		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
		    "kmf_set_csr_ku");
	}
	if (ekulist != NULL) {
		int i;
		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
			SET_VALUE(kmf_add_csr_eku(&csr,
			    &ekulist->ekulist[i],
			    ekulist->critlist[i]),
			    "Extended Key Usage");
		}
	}
	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
	    KMF_OK) {
		kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath);
	}

cleanup:
	if (fullkeypath)
		free(fullkeypath);
	if (fullcsrpath)
		free(fullcsrpath);

	kmf_free_data(&signedCsr);
	kmf_free_kmf_key(kmfhandle, &prik);
	kmf_free_signed_csr(&csr);

	return (kmfrv);
}
Example #14
0
int
pk_gencert(int argc, char *argv[])
{
	int rv;
	int opt;
	extern int	optind_av;
	extern char	*optarg_av;
	KMF_KEYSTORE_TYPE kstype = 0;
	char *subject = NULL;
	char *tokenname = NULL;
	char *dir = NULL;
	char *prefix = NULL;
	char *keytype = PK_DEFAULT_KEYTYPE;
	int keylen = PK_DEFAULT_KEYLENGTH;
	char *trust = NULL;
	char *lifetime = NULL;
	char *certlabel = NULL;
	char *outcert = NULL;
	char *outkey = NULL;
	char *format = NULL;
	char *serstr = NULL;
	char *altname = NULL;
	char *keyusagestr = NULL;
	char *ekustr = NULL;
	char *hashname = NULL;
	KMF_GENERALNAMECHOICES alttype = 0;
	KMF_BIGINT serial = { NULL, 0 };
	uint32_t ltime;
	KMF_HANDLE_T kmfhandle = NULL;
	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
	KMF_KEY_ALG keyAlg = KMF_RSA;
	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_SHA1WithRSA;
	boolean_t interactive = B_FALSE;
	char *subname = NULL;
	KMF_CREDENTIAL tokencred = { NULL, 0 };
	uint16_t kubits = 0;
	int altcrit = 0, kucrit = 0;
	EKU_LIST *ekulist = NULL;
	KMF_OID *curveoid = NULL; /* ECC */
	KMF_OID *hashoid = NULL;
	int y_flag = 0;

	while ((opt = getopt_av(argc, argv,
	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
	    "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
	    "r:(trust)L:(lifetime)l:(label)c:(outcert)e:(eku)"
	    "K:(outkey)S:(serial)F:(format)u:(keyusage)C:(curve)"
	    "E(listcurves)h:(hash)")) != EOF) {

		if (opt != 'i' && opt != 'E' && EMPTYSTRING(optarg_av))
			return (PK_ERR_USAGE);

		switch (opt) {
			case 'A':
				altname = optarg_av;
				break;
			case 'i':
				if (interactive || subject)
					return (PK_ERR_USAGE);
				else
					interactive = B_TRUE;
				break;
			case 'k':
				kstype = KS2Int(optarg_av);
				if (kstype == 0)
					return (PK_ERR_USAGE);
				break;
			case 's':
				if (interactive || subject)
					return (PK_ERR_USAGE);
				else
					subject = optarg_av;
				break;
			case 'l':
			case 'n':
				if (certlabel)
					return (PK_ERR_USAGE);
				certlabel = optarg_av;
				break;
			case 'T':
				if (tokenname)
					return (PK_ERR_USAGE);
				tokenname = optarg_av;
				break;
			case 'd':
				if (dir)
					return (PK_ERR_USAGE);
				dir = optarg_av;
				break;
			case 'p':
				if (prefix)
					return (PK_ERR_USAGE);
				prefix = optarg_av;
				break;
			case 't':
				keytype = optarg_av;
				break;
			case 'u':
				keyusagestr = optarg_av;
				break;
			case 'y':
				if (sscanf(optarg_av, "%d",
				    &keylen) != 1) {
					cryptoerror(LOG_STDERR,
					    gettext("key length must be"
					    "a numeric value (%s)\n"),
					    optarg_av);
					return (PK_ERR_USAGE);
				}
				y_flag++;
				break;
			case 'r':
				if (trust)
					return (PK_ERR_USAGE);
				trust = optarg_av;
				break;
			case 'L':
				if (lifetime)
					return (PK_ERR_USAGE);
				lifetime = optarg_av;
				break;
			case 'c':
				if (outcert)
					return (PK_ERR_USAGE);
				outcert = optarg_av;
				break;
			case 'K':
				if (outkey)
					return (PK_ERR_USAGE);
				outkey = optarg_av;
				break;
			case 'S':
				serstr = optarg_av;
				break;
			case 'F':
				if (format)
					return (PK_ERR_USAGE);
				format = optarg_av;
				break;
			case 'e':
				ekustr = optarg_av;
				break;
			case 'C':
				curveoid = ecc_name_to_oid(optarg_av);
				if (curveoid == NULL) {
					cryptoerror(LOG_STDERR,
					    gettext("Unrecognized ECC "
					    "curve.\n"));
					return (PK_ERR_USAGE);
				}
				break;
			case 'E':
				/*
				 * This argument is only to be used
				 * by itself, no other options should
				 * be present.
				 */
				if (argc != 2) {
					cryptoerror(LOG_STDERR,
					    gettext("listcurves has no other "
					    "options.\n"));
					return (PK_ERR_USAGE);
				}
				show_ecc_curves();
				return (0);
			case 'h':
				hashname = optarg_av;
				hashoid = ecc_name_to_oid(optarg_av);
				if (hashoid == NULL) {
					cryptoerror(LOG_STDERR,
					    gettext("Unrecognized hash.\n"));
					return (PK_ERR_USAGE);
				}
				break;
			default:
				return (PK_ERR_USAGE);
		}
	}

	/* No additional args allowed. */
	argc -= optind_av;
	argv += optind_av;
	if (argc) {
		return (PK_ERR_USAGE);
	}

	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
		return (PK_ERR_USAGE);
	}

	/* Assume keystore = PKCS#11 if not specified. */
	if (kstype == 0)
		kstype = KMF_KEYSTORE_PK11TOKEN;

	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
		if (interactive && EMPTYSTRING(certlabel)) {
			(void) get_certlabel(&certlabel);
		}
		/* It better not be empty now */
		if (EMPTYSTRING(certlabel)) {
			cryptoerror(LOG_STDERR, gettext("A label must be "
			    "specified to create a self-signed certificate."
			    "\n"));
			return (PK_ERR_USAGE);
		}
	} else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
		cryptoerror(LOG_STDERR, gettext("A certificate filename must "
		    "be specified to create a self-signed certificate.\n"));
		return (PK_ERR_USAGE);
	}

	DIR_OPTION_CHECK(kstype, dir);

	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
		cryptoerror(LOG_STDERR,
		    gettext("Error parsing format string (%s).\n"),
		    format);
		return (PK_ERR_USAGE);
	}

	if (Str2Lifetime(lifetime, &ltime) != 0) {
		cryptoerror(LOG_STDERR,
		    gettext("Error parsing lifetime string\n"));
		return (PK_ERR_USAGE);
	}

	if (Str2KeyType(keytype, hashoid, &keyAlg, &sigAlg) != 0) {
		cryptoerror(LOG_STDERR,
		    gettext("Unsupported key/hash combination (%s/%s).\n"),
		    keytype, (hashname ? hashname : "none"));
		return (PK_ERR_USAGE);
	}
	if (curveoid != NULL && keyAlg != KMF_ECDSA) {
		cryptoerror(LOG_STDERR, gettext("EC curves are only "
		    "valid for EC keytypes.\n"));
		return (PK_ERR_USAGE);
	}
	if (keyAlg == KMF_ECDSA && curveoid == NULL) {
		cryptoerror(LOG_STDERR, gettext("A curve must be "
		    "specifed when using EC keys.\n"));
		return (PK_ERR_USAGE);
	}
	/* Adjust default keylength for NSS and DSA */
	if (keyAlg == KMF_DSA && !y_flag && kstype == KMF_KEYSTORE_NSS)
		keylen = 1024;

	/*
	 * Check the subject name.
	 * If interactive is true, get it now interactively.
	 */
	if (interactive) {
		subname = NULL;
		if (get_subname(&subname) != KMF_OK || subname == NULL) {
			cryptoerror(LOG_STDERR, gettext("Failed to get the "
			    "subject name interactively.\n"));
			return (PK_ERR_USAGE);
		}
		if (serstr == NULL) {
			(void) get_serial(&serstr);
		}
	} else {
		if (EMPTYSTRING(subject)) {
			cryptoerror(LOG_STDERR, gettext("A subject name or "
			    "-i must be specified to create a self-signed "
			    "certificate.\n"));
			return (PK_ERR_USAGE);
		} else {
			subname = strdup(subject);
			if (subname == NULL) {
				cryptoerror(LOG_STDERR,
				    gettext("Out of memory.\n"));
				return (PK_ERR_SYSTEM);
			}
		}
	}

	if (serstr == NULL) {
		(void) fprintf(stderr, gettext("A serial number "
		    "must be specified as a hex number when creating"
		    " a self-signed certificate "
		    "(ex: serial=0x0102030405feedface)\n"));
		rv = PK_ERR_USAGE;
		goto end;
	} else {
		uchar_t *bytes = NULL;
		size_t bytelen;

		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
		if (rv != KMF_OK || bytes == NULL) {
			(void) fprintf(stderr, gettext("serial number "
			    "must be specified as a hex number "
			    "(ex: 0x0102030405ffeeddee)\n"));
			rv = PK_ERR_USAGE;
			goto end;
		}
		serial.val = bytes;
		serial.len = bytelen;
	}

	if (altname != NULL) {
		rv = verify_altname(altname, &alttype, &altcrit);
		if (rv != KMF_OK) {
			(void) fprintf(stderr, gettext("Subject AltName "
			    "must be specified as a name=value pair. "
			    "See the man page for details.\n"));
			rv = PK_ERR_USAGE;
			goto end;
		} else {
			/* advance the altname past the '=' sign */
			char *p = strchr(altname, '=');
			if (p != NULL)
				altname = p + 1;
		}
	}

	if (keyusagestr != NULL) {
		rv = verify_keyusage(keyusagestr, &kubits, &kucrit);
		if (rv != KMF_OK) {
			(void) fprintf(stderr, gettext("KeyUsage "
			    "must be specified as a comma-separated list. "
			    "See the man page for details.\n"));
			rv = PK_ERR_USAGE;
			goto end;
		}
	}
	if (ekustr != NULL) {
		rv = verify_ekunames(ekustr, &ekulist);
		if (rv != KMF_OK) {
			(void) fprintf(stderr, gettext("EKUs must "
			    "be specified as a comma-separated list. "
			    "See the man page for details.\n"));
			rv = PK_ERR_USAGE;
			goto end;
		}
	}
	if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
		(void) fprintf(stderr, gettext("ECC certificates are"
		    "only supported with the pkcs11 and nss keystores\n"));
		rv = PK_ERR_USAGE;
		goto end;
	}

	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
		if (tokenname == NULL || !strlen(tokenname)) {
			if (kstype == KMF_KEYSTORE_NSS) {
				tokenname = "internal";
			} else  {
				tokenname = PK_DEFAULT_PK11TOKEN;
			}
		}

		(void) get_token_password(kstype, tokenname, &tokencred);
	}

	if (kstype == KMF_KEYSTORE_NSS) {
		if (dir == NULL)
			dir = PK_DEFAULT_DIRECTORY;

		rv = gencert_nss(kmfhandle,
		    tokenname, subname, altname, alttype, altcrit,
		    certlabel, dir, prefix, keyAlg, sigAlg, keylen,
		    trust, ltime, &serial, kubits, kucrit, &tokencred,
		    ekulist, curveoid);

	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
		rv = gencert_pkcs11(kmfhandle,
		    tokenname, subname, altname, alttype, altcrit,
		    certlabel, keyAlg, sigAlg, keylen, ltime,
		    &serial, kubits, kucrit, &tokencred, ekulist,
		    curveoid);

	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
		rv = gencert_file(kmfhandle,
		    keyAlg, sigAlg, keylen, fmt,
		    ltime, subname, altname, alttype, altcrit,
		    &serial, kubits, kucrit, outcert, outkey,
		    ekulist);
	}

	if (rv != KMF_OK)
		display_error(kmfhandle, rv,
		    gettext("Error creating certificate and keypair"));
end:
	if (ekulist != NULL)
		free_eku_list(ekulist);
	if (subname)
		free(subname);
	if (tokencred.cred != NULL)
		free(tokencred.cred);

	if (serial.val != NULL)
		free(serial.val);

	(void) kmf_finalize(kmfhandle);
	return (rv);
}
Example #15
0
/*
 * 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);
}
Example #16
0
/*
 * Disable a kernel software provider.
 * This implements the "cryptoadm disable" command for
 * kernel software providers.
 */
int
disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag,
    mechlist_t *dislist)
{
	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
	mechlist_t			*infolist = NULL;
	entry_t				*pent = NULL;
	entrylist_t			*phardlist = NULL;
	entrylist_t			*psoftlist = NULL;
	boolean_t			in_kernel = B_FALSE;
	int				fd = -1;
	int				rc = SUCCESS;

	if (provname == NULL) {
		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.
	 */
	if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
		return (FAILURE);
	} else if (in_kernel == B_FALSE) {
		cryptoerror(LOG_STDERR,
		    gettext("%s is not loaded or does not exist."),
		    provname);
		return (FAILURE);
	}

	if (get_kcfconf_info(&phardlist, &psoftlist) == FAILURE) {
		cryptoerror(LOG_ERR,
		    "failed to retrieve the providers' "
		    "information from the configuration file - %s.",
		    _PATH_KCF_CONF);
		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.
	 */
	pent = getent_kef(provname, phardlist, psoftlist);
	if (pent == NULL) { /* create a new entry */
		pent = create_entry(provname);
		if (pent == NULL) {
			cryptodebug("out of memory.");
			rc = FAILURE;
			goto out;
		}
	}

	/* Get the mechanism list for the software provider from the kernel */
	if (get_soft_info(provname, &infolist, phardlist, psoftlist) ==
	    FAILURE) {
		rc = FAILURE;
		goto out;
	}

	if ((infolist != NULL) && (infolist->name[0] != '\0')) {
		/*
		 * 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.
		 */
		free_mechlist(pent->suplist);
		pent->suplist = infolist;
	}

	/*
	 * 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) {
		(void) filter_mechlist(&infolist, RANDOM);
	}

	/* Calculate the new disabled list */
	if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) {
		rc = FAILURE;
		goto out;
	}

	/* Update the kcf.conf file with the updated entry */
	if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) {
		rc = FAILURE;
		goto out;
	}

	/* Setup argument to inform kernel about the new disabled list. */
	if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
		rc = FAILURE;
		goto out;
	}

	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
		cryptoerror(LOG_STDERR,
		    gettext("failed to open %s for RW: %s"),
		    ADMIN_IOCTL_DEVICE, strerror(errno));
		rc = FAILURE;
		goto out;
	}

	/* Inform kernel about the new disabled list. */
	if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) {
		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
		    strerror(errno));
		rc = FAILURE;
		goto out;
	}

	if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
		cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
		    "%d", pload_soft_dis->sd_return_value);
		rc = FAILURE;
		goto out;
	}

out:
	free_entrylist(phardlist);
	free_entrylist(psoftlist);
	free_mechlist(infolist);
	free_entry(pent);
	free(pload_soft_dis);
	if (fd != -1)
		(void) close(fd);
	return (rc);
}
Example #17
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);
}
Example #18
0
/*
 * Enable a kernel software or hardware provider.
 * This implements the "cryptoadm enable" command for kernel providers.
 */
int
enable_kef(char *provname, boolean_t rndflag, boolean_t allflag,
    mechlist_t *mlist)
{
	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
	crypto_load_dev_disabled_t	*pload_dev_dis = NULL;
	entry_t				*pent = NULL;
	boolean_t			redo_flag = B_FALSE;
	boolean_t			in_kernel = B_FALSE;
	int				fd = -1;
	int				rc = SUCCESS;


	/* Get the entry of this provider from the kcf.conf file, if any. */
	pent = getent_kef(provname, NULL, NULL);

	if (is_device(provname)) {
		if (pent == NULL) {
			/*
			 * This device doesn't have an entry in the config
			 * file, therefore nothing is disabled.
			 */
			cryptoerror(LOG_STDERR, gettext(
			    "all mechanisms are enabled already for %s."),
			    provname);
			free_entry(pent);
			return (SUCCESS);
		}
	} else { /* a software module */
		if (check_kernel_for_soft(provname, NULL, &in_kernel) ==
		    FAILURE) {
			free_entry(pent);
			return (FAILURE);
		} else if (in_kernel == B_FALSE) {
			cryptoerror(LOG_STDERR, gettext("%s does not exist."),
			    provname);
			free_entry(pent);
			return (FAILURE);
		} else if ((pent == NULL) || (pent->dis_count == 0)) {
			/* nothing to be enabled. */
			cryptoerror(LOG_STDERR, gettext(
			    "all mechanisms are enabled already for %s."),
			    provname);
			free_entry(pent);
			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) {
		redo_flag = filter_mechlist(&pent->dislist, RANDOM);
		if (redo_flag)
			pent->dis_count--;
	}

	/* Update the entry by enabling mechanisms for this provider */
	if ((rc = enable_mechs(&pent, allflag, mlist)) != SUCCESS) {
		free_entry(pent);
		return (rc);
	}

	if (redo_flag) {
		mechlist_t *tmp;

		if ((tmp = create_mech(RANDOM)) == NULL) {
			free_entry(pent);
			return (FAILURE);
		}
		tmp->next = pent->dislist;
		pent->dislist = tmp;
		pent->dis_count++;
	}

	/*
	 * 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.
	 */
	if (is_device(pent->name) && (pent->dis_count == 0)) {
		rc = update_kcfconf(pent, DELETE_MODE);
	} else {
		rc = update_kcfconf(pent, MODIFY_MODE);
	}

	if (rc == FAILURE) {
		free_entry(pent);
		return (FAILURE);
	}


	/* Inform Kernel about the policy change */

	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
		    ADMIN_IOCTL_DEVICE, strerror(errno));
		free_entry(pent);
		return (FAILURE);
	}

	if (is_device(provname)) {
		/*  LOAD_DEV_DISABLED */
		if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) {
			free_entry(pent);
			return (FAILURE);
		}

		if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) {
			cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: "
			    "%s", strerror(errno));
			free_entry(pent);
			free(pload_dev_dis);
			(void) close(fd);
			return (FAILURE);
		}

		if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
			cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
			    "return_value = %d",
			    pload_dev_dis->dd_return_value);
			free_entry(pent);
			free(pload_dev_dis);
			(void) close(fd);
			return (FAILURE);
		}

	} else { /* a software module */
		/* LOAD_SOFT_DISABLED */
		if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
			free_entry(pent);
			return (FAILURE);
		}

		if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis)
		    == -1) {
			cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: "
			    "%s", strerror(errno));
			free_entry(pent);
			free(pload_soft_dis);
			(void) close(fd);
			return (FAILURE);
		}

		if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
			cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
			    "return_value = %d",
			    pload_soft_dis->sd_return_value);
			free_entry(pent);
			free(pload_soft_dis);
			(void) close(fd);
			return (FAILURE);
		}
	}

	free_entry(pent);
	free(pload_soft_dis);
	(void) close(fd);
	return (SUCCESS);
}
Example #19
0
/*
 * Set up metaslot for the framework using either user configuration
 * or system wide configuration options
 *
 * Also sets up the global "slottable" to have the first slot be metaslot.
 */
static CK_RV
setup_metaslot(uentry_t *metaslot_entry) {
	CK_RV rv;
	CK_MECHANISM_TYPE_PTR prov_pol_mechs = NULL;
	pkcs11_slot_t *cur_slot;

	/* process policies for mechanisms */
	if ((metaslot_entry) && (metaslot_entry->count > 0)) {
		rv = pkcs11_mech_parse(metaslot_entry->policylist,
		    &prov_pol_mechs, metaslot_entry->count);

		if (rv == CKR_HOST_MEMORY) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Could not parse configuration,"
			    "out of memory. Cannot continue parsing "
			    "%s.\n", _PATH_PKCS11_CONF);
			return (rv);
		} else if (rv == CKR_MECHANISM_INVALID) {
			/*
			 * Configuration file is corrupted for metaslot
			 */
			cryptoerror(LOG_ERR,
			    "libpkcs11: Policy invalid or corrupted "
			    "for metaslot. Use cryptoadm(1M) to fix "
			    "this. Disabling metaslot functionality.\n");
			metaslot_enabled = B_FALSE;
			return (rv);
		}
	}

	/*
	 * Check for metaslot policy.  If all mechanisms are
	 * disabled, disable metaslot since there is nothing
	 * interesting for it to do
	 */
	if ((metaslot_entry) && (metaslot_entry->flag_enabledlist) &&
	    (prov_pol_mechs == NULL)) {
		metaslot_enabled = B_FALSE;
		return (rv);
	}

	/*
	 * save system wide value for metaslot's keystore.
	 * If either slot description or token label is specified by
	 * the user, the system wide value for both is ignored.
	 */
	if ((metaslot_entry) &&
	    (!metaslot_config.keystore_token_specified) &&
	    (!metaslot_config.keystore_slot_specified)) {
		/*
		 * blank_str is used for comparing with token label,
		 * and slot description, make sure it is better than
		 * the larger of both
		 */
		char blank_str[TOKEN_LABEL_SIZE + SLOT_DESCRIPTION_SIZE];

		bzero(blank_str, sizeof (blank_str));

		if (memcmp(metaslot_entry->metaslot_ks_token,
		    blank_str, TOKEN_LABEL_SIZE) != 0) {
			metaslot_config.keystore_token_specified = B_TRUE;
			(void) strlcpy(
			    (char *)metaslot_config.keystore_token,
			    (const char *)metaslot_entry->metaslot_ks_token,
			    TOKEN_LABEL_SIZE);
		}

		if (memcmp(metaslot_entry->metaslot_ks_slot,
		    blank_str, SLOT_DESCRIPTION_SIZE) != 0) {
			metaslot_config.keystore_slot_specified = B_TRUE;
			(void) strlcpy(
			    (char *)metaslot_config.keystore_slot,
			    (const char *)metaslot_entry->metaslot_ks_slot,
			    SLOT_DESCRIPTION_SIZE);
		}
	}

	/* check system-wide value for auto_key_migrate */
	if (metaslot_config.auto_key_migrate_specified) {
		/* take user's specified value */
		metaslot_auto_key_migrate = metaslot_config.auto_key_migrate;
	} else {
		if (metaslot_entry) {
			/* use system-wide default */
			metaslot_auto_key_migrate =
			    metaslot_entry->flag_metaslot_auto_key_migrate;
		} else {
			/*
			 * there's no system wide metaslot entry,
			 * default auto_key_migrate to true
			 */
			metaslot_auto_key_migrate = B_TRUE;
		}
	}


	/* Make first slotID be 0, for metaslot. */
	slottable->st_first = 0;

	/* Set up the slottable entry for metaslot */
	slottable->st_slots[0] = NULL;
	cur_slot = calloc(1, sizeof (pkcs11_slot_t));
	if (cur_slot == NULL) {
		rv = CKR_HOST_MEMORY;
		return (rv);
	}
	cur_slot->sl_wfse_state = WFSE_CLEAR;
	cur_slot->sl_enabledpol = B_FALSE;
	cur_slot->sl_no_wfse = B_FALSE;
	(void) pthread_mutex_init(&cur_slot->sl_mutex, NULL);

	/*
	 * The metaslot entry was prealloc'd by
	 * pkcs11_slottable_increase()
	 */
	(void) pthread_mutex_lock(&slottable->st_mutex);
	slottable->st_slots[0] = cur_slot;
	(void) pthread_mutex_unlock(&slottable->st_mutex);

	(void) pthread_mutex_lock(&cur_slot->sl_mutex);
	cur_slot->sl_id = METASLOT_SLOTID;
	cur_slot->sl_func_list = &metaslot_functionList;
	if (metaslot_entry) {
		cur_slot->sl_enabledpol = metaslot_entry->flag_enabledlist;
		cur_slot->sl_pol_count = metaslot_entry->count;
	} else {
		/* if no metaslot entry, assume all mechs are enabled */
		cur_slot->sl_enabledpol = B_FALSE;
		cur_slot->sl_pol_count = 0;
	}
	cur_slot->sl_pol_mechs = prov_pol_mechs;
	cur_slot->sl_dldesc = NULL; /* not applicable */
	cur_slot->sl_prov_id = 0;
	(void) pthread_mutex_unlock(&cur_slot->sl_mutex);

	/* Call the meta_Initialize() to initialize metaslot */
	rv = meta_Initialize(NULL);
	if (rv != CKR_OK) {
		cryptoerror(LOG_ERR,
		    "libpkcs11: Can't initialize metaslot (%s)",
		    pkcs11_strerror(rv));
		goto cleanup;
	}

	return (CKR_OK);

cleanup:
	metaslot_enabled = B_FALSE;
	slottable->st_slots[0] = NULL;

	if (cur_slot) {
		(void) pthread_mutex_destroy(&cur_slot->sl_mutex);
		free(cur_slot);
	}
	return (rv);
}
Example #20
0
/*
 * 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
install_kef(char *provname, mechlist_t *mlist)
{
	crypto_load_soft_config_t	*pload_soft_conf = NULL;
	boolean_t			found;
	entry_t				*pent = NULL;
	FILE				*pfile = NULL;
	FILE				*pfile_tmp = NULL;
	char				tmpfile_name[MAXPATHLEN];
	char				*ptr;
	char				*str;
	char				*name;
	char				buffer[BUFSIZ];
	char				buffer2[BUFSIZ];
	int				found_count;
	int				fd = -1;
	int				rc = SUCCESS;
	int				err;

	if ((provname == NULL) || (mlist == NULL)) {
		return (FAILURE);
	}

	/* Check if the provider already exists */
	if ((pent = getent_kef(provname, NULL, NULL)) != NULL) {
		cryptoerror(LOG_STDERR, gettext("%s exists already."),
		    provname);
		free_entry(pent);
		return (FAILURE);
	}

	/* Create an entry with provname and mlist. */
	if ((pent = create_entry(provname)) == NULL) {
		cryptoerror(LOG_STDERR, gettext("out of memory."));
		return (FAILURE);
	}
	pent->sup_count = get_mech_count(mlist);
	pent->suplist = mlist;

	/* Append an entry for this software module to the kcf.conf file. */
	if ((str = ent2str(pent)) == NULL) {
		free_entry(pent);
		return (FAILURE);
	}

	if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
		err = errno;
		cryptoerror(LOG_STDERR,
		    gettext("failed to update the configuration - %s"),
		    strerror(err));
		cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
		free_entry(pent);
		return (FAILURE);
	}

	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
		err = errno;
		cryptoerror(LOG_STDERR,
		    gettext("failed to lock the configuration - %s"),
		    strerror(err));
		free_entry(pent);
		(void) fclose(pfile);
		return (FAILURE);
	}

	/*
	 * Create a temporary file in the /etc/crypto directory.
	 */
	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
	if (mkstemp(tmpfile_name) == -1) {
		err = errno;
		cryptoerror(LOG_STDERR,
		    gettext("failed to create a temporary file - %s"),
		    strerror(err));
		free_entry(pent);
		(void) fclose(pfile);
		return (FAILURE);
	}

	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
		err = errno;
		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
		    tmpfile_name, strerror(err));
		free_entry(pent);
		(void) fclose(pfile);
		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;
	rc = SUCCESS;
	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
		found = B_FALSE;
		if (buffer[0] == '#') {
			(void) strlcpy(buffer2, buffer, BUFSIZ);
			ptr = buffer2;
			ptr++;
			if ((name = strtok(ptr, SEP_COLON)) == NULL) {
				rc = FAILURE;
				break;
			} else if (strcmp(provname, name) == 0) {
				found = B_TRUE;
				found_count++;
			}
		}

		if (found == B_FALSE) {
			if (fputs(buffer, pfile_tmp) == EOF) {
				rc = FAILURE;
			}
		} else {
			if (found_count == 1) {
				if (fputs(str, pfile_tmp) == EOF) {
					rc = FAILURE;
				}
			} else {
				/*
				 * Found a second entry with #libname.
				 * Should not happen. The kcf.conf file
				 * is corrupted. Give a warning and skip
				 * this entry.
				 */
				cryptoerror(LOG_STDERR, gettext(
				    "(Warning) Found an additional reserved "
				    "entry for %s."), provname);
			}
		}

		if (rc == FAILURE) {
			break;
		}
	}
	(void) fclose(pfile);

	if (rc == FAILURE) {
		cryptoerror(LOG_STDERR, gettext("write error."));
		(void) fclose(pfile_tmp);
		if (unlink(tmpfile_name) != 0) {
			err = errno;
			cryptoerror(LOG_STDERR, gettext(
			    "(Warning) failed to remove %s: %s"), tmpfile_name,
			    strerror(err));
		}
		free_entry(pent);
		return (FAILURE);
	}

	if (found_count == 0) {
		/*
		 * This libname was not in package before, append it to the
		 * end of the temp file.
		 */
		if (fputs(str, pfile_tmp) == EOF) {
			cryptoerror(LOG_STDERR, gettext(
			    "failed to write to %s: %s"), tmpfile_name,
			    strerror(errno));
			(void) fclose(pfile_tmp);
			if (unlink(tmpfile_name) != 0) {
				err = errno;
				cryptoerror(LOG_STDERR, gettext(
				    "(Warning) failed to remove %s: %s"),
				    tmpfile_name, strerror(err));
			}
			free_entry(pent);
			return (FAILURE);
		}
	}

	if (fclose(pfile_tmp) != 0) {
		err = errno;
		cryptoerror(LOG_STDERR,
		    gettext("failed to close %s: %s"), tmpfile_name,
		    strerror(err));
		free_entry(pent);
		return (FAILURE);
	}

	if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
		err = errno;
		cryptoerror(LOG_STDERR,
		    gettext("failed to update the configuration - %s"),
		    strerror(err));
		cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
		    _PATH_KCF_CONF, strerror(err));
		rc = FAILURE;
	} else if (chmod(_PATH_KCF_CONF,
	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
		err = errno;
		cryptoerror(LOG_STDERR,
		    gettext("failed to update the configuration - %s"),
		    strerror(err));
		cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
		    strerror(err));
		rc = FAILURE;
	} else {
		rc = SUCCESS;
	}

	if (rc == FAILURE) {
		if (unlink(tmpfile_name) != 0) {
			err = errno;
			cryptoerror(LOG_STDERR, gettext(
			    "(Warning) failed to remove %s: %s"),
			    tmpfile_name, strerror(err));
		}
		free_entry(pent);
		return (FAILURE);
	}


	/* Inform kernel of this new software module. */

	if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
		free_entry(pent);
		return (FAILURE);
	}

	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
		    ADMIN_IOCTL_DEVICE, strerror(errno));
		free_entry(pent);
		free(pload_soft_conf);
		return (FAILURE);
	}

	if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) {
		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
		    strerror(errno));
		free_entry(pent);
		free(pload_soft_conf);
		(void) close(fd);
		return (FAILURE);
	}

	if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed, "
		    "return_value = %d", pload_soft_conf->sc_return_value);
		free_entry(pent);
		free(pload_soft_conf);
		(void) close(fd);
		return (FAILURE);
	}

	free_entry(pent);
	free(pload_soft_conf);
	(void) close(fd);
	return (SUCCESS);
}
Example #21
0
/*
 * Print a list all the the providers.
 * Called for "cryptoadm list" or "cryptoadm list -v" (no -m or -p).
 */
static int
list_simple_for_all(boolean_t verbose)
{
	uentrylist_t		*pliblist = NULL;
	uentrylist_t		*plibptr = NULL;
	entry_t			*pent = NULL;
	crypto_get_dev_list_t	*pdevlist_kernel = NULL;
	int			rc = SUCCESS;
	int			i;

	/* get user-level providers */
	(void) printf(gettext("\nUser-level providers:\n"));
	if (get_pkcs11conf_info(&pliblist) != SUCCESS) {
		cryptoerror(LOG_STDERR, gettext(
		    "failed to retrieve the list of user-level providers."));
		rc = FAILURE;
	}

	for (plibptr = pliblist; plibptr != NULL; plibptr = plibptr->next) {
		/* skip metaslot and fips-140 entry */
		if ((strcmp(plibptr->puent->name, METASLOT_KEYWORD) != 0) &&
		    (strcmp(plibptr->puent->name, FIPS_KEYWORD) != 0)) {
			(void) printf(gettext("Provider: %s\n"),
			    plibptr->puent->name);
			if (verbose) {
				(void) list_mechlist_for_lib(
				    plibptr->puent->name, mecharglist, NULL,
				    B_FALSE, verbose, B_FALSE);
				(void) printf("\n");
			}
		}
	}
	free_uentrylist(pliblist);

	/* get kernel software providers */
	(void) printf(gettext("\nKernel software providers:\n"));

	if (getzoneid() == GLOBAL_ZONEID) {
		/* get kernel software providers from kernel ioctl */
		crypto_get_soft_list_t		*psoftlist_kernel = NULL;
		uint_t				sl_soft_count;
		char				*psoftname;
		entrylist_t			*pdevlist_conf = NULL;
		entrylist_t			*psoftlist_conf = NULL;

		if (get_soft_list(&psoftlist_kernel) == FAILURE) {
			cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
			    "software provider list from kernel."));
			rc = FAILURE;
		} else {
			sl_soft_count = psoftlist_kernel->sl_soft_count;

			if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf)
			    == FAILURE) {
				cryptoerror(LOG_ERR,
				    "failed to retrieve the providers' "
				    "information from file kcf.conf - %s.",
				    _PATH_KCF_CONF);
				free(psoftlist_kernel);
				rc = FAILURE;
			} else {

				for (i = 0,
				    psoftname = psoftlist_kernel->sl_soft_names;
				    i < sl_soft_count;
				    ++i, psoftname += strlen(psoftname) + 1) {
					pent = getent_kef(psoftname,
					    pdevlist_conf, psoftlist_conf);
					(void) printf("\t%s%s\n", psoftname,
					    (pent == NULL) || (pent->load) ?
					    "" : gettext(" (inactive)"));
				}
				free_entrylist(pdevlist_conf);
				free_entrylist(psoftlist_conf);
			}
			free(psoftlist_kernel);
		}

	} else {
		/* kcf.conf not there in non-global zone, use /dev/cryptoadm */
		entrylist_t	*pdevlist_zone = NULL;
		entrylist_t	*psoftlist_zone = NULL;
		entrylist_t	*ptr;

		if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) !=
		    SUCCESS) {
			cryptoerror(LOG_STDERR,
			    gettext("failed to retrieve the "
			    "list of kernel software providers.\n"));
			rc = FAILURE;
		}

		ptr = psoftlist_zone;
		while (ptr != NULL) {
			(void) printf("\t%s\n", ptr->pent->name);
			ptr = ptr->next;
		}

		free_entrylist(pdevlist_zone);
		free_entrylist(psoftlist_zone);
	}

	/* get kernel hardware providers */
	(void) printf(gettext("\nKernel hardware providers:\n"));
	if (get_dev_list(&pdevlist_kernel) == FAILURE) {
		cryptoerror(LOG_STDERR, gettext("failed to retrieve "
		    "the list of kernel hardware providers.\n"));
		rc = FAILURE;
	} else {
		for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
			(void) printf("\t%s/%d\n",
			    pdevlist_kernel->dl_devs[i].le_dev_name,
			    pdevlist_kernel->dl_devs[i].le_dev_instance);
		}
	}
	free(pdevlist_kernel);

	return (rc);
}
Example #22
0
/*
 * 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
uninstall_kef(char *provname)
{
	entry_t		*pent = NULL;
	int		rc = SUCCESS;
	boolean_t	in_kernel = B_FALSE;
	boolean_t	in_kcfconf = B_FALSE;
	int		fd = -1;
	crypto_load_soft_config_t *pload_soft_conf = NULL;

	/* Check to see if the provider exists first. */
	if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
		return (FAILURE);
	} else if (in_kernel == B_FALSE) {
		cryptoerror(LOG_STDERR, gettext("%s does not exist."),
		    provname);
		return (FAILURE);
	}

	/*
	 * If it is loaded, unload it first.  This does 2 ioctl calls:
	 * CRYPTO_UNLOAD_SOFT_MODULE and CRYPTO_LOAD_SOFT_DISABLED.
	 */
	if (unload_kef_soft(provname) == FAILURE) {
		cryptoerror(LOG_STDERR,
		    gettext("failed to unload %s during uninstall.\n"),
		    provname);
		return (FAILURE);
	}

	/*
	 * Inform kernel to remove the configuration of this software module.
	 */

	/* Setup ioctl() parameter */
	pent = getent_kef(provname, NULL, NULL);
	if (pent != NULL) { /* in kcf.conf */
		in_kcfconf = B_TRUE;
		free_mechlist(pent->suplist);
		pent->suplist = NULL;
		pent->sup_count = 0;
	} else if ((pent = create_entry(provname)) == NULL) {
		cryptoerror(LOG_STDERR, gettext("out of memory."));
		return (FAILURE);
	}
	if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
		free_entry(pent);
		return (FAILURE);
	}

	/* Open the /dev/cryptoadm device */
	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
		int	err = errno;
		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
		    ADMIN_IOCTL_DEVICE, strerror(err));
		free_entry(pent);
		free(pload_soft_conf);
		return (FAILURE);
	}

	if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG,
	    pload_soft_conf) == -1) {
		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
		    strerror(errno));
		free_entry(pent);
		free(pload_soft_conf);
		(void) close(fd);
		return (FAILURE);
	}

	if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
		cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl = return_value = %d",
		    pload_soft_conf->sc_return_value);
		free_entry(pent);
		free(pload_soft_conf);
		(void) close(fd);
		return (FAILURE);
	}

	/* ioctl cleanup */
	free(pload_soft_conf);
	(void) close(fd);


	/* Finally, remove entry from kcf.conf, if present */
	if (in_kcfconf && (pent != NULL)) {
		rc = update_kcfconf(pent, DELETE_MODE);
	}

	free_entry(pent);
	return (rc);
}
Example #23
0
/*
 * List all the providers. And for each provider, list the policy information.
 * Called for "cryptoadm list -p".
 */
static int
list_policy_for_all(void)
{
	crypto_get_dev_list_t	*pdevlist_kernel = NULL;
	uentrylist_t		*pliblist = NULL;
	entrylist_t		*pdevlist_conf = NULL;
	entrylist_t		*psoftlist_conf = NULL;
	entrylist_t		*ptr = NULL;
	entrylist_t		*phead = NULL;
	boolean_t		found = B_FALSE;
	char			provname[MAXNAMELEN];
	int			i;
	int			rc = SUCCESS;

	/* Get user-level providers */
	(void) printf(gettext("\nUser-level providers:\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"));
	if (get_pkcs11conf_info(&pliblist) == FAILURE) {
		cryptoerror(LOG_STDERR, gettext("failed to retrieve "
		    "the list of user-level providers.\n"));
		rc = FAILURE;
	} else {
		uentrylist_t	*plibptr = pliblist;

		while (plibptr != NULL) {
			/* skip metaslot and fips-140 entry */
			if ((strcmp(plibptr->puent->name,
			    METASLOT_KEYWORD) != 0) &&
			    (strcmp(plibptr->puent->name,
			    FIPS_KEYWORD) != 0)) {
				if (print_uef_policy(plibptr->puent)
				    == FAILURE) {
					rc = FAILURE;
				}
			}
			plibptr = plibptr->next;
		}
		free_uentrylist(pliblist);
	}

	/* kernel software providers */
	(void) printf(gettext("\nKernel software providers:\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"));

	/* Get all entries from the kernel */
	if (getzoneid() == GLOBAL_ZONEID) {
		/* get kernel software providers from kernel ioctl */
		crypto_get_soft_list_t		*psoftlist_kernel = NULL;
		uint_t				sl_soft_count;
		char				*psoftname;
		int				i;

		if (get_soft_list(&psoftlist_kernel) == FAILURE) {
			cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
			    "software provider list from kernel."));
			rc = FAILURE;
		} else {
			sl_soft_count = psoftlist_kernel->sl_soft_count;

			for (i = 0, psoftname = psoftlist_kernel->sl_soft_names;
			    i < sl_soft_count;
			    ++i, psoftname += strlen(psoftname) + 1) {
				(void) list_policy_for_soft(psoftname,
				    pdevlist_conf, psoftlist_conf);
			}
			free(psoftlist_kernel);
		}

	} else {
		/* kcf.conf not there in non-global zone, no policy info */

		/*
		 * TRANSLATION_NOTE
		 * "global" is keyword and not to be translated.
		 */
		cryptoerror(LOG_STDERR, gettext(
		    "policy information for kernel software providers is "
		    "available in the %s zone only"), "global");
	}

	/* Kernel hardware providers */
	(void) printf(gettext("\nKernel hardware providers:\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"));

	if (getzoneid() != GLOBAL_ZONEID) {
		/*
		 * TRANSLATION_NOTE
		 * "global" is keyword and not to be translated.
		 */
		cryptoerror(LOG_STDERR, gettext(
		    "policy information for kernel hardware providers is "
		    "available in the %s zone only"), "global");
		return (FAILURE);
	}

	/* Get the hardware provider list from kernel */
	if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
		cryptoerror(LOG_STDERR, gettext(
		    "failed to retrieve the list of hardware providers.\n"));
		return (FAILURE);
	}

	if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) == FAILURE) {
		cryptoerror(LOG_ERR, "failed to retrieve the providers' "
		    "information from file kcf.conf - %s.",
		    _PATH_KCF_CONF);
		return (FAILURE);
	}


	/*
	 * For each hardware provider from kernel, check if it has an entry
	 * in the config file.  If it has an entry, print out the policy from
	 * config file and remove the entry from the hardware provider list
	 * of the config file.  If it does not have an entry in the config
	 * file, no mechanisms of it have been disabled. But, we still call
	 * list_policy_for_hard() to account for the "random" feature.
	 */
	for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
		(void) snprintf(provname, sizeof (provname), "%s/%d",
		    pdevlist_kernel->dl_devs[i].le_dev_name,
		    pdevlist_kernel->dl_devs[i].le_dev_instance);

		found = B_FALSE;
		phead = ptr = pdevlist_conf;
		while (!found && ptr) {
			if (strcmp(ptr->pent->name, provname) == 0) {
				found = B_TRUE;
			} else {
				phead = ptr;
				ptr = ptr->next;
			}
		}

		if (found) {
			(void) list_policy_for_hard(ptr->pent->name,
			    pdevlist_conf, psoftlist_conf, pdevlist_kernel);
			if (phead == ptr) {
				pdevlist_conf = pdevlist_conf->next;
			} else {
				phead->next = ptr->next;
			}
			free_entry(ptr->pent);
			free(ptr);
		} else {
			(void) list_policy_for_hard(provname, pdevlist_conf,
			    psoftlist_conf, pdevlist_kernel);
		}
	}

	/*
	 * If there are still entries left in the pdevlist_conf list from
	 * the config file, these providers must have been detached.
	 * Should print out their policy information also.
	 */
	for (ptr = pdevlist_conf; ptr != NULL; ptr = ptr->next) {
		print_kef_policy(ptr->pent->name, ptr->pent, B_FALSE, B_TRUE);
	}

	free_entrylist(pdevlist_conf);
	free_entrylist(psoftlist_conf);
	free(pdevlist_kernel);

	return (rc);
}
Example #24
0
int
pk_inittoken(int argc, char *argv[])
/* ARGSUSED */
{
	int		opt;
	int		rv;
	extern int	optind_av;
	extern char	*optarg_av;
	char		*newlabel = NULL;
	char		*currlabel = NULL;
	CK_UTF8CHAR_PTR	sopin;
	CK_ULONG	sopinlen;
	KMF_HANDLE_T	handle;

	/* Parse command line options.  Do NOT i18n/l10n. */
	while ((opt = getopt_av(argc, argv,
		"n:(newlabel)"
		"l:(currlabel)")) != EOF) {
		switch (opt) {
			case 'l':	/* token specifier */
				if (currlabel)
					return (PK_ERR_USAGE);
				currlabel = optarg_av;
				break;
			case 'n': /* token specifier */
				if (newlabel)
					return (PK_ERR_USAGE);
				newlabel = optarg_av;
				break;
			default:
				return (PK_ERR_USAGE);
				break;
		}
	}

	/* No additional args allowed. */
	argc -= optind_av;
	argv += optind_av;
	if (argc != 0)
		return (PK_ERR_USAGE);

	if ((rv = kmf_initialize(&handle, NULL, NULL)) != KMF_OK)
		return (rv);

	if ((rv = get_pin(gettext("Enter SO PIN:"), NULL, &sopin, &sopinlen))
	    != CKR_OK) {
		cryptoerror(LOG_STDERR,
		    gettext("Unable to get SO PIN for token"));
		return (PK_ERR_SYSTEM);
	}
	if ((currlabel == NULL || !strlen(currlabel))) {
		cryptoerror(LOG_STDERR,
		    gettext("The current token is not identified by label."));
		return (PK_ERR_SYSTEM);
	}

	rv = kmf_pk11_init_token(handle, currlabel, newlabel,
	    sopin, sopinlen);

	(void) kmf_finalize(handle);

	free(sopin);

	if (rv == KMF_ERR_AUTH_FAILED) {
		cryptoerror(LOG_STDERR,
		    gettext("Incorrect passphrase."));
		return (PK_ERR_SYSTEM);
	} else if (rv != CKR_OK) {
		cryptoerror(LOG_STDERR,
		    gettext("Unable to initialize token."));
		return (PK_ERR_SYSTEM);
	} else {
		(void) fprintf(stdout, gettext("Token %s initialized.\n"),
		    (newlabel ? newlabel : currlabel));
	}
	return (0);
}
Example #25
0
/*
 * Process the mechanism operands for the disable, enable and install
 * subcommands.  This function sets the static variable allflag to be B_TRUE
 * if the keyword "all" is specified, otherwise builds a link list of the
 * mechanism operands and save it in the static variable mecharglist.
 *
 * This function returns
 *	ERROR_USAGE: mechanism operand is missing.
 *	FAILURE: out of memory.
 *	SUCCESS: otherwise.
 */
static int
process_mech_operands(int argc, char **argv, boolean_t quiet)
{
	mechlist_t	*pmech;
	mechlist_t	*pcur = NULL;
	mechlist_t	*phead = NULL;
	boolean_t	found = B_FALSE;
	char		*mechliststr = NULL;
	char		*curmech = NULL;
	int		c = -1;
	int		rc = SUCCESS;

	while (!found && ++c < argc) {
		if ((strncmp(argv[c], KN_MECH, strlen(KN_MECH)) == 0) &&
		    strlen(argv[c]) > strlen(KN_MECH)) {
			found = B_TRUE;
		}
	}
	if (!found) {
		if (!quiet)
			/*
			 * TRANSLATION_NOTE
			 * "mechanism" could be either a literal keyword
			 * and hence not to be translated, or a descriptive
			 * word and translatable.  A choice was made to
			 * view it as a literal keyword.
			 */
			cryptoerror(LOG_STDERR,
			    gettext("the %s operand is missing.\n"),
			    "mechanism");
		return (ERROR_USAGE);
	}
	(void) strtok(argv[c], "=");
	mechliststr = strtok(NULL, "=");

	if (strcmp(mechliststr, "all") == 0) {
		allflag = B_TRUE;
		mecharglist = NULL;
		return (SUCCESS);
	}

	curmech = strtok(mechliststr, ",");
	do {
		if ((pmech = create_mech(curmech)) == NULL) {
			rc = FAILURE;
			break;
		} else {
			if (phead == NULL) {
				phead = pcur = pmech;
			} else {
				pcur->next = pmech;
				pcur = pmech;
			}
		}
	} while ((curmech = strtok(NULL, ",")) != NULL);

	if (rc == FAILURE) {
		cryptoerror(LOG_STDERR, gettext("out of memory."));
		free_mechlist(phead);
	} else {
		mecharglist = phead;
		rc = SUCCESS;
	}
	return (rc);
}
Example #26
0
/*
 * MAIN() -- where all the action is
 */
int
main(int argc, char *argv[], char *envp[])
/* ARGSUSED2 */
{
	int	i, found = -1;
	int	rv;
	int	pk_argc = 0;
	char	**pk_argv = NULL;
	int	save_errno = 0;

	/* Set up for i18n/l10n. */
	(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D. */
#define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it isn't. */
#endif
	(void) textdomain(TEXT_DOMAIN);

	init_command_list();

	/* Get program base name and move pointer over 0th arg. */
	prog = basename(argv[0]);
	argv++, argc--;

	/* Set up for debug and error output. */
	if (argc == 0) {
		usage(-1);
		return (1);
	}

	/* Check for help options.  For CLIP-compliance. */
	if (strcmp(argv[0], "-?") == 0) {
		return (pk_help(argc, argv));
	} else if (strcmp(argv[0], "-f") == 0 && argc == 2) {
		rv = process_arg_file(argv[1], &pk_argv, &pk_argc);
		if (rv)
			return (rv);
	} else if (argc >= 1 && argv[0][0] == '-') {
		usage(-1);
		return (1);
	}

	/* Always turns off Metaslot so that we can see softtoken. */
	if (setenv("METASLOT_ENABLED", "false", 1) < 0) {
		save_errno = errno;
		cryptoerror(LOG_STDERR,
		    gettext("Disabling Metaslot failed (%s)."),
		    strerror(save_errno));
		return (1);
	}

	/* Begin parsing command line. */
	if (pk_argc == 0 && pk_argv == NULL) {
		pk_argc = argc;
		pk_argv = argv;
	}

	/* Check for valid verb (or an abbreviation of it). */
	found = -1;
	for (i = 0; i < num_cmds; i++) {
		if (strcmp(cmds[i].verb, pk_argv[0]) == 0) {
			if (found < 0) {
				found = i;
				break;
			}
		}
	}
	/* Stop here if no valid verb found. */
	if (found < 0) {
		cryptoerror(LOG_STDERR, gettext("Invalid verb: %s"),
		    pk_argv[0]);
		return (1);
	}

	/* Get to work! */
	rv = (*cmds[found].action)(pk_argc, pk_argv);
	switch (rv) {
	case PK_ERR_NONE:
		break;		/* Command succeeded, do nothing. */
	case PK_ERR_USAGE:
		usage(found);
		break;
	case PK_ERR_QUIT:
		exit(0);
		/* NOTREACHED */
	case PK_ERR_PK11:
	case PK_ERR_SYSTEM:
	case PK_ERR_OPENSSL:
	case PK_ERR_NSS:
	default:
		break;
	}
	return (rv);
}
Example #27
0
/*
 * The top level function for the "cryptoadm enable" subcommand.
 */
static int
do_enable(int argc, char **argv)
{
	cryptoadm_provider_t	*prov = NULL;
	int			rc = SUCCESS;
	char 			*alt_token = NULL, *alt_slot = NULL;
	boolean_t		use_default = B_FALSE;
	boolean_t		auto_key_migrate_flag = B_FALSE;

	if ((argc == 3) && (strncmp(argv[2], FIPS_KEYWORD,
	    strlen(FIPS_KEYWORD))) == 0) {
		/*
		 * cryptoadm enable fips-140
		 */
		rc = do_fips_actions(FIPS140_ENABLE, NOT_REFRESH);
		return (rc);
	}

	if ((argc < 3) || (argc > 6)) {
		usage();
		return (ERROR_USAGE);
	}

	prov = get_provider(argc, argv);
	if (prov == NULL) {
		usage();
		return (ERROR_USAGE);
	}
	if ((prov->cp_type != METASLOT) && (argc != 4)) {
		usage();
		return (ERROR_USAGE);
	}
	if (prov->cp_type == PROV_BADNAME) {
		rc = FAILURE;
		goto out;
	}


	if (prov->cp_type == METASLOT) {
		if ((rc = process_metaslot_operands(argc, argv, &alt_token,
		    &alt_slot, &use_default, &auto_key_migrate_flag))
		    != SUCCESS) {
			usage();
			goto out;
		}
		if ((alt_slot || alt_token) && use_default) {
			usage();
			rc = FAILURE;
			goto out;
		}
	} else {
		if ((rc = process_feature_operands(argc, argv)) != SUCCESS) {
			goto out;
		}

		/*
		 * If allflag or rndflag has already been set there is
		 * no reason to process mech=
		 */
		if (!allflag && !rndflag &&
		    (rc = process_mech_operands(argc, argv, B_FALSE))
		    != SUCCESS) {
			goto out;
		}
	}

	switch (prov->cp_type) {
	case METASLOT:
		rc = enable_metaslot(alt_token, alt_slot, use_default,
		    mecharglist, allflag, auto_key_migrate_flag);
		break;
	case PROV_UEF_LIB:
		rc = enable_uef_lib(prov->cp_name, rndflag, allflag,
		    mecharglist);
		break;
	case PROV_KEF_SOFT:
	case PROV_KEF_HARD:
		if (rndflag && !allflag) {
			if ((mecharglist = create_mech(RANDOM)) == NULL) {
				rc = FAILURE;
				break;
			}
		}
		if (getzoneid() == GLOBAL_ZONEID) {
			rc = enable_kef(prov->cp_name, rndflag, allflag,
			    mecharglist);
		} else {
			/*
			 * TRANSLATION_NOTE
			 * "enable" could be either a literal keyword
			 * and hence not to be translated, or a verb and
			 * translatable.  A choice was made to view it as
			 * a literal keyword.  "global" is keyword and not
			 * to be translated.
			 */
			cryptoerror(LOG_STDERR, gettext("%1$s for kernel "
			    "providers is supported in the %2$s zone only"),
			    "enable", "global");
			rc = FAILURE;
		}
		break;
	default: /* should not come here */
		rc = FAILURE;
		break;
	}
out:
	free(prov);
	if (mecharglist != NULL) {
		free_mechlist(mecharglist);
	}
	if (alt_token != NULL) {
		free(alt_token);
	}
	if (alt_slot != NULL) {
		free(alt_slot);
	}
	return (rc);
}
Example #28
0
/*
 * 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);
}
Example #29
0
/*
 * Get the device list from kernel.
 */
int
get_dev_list(crypto_get_dev_list_t **ppdevlist)
{
	crypto_get_dev_list_t *pdevlist;
	int fd;
	int count = DEFAULT_DEV_NUM;

	pdevlist = malloc(sizeof (crypto_get_dev_list_t) +
	    sizeof (crypto_dev_list_entry_t) * (count - 1));
	if (pdevlist == NULL) {
		cryptodebug("out of memory.");
		return (FAILURE);
	}

	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
		    ADMIN_IOCTL_DEVICE, strerror(errno));
		return (FAILURE);
	}

	pdevlist->dl_dev_count = count;
	if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) {
		cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s",
		    strerror(errno));
		free(pdevlist);
		(void) close(fd);
		return (FAILURE);
	}

	/* BUFFER is too small, get the number of devices and retry it. */
	if (pdevlist->dl_return_value == CRYPTO_BUFFER_TOO_SMALL) {
		count = pdevlist->dl_dev_count;
		free(pdevlist);
		pdevlist = malloc(sizeof (crypto_get_dev_list_t) +
		    sizeof (crypto_dev_list_entry_t) * (count - 1));
		if (pdevlist == NULL) {
			cryptodebug("out of memory.");
			(void) close(fd);
			return (FAILURE);
		}

		if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) {
			cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s",
			    strerror(errno));
			free(pdevlist);
			(void) close(fd);
			return (FAILURE);
		}
	}

	if (pdevlist->dl_return_value != CRYPTO_SUCCESS) {
		cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed, "
		    "return_value = %d", pdevlist->dl_return_value);
		free(pdevlist);
		(void) close(fd);
		return (FAILURE);
	}

	*ppdevlist = pdevlist;
	(void) close(fd);
	return (SUCCESS);
}
Example #30
0
static KMF_RETURN
gencert_nss(KMF_HANDLE_T kmfhandle,
	char *token, char *subject, char *altname,
	KMF_GENERALNAMECHOICES alttype, int altcrit,
	char *nickname, char *dir, char *prefix,
	KMF_KEY_ALG keyAlg,
	KMF_ALGORITHM_INDEX sigAlg,
	int keylen, char *trust,
	uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits,
	int kucrit, KMF_CREDENTIAL *tokencred,
	EKU_LIST *ekulist, KMF_OID *curveoid)
{
	KMF_RETURN kmfrv;
	KMF_KEY_HANDLE pubk, prik;
	KMF_X509_CERTIFICATE signedCert;
	KMF_X509_NAME	certSubject;
	KMF_X509_NAME	certIssuer;
	KMF_DATA x509DER;
	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
	KMF_ATTRIBUTE attrlist[16];
	int numattr = 0;

	if (token == NULL)
		token = DEFAULT_NSS_TOKEN;

	kmfrv = configure_nss(kmfhandle, dir, prefix);
	if (kmfrv != KMF_OK)
		return (kmfrv);

	(void) memset(&signedCert, 0, sizeof (signedCert));
	(void) memset(&certSubject, 0, sizeof (certSubject));
	(void) memset(&certIssuer, 0, sizeof (certIssuer));
	(void) memset(&x509DER, 0, sizeof (x509DER));

	/* If the subject name cannot be parsed, flag it now and exit */
	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
		cryptoerror(LOG_STDERR,
		    gettext("Subject name cannot be parsed.\n"));
		return (PK_ERR_USAGE);
	}

	/* For a self-signed cert, the issuser and subject are the same */
	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
		cryptoerror(LOG_STDERR,
		    gettext("Subject name cannot be parsed.\n"));
		return (PK_ERR_USAGE);
	}

	kmfrv = genkeypair_nss(kmfhandle, token, nickname, dir,
	    prefix, keyAlg, keylen, tokencred, curveoid,
	    &prik, &pubk);
	if (kmfrv != KMF_OK)
		return (kmfrv);

	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
	    "keypair");

	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");

	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
	    "serial number");

	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
	    "validity time");

	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
	    "signature algorithm");

	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
	    "subject name");

	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
	    "issuer name");

	if (altname != NULL)
		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
		    alttype, altname), "subjectAltName");

	if (kubits)
		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
		    "subjectAltName");

	if (ekulist != NULL) {
		int i;
		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
			SET_VALUE(kmf_add_cert_eku(&signedCert,
			    &ekulist->ekulist[i],
			    ekulist->critlist[i]), "Extended Key Usage");
		}
	}
	/*
	 * Construct attributes for the kmf_sign_cert operation.
	 */
	numattr = 0;
	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
	    &kstype, sizeof (kstype));
	numattr++;

	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
	numattr++;

	/* cert data that is to be signed */
	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
	numattr++;

	/* output buffer for the signed cert */
	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
	    &x509DER, sizeof (KMF_DATA));
	numattr++;

	kmf_set_attr_at_index(attrlist, numattr, KMF_ALGORITHM_INDEX_ATTR,
	    &sigAlg, sizeof (sigAlg));
	numattr++;

	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
	    KMF_OK) {
		goto cleanup;
	}

	/*
	 * Store the cert in the DB.
	 */
	numattr = 0;
	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
	    &kstype, sizeof (kstype));
	numattr++;

	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
	    &x509DER, sizeof (KMF_DATA));
	numattr++;

	if (nickname != NULL) {
		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
		    nickname, strlen(nickname));
		numattr++;
	}

	if (trust != NULL) {
		kmf_set_attr_at_index(attrlist, numattr, KMF_TRUSTFLAG_ATTR,
		    trust, strlen(trust));
		numattr++;
	}

	if (token != NULL) {
		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
		    token, strlen(token));
		numattr++;
	}

	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);

cleanup:
	kmf_free_data(&x509DER);
	kmf_free_dn(&certSubject);
	kmf_free_dn(&certIssuer);
	return (kmfrv);
}