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