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