xref: /freebsd/sys/contrib/openzfs/module/icp/core/kcf_prov_tabs.c (revision c7046f76c2c027b00c0e6ba57cfd28f1a78f5e23)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or https://opensource.org/licenses/CDDL-1.0.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * This file is part of the core Kernel Cryptographic Framework.
28  * It implements the management of tables of Providers. Entries to
29  * added and removed when cryptographic providers register with
30  * and unregister from the framework, respectively. The KCF scheduler
31  * and ioctl pseudo driver call this function to obtain the list
32  * of available providers.
33  *
34  * The provider table is indexed by crypto_provider_id_t. Each
35  * element of the table contains a pointer to a provider descriptor,
36  * or NULL if the entry is free.
37  *
38  * This file also implements helper functions to allocate and free
39  * provider descriptors.
40  */
41 
42 #include <sys/zfs_context.h>
43 #include <sys/crypto/common.h>
44 #include <sys/crypto/impl.h>
45 #include <sys/crypto/sched_impl.h>
46 #include <sys/crypto/spi.h>
47 
48 #define	KCF_MAX_PROVIDERS	8	/* max number of providers */
49 
50 /*
51  * Prov_tab is an array of providers which is updated when
52  * a crypto provider registers with kcf. The provider calls the
53  * SPI routine, crypto_register_provider(), which in turn calls
54  * kcf_prov_tab_add_provider().
55  *
56  * A provider unregisters by calling crypto_unregister_provider()
57  * which triggers the removal of the prov_tab entry.
58  * It also calls kcf_remove_mech_provider().
59  *
60  * prov_tab entries are not updated from kcf.conf or by cryptoadm(1M).
61  */
62 static kcf_provider_desc_t *prov_tab[KCF_MAX_PROVIDERS];
63 static kmutex_t prov_tab_mutex; /* ensure exclusive access to the table */
64 static uint_t prov_tab_num = 0; /* number of providers in table */
65 
66 void
kcf_prov_tab_destroy(void)67 kcf_prov_tab_destroy(void)
68 {
69 	mutex_destroy(&prov_tab_mutex);
70 }
71 
72 /*
73  * Initialize a mutex and the KCF providers table, prov_tab.
74  * The providers table is dynamically allocated with KCF_MAX_PROVIDERS entries.
75  * Called from kcf module _init().
76  */
77 void
kcf_prov_tab_init(void)78 kcf_prov_tab_init(void)
79 {
80 	mutex_init(&prov_tab_mutex, NULL, MUTEX_DEFAULT, NULL);
81 }
82 
83 /*
84  * Add a provider to the provider table. If no free entry can be found
85  * for the new provider, returns CRYPTO_HOST_MEMORY. Otherwise, add
86  * the provider to the table, initialize the pd_prov_id field
87  * of the specified provider descriptor to the index in that table,
88  * and return CRYPTO_SUCCESS. Note that a REFHOLD is done on the
89  * provider when pointed to by a table entry.
90  */
91 int
kcf_prov_tab_add_provider(kcf_provider_desc_t * prov_desc)92 kcf_prov_tab_add_provider(kcf_provider_desc_t *prov_desc)
93 {
94 	uint_t i;
95 
96 	mutex_enter(&prov_tab_mutex);
97 
98 	/* find free slot in providers table */
99 	for (i = 1; i < KCF_MAX_PROVIDERS && prov_tab[i] != NULL; i++)
100 		;
101 	if (i == KCF_MAX_PROVIDERS) {
102 		/* ran out of providers entries */
103 		mutex_exit(&prov_tab_mutex);
104 		cmn_err(CE_WARN, "out of providers entries");
105 		return (CRYPTO_HOST_MEMORY);
106 	}
107 
108 	/* initialize entry */
109 	prov_tab[i] = prov_desc;
110 	KCF_PROV_REFHOLD(prov_desc);
111 	KCF_PROV_IREFHOLD(prov_desc);
112 	prov_tab_num++;
113 
114 	mutex_exit(&prov_tab_mutex);
115 
116 	/* update provider descriptor */
117 	prov_desc->pd_prov_id = i;
118 
119 	/*
120 	 * The KCF-private provider handle is defined as the internal
121 	 * provider id.
122 	 */
123 	prov_desc->pd_kcf_prov_handle =
124 	    (crypto_kcf_provider_handle_t)prov_desc->pd_prov_id;
125 
126 	return (CRYPTO_SUCCESS);
127 }
128 
129 /*
130  * Remove the provider specified by its id. A REFRELE is done on the
131  * corresponding provider descriptor before this function returns.
132  * Returns CRYPTO_UNKNOWN_PROVIDER if the provider id is not valid.
133  */
134 int
kcf_prov_tab_rem_provider(crypto_provider_id_t prov_id)135 kcf_prov_tab_rem_provider(crypto_provider_id_t prov_id)
136 {
137 	kcf_provider_desc_t *prov_desc;
138 
139 	/*
140 	 * Validate provider id, since it can be specified by a 3rd-party
141 	 * provider.
142 	 */
143 
144 	mutex_enter(&prov_tab_mutex);
145 	if (prov_id >= KCF_MAX_PROVIDERS ||
146 	    ((prov_desc = prov_tab[prov_id]) == NULL)) {
147 		mutex_exit(&prov_tab_mutex);
148 		return (CRYPTO_INVALID_PROVIDER_ID);
149 	}
150 	mutex_exit(&prov_tab_mutex);
151 
152 	/*
153 	 * The provider id must remain valid until the associated provider
154 	 * descriptor is freed. For this reason, we simply release our
155 	 * reference to the descriptor here. When the reference count
156 	 * reaches zero, kcf_free_provider_desc() will be invoked and
157 	 * the associated entry in the providers table will be released
158 	 * at that time.
159 	 */
160 
161 	KCF_PROV_IREFRELE(prov_desc);
162 	KCF_PROV_REFRELE(prov_desc);
163 
164 	return (CRYPTO_SUCCESS);
165 }
166 
167 /*
168  * Returns the provider descriptor corresponding to the specified
169  * provider id. A REFHOLD is done on the descriptor before it is
170  * returned to the caller. It is the responsibility of the caller
171  * to do a REFRELE once it is done with the provider descriptor.
172  */
173 kcf_provider_desc_t *
kcf_prov_tab_lookup(crypto_provider_id_t prov_id)174 kcf_prov_tab_lookup(crypto_provider_id_t prov_id)
175 {
176 	kcf_provider_desc_t *prov_desc;
177 
178 	mutex_enter(&prov_tab_mutex);
179 
180 	prov_desc = prov_tab[prov_id];
181 
182 	if (prov_desc == NULL) {
183 		mutex_exit(&prov_tab_mutex);
184 		return (NULL);
185 	}
186 
187 	KCF_PROV_REFHOLD(prov_desc);
188 
189 	mutex_exit(&prov_tab_mutex);
190 
191 	return (prov_desc);
192 }
193 
194 /*
195  * Allocate a provider descriptor. mech_list_count specifies the
196  * number of mechanisms supported by the providers, and is used
197  * to allocate storage for the mechanism table.
198  * This function may sleep while allocating memory, which is OK
199  * since it is invoked from user context during provider registration.
200  */
201 kcf_provider_desc_t *
kcf_alloc_provider_desc(void)202 kcf_alloc_provider_desc(void)
203 {
204 	kcf_provider_desc_t *desc =
205 	    kmem_zalloc(sizeof (kcf_provider_desc_t), KM_SLEEP);
206 
207 	for (int i = 0; i < KCF_OPS_CLASSSIZE; i++)
208 		for (int j = 0; j < KCF_MAXMECHTAB; j++)
209 			desc->pd_mech_indx[i][j] = KCF_INVALID_INDX;
210 
211 	desc->pd_prov_id = KCF_PROVID_INVALID;
212 	desc->pd_state = KCF_PROV_ALLOCATED;
213 
214 	mutex_init(&desc->pd_lock, NULL, MUTEX_DEFAULT, NULL);
215 	cv_init(&desc->pd_remove_cv, NULL, CV_DEFAULT, NULL);
216 
217 	return (desc);
218 }
219 
220 /*
221  * Called by KCF_PROV_REFRELE when a provider's reference count drops
222  * to zero. We free the descriptor when the last reference is released.
223  * However, for providers, we do not free it when there is an
224  * unregister thread waiting. We signal that thread in this case and
225  * that thread is responsible for freeing the descriptor.
226  */
227 void
kcf_provider_zero_refcnt(kcf_provider_desc_t * desc)228 kcf_provider_zero_refcnt(kcf_provider_desc_t *desc)
229 {
230 	mutex_enter(&desc->pd_lock);
231 	if (desc->pd_state == KCF_PROV_REMOVED ||
232 	    desc->pd_state == KCF_PROV_DISABLED) {
233 		desc->pd_state = KCF_PROV_FREED;
234 		cv_broadcast(&desc->pd_remove_cv);
235 		mutex_exit(&desc->pd_lock);
236 		return;
237 	}
238 
239 	mutex_exit(&desc->pd_lock);
240 	kcf_free_provider_desc(desc);
241 }
242 
243 /*
244  * Free a provider descriptor.
245  */
246 void
kcf_free_provider_desc(kcf_provider_desc_t * desc)247 kcf_free_provider_desc(kcf_provider_desc_t *desc)
248 {
249 	if (desc == NULL)
250 		return;
251 
252 	mutex_enter(&prov_tab_mutex);
253 	if (desc->pd_prov_id != KCF_PROVID_INVALID) {
254 		/* release the associated providers table entry */
255 		ASSERT(prov_tab[desc->pd_prov_id] != NULL);
256 		prov_tab[desc->pd_prov_id] = NULL;
257 		prov_tab_num--;
258 	}
259 	mutex_exit(&prov_tab_mutex);
260 
261 	/* free the kernel memory associated with the provider descriptor */
262 
263 	mutex_destroy(&desc->pd_lock);
264 	cv_destroy(&desc->pd_remove_cv);
265 
266 	kmem_free(desc, sizeof (kcf_provider_desc_t));
267 }
268 
269 /*
270  * Returns in the location pointed to by pd a pointer to the descriptor
271  * for the provider for the specified mechanism.
272  * The provider descriptor is returned held and it is the caller's
273  * responsibility to release it when done. The mechanism entry
274  * is returned if the optional argument mep is non NULL.
275  *
276  * Returns one of the CRYPTO_ * error codes on failure, and
277  * CRYPTO_SUCCESS on success.
278  */
279 int
kcf_get_sw_prov(crypto_mech_type_t mech_type,kcf_provider_desc_t ** pd,kcf_mech_entry_t ** mep,boolean_t log_warn)280 kcf_get_sw_prov(crypto_mech_type_t mech_type, kcf_provider_desc_t **pd,
281     kcf_mech_entry_t **mep, boolean_t log_warn)
282 {
283 	kcf_mech_entry_t *me;
284 
285 	/* get the mechanism entry for this mechanism */
286 	if (kcf_get_mech_entry(mech_type, &me) != KCF_SUCCESS)
287 		return (CRYPTO_MECHANISM_INVALID);
288 
289 	/* Get the provider for this mechanism. */
290 	if (me->me_sw_prov == NULL ||
291 	    (*pd = me->me_sw_prov->pm_prov_desc) == NULL) {
292 		/* no provider for this mechanism */
293 		if (log_warn)
294 			cmn_err(CE_WARN, "no provider for \"%s\"\n",
295 			    me->me_name);
296 		return (CRYPTO_MECH_NOT_SUPPORTED);
297 	}
298 
299 	KCF_PROV_REFHOLD(*pd);
300 
301 	if (mep != NULL)
302 		*mep = me;
303 
304 	return (CRYPTO_SUCCESS);
305 }
306