コード例 #1
0
ファイル: kcf_cryptoadm.c プロジェクト: andreiw/polaris
static void
free_soft_config_entry(kcf_soft_conf_entry_t *p)
{
	kmem_free(p->ce_name, strlen(p->ce_name) + 1);
	crypto_free_mech_list(p->ce_mechs, p->ce_count);
	kmem_free(p, sizeof (kcf_soft_conf_entry_t));
}
コード例 #2
0
ファイル: kcf_cryptoadm.c プロジェクト: andreiw/polaris
/*
 * 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);
}
コード例 #3
0
ファイル: kcf_cryptoadm.c プロジェクト: andreiw/polaris
/*
 * Called from the CRYPTO_LOAD_SOFT_CONFIG ioctl, this routine stores
 * configuration information for software providers in a linked list.
 * If the list already contains an entry for the specified provider
 * and the specified mechanism list has at least one mechanism, then
 * the mechanism list for the provider is updated. If the mechanism list
 * is empty, the entry for the provider is removed.
 *
 * Important note: the array argument is consumed.
 */
static int
add_soft_config(char *name, uint_t count, crypto_mech_name_t *array)
{
	static uint_t soft_config_count = 0;
	kcf_soft_conf_entry_t *prev = NULL, *entry = NULL, *new_entry, *p;
	size_t name_len;

	/*
	 * Allocate storage for a new entry.
	 * Free later if an entry already exists.
	 */
	name_len = strlen(name) + 1;
	new_entry = kmem_zalloc(sizeof (kcf_soft_conf_entry_t), KM_SLEEP);
	new_entry->ce_name = kmem_alloc(name_len, KM_SLEEP);
	(void) strcpy(new_entry->ce_name, name);

	mutex_enter(&soft_config_mutex);
	p = soft_config_list;
	if (p != NULL) {
		do {
			if (strncmp(name, p->ce_name, MAXNAMELEN) == 0) {
				entry = p;
				break;
			}
			prev = p;

		} while ((p = p->ce_next) != NULL);
	}

	if (entry == NULL) {
		if (count == 0) {
			mutex_exit(&soft_config_mutex);
			kmem_free(new_entry->ce_name, name_len);
			kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
			return (CRYPTO_SUCCESS);
		}

		if (soft_config_count > KCF_MAX_CONFIG_ENTRIES) {
			mutex_exit(&soft_config_mutex);
			kmem_free(new_entry->ce_name, name_len);
			kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
			cmn_err(CE_WARN, "out of soft_config_list entries");
			return (CRYPTO_FAILED);
		}

		/* add to head of list */
		new_entry->ce_next = soft_config_list;
		soft_config_list = new_entry;
		soft_config_count++;
		entry = new_entry;
	} else {
		kmem_free(new_entry->ce_name, name_len);
		kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
	}

	/* mechanism count == 0 means remove entry from list */
	if (count == 0) {
		if (prev == NULL) {
			/* remove first in list */
			soft_config_list = entry->ce_next;
		} else {
			prev->ce_next = entry->ce_next;
		}
		soft_config_count--;
		mutex_exit(&soft_config_mutex);

		/* free entry */
		free_soft_config_entry(entry);

		return (CRYPTO_SUCCESS);
	}


	/* replace mechanisms */
	if (entry->ce_mechs != NULL)
		crypto_free_mech_list(entry->ce_mechs, entry->ce_count);

	entry->ce_mechs = array;
	entry->ce_count = count;
	mutex_exit(&soft_config_mutex);

	return (CRYPTO_SUCCESS);
}
コード例 #4
0
ファイル: kcf_cryptoadm.c プロジェクト: andreiw/polaris
/*
 * Called from CRYPTO_LOAD_SOFT_DISABLED ioctl.
 * If new_count is 0, then completely remove the entry.
 */
int
crypto_load_soft_disabled(char *name, uint_t new_count,
    crypto_mech_name_t *new_array)
{
	kcf_provider_desc_t *provider = NULL;
	crypto_mech_name_t *prev_array;
	uint_t prev_count = 0;
	int rv;

	provider = kcf_prov_tab_lookup_by_name(name);
	if (provider != NULL) {
		mutex_enter(&provider->pd_lock);
		/*
		 * Check if any other thread is disabling or removing
		 * this provider. We return if this is the case.
		 */
		if (provider->pd_state >= KCF_PROV_DISABLED) {
			mutex_exit(&provider->pd_lock);
			KCF_PROV_REFRELE(provider);
			return (CRYPTO_BUSY);
		}
		provider->pd_state = KCF_PROV_DISABLED;
		mutex_exit(&provider->pd_lock);

		undo_register_provider(provider, B_TRUE);
		KCF_PROV_REFRELE(provider);
		if (provider->pd_kstat != NULL)
			KCF_PROV_REFRELE(provider);

		mutex_enter(&provider->pd_lock);
		/* Wait till the existing requests complete. */
		while (provider->pd_state != KCF_PROV_FREED) {
			cv_wait(&provider->pd_remove_cv, &provider->pd_lock);
		}
		mutex_exit(&provider->pd_lock);
	}

	if (new_count == 0) {
		kcf_policy_remove_by_name(name, &prev_count, &prev_array);
		crypto_free_mech_list(prev_array, prev_count);
		rv = CRYPTO_SUCCESS;
		goto out;
	}

	/* put disabled mechanisms into policy table */
	if ((rv = kcf_policy_load_soft_disabled(name, new_count, new_array,
	    &prev_count, &prev_array)) == CRYPTO_SUCCESS) {
		crypto_free_mech_list(prev_array, prev_count);
	}

out:
	if (provider != NULL) {
		redo_register_provider(provider);
		if (provider->pd_kstat != NULL)
			KCF_PROV_REFHOLD(provider);
		mutex_enter(&provider->pd_lock);
		provider->pd_state = KCF_PROV_READY;
		mutex_exit(&provider->pd_lock);
	} else if (rv == CRYPTO_SUCCESS) {
		/*
		 * There are some cases where it is useful to kCF clients
		 * to have a provider whose mechanism is enabled now to be
		 * available. So, we attempt to load it here.
		 *
		 * The check, new_count < prev_count, ensures that we do this
		 * only in the case where a mechanism(s) is now enabled.
		 * This check assumes that enable and disable are separate
		 * administrative actions and are not done in a single action.
		 */
		if (new_count < prev_count && (in_soft_config_list(name)) &&
		    (modload("crypto", name) != -1)) {
			struct modctl *mcp;
			boolean_t load_again = B_FALSE;

			if ((mcp = mod_hold_by_name(name)) != NULL) {
				mcp->mod_loadflags |= MOD_NOAUTOUNLOAD;

				/* memory pressure may have unloaded module */
				if (!mcp->mod_installed)
					load_again = B_TRUE;
				mod_release_mod(mcp);

				if (load_again)
					(void) modload("crypto", name);
			}
		}
	}

	return (rv);
}
コード例 #5
0
/* ARGSUSED */
static int
get_soft_info(dev_t dev, caddr_t arg, int mode, int *rval)
{
	crypto_get_soft_info_t soft_info;
	crypto_mech_name_t *entries;
	size_t copyout_size;
	uint_t count;
	ulong_t offset;
	char *name;

	if (copyin(arg, &soft_info, sizeof (soft_info)) != 0)
		return (EFAULT);

	name = soft_info.si_name;
	/* make sure the provider name is null terminated */
	if (!null_terminated(name)) {
		soft_info.si_return_value = CRYPTO_ARGUMENTS_BAD;
		if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) {
			return (EFAULT);
		}
		return (0);
	}

	/* get mechanism names from the core module */
	if (crypto_get_soft_info(name, &count, &entries) != 0) {
		soft_info.si_return_value = CRYPTO_FAILED;
		if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) {
			return (EFAULT);
		}
		return (0);
	}

	/* check if buffer is too small */
	if (count > soft_info.si_count) {
		soft_info.si_count = count;
		soft_info.si_return_value = CRYPTO_BUFFER_TOO_SMALL;
		crypto_free_mech_list(entries, count);
		if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) {
			return (EFAULT);
		}
		return (0);
	}

	soft_info.si_count = count;
	soft_info.si_return_value = CRYPTO_SUCCESS;
	copyout_size = count * sizeof (crypto_mech_name_t);

	/* copyout the first stuff */
	if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) {
		crypto_free_mech_list(entries, count);
		return (EFAULT);
	}

	/* copyout entries */
	offset = offsetof(crypto_get_soft_info_t, si_list);
	if (copyout(entries, arg + offset, copyout_size) != 0) {
		crypto_free_mech_list(entries, count);
		return (EFAULT);
	}
	crypto_free_mech_list(entries, count);
	return (0);
}
コード例 #6
0
/* ARGSUSED */
static int
get_dev_info(dev_t dev, caddr_t arg, int mode, int *rval)
{
	crypto_get_dev_info_t dev_info;
	crypto_mech_name_t *entries;
	size_t copyout_size;
	uint_t count;
	ulong_t offset;
	char *dev_name;
	int rv;

	if (copyin(arg, &dev_info, sizeof (dev_info)) != 0)
		return (EFAULT);

	dev_name = dev_info.di_dev_name;
	/* make sure the device name is null terminated */
	if (!null_terminated(dev_name)) {
		dev_info.di_return_value = CRYPTO_ARGUMENTS_BAD;
		if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) {
			return (EFAULT);
		}
		return (0);
	}

	/* get mechanism names from the core module */
	if ((rv = crypto_get_dev_info(dev_name, dev_info.di_dev_instance,
	    &count, &entries)) != CRYPTO_SUCCESS) {
		dev_info.di_return_value = rv;
		if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) {
			return (EFAULT);
		}
		return (0);
	}

	/* check if buffer is too small */
	if (count > dev_info.di_count) {
		dev_info.di_count = count;
		dev_info.di_return_value = CRYPTO_BUFFER_TOO_SMALL;
		crypto_free_mech_list(entries, count);
		if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) {
			return (EFAULT);
		}
		return (0);
	}

	dev_info.di_count = count;
	dev_info.di_return_value = CRYPTO_SUCCESS;

	copyout_size = count * sizeof (crypto_mech_name_t);

	/* copyout the first stuff */
	if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) {
		crypto_free_mech_list(entries, count);
		return (EFAULT);
	}

	/* copyout entries */
	offset = offsetof(crypto_get_dev_info_t, di_list);
	if (copyout(entries, arg + offset, copyout_size) != 0) {
		crypto_free_mech_list(entries, count);
		return (EFAULT);
	}
	crypto_free_mech_list(entries, count);
	return (0);
}