xref: /freebsd/sys/contrib/openzfs/module/icp/core/kcf_mech_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 #include <sys/zfs_context.h>
28 #include <sys/crypto/common.h>
29 #include <sys/crypto/api.h>
30 #include <sys/crypto/impl.h>
31 
32 /* Cryptographic mechanisms tables and their access functions */
33 
34 /*
35  * Internal numbers assigned to mechanisms are coded as follows:
36  *
37  * +----------------+----------------+
38  * | mech. class    | mech. index    |
39  * <--- 32-bits --->+<--- 32-bits --->
40  *
41  * the mech_class identifies the table the mechanism belongs to.
42  * mech_index  is the index for that mechanism in the table.
43  * A mechanism belongs to exactly 1 table.
44  * The tables are:
45  * . cipher_mechs_tab[] for encrypt/decrypt and wrap/unwrap mechs.
46  * . mac_mechs_tab[] for MAC mechs.
47  * . sign_mechs_tab[] for sign & verify mechs.
48  * . keyops_mechs_tab[] for key/key pair generation, and key derivation.
49  * . misc_mechs_tab[] for mechs that don't belong to any of the above.
50  *
51  * There are no holes in the tables.
52  */
53 
54 /*
55  * Locking conventions:
56  * --------------------
57  * A mutex is associated with every entry of the tables.
58  * The mutex is acquired whenever the entry is accessed for
59  * 1) retrieving the mech_id (comparing the mech name)
60  * 2) finding a provider for an xxx_init() or atomic operation.
61  * 3) altering the mechs entry to add or remove a provider.
62  *
63  * In 2), after a provider is chosen, its prov_desc is held and the
64  * entry's mutex must be dropped. The provider's working function (SPI) is
65  * called outside the mech_entry's mutex.
66  *
67  * The number of providers for a particular mechanism is not expected to be
68  * long enough to justify the cost of using rwlocks, so the per-mechanism
69  * entry mutex won't be very *hot*.
70  *
71  */
72 
73 		/* Mechanisms tables */
74 
75 
76 /* RFE 4687834 Will deal with the extensibility of these tables later */
77 
78 static kcf_mech_entry_t kcf_cipher_mechs_tab[KCF_MAXCIPHER];
79 static kcf_mech_entry_t kcf_mac_mechs_tab[KCF_MAXMAC];
80 
81 const kcf_mech_entry_tab_t kcf_mech_tabs_tab[KCF_LAST_OPSCLASS + 1] = {
82 	{0, NULL},				/* No class zero */
83 	{KCF_MAXCIPHER, kcf_cipher_mechs_tab},
84 	{KCF_MAXMAC, kcf_mac_mechs_tab},
85 };
86 
87 static avl_tree_t kcf_mech_hash;
88 
89 static int
kcf_mech_hash_compar(const void * lhs,const void * rhs)90 kcf_mech_hash_compar(const void *lhs, const void *rhs)
91 {
92 	const kcf_mech_entry_t *l = lhs, *r = rhs;
93 	int cmp = strncmp(l->me_name, r->me_name, CRYPTO_MAX_MECH_NAME);
94 	return ((0 < cmp) - (cmp < 0));
95 }
96 
97 void
kcf_destroy_mech_tabs(void)98 kcf_destroy_mech_tabs(void)
99 {
100 	for (void *cookie = NULL; avl_destroy_nodes(&kcf_mech_hash, &cookie); )
101 		;
102 	avl_destroy(&kcf_mech_hash);
103 }
104 
105 /*
106  * kcf_init_mech_tabs()
107  *
108  * Called by the misc/kcf's _init() routine to initialize the tables
109  * of mech_entry's.
110  */
111 void
kcf_init_mech_tabs(void)112 kcf_init_mech_tabs(void)
113 {
114 	avl_create(&kcf_mech_hash, kcf_mech_hash_compar,
115 	    sizeof (kcf_mech_entry_t), offsetof(kcf_mech_entry_t, me_node));
116 }
117 
118 /*
119  * kcf_create_mech_entry()
120  *
121  * Arguments:
122  *	. The class of mechanism.
123  *	. the name of the new mechanism.
124  *
125  * Description:
126  *	Creates a new mech_entry for a mechanism not yet known to the
127  *	framework.
128  *	This routine is called by kcf_add_mech_provider, which is
129  *	in turn invoked for each mechanism supported by a provider.
130  *	The'class' argument depends on the crypto_func_group_t bitmask
131  *	in the registering provider's mech_info struct for this mechanism.
132  *	When there is ambiguity in the mapping between the crypto_func_group_t
133  *	and a class (dual ops, ...) the KCF_MISC_CLASS should be used.
134  *
135  * Context:
136  *	User context only.
137  *
138  * Returns:
139  *	KCF_INVALID_MECH_CLASS or KCF_INVALID_MECH_NAME if the class or
140  *	the mechname is bogus.
141  *	KCF_MECH_TAB_FULL when there is no room left in the mech. tabs.
142  *	KCF_SUCCESS otherwise.
143  */
144 static int
kcf_create_mech_entry(kcf_ops_class_t class,const char * mechname)145 kcf_create_mech_entry(kcf_ops_class_t class, const char *mechname)
146 {
147 	if ((class < KCF_FIRST_OPSCLASS) || (class > KCF_LAST_OPSCLASS))
148 		return (KCF_INVALID_MECH_CLASS);
149 
150 	if ((mechname == NULL) || (mechname[0] == 0))
151 		return (KCF_INVALID_MECH_NAME);
152 	/*
153 	 * First check if the mechanism is already in one of the tables.
154 	 * The mech_entry could be in another class.
155 	 */
156 	avl_index_t where = 0;
157 	kcf_mech_entry_t tmptab;
158 	strlcpy(tmptab.me_name, mechname, CRYPTO_MAX_MECH_NAME);
159 	if (avl_find(&kcf_mech_hash, &tmptab, &where) != NULL)
160 		return (KCF_SUCCESS);
161 	/* Now take the next unused mech entry in the class's tab */
162 	kcf_mech_entry_t *me_tab = kcf_mech_tabs_tab[class].met_tab;
163 	int size = kcf_mech_tabs_tab[class].met_size;
164 
165 	for (int i = 0; i < size; ++i)
166 		if (me_tab[i].me_name[0] == 0) {
167 			/* Found an empty spot */
168 			strlcpy(me_tab[i].me_name, mechname,
169 			    CRYPTO_MAX_MECH_NAME);
170 			me_tab[i].me_mechid = KCF_MECHID(class, i);
171 
172 			/* Add the new mechanism to the hash table */
173 			avl_insert(&kcf_mech_hash, &me_tab[i], where);
174 			return (KCF_SUCCESS);
175 		}
176 
177 	return (KCF_MECH_TAB_FULL);
178 }
179 
180 /*
181  * kcf_add_mech_provider()
182  *
183  * Arguments:
184  *	. An index in to  the provider mechanism array
185  *      . A pointer to the provider descriptor
186  *	. A storage for the kcf_prov_mech_desc_t the entry was added at.
187  *
188  * Description:
189  *      Adds  a new provider of a mechanism to the mechanism's mech_entry
190  *	chain.
191  *
192  * Context:
193  *      User context only.
194  *
195  * Returns
196  *      KCF_SUCCESS on success
197  *      KCF_MECH_TAB_FULL otherwise.
198  */
199 int
kcf_add_mech_provider(short mech_indx,kcf_provider_desc_t * prov_desc,kcf_prov_mech_desc_t ** pmdpp)200 kcf_add_mech_provider(short mech_indx,
201     kcf_provider_desc_t *prov_desc, kcf_prov_mech_desc_t **pmdpp)
202 {
203 	int error;
204 	kcf_mech_entry_t *mech_entry = NULL;
205 	const crypto_mech_info_t *mech_info;
206 	crypto_mech_type_t kcf_mech_type;
207 	kcf_prov_mech_desc_t *prov_mech;
208 
209 	mech_info = &prov_desc->pd_mechanisms[mech_indx];
210 
211 	/*
212 	 * A mechanism belongs to exactly one mechanism table.
213 	 * Find the class corresponding to the function group flag of
214 	 * the mechanism.
215 	 */
216 	kcf_mech_type = crypto_mech2id(mech_info->cm_mech_name);
217 	if (kcf_mech_type == CRYPTO_MECH_INVALID) {
218 		crypto_func_group_t fg = mech_info->cm_func_group_mask;
219 		kcf_ops_class_t class;
220 
221 		if (fg & CRYPTO_FG_ENCRYPT_ATOMIC ||
222 		    fg & CRYPTO_FG_DECRYPT_ATOMIC)
223 			class = KCF_CIPHER_CLASS;
224 		else if (fg & CRYPTO_FG_MAC || fg & CRYPTO_FG_MAC_ATOMIC)
225 			class = KCF_MAC_CLASS;
226 		else
227 			__builtin_unreachable();
228 
229 		/*
230 		 * Attempt to create a new mech_entry for the specified
231 		 * mechanism. kcf_create_mech_entry() can handle the case
232 		 * where such an entry already exists.
233 		 */
234 		if ((error = kcf_create_mech_entry(class,
235 		    mech_info->cm_mech_name)) != KCF_SUCCESS) {
236 			return (error);
237 		}
238 		/* get the KCF mech type that was assigned to the mechanism */
239 		kcf_mech_type = crypto_mech2id(mech_info->cm_mech_name);
240 		ASSERT(kcf_mech_type != CRYPTO_MECH_INVALID);
241 	}
242 
243 	error = kcf_get_mech_entry(kcf_mech_type, &mech_entry);
244 	ASSERT(error == KCF_SUCCESS);
245 
246 	/* allocate and initialize new kcf_prov_mech_desc */
247 	prov_mech = kmem_zalloc(sizeof (kcf_prov_mech_desc_t), KM_SLEEP);
248 	memcpy(&prov_mech->pm_mech_info, mech_info,
249 	    sizeof (crypto_mech_info_t));
250 	prov_mech->pm_prov_desc = prov_desc;
251 	prov_desc->pd_mech_indx[KCF_MECH2CLASS(kcf_mech_type)]
252 	    [KCF_MECH2INDEX(kcf_mech_type)] = mech_indx;
253 
254 	KCF_PROV_REFHOLD(prov_desc);
255 	KCF_PROV_IREFHOLD(prov_desc);
256 
257 	/*
258 	 * Add new kcf_prov_mech_desc at the front of HW providers
259 	 * chain.
260 	 */
261 	if (mech_entry->me_sw_prov != NULL) {
262 		/*
263 		 * There is already a provider for this mechanism.
264 		 * Since we allow only one provider per mechanism,
265 		 * report this condition.
266 		 */
267 		cmn_err(CE_WARN, "The cryptographic provider "
268 		    "\"%s\" will not be used for %s. The provider "
269 		    "\"%s\" will be used for this mechanism "
270 		    "instead.", prov_desc->pd_description,
271 		    mech_info->cm_mech_name,
272 		    mech_entry->me_sw_prov->pm_prov_desc->
273 		    pd_description);
274 		KCF_PROV_REFRELE(prov_desc);
275 		kmem_free(prov_mech, sizeof (kcf_prov_mech_desc_t));
276 		prov_mech = NULL;
277 	} else {
278 		/*
279 		 * Set the provider as the provider for
280 		 * this mechanism.
281 		 */
282 		mech_entry->me_sw_prov = prov_mech;
283 	}
284 
285 	*pmdpp = prov_mech;
286 
287 	return (KCF_SUCCESS);
288 }
289 
290 /*
291  * kcf_remove_mech_provider()
292  *
293  * Arguments:
294  *      . mech_name: the name of the mechanism.
295  *      . prov_desc: The provider descriptor
296  *
297  * Description:
298  *      Removes a provider from chain of provider descriptors.
299  *	The provider is made unavailable to kernel consumers for the specified
300  *	mechanism.
301  *
302  * Context:
303  *      User context only.
304  */
305 void
kcf_remove_mech_provider(const char * mech_name,kcf_provider_desc_t * prov_desc)306 kcf_remove_mech_provider(const char *mech_name, kcf_provider_desc_t *prov_desc)
307 {
308 	crypto_mech_type_t mech_type;
309 	kcf_prov_mech_desc_t *prov_mech = NULL;
310 	kcf_mech_entry_t *mech_entry;
311 
312 	/* get the KCF mech type that was assigned to the mechanism */
313 	if ((mech_type = crypto_mech2id(mech_name)) ==
314 	    CRYPTO_MECH_INVALID) {
315 		/*
316 		 * Provider was not allowed for this mech due to policy or
317 		 * configuration.
318 		 */
319 		return;
320 	}
321 
322 	/* get a ptr to the mech_entry that was created */
323 	if (kcf_get_mech_entry(mech_type, &mech_entry) != KCF_SUCCESS) {
324 		/*
325 		 * Provider was not allowed for this mech due to policy or
326 		 * configuration.
327 		 */
328 		return;
329 	}
330 
331 	if (mech_entry->me_sw_prov == NULL ||
332 	    mech_entry->me_sw_prov->pm_prov_desc != prov_desc) {
333 		/* not the provider for this mechanism */
334 		return;
335 	}
336 	prov_mech = mech_entry->me_sw_prov;
337 	mech_entry->me_sw_prov = NULL;
338 
339 	/* free entry  */
340 	KCF_PROV_IREFRELE(prov_mech->pm_prov_desc);
341 	KCF_PROV_REFRELE(prov_mech->pm_prov_desc);
342 	kmem_free(prov_mech, sizeof (kcf_prov_mech_desc_t));
343 }
344 
345 /*
346  * kcf_get_mech_entry()
347  *
348  * Arguments:
349  *      . The framework mechanism type
350  *      . Storage for the mechanism entry
351  *
352  * Description:
353  *      Retrieves the mechanism entry for the mech.
354  *
355  * Context:
356  *      User and interrupt contexts.
357  *
358  * Returns:
359  *      KCF_MECHANISM_XXX appropriate error code.
360  *      KCF_SUCCESS otherwise.
361  */
362 int
kcf_get_mech_entry(crypto_mech_type_t mech_type,kcf_mech_entry_t ** mep)363 kcf_get_mech_entry(crypto_mech_type_t mech_type, kcf_mech_entry_t **mep)
364 {
365 	kcf_ops_class_t		class;
366 	int			index;
367 	const kcf_mech_entry_tab_t	*me_tab;
368 
369 	ASSERT(mep != NULL);
370 
371 	class = KCF_MECH2CLASS(mech_type);
372 
373 	if ((class < KCF_FIRST_OPSCLASS) || (class > KCF_LAST_OPSCLASS)) {
374 		/* the caller won't need to know it's an invalid class */
375 		return (KCF_INVALID_MECH_NUMBER);
376 	}
377 
378 	me_tab = &kcf_mech_tabs_tab[class];
379 	index = KCF_MECH2INDEX(mech_type);
380 
381 	if ((index < 0) || (index >= me_tab->met_size)) {
382 		return (KCF_INVALID_MECH_NUMBER);
383 	}
384 
385 	*mep = &((me_tab->met_tab)[index]);
386 
387 	return (KCF_SUCCESS);
388 }
389 
390 /*
391  * crypto_mech2id()
392  *
393  * Arguments:
394  *	. mechname: A null-terminated string identifying the mechanism name.
395  *
396  * Description:
397  *	Walks the mechanisms tables, looking for an entry that matches the
398  *	mechname. Once it find it, it builds the 64-bit mech_type and returns
399  *	it.
400  *
401  * Context:
402  *	Process and interruption.
403  *
404  * Returns:
405  *	The unique mechanism identified by 'mechname', if found.
406  *	CRYPTO_MECH_INVALID otherwise.
407  */
408 /*
409  * Lookup the hash table for an entry that matches the mechname.
410  * If there are no providers for the mechanism,
411  * but there is an unloaded provider, this routine will attempt
412  * to load it.
413  */
414 crypto_mech_type_t
crypto_mech2id(const char * mechname)415 crypto_mech2id(const char *mechname)
416 {
417 	kcf_mech_entry_t tmptab, *found;
418 	strlcpy(tmptab.me_name, mechname, CRYPTO_MAX_MECH_NAME);
419 
420 	if ((found = avl_find(&kcf_mech_hash, &tmptab, NULL))) {
421 		ASSERT(found->me_mechid != CRYPTO_MECH_INVALID);
422 		return (found->me_mechid);
423 	}
424 
425 	return (CRYPTO_MECH_INVALID);
426 }
427 
428 #if defined(_KERNEL)
429 EXPORT_SYMBOL(crypto_mech2id);
430 #endif
431