Ejemplo n.º 1
0
/*
 * Display the mechanism list for a kernel hardware provider.
 * This implements part of the "cryptoadm list -m" command.
 */
int
list_mechlist_for_hard(char *provname)
{
	mechlist_t	*pmechlist = NULL;
	char		devname[MAXNAMELEN];
	int		inst_num;
	int		count;
	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 ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) ==
	    SUCCESS) {
		(void) filter_mechlist(&pmechlist, RANDOM);
		print_mechlist(provname, pmechlist);
		free_mechlist(pmechlist);
	}

	return (rc);
}
Ejemplo n.º 2
0
/*
 * Display the policy information for a kernel software provider.
 * This implements part of the "cryptoadm list -p" command.
 *
 * Parameters phardlist and psoftlist are supplied by
 * getent_kef().
 * If NULL, this function obtains it by calling get_kcfconf_info()
 * via getent_kef() internally.
 */
int
list_policy_for_soft(char *provname,
    entrylist_t *phardlist, entrylist_t *psoftlist)
{
	int		rc;
	entry_t		*pent = NULL;
	mechlist_t	*pmechlist = NULL;
	boolean_t	has_random = B_FALSE;
	boolean_t	has_mechs = B_FALSE;
	boolean_t	in_kernel = B_FALSE;

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

	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);
	}
	pent = getent_kef(provname, phardlist, psoftlist);

	rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist);
	if (rc == 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."),
		    provname);
		return (rc);
	}

	print_kef_policy(provname, pent, has_random, has_mechs);
	free_entry(pent);
	return (SUCCESS);
}
Ejemplo n.º 3
0
/*
 * Display the mechanism list for a kernel software provider.
 * This implements part of the "cryptoadm list -m" command.
 *
 * Parameters phardlist and psoftlist are supplied by
 * get_soft_info().
 * If NULL, this function obtains it by calling getent_kef() and
 * then get_kcfconf_info() via get_soft_info() internally.
 */
int
list_mechlist_for_soft(char *provname,
    entrylist_t *phardlist, entrylist_t *psoftlist)
{
	mechlist_t	*pmechlist = NULL;
	int		rc;

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

	rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist);
	if (rc == SUCCESS) {
		(void) filter_mechlist(&pmechlist, RANDOM);
		print_mechlist(provname, pmechlist);
		free_mechlist(pmechlist);
	} else {
		cryptoerror(LOG_STDERR, gettext(
		    "failed to retrieve the mechanism list for %s."),
		    provname);
	}

	return (rc);
}
Ejemplo n.º 4
0
/*
 * Get the supported mechanism list of the software provider from kernel.
 */
int
get_soft_info(char *provname, mechlist_t **ppmechlist)
{
	crypto_get_soft_info_t	*psoft_info;
	mechlist_t	*phead;
	mechlist_t	*pmech;
	mechlist_t	*pcur;
	entry_t	*pent;
	int	count;
	int	fd;
	int	rc;
	int	i;

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

	if (getzoneid() == GLOBAL_ZONEID) {
		/* use kcf.conf for kernel software providers in global zone */
		if ((pent = getent_kef(provname)) == NULL) {
			cryptoerror(LOG_STDERR, gettext("%s does not exist."),
			    provname);
			return (FAILURE);
		}
		count = pent->sup_count;
		free_entry(pent);
	} else {
		/*
		 * kcf.conf not there in non-global zone, set mech count to 1;
		 * it will be reset to the correct value later if the setup
		 * buffer is too small
		 */
		count = 1;
	}

	if ((psoft_info = setup_get_soft_info(provname, count)) == NULL) {
		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));
		free(psoft_info);
		return (FAILURE);
	}

	/* make GET_SOFT_INFO ioctl call */
	if ((rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info)) == -1) {
		cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed: %s",
		    strerror(errno));
		(void) close(fd);
		free(psoft_info);
		return (FAILURE);
	}

	/* BUFFER is too small, get the number of mechanisms and retry it. */
	if (psoft_info->si_return_value == CRYPTO_BUFFER_TOO_SMALL) {
		count = psoft_info->si_count;
		free(psoft_info);
		if ((psoft_info = setup_get_soft_info(provname, count))
		    == NULL) {
			(void) close(fd);
			return (FAILURE);
		} else {
			rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info);
			if (rc == -1) {
				cryptodebug("CRYPTO_GET_SOFT_INFO ioctl "
				    "failed: %s", strerror(errno));
				(void) close(fd);
				free(psoft_info);
				return (FAILURE);
			}
		}
	}

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


	/* Get the mechanism list and return it */
	rc = SUCCESS;
	phead = pcur = NULL;
	for (i = 0; i < psoft_info->si_count; i++) {
		pmech = create_mech(&psoft_info->si_list[i][0]);
		if (pmech == NULL) {
			rc = FAILURE;
			break;
		} else {
			if (phead == NULL) {
				phead = pcur = pmech;
			} else {
				pcur->next = pmech;
				pcur = pmech;
			}
		}
	}

	if (rc == FAILURE) {
		free_mechlist(phead);
	} else {
		*ppmechlist = phead;
	}

	free(psoft_info);
	return (rc);
}
Ejemplo n.º 5
0
/*
 * Get all the mechanisms supported by the hardware provider.
 * The result will be stored in the second argument.
 */
int
get_dev_info(char *devname, int inst_num, int count, mechlist_t **ppmechlist)
{
	crypto_get_dev_info_t *dev_info;
	mechlist_t *phead;
	mechlist_t *pcur;
	mechlist_t *pmech;
	int fd;
	int i;
	int rc;

	if (devname == NULL || count < 1) {
		cryptodebug("get_dev_info(): devname is NULL or bogus count");
		return (FAILURE);
	}

	/* Set up the argument for the CRYPTO_GET_DEV_INFO ioctl call */
	dev_info = malloc(sizeof (crypto_get_dev_info_t) +
	    sizeof (crypto_mech_name_t) * (count - 1));
	if (dev_info == NULL) {
		cryptodebug("out of memory.");
		return (FAILURE);
	}
	(void) strlcpy(dev_info->di_dev_name, devname, MAXNAMELEN);
	dev_info->di_dev_instance = inst_num;
	dev_info->di_count = count;

	/* Open the ioctl device */
	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
		    ADMIN_IOCTL_DEVICE, strerror(errno));
		free(dev_info);
		return (FAILURE);
	}

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

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

	phead = pcur = NULL;
	rc = SUCCESS;
	for (i = 0; i < dev_info->di_count; i++) {
		pmech = create_mech(&dev_info->di_list[i][0]);
		if (pmech == NULL) {
			rc = FAILURE;
			break;
		} else {
			if (phead == NULL) {
				phead = pcur = pmech;
			} else {
				pcur->next = pmech;
				pcur = pmech;
			}
		}
	}

	if (rc == SUCCESS) {
		*ppmechlist = phead;
	} else {
		free_mechlist(phead);
	}

	free(dev_info);
	(void) close(fd);
	return (rc);
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
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);
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
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);
}
Ejemplo n.º 11
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);
}
Ejemplo n.º 12
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);
}
Ejemplo n.º 13
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);
		}
	}
}
Ejemplo n.º 14
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);
}