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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/zfs_context.h>
27 #include <sys/crypto/common.h>
28 #include <sys/crypto/api.h>
29 #include <sys/crypto/impl.h>
31 /* Cryptographic mechanisms tables and their access functions */
34 * Internal numbers assigned to mechanisms are coded as follows:
36 * +----------------+----------------+
37 * | mech. class | mech. index |
38 * <--- 32-bits --->+<--- 32-bits --->
40 * the mech_class identifies the table the mechanism belongs to.
41 * mech_index is the index for that mechanism in the table.
42 * A mechanism belongs to exactly 1 table.
44 * . cipher_mechs_tab[] for encrypt/decrypt and wrap/unwrap mechs.
45 * . mac_mechs_tab[] for MAC mechs.
46 * . sign_mechs_tab[] for sign & verify mechs.
47 * . keyops_mechs_tab[] for key/key pair generation, and key derivation.
48 * . misc_mechs_tab[] for mechs that don't belong to any of the above.
50 * There are no holes in the tables.
54 * Locking conventions:
55 * --------------------
56 * A mutex is associated with every entry of the tables.
57 * The mutex is acquired whenever the entry is accessed for
58 * 1) retrieving the mech_id (comparing the mech name)
59 * 2) finding a provider for an xxx_init() or atomic operation.
60 * 3) altering the mechs entry to add or remove a provider.
62 * In 2), after a provider is chosen, its prov_desc is held and the
63 * entry's mutex must be dropped. The provider's working function (SPI) is
64 * called outside the mech_entry's mutex.
66 * The number of providers for a particular mechanism is not expected to be
67 * long enough to justify the cost of using rwlocks, so the per-mechanism
68 * entry mutex won't be very *hot*.
72 /* Mechanisms tables */
75 /* RFE 4687834 Will deal with the extensibility of these tables later */
77 static kcf_mech_entry_t kcf_cipher_mechs_tab
[KCF_MAXCIPHER
];
78 static kcf_mech_entry_t kcf_mac_mechs_tab
[KCF_MAXMAC
];
80 const kcf_mech_entry_tab_t kcf_mech_tabs_tab
[KCF_LAST_OPSCLASS
+ 1] = {
81 {0, NULL
}, /* No class zero */
82 {KCF_MAXCIPHER
, kcf_cipher_mechs_tab
},
83 {KCF_MAXMAC
, kcf_mac_mechs_tab
},
86 static avl_tree_t kcf_mech_hash
;
89 kcf_mech_hash_compar(const void *lhs
, const void *rhs
)
91 const kcf_mech_entry_t
*l
= lhs
, *r
= rhs
;
92 int cmp
= strncmp(l
->me_name
, r
->me_name
, CRYPTO_MAX_MECH_NAME
);
93 return ((0 < cmp
) - (cmp
< 0));
97 kcf_destroy_mech_tabs(void)
99 for (void *cookie
= NULL
; avl_destroy_nodes(&kcf_mech_hash
, &cookie
); )
101 avl_destroy(&kcf_mech_hash
);
105 * kcf_init_mech_tabs()
107 * Called by the misc/kcf's _init() routine to initialize the tables
111 kcf_init_mech_tabs(void)
113 avl_create(&kcf_mech_hash
, kcf_mech_hash_compar
,
114 sizeof (kcf_mech_entry_t
), offsetof(kcf_mech_entry_t
, me_node
));
118 * kcf_create_mech_entry()
121 * . The class of mechanism.
122 * . the name of the new mechanism.
125 * Creates a new mech_entry for a mechanism not yet known to the
127 * This routine is called by kcf_add_mech_provider, which is
128 * in turn invoked for each mechanism supported by a provider.
129 * The'class' argument depends on the crypto_func_group_t bitmask
130 * in the registering provider's mech_info struct for this mechanism.
131 * When there is ambiguity in the mapping between the crypto_func_group_t
132 * and a class (dual ops, ...) the KCF_MISC_CLASS should be used.
138 * KCF_INVALID_MECH_CLASS or KCF_INVALID_MECH_NAME if the class or
139 * the mechname is bogus.
140 * KCF_MECH_TAB_FULL when there is no room left in the mech. tabs.
141 * KCF_SUCCESS otherwise.
144 kcf_create_mech_entry(kcf_ops_class_t
class, const char *mechname
)
146 if ((class < KCF_FIRST_OPSCLASS
) || (class > KCF_LAST_OPSCLASS
))
147 return (KCF_INVALID_MECH_CLASS
);
149 if ((mechname
== NULL
) || (mechname
[0] == 0))
150 return (KCF_INVALID_MECH_NAME
);
152 * First check if the mechanism is already in one of the tables.
153 * The mech_entry could be in another class.
155 avl_index_t where
= 0;
156 kcf_mech_entry_t tmptab
;
157 strlcpy(tmptab
.me_name
, mechname
, CRYPTO_MAX_MECH_NAME
);
158 if (avl_find(&kcf_mech_hash
, &tmptab
, &where
) != NULL
)
159 return (KCF_SUCCESS
);
160 /* Now take the next unused mech entry in the class's tab */
161 kcf_mech_entry_t
*me_tab
= kcf_mech_tabs_tab
[class].met_tab
;
162 int size
= kcf_mech_tabs_tab
[class].met_size
;
164 for (int i
= 0; i
< size
; ++i
)
165 if (me_tab
[i
].me_name
[0] == 0) {
166 /* Found an empty spot */
167 strlcpy(me_tab
[i
].me_name
, mechname
,
168 CRYPTO_MAX_MECH_NAME
);
169 me_tab
[i
].me_mechid
= KCF_MECHID(class, i
);
171 /* Add the new mechanism to the hash table */
172 avl_insert(&kcf_mech_hash
, &me_tab
[i
], where
);
173 return (KCF_SUCCESS
);
176 return (KCF_MECH_TAB_FULL
);
180 * kcf_add_mech_provider()
183 * . An index in to the provider mechanism array
184 * . A pointer to the provider descriptor
185 * . A storage for the kcf_prov_mech_desc_t the entry was added at.
188 * Adds a new provider of a mechanism to the mechanism's mech_entry
195 * KCF_SUCCESS on success
196 * KCF_MECH_TAB_FULL otherwise.
199 kcf_add_mech_provider(short mech_indx
,
200 kcf_provider_desc_t
*prov_desc
, kcf_prov_mech_desc_t
**pmdpp
)
203 kcf_mech_entry_t
*mech_entry
= NULL
;
204 const crypto_mech_info_t
*mech_info
;
205 crypto_mech_type_t kcf_mech_type
;
206 kcf_prov_mech_desc_t
*prov_mech
;
208 mech_info
= &prov_desc
->pd_mechanisms
[mech_indx
];
211 * A mechanism belongs to exactly one mechanism table.
212 * Find the class corresponding to the function group flag of
215 kcf_mech_type
= crypto_mech2id(mech_info
->cm_mech_name
);
216 if (kcf_mech_type
== CRYPTO_MECH_INVALID
) {
217 crypto_func_group_t fg
= mech_info
->cm_func_group_mask
;
218 kcf_ops_class_t
class;
220 if (fg
& CRYPTO_FG_ENCRYPT_ATOMIC
||
221 fg
& CRYPTO_FG_DECRYPT_ATOMIC
)
222 class = KCF_CIPHER_CLASS
;
223 else if (fg
& CRYPTO_FG_MAC
|| fg
& CRYPTO_FG_MAC_ATOMIC
)
224 class = KCF_MAC_CLASS
;
226 __builtin_unreachable();
229 * Attempt to create a new mech_entry for the specified
230 * mechanism. kcf_create_mech_entry() can handle the case
231 * where such an entry already exists.
233 if ((error
= kcf_create_mech_entry(class,
234 mech_info
->cm_mech_name
)) != KCF_SUCCESS
) {
237 /* get the KCF mech type that was assigned to the mechanism */
238 kcf_mech_type
= crypto_mech2id(mech_info
->cm_mech_name
);
239 ASSERT(kcf_mech_type
!= CRYPTO_MECH_INVALID
);
242 error
= kcf_get_mech_entry(kcf_mech_type
, &mech_entry
);
243 ASSERT(error
== KCF_SUCCESS
);
245 /* allocate and initialize new kcf_prov_mech_desc */
246 prov_mech
= kmem_zalloc(sizeof (kcf_prov_mech_desc_t
), KM_SLEEP
);
247 memcpy(&prov_mech
->pm_mech_info
, mech_info
,
248 sizeof (crypto_mech_info_t
));
249 prov_mech
->pm_prov_desc
= prov_desc
;
250 prov_desc
->pd_mech_indx
[KCF_MECH2CLASS(kcf_mech_type
)]
251 [KCF_MECH2INDEX(kcf_mech_type
)] = mech_indx
;
253 KCF_PROV_REFHOLD(prov_desc
);
254 KCF_PROV_IREFHOLD(prov_desc
);
257 * Add new kcf_prov_mech_desc at the front of HW providers
260 if (mech_entry
->me_sw_prov
!= NULL
) {
262 * There is already a provider for this mechanism.
263 * Since we allow only one provider per mechanism,
264 * report this condition.
266 cmn_err(CE_WARN
, "The cryptographic provider "
267 "\"%s\" will not be used for %s. The provider "
268 "\"%s\" will be used for this mechanism "
269 "instead.", prov_desc
->pd_description
,
270 mech_info
->cm_mech_name
,
271 mech_entry
->me_sw_prov
->pm_prov_desc
->
273 KCF_PROV_REFRELE(prov_desc
);
274 kmem_free(prov_mech
, sizeof (kcf_prov_mech_desc_t
));
278 * Set the provider as the provider for
281 mech_entry
->me_sw_prov
= prov_mech
;
286 return (KCF_SUCCESS
);
290 * kcf_remove_mech_provider()
293 * . mech_name: the name of the mechanism.
294 * . prov_desc: The provider descriptor
297 * Removes a provider from chain of provider descriptors.
298 * The provider is made unavailable to kernel consumers for the specified
305 kcf_remove_mech_provider(const char *mech_name
, kcf_provider_desc_t
*prov_desc
)
307 crypto_mech_type_t mech_type
;
308 kcf_prov_mech_desc_t
*prov_mech
= NULL
;
309 kcf_mech_entry_t
*mech_entry
;
311 /* get the KCF mech type that was assigned to the mechanism */
312 if ((mech_type
= crypto_mech2id(mech_name
)) ==
313 CRYPTO_MECH_INVALID
) {
315 * Provider was not allowed for this mech due to policy or
321 /* get a ptr to the mech_entry that was created */
322 if (kcf_get_mech_entry(mech_type
, &mech_entry
) != KCF_SUCCESS
) {
324 * Provider was not allowed for this mech due to policy or
330 if (mech_entry
->me_sw_prov
== NULL
||
331 mech_entry
->me_sw_prov
->pm_prov_desc
!= prov_desc
) {
332 /* not the provider for this mechanism */
335 prov_mech
= mech_entry
->me_sw_prov
;
336 mech_entry
->me_sw_prov
= NULL
;
339 KCF_PROV_IREFRELE(prov_mech
->pm_prov_desc
);
340 KCF_PROV_REFRELE(prov_mech
->pm_prov_desc
);
341 kmem_free(prov_mech
, sizeof (kcf_prov_mech_desc_t
));
345 * kcf_get_mech_entry()
348 * . The framework mechanism type
349 * . Storage for the mechanism entry
352 * Retrieves the mechanism entry for the mech.
355 * User and interrupt contexts.
358 * KCF_MECHANISM_XXX appropriate error code.
359 * KCF_SUCCESS otherwise.
362 kcf_get_mech_entry(crypto_mech_type_t mech_type
, kcf_mech_entry_t
**mep
)
364 kcf_ops_class_t
class;
366 const kcf_mech_entry_tab_t
*me_tab
;
370 class = KCF_MECH2CLASS(mech_type
);
372 if ((class < KCF_FIRST_OPSCLASS
) || (class > KCF_LAST_OPSCLASS
)) {
373 /* the caller won't need to know it's an invalid class */
374 return (KCF_INVALID_MECH_NUMBER
);
377 me_tab
= &kcf_mech_tabs_tab
[class];
378 index
= KCF_MECH2INDEX(mech_type
);
380 if ((index
< 0) || (index
>= me_tab
->met_size
)) {
381 return (KCF_INVALID_MECH_NUMBER
);
384 *mep
= &((me_tab
->met_tab
)[index
]);
386 return (KCF_SUCCESS
);
393 * . mechname: A null-terminated string identifying the mechanism name.
396 * Walks the mechanisms tables, looking for an entry that matches the
397 * mechname. Once it find it, it builds the 64-bit mech_type and returns
401 * Process and interruption.
404 * The unique mechanism identified by 'mechname', if found.
405 * CRYPTO_MECH_INVALID otherwise.
408 * Lookup the hash table for an entry that matches the mechname.
409 * If there are no providers for the mechanism,
410 * but there is an unloaded provider, this routine will attempt
414 crypto_mech2id(const char *mechname
)
416 kcf_mech_entry_t tmptab
, *found
;
417 strlcpy(tmptab
.me_name
, mechname
, CRYPTO_MAX_MECH_NAME
);
419 if ((found
= avl_find(&kcf_mech_hash
, &tmptab
, NULL
))) {
420 ASSERT(found
->me_mechid
!= CRYPTO_MECH_INVALID
);
421 return (found
->me_mechid
);
424 return (CRYPTO_MECH_INVALID
);
428 EXPORT_SYMBOL(crypto_mech2id
);