Exemple #1
0
/* called from the CRYPTO_GET_DEV_LIST ioctl */
int
crypto_get_dev_list(uint_t *count, crypto_dev_list_entry_t **array)
{
	kcf_provider_desc_t **provider_array;
	kcf_provider_desc_t *pd;
	crypto_dev_list_entry_t *p;
	size_t skip_providers_size, mech_counts_size;
	char *skip_providers;
	uint_t provider_count;
	int rval, i, j, new_count, *mech_counts;

	/*
	 * Take snapshot of provider table returning only hardware providers
	 * that are in a usable state. Logical providers not included.
	 */
	rval =  kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
	    NULL, 0, B_FALSE);
	if (rval != CRYPTO_SUCCESS)
		return (rval);

	if (provider_count == 0) {
		*array = NULL;
		*count = 0;
		return (CRYPTO_SUCCESS);
	}

	skip_providers_size = provider_count * sizeof (char);
	mech_counts_size = provider_count * sizeof (int);

	skip_providers = kmem_zalloc(skip_providers_size, KM_SLEEP);
	mech_counts = kmem_zalloc(mech_counts_size, KM_SLEEP);
	filter_providers(provider_count, provider_array, skip_providers,
	    mech_counts, &new_count);

	p = kmem_alloc(new_count * sizeof (crypto_dev_list_entry_t), KM_SLEEP);
	for (i = 0, j = 0; i < provider_count; i++) {
		if (skip_providers[i] == 1) {
			ASSERT(mech_counts[i] == 0);
			continue;
		}
		pd = provider_array[i];
		p[j].le_mechanism_count = mech_counts[i];
		p[j].le_dev_instance = pd->pd_instance;
		(void) strncpy(p[j].le_dev_name, pd->pd_name, MAXNAMELEN);
		j++;
	}

	kcf_free_provider_tab(provider_count, provider_array);
	kmem_free(skip_providers, skip_providers_size);
	kmem_free(mech_counts, mech_counts_size);

	*array = p;
	*count = new_count;
	return (CRYPTO_SUCCESS);
}
Exemple #2
0
/* called from the CRYPTO_GET_DEV_INFO ioctl */
int
crypto_get_dev_info(char *name, uint_t instance, uint_t *count,
    crypto_mech_name_t **array)
{
	int rv;
	crypto_mech_name_t *mech_names;
	int i, j, k, all_count;
	uint_t provider_count;
	kcf_provider_desc_t **provider_array;
	kcf_provider_desc_t *pd;

	/*
	 * Get provider table entries matching name and instance
	 * for hardware providers that are in a usable state.
	 * Logical providers not included. NULL name matches
	 * all hardware providers.
	 */
	rv =  kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
	    name, instance, B_FALSE);
	if (rv != CRYPTO_SUCCESS)
		return (rv);

	if (provider_count == 0)
		return (CRYPTO_ARGUMENTS_BAD);

	/* Get count */
	all_count = 0;
	for (i = 0; i < provider_count; i++)
		all_count += provider_array[i]->pd_mech_list_count;

	if (all_count == 0) {
		mech_names = NULL;
		goto out;
	}

	/* Allocate space and copy mech names */
	mech_names = kmem_alloc(all_count * sizeof (crypto_mech_name_t),
	    KM_SLEEP);

	k = 0;
	for (i = 0; i < provider_count; i++) {
		pd = provider_array[i];
		for (j = 0; j < pd->pd_mech_list_count; j++, k++)
			bcopy(&pd->pd_mechanisms[j].cm_mech_name[0],
			    &mech_names[k][0], sizeof (crypto_mech_name_t));
	}

out:
	kcf_free_provider_tab(provider_count, provider_array);
	*count = all_count;
	*array = mech_names;

	return (CRYPTO_SUCCESS);
}
Exemple #3
0
/*
 * Called from CRYPTO_LOAD_DEV_DISABLED ioctl.
 * If new_count is 0, then completely remove the entry.
 */
int
crypto_load_dev_disabled(char *name, uint_t instance, uint_t new_count,
    crypto_mech_name_t *new_array)
{
	kcf_provider_desc_t *provider = NULL;
	kcf_provider_desc_t **provider_array;
	crypto_mech_name_t *prev_array;
	uint_t provider_count, prev_count;
	int i, rv = CRYPTO_SUCCESS;

	/*
	 * Remove the policy entry if new_count is 0, otherwise put disabled
	 * mechanisms into policy table.
	 */
	if (new_count == 0) {
		kcf_policy_remove_by_dev(name, instance, &prev_count,
		    &prev_array);
	} else if ((rv = kcf_policy_load_dev_disabled(name, instance, new_count,
	    new_array, &prev_count, &prev_array)) != CRYPTO_SUCCESS) {
		return (rv);
	}

	/*
	 * Get provider table entries matching name and instance
	 * for providers that are are in a usable or unverified state.
	 */
	rv =  kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
	    name, instance, B_TRUE);
	if (rv != CRYPTO_SUCCESS)
		return (rv);

	for (i = 0; i < provider_count; i++) {
		provider = provider_array[i];

		/* previously disabled mechanisms may become enabled */
		if (prev_array != NULL) {
			kcf_compare_mechs(new_count, new_array,
			    prev_count, prev_array);
			kcf_change_mechs(provider, prev_count, prev_array,
			    CRYPTO_EVENT_CHANGE_ADDED);
		}

		kcf_change_mechs(provider, new_count, new_array,
		    CRYPTO_EVENT_CHANGE_REMOVED);
	}

	kcf_free_provider_tab(provider_count, provider_array);
	crypto_free_mech_list(prev_array, prev_count);
	return (rv);
}
/*
 * Returns an array of hardware provider descriptors. This routine
 * used by cryptoadm(1M). A REFHOLD is done on each descriptor before
 * the array is returned. The entire table can be freed by calling
 * kcf_free_provider_tab().
 *
 * A NULL name argument puts all hardware providers in the array.
 * A non-NULL name argument puts only those providers in the array
 * which match the name and instance arguments.
 */
int
kcf_get_hw_prov_tab(uint_t *count, kcf_provider_desc_t ***array,  int kmflag,
    char *name, uint_t instance, boolean_t unverified)
{
	kcf_provider_desc_t *prov_desc;
	kcf_provider_desc_t **p = NULL;
	char *last;
	uint_t cnt = 0;
	uint_t i, j;
	int rval = CRYPTO_SUCCESS;
	size_t n, final_size;

	/* count the providers */
	mutex_enter(&prov_tab_mutex);
	for (i = 0; i < KCF_MAX_PROVIDERS; i++) {
		if ((prov_desc = prov_tab[i]) != NULL &&
		    prov_desc->pd_prov_type == CRYPTO_HW_PROVIDER) {
			if (KCF_IS_PROV_USABLE(prov_desc) ||
			    (unverified && KCF_IS_PROV_UNVERIFIED(prov_desc))) {
				if (name == NULL ||
				    (strncmp(prov_desc->pd_name, name,
				    MAXNAMELEN) == 0 &&
				    prov_desc->pd_instance == instance)) {
					cnt++;
				}
			}
		}
	}
	mutex_exit(&prov_tab_mutex);

	if (cnt == 0)
		goto out;

	n = cnt * sizeof (kcf_provider_desc_t *);
again:
	p = kmem_zalloc(n, kmflag);
	if (p == NULL) {
		rval = CRYPTO_HOST_MEMORY;
		goto out;
	}
	/* pointer to last entry in the array */
	last = (char *)&p[cnt-1];

	mutex_enter(&prov_tab_mutex);
	for (i = 0, j = 0; i < KCF_MAX_PROVIDERS; i++) {
		if ((prov_desc = prov_tab[i]) != NULL &&
		    prov_desc->pd_prov_type == CRYPTO_HW_PROVIDER) {
			if (KCF_IS_PROV_USABLE(prov_desc) ||
			    (unverified && KCF_IS_PROV_UNVERIFIED(prov_desc))) {
				if (name == NULL ||
				    (strncmp(prov_desc->pd_name, name,
				    MAXNAMELEN) == 0 &&
				    prov_desc->pd_instance == instance)) {
					if ((char *)&p[j] > last) {
						mutex_exit(&prov_tab_mutex);
						kcf_free_provider_tab(cnt, p);
						n = n << 1;
						cnt = cnt << 1;
						goto again;
					}
					p[j++] = prov_desc;
					KCF_PROV_REFHOLD(prov_desc);
				}
			}
		}
	}
	mutex_exit(&prov_tab_mutex);

	final_size = j * sizeof (kcf_provider_desc_t *);
	ASSERT(final_size <= n);

	/* check if buffer we allocated is too large */
	if (final_size < n) {
		char *final_buffer = NULL;

		if (final_size > 0) {
			final_buffer = kmem_alloc(final_size, kmflag);
			if (final_buffer == NULL) {
				kcf_free_provider_tab(cnt, p);
				cnt = 0;
				p = NULL;
				rval = CRYPTO_HOST_MEMORY;
				goto out;
			}
			bcopy(p, final_buffer, final_size);
		}
		kmem_free(p, n);
		p = (kcf_provider_desc_t **)final_buffer;
	}
	cnt = j;
out:
	*count = cnt;
	*array = p;
	return (rval);
}
/*
 * Returns an array of hardware and logical provider descriptors,
 * a.k.a the PKCS#11 slot list. A REFHOLD is done on each descriptor
 * before the array is returned. The entire table can be freed by
 * calling kcf_free_provider_tab().
 */
int
kcf_get_slot_list(uint_t *count, kcf_provider_desc_t ***array,
    boolean_t unverified)
{
	kcf_provider_desc_t *prov_desc;
	kcf_provider_desc_t **p = NULL;
	char *last;
	uint_t cnt = 0;
	uint_t i, j;
	int rval = CRYPTO_SUCCESS;
	size_t n, final_size;

	/* count the providers */
	mutex_enter(&prov_tab_mutex);
	for (i = 0; i < KCF_MAX_PROVIDERS; i++) {
		if ((prov_desc = prov_tab[i]) != NULL &&
		    ((prov_desc->pd_prov_type == CRYPTO_HW_PROVIDER &&
		    (prov_desc->pd_flags & CRYPTO_HIDE_PROVIDER) == 0) ||
		    prov_desc->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)) {
			if (KCF_IS_PROV_USABLE(prov_desc) ||
			    (unverified && KCF_IS_PROV_UNVERIFIED(prov_desc))) {
				cnt++;
			}
		}
	}
	mutex_exit(&prov_tab_mutex);

	if (cnt == 0)
		goto out;

	n = cnt * sizeof (kcf_provider_desc_t *);
again:
	p = kmem_zalloc(n, KM_SLEEP);

	/* pointer to last entry in the array */
	last = (char *)&p[cnt-1];

	mutex_enter(&prov_tab_mutex);
	/* fill the slot list */
	for (i = 0, j = 0; i < KCF_MAX_PROVIDERS; i++) {
		if ((prov_desc = prov_tab[i]) != NULL &&
		    ((prov_desc->pd_prov_type == CRYPTO_HW_PROVIDER &&
		    (prov_desc->pd_flags & CRYPTO_HIDE_PROVIDER) == 0) ||
		    prov_desc->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)) {
			if (KCF_IS_PROV_USABLE(prov_desc) ||
			    (unverified && KCF_IS_PROV_UNVERIFIED(prov_desc))) {
				if ((char *)&p[j] > last) {
					mutex_exit(&prov_tab_mutex);
					kcf_free_provider_tab(cnt, p);
					n = n << 1;
					cnt = cnt << 1;
					goto again;
				}
				p[j++] = prov_desc;
				KCF_PROV_REFHOLD(prov_desc);
			}
		}
	}
	mutex_exit(&prov_tab_mutex);

	final_size = j * sizeof (kcf_provider_desc_t *);
	cnt = j;
	ASSERT(final_size <= n);

	/* check if buffer we allocated is too large */
	if (final_size < n) {
		char *final_buffer = NULL;

		if (final_size > 0) {
			final_buffer = kmem_alloc(final_size, KM_SLEEP);
			bcopy(p, final_buffer, final_size);
		}
		kmem_free(p, n);
		p = (kcf_provider_desc_t **)final_buffer;
	}
out:
	*count = cnt;
	*array = p;
	return (rval);
}