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 * . digest_mechs_tab[] for the msg digest mechs.
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.
51 * There are no holes in the tables.
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.
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.
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*.
73 /* Mechanisms tables */
76 /* RFE 4687834 Will deal with the extensibility of these tables later */
78 static kcf_mech_entry_t kcf_digest_mechs_tab
[KCF_MAXDIGEST
];
79 static kcf_mech_entry_t kcf_cipher_mechs_tab
[KCF_MAXCIPHER
];
80 static kcf_mech_entry_t kcf_mac_mechs_tab
[KCF_MAXMAC
];
82 const kcf_mech_entry_tab_t kcf_mech_tabs_tab
[KCF_LAST_OPSCLASS
+ 1] = {
83 {0, NULL
}, /* No class zero */
84 {KCF_MAXDIGEST
, kcf_digest_mechs_tab
},
85 {KCF_MAXCIPHER
, kcf_cipher_mechs_tab
},
86 {KCF_MAXMAC
, kcf_mac_mechs_tab
},
89 static avl_tree_t kcf_mech_hash
;
92 kcf_mech_hash_compar(const void *lhs
, const void *rhs
)
94 const kcf_mech_entry_t
*l
= lhs
, *r
= rhs
;
95 int cmp
= strncmp(l
->me_name
, r
->me_name
, CRYPTO_MAX_MECH_NAME
);
96 return ((0 < cmp
) - (cmp
< 0));
100 kcf_destroy_mech_tabs(void)
102 for (void *cookie
= NULL
; avl_destroy_nodes(&kcf_mech_hash
, &cookie
); )
104 avl_destroy(&kcf_mech_hash
);
108 * kcf_init_mech_tabs()
110 * Called by the misc/kcf's _init() routine to initialize the tables
114 kcf_init_mech_tabs(void)
116 avl_create(&kcf_mech_hash
, kcf_mech_hash_compar
,
117 sizeof (kcf_mech_entry_t
), offsetof(kcf_mech_entry_t
, me_node
));
121 * kcf_create_mech_entry()
124 * . The class of mechanism.
125 * . the name of the new mechanism.
128 * Creates a new mech_entry for a mechanism not yet known to the
130 * This routine is called by kcf_add_mech_provider, which is
131 * in turn invoked for each mechanism supported by a provider.
132 * The'class' argument depends on the crypto_func_group_t bitmask
133 * in the registering provider's mech_info struct for this mechanism.
134 * When there is ambiguity in the mapping between the crypto_func_group_t
135 * and a class (dual ops, ...) the KCF_MISC_CLASS should be used.
141 * KCF_INVALID_MECH_CLASS or KCF_INVALID_MECH_NAME if the class or
142 * the mechname is bogus.
143 * KCF_MECH_TAB_FULL when there is no room left in the mech. tabs.
144 * KCF_SUCCESS otherwise.
147 kcf_create_mech_entry(kcf_ops_class_t
class, const char *mechname
)
149 if ((class < KCF_FIRST_OPSCLASS
) || (class > KCF_LAST_OPSCLASS
))
150 return (KCF_INVALID_MECH_CLASS
);
152 if ((mechname
== NULL
) || (mechname
[0] == 0))
153 return (KCF_INVALID_MECH_NAME
);
155 * First check if the mechanism is already in one of the tables.
156 * The mech_entry could be in another class.
158 avl_index_t where
= 0;
159 kcf_mech_entry_t tmptab
;
160 strlcpy(tmptab
.me_name
, mechname
, CRYPTO_MAX_MECH_NAME
);
161 if (avl_find(&kcf_mech_hash
, &tmptab
, &where
) != NULL
)
162 return (KCF_SUCCESS
);
163 /* Now take the next unused mech entry in the class's tab */
164 kcf_mech_entry_t
*me_tab
= kcf_mech_tabs_tab
[class].met_tab
;
165 int size
= kcf_mech_tabs_tab
[class].met_size
;
167 for (int i
= 0; i
< size
; ++i
)
168 if (me_tab
[i
].me_name
[0] == 0) {
169 /* Found an empty spot */
170 strlcpy(me_tab
[i
].me_name
, mechname
,
171 CRYPTO_MAX_MECH_NAME
);
172 me_tab
[i
].me_mechid
= KCF_MECHID(class, i
);
174 /* Add the new mechanism to the hash table */
175 avl_insert(&kcf_mech_hash
, &me_tab
[i
], where
);
176 return (KCF_SUCCESS
);
179 return (KCF_MECH_TAB_FULL
);
183 * kcf_add_mech_provider()
186 * . An index in to the provider mechanism array
187 * . A pointer to the provider descriptor
188 * . A storage for the kcf_prov_mech_desc_t the entry was added at.
191 * Adds a new provider of a mechanism to the mechanism's mech_entry
198 * KCF_SUCCESS on success
199 * KCF_MECH_TAB_FULL otherwise.
202 kcf_add_mech_provider(short mech_indx
,
203 kcf_provider_desc_t
*prov_desc
, kcf_prov_mech_desc_t
**pmdpp
)
206 kcf_mech_entry_t
*mech_entry
= NULL
;
207 const crypto_mech_info_t
*mech_info
;
208 crypto_mech_type_t kcf_mech_type
;
209 kcf_prov_mech_desc_t
*prov_mech
;
211 mech_info
= &prov_desc
->pd_mechanisms
[mech_indx
];
214 * A mechanism belongs to exactly one mechanism table.
215 * Find the class corresponding to the function group flag of
218 kcf_mech_type
= crypto_mech2id(mech_info
->cm_mech_name
);
219 if (kcf_mech_type
== CRYPTO_MECH_INVALID
) {
220 crypto_func_group_t fg
= mech_info
->cm_func_group_mask
;
221 kcf_ops_class_t
class;
223 if (fg
& CRYPTO_FG_DIGEST
|| fg
& CRYPTO_FG_DIGEST_ATOMIC
)
224 class = KCF_DIGEST_CLASS
;
225 else if (fg
& CRYPTO_FG_ENCRYPT
|| fg
& CRYPTO_FG_DECRYPT
||
226 fg
& CRYPTO_FG_ENCRYPT_ATOMIC
||
227 fg
& CRYPTO_FG_DECRYPT_ATOMIC
)
228 class = KCF_CIPHER_CLASS
;
229 else if (fg
& CRYPTO_FG_MAC
|| fg
& CRYPTO_FG_MAC_ATOMIC
)
230 class = KCF_MAC_CLASS
;
232 __builtin_unreachable();
235 * Attempt to create a new mech_entry for the specified
236 * mechanism. kcf_create_mech_entry() can handle the case
237 * where such an entry already exists.
239 if ((error
= kcf_create_mech_entry(class,
240 mech_info
->cm_mech_name
)) != KCF_SUCCESS
) {
243 /* get the KCF mech type that was assigned to the mechanism */
244 kcf_mech_type
= crypto_mech2id(mech_info
->cm_mech_name
);
245 ASSERT(kcf_mech_type
!= CRYPTO_MECH_INVALID
);
248 error
= kcf_get_mech_entry(kcf_mech_type
, &mech_entry
);
249 ASSERT(error
== KCF_SUCCESS
);
251 /* allocate and initialize new kcf_prov_mech_desc */
252 prov_mech
= kmem_zalloc(sizeof (kcf_prov_mech_desc_t
), KM_SLEEP
);
253 memcpy(&prov_mech
->pm_mech_info
, mech_info
,
254 sizeof (crypto_mech_info_t
));
255 prov_mech
->pm_prov_desc
= prov_desc
;
256 prov_desc
->pd_mech_indx
[KCF_MECH2CLASS(kcf_mech_type
)]
257 [KCF_MECH2INDEX(kcf_mech_type
)] = mech_indx
;
259 KCF_PROV_REFHOLD(prov_desc
);
260 KCF_PROV_IREFHOLD(prov_desc
);
263 * Add new kcf_prov_mech_desc at the front of HW providers
266 if (mech_entry
->me_sw_prov
!= NULL
) {
268 * There is already a provider for this mechanism.
269 * Since we allow only one provider per mechanism,
270 * report this condition.
272 cmn_err(CE_WARN
, "The cryptographic provider "
273 "\"%s\" will not be used for %s. The provider "
274 "\"%s\" will be used for this mechanism "
275 "instead.", prov_desc
->pd_description
,
276 mech_info
->cm_mech_name
,
277 mech_entry
->me_sw_prov
->pm_prov_desc
->
279 KCF_PROV_REFRELE(prov_desc
);
280 kmem_free(prov_mech
, sizeof (kcf_prov_mech_desc_t
));
284 * Set the provider as the provider for
287 mech_entry
->me_sw_prov
= prov_mech
;
292 return (KCF_SUCCESS
);
296 * kcf_remove_mech_provider()
299 * . mech_name: the name of the mechanism.
300 * . prov_desc: The provider descriptor
303 * Removes a provider from chain of provider descriptors.
304 * The provider is made unavailable to kernel consumers for the specified
311 kcf_remove_mech_provider(const char *mech_name
, kcf_provider_desc_t
*prov_desc
)
313 crypto_mech_type_t mech_type
;
314 kcf_prov_mech_desc_t
*prov_mech
= NULL
;
315 kcf_mech_entry_t
*mech_entry
;
317 /* get the KCF mech type that was assigned to the mechanism */
318 if ((mech_type
= crypto_mech2id(mech_name
)) ==
319 CRYPTO_MECH_INVALID
) {
321 * Provider was not allowed for this mech due to policy or
327 /* get a ptr to the mech_entry that was created */
328 if (kcf_get_mech_entry(mech_type
, &mech_entry
) != KCF_SUCCESS
) {
330 * Provider was not allowed for this mech due to policy or
336 if (mech_entry
->me_sw_prov
== NULL
||
337 mech_entry
->me_sw_prov
->pm_prov_desc
!= prov_desc
) {
338 /* not the provider for this mechanism */
341 prov_mech
= mech_entry
->me_sw_prov
;
342 mech_entry
->me_sw_prov
= NULL
;
345 KCF_PROV_IREFRELE(prov_mech
->pm_prov_desc
);
346 KCF_PROV_REFRELE(prov_mech
->pm_prov_desc
);
347 kmem_free(prov_mech
, sizeof (kcf_prov_mech_desc_t
));
351 * kcf_get_mech_entry()
354 * . The framework mechanism type
355 * . Storage for the mechanism entry
358 * Retrieves the mechanism entry for the mech.
361 * User and interrupt contexts.
364 * KCF_MECHANISM_XXX appropriate error code.
365 * KCF_SUCCESS otherwise.
368 kcf_get_mech_entry(crypto_mech_type_t mech_type
, kcf_mech_entry_t
**mep
)
370 kcf_ops_class_t
class;
372 const kcf_mech_entry_tab_t
*me_tab
;
376 class = KCF_MECH2CLASS(mech_type
);
378 if ((class < KCF_FIRST_OPSCLASS
) || (class > KCF_LAST_OPSCLASS
)) {
379 /* the caller won't need to know it's an invalid class */
380 return (KCF_INVALID_MECH_NUMBER
);
383 me_tab
= &kcf_mech_tabs_tab
[class];
384 index
= KCF_MECH2INDEX(mech_type
);
386 if ((index
< 0) || (index
>= me_tab
->met_size
)) {
387 return (KCF_INVALID_MECH_NUMBER
);
390 *mep
= &((me_tab
->met_tab
)[index
]);
392 return (KCF_SUCCESS
);
399 * . mechname: A null-terminated string identifying the mechanism name.
402 * Walks the mechanisms tables, looking for an entry that matches the
403 * mechname. Once it find it, it builds the 64-bit mech_type and returns
407 * Process and interruption.
410 * The unique mechanism identified by 'mechname', if found.
411 * CRYPTO_MECH_INVALID otherwise.
414 * Lookup the hash table for an entry that matches the mechname.
415 * If there are no providers for the mechanism,
416 * but there is an unloaded provider, this routine will attempt
420 crypto_mech2id(const char *mechname
)
422 kcf_mech_entry_t tmptab
, *found
;
423 strlcpy(tmptab
.me_name
, mechname
, CRYPTO_MAX_MECH_NAME
);
425 if ((found
= avl_find(&kcf_mech_hash
, &tmptab
, NULL
))) {
426 ASSERT(found
->me_mechid
!= CRYPTO_MECH_INVALID
);
427 return (found
->me_mechid
);
430 return (CRYPTO_MECH_INVALID
);
434 EXPORT_SYMBOL(crypto_mech2id
);