17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*95014fbbSDan OpenSolaris Anderson  * Common Development and Distribution License (the "License").
6*95014fbbSDan OpenSolaris Anderson  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*95014fbbSDan OpenSolaris Anderson  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * This file is part of the core Kernel Cryptographic Framework.
287c478bd9Sstevel@tonic-gate  * It implements the management of the policy table. Entries are
297c478bd9Sstevel@tonic-gate  * added and removed by administrative ioctls.
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * Each element of the policy table contains a pointer to a
327c478bd9Sstevel@tonic-gate  * policy descriptor, or NULL if the entry is free.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <sys/types.h>
367c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
377c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
387c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
397c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
407c478bd9Sstevel@tonic-gate #include <sys/ksynch.h>
417c478bd9Sstevel@tonic-gate #include <sys/crypto/common.h>
427c478bd9Sstevel@tonic-gate #include <sys/crypto/impl.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #define	KCF_MAX_POLICY	512	/* max number of policy entries */
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate static kmutex_t policy_tab_mutex; /* ensure exclusive access to the table */
477c478bd9Sstevel@tonic-gate static kcf_policy_desc_t **policy_tab = NULL;
487c478bd9Sstevel@tonic-gate static uint_t policy_tab_num = 0; /* number of providers in table */
497c478bd9Sstevel@tonic-gate static uint_t policy_tab_max = KCF_MAX_POLICY;
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate static int kcf_policy_add_entry(kcf_policy_desc_t *);
527c478bd9Sstevel@tonic-gate static kcf_policy_desc_t *kcf_policy_alloc_desc(int);
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * Initialize the policy table. The policy table is dynamically
567c478bd9Sstevel@tonic-gate  * allocated with policy_tab_max entries.
577c478bd9Sstevel@tonic-gate  */
587c478bd9Sstevel@tonic-gate void
kcf_policy_tab_init(void)597c478bd9Sstevel@tonic-gate kcf_policy_tab_init(void)
607c478bd9Sstevel@tonic-gate {
617c478bd9Sstevel@tonic-gate 	mutex_init(&policy_tab_mutex, NULL, MUTEX_DRIVER, NULL);
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 	policy_tab = kmem_zalloc(policy_tab_max * sizeof (kcf_policy_desc_t *),
647c478bd9Sstevel@tonic-gate 	    KM_SLEEP);
657c478bd9Sstevel@tonic-gate }
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /*
687c478bd9Sstevel@tonic-gate  * Add entry to the policy table. If no free slot can be found
697c478bd9Sstevel@tonic-gate  * return CRYPTO_HOST_MEMORY, otherwise CRYPTO_SUCCESS.
707c478bd9Sstevel@tonic-gate  *
717c478bd9Sstevel@tonic-gate  * policy_tab_mutex must already be held.
727c478bd9Sstevel@tonic-gate  */
737c478bd9Sstevel@tonic-gate static int
kcf_policy_add_entry(kcf_policy_desc_t * policy_desc)747c478bd9Sstevel@tonic-gate kcf_policy_add_entry(kcf_policy_desc_t *policy_desc)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate 	uint_t i = 0;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	ASSERT(policy_tab != NULL);
797c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&policy_tab_mutex));
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	/* find free slot in policy table */
827c478bd9Sstevel@tonic-gate 	while (i < KCF_MAX_POLICY && policy_tab[i] != NULL)
837c478bd9Sstevel@tonic-gate 		i++;
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	if (i == KCF_MAX_POLICY) {
867c478bd9Sstevel@tonic-gate 		/* ran out of policy entries */
877c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "out of policy entries");
887c478bd9Sstevel@tonic-gate 		return (CRYPTO_HOST_MEMORY);
897c478bd9Sstevel@tonic-gate 	}
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 	/* initialize entry */
927c478bd9Sstevel@tonic-gate 	policy_tab[i] = policy_desc;
937c478bd9Sstevel@tonic-gate 	KCF_POLICY_REFHOLD(policy_desc);
947c478bd9Sstevel@tonic-gate 	policy_tab_num++;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate  * Remove policy descriptor for the specified software module.
1017c478bd9Sstevel@tonic-gate  */
1027c478bd9Sstevel@tonic-gate void
kcf_policy_remove_by_name(char * module_name,uint_t * count,crypto_mech_name_t ** array)1037c478bd9Sstevel@tonic-gate kcf_policy_remove_by_name(char *module_name, uint_t *count,
1047c478bd9Sstevel@tonic-gate     crypto_mech_name_t **array)
1057c478bd9Sstevel@tonic-gate {
1067c478bd9Sstevel@tonic-gate 	kcf_policy_desc_t *policy_desc;
1077c478bd9Sstevel@tonic-gate 	int i;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	ASSERT(policy_tab != NULL);
110*95014fbbSDan OpenSolaris Anderson 	ASSERT(policy_tab_num != (uint_t)-1); /* underflow */
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	mutex_enter(&policy_tab_mutex);
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	for (i = 0; i < KCF_MAX_POLICY; i++) {
1157c478bd9Sstevel@tonic-gate 		if ((policy_desc = policy_tab[i]) != NULL &&
1167c478bd9Sstevel@tonic-gate 		    policy_desc->pd_prov_type == CRYPTO_SW_PROVIDER) {
1177c478bd9Sstevel@tonic-gate 			ASSERT(policy_desc->pd_name != NULL);
1187c478bd9Sstevel@tonic-gate 			if (strncmp(module_name, policy_desc->pd_name,
1197c478bd9Sstevel@tonic-gate 			    MAXNAMELEN) == 0) {
1207c478bd9Sstevel@tonic-gate 				*count = policy_desc->pd_disabled_count;
1217c478bd9Sstevel@tonic-gate 				*array = policy_desc->pd_disabled_mechs;
1227c478bd9Sstevel@tonic-gate 				mutex_destroy(&policy_desc->pd_mutex);
1237c478bd9Sstevel@tonic-gate 				kmem_free(policy_desc->pd_name,
1247c478bd9Sstevel@tonic-gate 				    strlen(policy_desc->pd_name) + 1);
1257c478bd9Sstevel@tonic-gate 				kmem_free(policy_desc,
1267c478bd9Sstevel@tonic-gate 				    sizeof (kcf_policy_desc_t));
1277c478bd9Sstevel@tonic-gate 				policy_tab[i] = NULL;
1287c478bd9Sstevel@tonic-gate 				policy_tab_num--;
1297c478bd9Sstevel@tonic-gate 				break;
1307c478bd9Sstevel@tonic-gate 			}
1317c478bd9Sstevel@tonic-gate 		}
1327c478bd9Sstevel@tonic-gate 	}
1337c478bd9Sstevel@tonic-gate 	if (i == KCF_MAX_POLICY) {
1347c478bd9Sstevel@tonic-gate 		*count = 0;
1357c478bd9Sstevel@tonic-gate 		*array = NULL;
1367c478bd9Sstevel@tonic-gate 	}
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	mutex_exit(&policy_tab_mutex);
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate /*
1427c478bd9Sstevel@tonic-gate  * Remove policy descriptor for the specified device.
1437c478bd9Sstevel@tonic-gate  */
1447c478bd9Sstevel@tonic-gate void
kcf_policy_remove_by_dev(char * name,uint_t instance,uint_t * count,crypto_mech_name_t ** array)1457c478bd9Sstevel@tonic-gate kcf_policy_remove_by_dev(char *name, uint_t instance, uint_t *count,
1467c478bd9Sstevel@tonic-gate     crypto_mech_name_t **array)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate 	kcf_policy_desc_t *policy_desc;
1497c478bd9Sstevel@tonic-gate 	int i;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	ASSERT(policy_tab != NULL);
152*95014fbbSDan OpenSolaris Anderson 	ASSERT(policy_tab_num != (uint_t)-1); /* underflow */
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	mutex_enter(&policy_tab_mutex);
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	for (i = 0; i < KCF_MAX_POLICY; i++) {
1577c478bd9Sstevel@tonic-gate 		if ((policy_desc = policy_tab[i]) != NULL &&
1587c478bd9Sstevel@tonic-gate 		    policy_desc->pd_prov_type == CRYPTO_HW_PROVIDER &&
1597c478bd9Sstevel@tonic-gate 		    strncmp(policy_desc->pd_name, name, MAXNAMELEN) == 0 &&
1607c478bd9Sstevel@tonic-gate 		    policy_desc->pd_instance == instance) {
1617c478bd9Sstevel@tonic-gate 			*count = policy_desc->pd_disabled_count;
1627c478bd9Sstevel@tonic-gate 			*array = policy_desc->pd_disabled_mechs;
1637c478bd9Sstevel@tonic-gate 			mutex_destroy(&policy_desc->pd_mutex);
1647c478bd9Sstevel@tonic-gate 			kmem_free(policy_desc->pd_name,
1657c478bd9Sstevel@tonic-gate 			    strlen(policy_desc->pd_name) + 1);
1667c478bd9Sstevel@tonic-gate 			kmem_free(policy_desc, sizeof (kcf_policy_desc_t));
1677c478bd9Sstevel@tonic-gate 			policy_tab[i] = NULL;
1687c478bd9Sstevel@tonic-gate 			policy_tab_num--;
1697c478bd9Sstevel@tonic-gate 			break;
1707c478bd9Sstevel@tonic-gate 		}
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 	if (i == KCF_MAX_POLICY) {
1737c478bd9Sstevel@tonic-gate 		*count = 0;
1747c478bd9Sstevel@tonic-gate 		*array = NULL;
1757c478bd9Sstevel@tonic-gate 	}
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	mutex_exit(&policy_tab_mutex);
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate /*
1817c478bd9Sstevel@tonic-gate  * Returns policy descriptor for the specified software module.
1827c478bd9Sstevel@tonic-gate  */
1837c478bd9Sstevel@tonic-gate kcf_policy_desc_t *
kcf_policy_lookup_by_name(char * module_name)1847c478bd9Sstevel@tonic-gate kcf_policy_lookup_by_name(char *module_name)
1857c478bd9Sstevel@tonic-gate {
1867c478bd9Sstevel@tonic-gate 	kcf_policy_desc_t *policy_desc;
1877c478bd9Sstevel@tonic-gate 	uint_t i;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	mutex_enter(&policy_tab_mutex);
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	for (i = 0; i < KCF_MAX_POLICY; i++) {
1927c478bd9Sstevel@tonic-gate 		if ((policy_desc = policy_tab[i]) != NULL &&
1937c478bd9Sstevel@tonic-gate 		    policy_desc->pd_prov_type == CRYPTO_SW_PROVIDER) {
1947c478bd9Sstevel@tonic-gate 			ASSERT(policy_desc->pd_name != NULL);
1957c478bd9Sstevel@tonic-gate 			if (strncmp(module_name, policy_desc->pd_name,
1967c478bd9Sstevel@tonic-gate 			    MAXNAMELEN) == 0) {
1977c478bd9Sstevel@tonic-gate 				KCF_POLICY_REFHOLD(policy_desc);
1987c478bd9Sstevel@tonic-gate 				mutex_exit(&policy_tab_mutex);
1997c478bd9Sstevel@tonic-gate 				return (policy_desc);
2007c478bd9Sstevel@tonic-gate 			}
2017c478bd9Sstevel@tonic-gate 		}
2027c478bd9Sstevel@tonic-gate 	}
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	mutex_exit(&policy_tab_mutex);
2057c478bd9Sstevel@tonic-gate 	return (NULL);
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate /*
2097c478bd9Sstevel@tonic-gate  * Returns policy descriptor for the specified device.
2107c478bd9Sstevel@tonic-gate  */
2117c478bd9Sstevel@tonic-gate kcf_policy_desc_t *
kcf_policy_lookup_by_dev(char * name,uint_t instance)2127c478bd9Sstevel@tonic-gate kcf_policy_lookup_by_dev(char *name, uint_t instance)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate 	kcf_policy_desc_t *policy_desc;
2157c478bd9Sstevel@tonic-gate 	uint_t i;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	mutex_enter(&policy_tab_mutex);
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	for (i = 0; i < KCF_MAX_POLICY; i++) {
2207c478bd9Sstevel@tonic-gate 		if ((policy_desc = policy_tab[i]) != NULL &&
2217c478bd9Sstevel@tonic-gate 		    policy_desc->pd_prov_type == CRYPTO_HW_PROVIDER &&
2227c478bd9Sstevel@tonic-gate 		    strncmp(policy_desc->pd_name, name, MAXNAMELEN) == 0 &&
2237c478bd9Sstevel@tonic-gate 		    policy_desc->pd_instance == instance) {
2247c478bd9Sstevel@tonic-gate 			KCF_POLICY_REFHOLD(policy_desc);
2257c478bd9Sstevel@tonic-gate 			mutex_exit(&policy_tab_mutex);
2267c478bd9Sstevel@tonic-gate 			return (policy_desc);
2277c478bd9Sstevel@tonic-gate 		}
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	mutex_exit(&policy_tab_mutex);
2317c478bd9Sstevel@tonic-gate 	return (NULL);
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate /*
2357c478bd9Sstevel@tonic-gate  * Loads disabled mechanism array for specified software provider, and
2367c478bd9Sstevel@tonic-gate  * creates a policy descriptor if one does not already exist.
2377c478bd9Sstevel@tonic-gate  * Important note: new_array is consumed.
2387c478bd9Sstevel@tonic-gate  */
2397c478bd9Sstevel@tonic-gate int
kcf_policy_load_soft_disabled(char * module_name,uint_t new_count,crypto_mech_name_t * new_array,uint_t * prev_count,crypto_mech_name_t ** prev_array)2407c478bd9Sstevel@tonic-gate kcf_policy_load_soft_disabled(char *module_name, uint_t new_count,
2417c478bd9Sstevel@tonic-gate     crypto_mech_name_t *new_array, uint_t *prev_count,
2427c478bd9Sstevel@tonic-gate     crypto_mech_name_t **prev_array)
2437c478bd9Sstevel@tonic-gate {
2447c478bd9Sstevel@tonic-gate 	kcf_policy_desc_t *new_desc, *policy_desc = NULL;
2457c478bd9Sstevel@tonic-gate 	uint_t i;
2467c478bd9Sstevel@tonic-gate 	int rv;
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	/*
2497c478bd9Sstevel@tonic-gate 	 * Allocate storage for a new entry.
2507c478bd9Sstevel@tonic-gate 	 * Free new entry if a policy descriptor already exists.
2517c478bd9Sstevel@tonic-gate 	 */
2527c478bd9Sstevel@tonic-gate 	new_desc = kcf_policy_alloc_desc(KM_SLEEP);
2537c478bd9Sstevel@tonic-gate 	new_desc->pd_prov_type = CRYPTO_SW_PROVIDER;
2547c478bd9Sstevel@tonic-gate 	new_desc->pd_name = kmem_alloc(strlen(module_name) + 1, KM_SLEEP);
2557c478bd9Sstevel@tonic-gate 	(void) strcpy(new_desc->pd_name, module_name);
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	mutex_enter(&policy_tab_mutex);
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	/*
2607c478bd9Sstevel@tonic-gate 	 * Search for an existing entry.
2617c478bd9Sstevel@tonic-gate 	 */
2627c478bd9Sstevel@tonic-gate 	for (i = 0; i < KCF_MAX_POLICY; i++) {
2637c478bd9Sstevel@tonic-gate 		if (policy_tab[i] != NULL &&
2647c478bd9Sstevel@tonic-gate 		    policy_tab[i]->pd_prov_type == CRYPTO_SW_PROVIDER) {
2657c478bd9Sstevel@tonic-gate 			ASSERT(policy_tab[i]->pd_name != NULL);
2667c478bd9Sstevel@tonic-gate 			if (strncmp(policy_tab[i]->pd_name, module_name,
2677c478bd9Sstevel@tonic-gate 			    MAXNAMELEN) == 0) {
2687c478bd9Sstevel@tonic-gate 				policy_desc = policy_tab[i];
2697c478bd9Sstevel@tonic-gate 				break;
2707c478bd9Sstevel@tonic-gate 			}
2717c478bd9Sstevel@tonic-gate 		}
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate 	if (policy_desc == NULL) {
2747c478bd9Sstevel@tonic-gate 		rv = kcf_policy_add_entry(new_desc);
2757c478bd9Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS) {
2767c478bd9Sstevel@tonic-gate 			mutex_exit(&policy_tab_mutex);
2777c478bd9Sstevel@tonic-gate 			kcf_policy_free_desc(new_desc);
2787c478bd9Sstevel@tonic-gate 			return (rv);
2797c478bd9Sstevel@tonic-gate 		}
2807c478bd9Sstevel@tonic-gate 		policy_desc = new_desc;
2817c478bd9Sstevel@tonic-gate 	} else {
2827c478bd9Sstevel@tonic-gate 		kcf_policy_free_desc(new_desc);
2837c478bd9Sstevel@tonic-gate 	}
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	mutex_enter(&policy_desc->pd_mutex);
2867c478bd9Sstevel@tonic-gate 	*prev_count = policy_desc->pd_disabled_count;
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	/* prev_array is freed by the caller */
2897c478bd9Sstevel@tonic-gate 	*prev_array = policy_desc->pd_disabled_mechs;
2907c478bd9Sstevel@tonic-gate 	policy_desc->pd_disabled_count = new_count;
2917c478bd9Sstevel@tonic-gate 	policy_desc->pd_disabled_mechs = new_array;
2927c478bd9Sstevel@tonic-gate 	mutex_exit(&policy_desc->pd_mutex);
2937c478bd9Sstevel@tonic-gate 	mutex_exit(&policy_tab_mutex);
2947c478bd9Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate /*
2987c478bd9Sstevel@tonic-gate  * Loads disabled mechanism array for specified device, and
2997c478bd9Sstevel@tonic-gate  * creates a policy descriptor if one does not already exist.
3007c478bd9Sstevel@tonic-gate  * Important note: new_array is consumed.
3017c478bd9Sstevel@tonic-gate  */
3027c478bd9Sstevel@tonic-gate int
kcf_policy_load_dev_disabled(char * name,uint_t instance,uint_t new_count,crypto_mech_name_t * new_array,uint_t * prev_count,crypto_mech_name_t ** prev_array)3037c478bd9Sstevel@tonic-gate kcf_policy_load_dev_disabled(char *name, uint_t instance, uint_t new_count,
3047c478bd9Sstevel@tonic-gate     crypto_mech_name_t *new_array, uint_t *prev_count,
3057c478bd9Sstevel@tonic-gate     crypto_mech_name_t **prev_array)
3067c478bd9Sstevel@tonic-gate {
3077c478bd9Sstevel@tonic-gate 	kcf_policy_desc_t *new_desc, *policy_desc = NULL;
3087c478bd9Sstevel@tonic-gate 	uint_t i;
3097c478bd9Sstevel@tonic-gate 	int rv;
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	/*
3127c478bd9Sstevel@tonic-gate 	 * Allocate storage for a new entry.
3137c478bd9Sstevel@tonic-gate 	 * Free new entry if a policy descriptor already exists.
3147c478bd9Sstevel@tonic-gate 	 */
3157c478bd9Sstevel@tonic-gate 	new_desc = kcf_policy_alloc_desc(KM_SLEEP);
3167c478bd9Sstevel@tonic-gate 	new_desc->pd_prov_type = CRYPTO_HW_PROVIDER;
3177c478bd9Sstevel@tonic-gate 	new_desc->pd_name = kmem_alloc(strlen(name) + 1, KM_SLEEP);
3187c478bd9Sstevel@tonic-gate 	(void) strcpy(new_desc->pd_name, name);
3197c478bd9Sstevel@tonic-gate 	new_desc->pd_instance = instance;
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	mutex_enter(&policy_tab_mutex);
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	/*
3247c478bd9Sstevel@tonic-gate 	 * Search for an existing entry.
3257c478bd9Sstevel@tonic-gate 	 */
3267c478bd9Sstevel@tonic-gate 	for (i = 0; i < KCF_MAX_POLICY; i++) {
3277c478bd9Sstevel@tonic-gate 		if (policy_tab[i] != NULL &&
3287c478bd9Sstevel@tonic-gate 		    policy_tab[i]->pd_prov_type == CRYPTO_HW_PROVIDER &&
3297c478bd9Sstevel@tonic-gate 		    strncmp(policy_tab[i]->pd_name, name, MAXNAMELEN) == 0 &&
3307c478bd9Sstevel@tonic-gate 		    policy_tab[i]->pd_instance == instance) {
3317c478bd9Sstevel@tonic-gate 			policy_desc = policy_tab[i];
3327c478bd9Sstevel@tonic-gate 			break;
3337c478bd9Sstevel@tonic-gate 		}
3347c478bd9Sstevel@tonic-gate 	}
3357c478bd9Sstevel@tonic-gate 	if (policy_desc == NULL) {
3367c478bd9Sstevel@tonic-gate 		rv = kcf_policy_add_entry(new_desc);
3377c478bd9Sstevel@tonic-gate 		if (rv != CRYPTO_SUCCESS) {
3387c478bd9Sstevel@tonic-gate 			mutex_exit(&policy_tab_mutex);
3397c478bd9Sstevel@tonic-gate 			kcf_policy_free_desc(new_desc);
3407c478bd9Sstevel@tonic-gate 			return (rv);
3417c478bd9Sstevel@tonic-gate 		}
3427c478bd9Sstevel@tonic-gate 		policy_desc = new_desc;
3437c478bd9Sstevel@tonic-gate 	} else {
3447c478bd9Sstevel@tonic-gate 		kcf_policy_free_desc(new_desc);
3457c478bd9Sstevel@tonic-gate 	}
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	mutex_enter(&policy_desc->pd_mutex);
3487c478bd9Sstevel@tonic-gate 	*prev_count = policy_desc->pd_disabled_count;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	/* prev_array is freed by the caller */
3517c478bd9Sstevel@tonic-gate 	*prev_array = policy_desc->pd_disabled_mechs;
3527c478bd9Sstevel@tonic-gate 	policy_desc->pd_disabled_count = new_count;
3537c478bd9Sstevel@tonic-gate 	policy_desc->pd_disabled_mechs = new_array;
3547c478bd9Sstevel@tonic-gate 	mutex_exit(&policy_desc->pd_mutex);
3557c478bd9Sstevel@tonic-gate 	mutex_exit(&policy_tab_mutex);
3567c478bd9Sstevel@tonic-gate 	return (CRYPTO_SUCCESS);
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate  * Allocate a policy descriptor.
3617c478bd9Sstevel@tonic-gate  */
3627c478bd9Sstevel@tonic-gate static kcf_policy_desc_t *
kcf_policy_alloc_desc(int km_flag)3637c478bd9Sstevel@tonic-gate kcf_policy_alloc_desc(int km_flag)
3647c478bd9Sstevel@tonic-gate {
3657c478bd9Sstevel@tonic-gate 	kcf_policy_desc_t *desc;
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	if ((desc = kmem_zalloc(sizeof (kcf_policy_desc_t), km_flag)) == NULL)
3687c478bd9Sstevel@tonic-gate 		return (NULL);
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	mutex_init(&desc->pd_mutex, NULL, MUTEX_DEFAULT, NULL);
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	return (desc);
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate /*
3767c478bd9Sstevel@tonic-gate  * Free a policy descriptor.
3777c478bd9Sstevel@tonic-gate  */
3787c478bd9Sstevel@tonic-gate void
kcf_policy_free_desc(kcf_policy_desc_t * desc)3797c478bd9Sstevel@tonic-gate kcf_policy_free_desc(kcf_policy_desc_t *desc)
3807c478bd9Sstevel@tonic-gate {
3817c478bd9Sstevel@tonic-gate 	if (desc == NULL)
3827c478bd9Sstevel@tonic-gate 		return;
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	mutex_destroy(&desc->pd_mutex);
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	ASSERT(desc->pd_name != NULL);
3877c478bd9Sstevel@tonic-gate 	kmem_free(desc->pd_name, strlen(desc->pd_name) + 1);
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	if (desc->pd_disabled_mechs != NULL)
3907c478bd9Sstevel@tonic-gate 		kmem_free(desc->pd_disabled_mechs, sizeof (crypto_mech_name_t) *
3917c478bd9Sstevel@tonic-gate 		    desc->pd_disabled_count);
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	kmem_free(desc, sizeof (kcf_policy_desc_t));
3947c478bd9Sstevel@tonic-gate }
395