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 http://www.opensolaris.org/os/licensing.
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>
30 #include <sys/modhash.h>
32 /* Cryptographic mechanisms tables and their access functions */
35 * Internal numbers assigned to mechanisms are coded as follows:
37 * +----------------+----------------+
38 * | mech. class | mech. index |
39 * <--- 32-bits --->+<--- 32-bits --->
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.
45 * . digest_mechs_tab[] for the msg digest mechs.
46 * . cipher_mechs_tab[] for encrypt/decrypt and wrap/unwrap mechs.
47 * . mac_mechs_tab[] for MAC mechs.
48 * . sign_mechs_tab[] for sign & verify mechs.
49 * . keyops_mechs_tab[] for key/key pair generation, and key derivation.
50 * . misc_mechs_tab[] for mechs that don't belong to any of the above.
52 * There are no holes in the tables.
56 * Locking conventions:
57 * --------------------
58 * A global mutex, kcf_mech_tabs_lock, serializes writes to the
59 * mechanism table via kcf_create_mech_entry().
61 * A mutex is associated with every entry of the tables.
62 * The mutex is acquired whenever the entry is accessed for
63 * 1) retrieving the mech_id (comparing the mech name)
64 * 2) finding a provider for an xxx_init() or atomic operation.
65 * 3) altering the mechs entry to add or remove a provider.
67 * In 2), after a provider is chosen, its prov_desc is held and the
68 * entry's mutex must be dropped. The provider's working function (SPI) is
69 * called outside the mech_entry's mutex.
71 * The number of providers for a particular mechanism is not expected to be
72 * long enough to justify the cost of using rwlocks, so the per-mechanism
73 * entry mutex won't be very *hot*.
75 * When both kcf_mech_tabs_lock and a mech_entry mutex need to be held,
76 * kcf_mech_tabs_lock must always be acquired first.
80 /* Mechanisms tables */
83 /* RFE 4687834 Will deal with the extensibility of these tables later */
85 kcf_mech_entry_t kcf_digest_mechs_tab
[KCF_MAXDIGEST
];
86 kcf_mech_entry_t kcf_cipher_mechs_tab
[KCF_MAXCIPHER
];
87 kcf_mech_entry_t kcf_mac_mechs_tab
[KCF_MAXMAC
];
88 kcf_mech_entry_t kcf_sign_mechs_tab
[KCF_MAXSIGN
];
89 kcf_mech_entry_t kcf_keyops_mechs_tab
[KCF_MAXKEYOPS
];
90 kcf_mech_entry_t kcf_misc_mechs_tab
[KCF_MAXMISC
];
92 kcf_mech_entry_tab_t kcf_mech_tabs_tab
[KCF_LAST_OPSCLASS
+ 1] = {
93 {0, NULL
}, /* No class zero */
94 {KCF_MAXDIGEST
, kcf_digest_mechs_tab
},
95 {KCF_MAXCIPHER
, kcf_cipher_mechs_tab
},
96 {KCF_MAXMAC
, kcf_mac_mechs_tab
},
97 {KCF_MAXSIGN
, kcf_sign_mechs_tab
},
98 {KCF_MAXKEYOPS
, kcf_keyops_mechs_tab
},
99 {KCF_MAXMISC
, kcf_misc_mechs_tab
}
103 * Per-algorithm internal thresholds for the minimum input size of before
104 * offloading to hardware provider.
105 * Dispatching a crypto operation to a hardware provider entails paying the
106 * cost of an additional context switch. Measurments with Sun Accelerator 4000
107 * shows that 512-byte jobs or smaller are better handled in software.
108 * There is room for refinement here.
111 int kcf_md5_threshold
= 512;
112 int kcf_sha1_threshold
= 512;
113 int kcf_des_threshold
= 512;
114 int kcf_des3_threshold
= 512;
115 int kcf_aes_threshold
= 512;
116 int kcf_bf_threshold
= 512;
117 int kcf_rc4_threshold
= 512;
119 kmutex_t kcf_mech_tabs_lock
;
120 static uint32_t kcf_gen_swprov
= 0;
122 int kcf_mech_hash_size
= 256;
123 mod_hash_t
*kcf_mech_hash
; /* mech name to id hash */
125 static crypto_mech_type_t
126 kcf_mech_hash_find(char *mechname
)
129 crypto_mech_type_t mt
;
131 mt
= CRYPTO_MECH_INVALID
;
132 if (mod_hash_find(kcf_mech_hash
, (mod_hash_key_t
)mechname
, &hv
) == 0) {
133 mt
= *(crypto_mech_type_t
*)hv
;
134 ASSERT(mt
!= CRYPTO_MECH_INVALID
);
141 kcf_destroy_mech_tabs(void)
144 kcf_ops_class_t
class;
145 kcf_mech_entry_t
*me_tab
;
148 mod_hash_destroy_hash(kcf_mech_hash
);
150 mutex_destroy(&kcf_mech_tabs_lock
);
152 for (class = KCF_FIRST_OPSCLASS
; class <= KCF_LAST_OPSCLASS
; class++) {
153 max
= kcf_mech_tabs_tab
[class].met_size
;
154 me_tab
= kcf_mech_tabs_tab
[class].met_tab
;
155 for (i
= 0; i
< max
; i
++)
156 mutex_destroy(&(me_tab
[i
].me_mutex
));
161 * kcf_init_mech_tabs()
163 * Called by the misc/kcf's _init() routine to initialize the tables
167 kcf_init_mech_tabs(void)
170 kcf_ops_class_t
class;
171 kcf_mech_entry_t
*me_tab
;
173 /* Initializes the mutex locks. */
175 mutex_init(&kcf_mech_tabs_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
177 /* Then the pre-defined mechanism entries */
180 (void) strncpy(kcf_digest_mechs_tab
[0].me_name
, SUN_CKM_MD5
,
181 CRYPTO_MAX_MECH_NAME
);
182 kcf_digest_mechs_tab
[0].me_threshold
= kcf_md5_threshold
;
184 (void) strncpy(kcf_digest_mechs_tab
[1].me_name
, SUN_CKM_SHA1
,
185 CRYPTO_MAX_MECH_NAME
);
186 kcf_digest_mechs_tab
[1].me_threshold
= kcf_sha1_threshold
;
188 /* The symmetric ciphers in various modes */
189 (void) strncpy(kcf_cipher_mechs_tab
[0].me_name
, SUN_CKM_DES_CBC
,
190 CRYPTO_MAX_MECH_NAME
);
191 kcf_cipher_mechs_tab
[0].me_threshold
= kcf_des_threshold
;
193 (void) strncpy(kcf_cipher_mechs_tab
[1].me_name
, SUN_CKM_DES3_CBC
,
194 CRYPTO_MAX_MECH_NAME
);
195 kcf_cipher_mechs_tab
[1].me_threshold
= kcf_des3_threshold
;
197 (void) strncpy(kcf_cipher_mechs_tab
[2].me_name
, SUN_CKM_DES_ECB
,
198 CRYPTO_MAX_MECH_NAME
);
199 kcf_cipher_mechs_tab
[2].me_threshold
= kcf_des_threshold
;
201 (void) strncpy(kcf_cipher_mechs_tab
[3].me_name
, SUN_CKM_DES3_ECB
,
202 CRYPTO_MAX_MECH_NAME
);
203 kcf_cipher_mechs_tab
[3].me_threshold
= kcf_des3_threshold
;
205 (void) strncpy(kcf_cipher_mechs_tab
[4].me_name
, SUN_CKM_BLOWFISH_CBC
,
206 CRYPTO_MAX_MECH_NAME
);
207 kcf_cipher_mechs_tab
[4].me_threshold
= kcf_bf_threshold
;
209 (void) strncpy(kcf_cipher_mechs_tab
[5].me_name
, SUN_CKM_BLOWFISH_ECB
,
210 CRYPTO_MAX_MECH_NAME
);
211 kcf_cipher_mechs_tab
[5].me_threshold
= kcf_bf_threshold
;
213 (void) strncpy(kcf_cipher_mechs_tab
[6].me_name
, SUN_CKM_AES_CBC
,
214 CRYPTO_MAX_MECH_NAME
);
215 kcf_cipher_mechs_tab
[6].me_threshold
= kcf_aes_threshold
;
217 (void) strncpy(kcf_cipher_mechs_tab
[7].me_name
, SUN_CKM_AES_ECB
,
218 CRYPTO_MAX_MECH_NAME
);
219 kcf_cipher_mechs_tab
[7].me_threshold
= kcf_aes_threshold
;
221 (void) strncpy(kcf_cipher_mechs_tab
[8].me_name
, SUN_CKM_RC4
,
222 CRYPTO_MAX_MECH_NAME
);
223 kcf_cipher_mechs_tab
[8].me_threshold
= kcf_rc4_threshold
;
227 (void) strncpy(kcf_mac_mechs_tab
[0].me_name
, SUN_CKM_MD5_HMAC
,
228 CRYPTO_MAX_MECH_NAME
);
229 kcf_mac_mechs_tab
[0].me_threshold
= kcf_md5_threshold
;
231 (void) strncpy(kcf_mac_mechs_tab
[1].me_name
, SUN_CKM_MD5_HMAC_GENERAL
,
232 CRYPTO_MAX_MECH_NAME
);
233 kcf_mac_mechs_tab
[1].me_threshold
= kcf_md5_threshold
;
235 (void) strncpy(kcf_mac_mechs_tab
[2].me_name
, SUN_CKM_SHA1_HMAC
,
236 CRYPTO_MAX_MECH_NAME
);
237 kcf_mac_mechs_tab
[2].me_threshold
= kcf_sha1_threshold
;
239 (void) strncpy(kcf_mac_mechs_tab
[3].me_name
, SUN_CKM_SHA1_HMAC_GENERAL
,
240 CRYPTO_MAX_MECH_NAME
);
241 kcf_mac_mechs_tab
[3].me_threshold
= kcf_sha1_threshold
;
244 /* 1 random number generation pseudo mechanism */
245 (void) strncpy(kcf_misc_mechs_tab
[0].me_name
, SUN_RANDOM
,
246 CRYPTO_MAX_MECH_NAME
);
248 kcf_mech_hash
= mod_hash_create_strhash_nodtr("kcf mech2id hash",
249 kcf_mech_hash_size
, mod_hash_null_valdtor
);
251 for (class = KCF_FIRST_OPSCLASS
; class <= KCF_LAST_OPSCLASS
; class++) {
252 max
= kcf_mech_tabs_tab
[class].met_size
;
253 me_tab
= kcf_mech_tabs_tab
[class].met_tab
;
254 for (i
= 0; i
< max
; i
++) {
255 mutex_init(&(me_tab
[i
].me_mutex
), NULL
,
256 MUTEX_DEFAULT
, NULL
);
257 if (me_tab
[i
].me_name
[0] != 0) {
258 me_tab
[i
].me_mechid
= KCF_MECHID(class, i
);
259 (void) mod_hash_insert(kcf_mech_hash
,
260 (mod_hash_key_t
)me_tab
[i
].me_name
,
261 (mod_hash_val_t
)&(me_tab
[i
].me_mechid
));
268 * kcf_create_mech_entry()
271 * . The class of mechanism.
272 * . the name of the new mechanism.
275 * Creates a new mech_entry for a mechanism not yet known to the
277 * This routine is called by kcf_add_mech_provider, which is
278 * in turn invoked for each mechanism supported by a provider.
279 * The'class' argument depends on the crypto_func_group_t bitmask
280 * in the registering provider's mech_info struct for this mechanism.
281 * When there is ambiguity in the mapping between the crypto_func_group_t
282 * and a class (dual ops, ...) the KCF_MISC_CLASS should be used.
288 * KCF_INVALID_MECH_CLASS or KCF_INVALID_MECH_NAME if the class or
289 * the mechname is bogus.
290 * KCF_MECH_TAB_FULL when there is no room left in the mech. tabs.
291 * KCF_SUCCESS otherwise.
294 kcf_create_mech_entry(kcf_ops_class_t
class, char *mechname
)
296 crypto_mech_type_t mt
;
297 kcf_mech_entry_t
*me_tab
;
300 if ((class < KCF_FIRST_OPSCLASS
) || (class > KCF_LAST_OPSCLASS
))
301 return (KCF_INVALID_MECH_CLASS
);
303 if ((mechname
== NULL
) || (mechname
[0] == 0))
304 return (KCF_INVALID_MECH_NAME
);
306 * First check if the mechanism is already in one of the tables.
307 * The mech_entry could be in another class.
309 mutex_enter(&kcf_mech_tabs_lock
);
310 mt
= kcf_mech_hash_find(mechname
);
311 if (mt
!= CRYPTO_MECH_INVALID
) {
312 /* Nothing to do, regardless the suggested class. */
313 mutex_exit(&kcf_mech_tabs_lock
);
314 return (KCF_SUCCESS
);
316 /* Now take the next unused mech entry in the class's tab */
317 me_tab
= kcf_mech_tabs_tab
[class].met_tab
;
318 size
= kcf_mech_tabs_tab
[class].met_size
;
321 mutex_enter(&(me_tab
[i
].me_mutex
));
322 if (me_tab
[i
].me_name
[0] == 0) {
323 /* Found an empty spot */
324 (void) strncpy(me_tab
[i
].me_name
, mechname
,
325 CRYPTO_MAX_MECH_NAME
);
326 me_tab
[i
].me_name
[CRYPTO_MAX_MECH_NAME
-1] = '\0';
327 me_tab
[i
].me_mechid
= KCF_MECHID(class, i
);
329 * No a-priori information about the new mechanism, so
330 * the threshold is set to zero.
332 me_tab
[i
].me_threshold
= 0;
334 mutex_exit(&(me_tab
[i
].me_mutex
));
335 /* Add the new mechanism to the hash table */
336 (void) mod_hash_insert(kcf_mech_hash
,
337 (mod_hash_key_t
)me_tab
[i
].me_name
,
338 (mod_hash_val_t
)&(me_tab
[i
].me_mechid
));
341 mutex_exit(&(me_tab
[i
].me_mutex
));
345 mutex_exit(&kcf_mech_tabs_lock
);
348 return (KCF_MECH_TAB_FULL
);
351 return (KCF_SUCCESS
);
355 * kcf_add_mech_provider()
358 * . An index in to the provider mechanism array
359 * . A pointer to the provider descriptor
360 * . A storage for the kcf_prov_mech_desc_t the entry was added at.
363 * Adds a new provider of a mechanism to the mechanism's mech_entry
370 * KCF_SUCCESS on success
371 * KCF_MECH_TAB_FULL otherwise.
374 kcf_add_mech_provider(short mech_indx
,
375 kcf_provider_desc_t
*prov_desc
, kcf_prov_mech_desc_t
**pmdpp
)
378 kcf_mech_entry_t
*mech_entry
= NULL
;
379 crypto_mech_info_t
*mech_info
;
380 crypto_mech_type_t kcf_mech_type
, mt
;
381 kcf_prov_mech_desc_t
*prov_mech
, *prov_mech2
;
382 crypto_func_group_t simple_fg_mask
, dual_fg_mask
;
383 crypto_mech_info_t
*dmi
;
384 crypto_mech_info_list_t
*mil
, *mil2
;
385 kcf_mech_entry_t
*me
;
388 ASSERT(prov_desc
->pd_prov_type
!= CRYPTO_LOGICAL_PROVIDER
);
390 mech_info
= &prov_desc
->pd_mechanisms
[mech_indx
];
393 * A mechanism belongs to exactly one mechanism table.
394 * Find the class corresponding to the function group flag of
397 kcf_mech_type
= kcf_mech_hash_find(mech_info
->cm_mech_name
);
398 if (kcf_mech_type
== CRYPTO_MECH_INVALID
) {
399 crypto_func_group_t fg
= mech_info
->cm_func_group_mask
;
400 kcf_ops_class_t
class;
402 if (fg
& CRYPTO_FG_DIGEST
|| fg
& CRYPTO_FG_DIGEST_ATOMIC
)
403 class = KCF_DIGEST_CLASS
;
404 else if (fg
& CRYPTO_FG_ENCRYPT
|| fg
& CRYPTO_FG_DECRYPT
||
405 fg
& CRYPTO_FG_ENCRYPT_ATOMIC
||
406 fg
& CRYPTO_FG_DECRYPT_ATOMIC
)
407 class = KCF_CIPHER_CLASS
;
408 else if (fg
& CRYPTO_FG_MAC
|| fg
& CRYPTO_FG_MAC_ATOMIC
)
409 class = KCF_MAC_CLASS
;
410 else if (fg
& CRYPTO_FG_SIGN
|| fg
& CRYPTO_FG_VERIFY
||
411 fg
& CRYPTO_FG_SIGN_ATOMIC
||
412 fg
& CRYPTO_FG_VERIFY_ATOMIC
||
413 fg
& CRYPTO_FG_SIGN_RECOVER
||
414 fg
& CRYPTO_FG_VERIFY_RECOVER
)
415 class = KCF_SIGN_CLASS
;
416 else if (fg
& CRYPTO_FG_GENERATE
||
417 fg
& CRYPTO_FG_GENERATE_KEY_PAIR
||
418 fg
& CRYPTO_FG_WRAP
|| fg
& CRYPTO_FG_UNWRAP
||
419 fg
& CRYPTO_FG_DERIVE
)
420 class = KCF_KEYOPS_CLASS
;
422 class = KCF_MISC_CLASS
;
425 * Attempt to create a new mech_entry for the specified
426 * mechanism. kcf_create_mech_entry() can handle the case
427 * where such an entry already exists.
429 if ((error
= kcf_create_mech_entry(class,
430 mech_info
->cm_mech_name
)) != KCF_SUCCESS
) {
433 /* get the KCF mech type that was assigned to the mechanism */
434 kcf_mech_type
= kcf_mech_hash_find(mech_info
->cm_mech_name
);
435 ASSERT(kcf_mech_type
!= CRYPTO_MECH_INVALID
);
438 error
= kcf_get_mech_entry(kcf_mech_type
, &mech_entry
);
439 ASSERT(error
== KCF_SUCCESS
);
441 /* allocate and initialize new kcf_prov_mech_desc */
442 prov_mech
= kmem_zalloc(sizeof (kcf_prov_mech_desc_t
), KM_SLEEP
);
443 bcopy(mech_info
, &prov_mech
->pm_mech_info
, sizeof (crypto_mech_info_t
));
444 prov_mech
->pm_prov_desc
= prov_desc
;
445 prov_desc
->pd_mech_indx
[KCF_MECH2CLASS(kcf_mech_type
)]
446 [KCF_MECH2INDEX(kcf_mech_type
)] = mech_indx
;
448 KCF_PROV_REFHOLD(prov_desc
);
449 KCF_PROV_IREFHOLD(prov_desc
);
451 dual_fg_mask
= mech_info
->cm_func_group_mask
& CRYPTO_FG_DUAL_MASK
;
453 if (dual_fg_mask
== ((crypto_func_group_t
)0))
456 simple_fg_mask
= (mech_info
->cm_func_group_mask
&
457 CRYPTO_FG_SIMPLEOP_MASK
) | CRYPTO_FG_RANDOM
;
459 for (i
= 0; i
< prov_desc
->pd_mech_list_count
; i
++) {
460 dmi
= &prov_desc
->pd_mechanisms
[i
];
463 if (dmi
->cm_mech_number
== mech_info
->cm_mech_number
)
466 /* skip if not a dual operation mechanism */
467 if (!(dmi
->cm_func_group_mask
& dual_fg_mask
) ||
468 (dmi
->cm_func_group_mask
& simple_fg_mask
))
471 mt
= kcf_mech_hash_find(dmi
->cm_mech_name
);
472 if (mt
== CRYPTO_MECH_INVALID
)
475 if (kcf_get_mech_entry(mt
, &me
) != KCF_SUCCESS
)
478 mil
= kmem_zalloc(sizeof (*mil
), KM_SLEEP
);
479 mil2
= kmem_zalloc(sizeof (*mil2
), KM_SLEEP
);
482 * Ignore hard-coded entries in the mech table
483 * if the provider hasn't registered.
485 mutex_enter(&me
->me_mutex
);
486 if (me
->me_hw_prov_chain
== NULL
&& me
->me_sw_prov
== NULL
) {
487 mutex_exit(&me
->me_mutex
);
488 kmem_free(mil
, sizeof (*mil
));
489 kmem_free(mil2
, sizeof (*mil2
));
494 * Add other dual mechanisms that have registered
495 * with the framework to this mechanism's
496 * cross-reference list.
498 mil
->ml_mech_info
= *dmi
; /* struct assignment */
499 mil
->ml_kcf_mechid
= mt
;
501 /* add to head of list */
502 mil
->ml_next
= prov_mech
->pm_mi_list
;
503 prov_mech
->pm_mi_list
= mil
;
505 if (prov_desc
->pd_prov_type
== CRYPTO_HW_PROVIDER
)
506 prov_mech2
= me
->me_hw_prov_chain
;
508 prov_mech2
= me
->me_sw_prov
;
510 if (prov_mech2
== NULL
) {
511 kmem_free(mil2
, sizeof (*mil2
));
512 mutex_exit(&me
->me_mutex
);
517 * Update all other cross-reference lists by
518 * adding this new mechanism.
520 while (prov_mech2
!= NULL
) {
521 if (prov_mech2
->pm_prov_desc
== prov_desc
) {
522 /* struct assignment */
523 mil2
->ml_mech_info
= *mech_info
;
524 mil2
->ml_kcf_mechid
= kcf_mech_type
;
526 /* add to head of list */
527 mil2
->ml_next
= prov_mech2
->pm_mi_list
;
528 prov_mech2
->pm_mi_list
= mil2
;
531 prov_mech2
= prov_mech2
->pm_next
;
533 if (prov_mech2
== NULL
)
534 kmem_free(mil2
, sizeof (*mil2
));
536 mutex_exit(&me
->me_mutex
);
541 * Add new kcf_prov_mech_desc at the front of HW providers
544 switch (prov_desc
->pd_prov_type
) {
546 case CRYPTO_HW_PROVIDER
:
547 mutex_enter(&mech_entry
->me_mutex
);
548 prov_mech
->pm_me
= mech_entry
;
549 prov_mech
->pm_next
= mech_entry
->me_hw_prov_chain
;
550 mech_entry
->me_hw_prov_chain
= prov_mech
;
551 mech_entry
->me_num_hwprov
++;
552 mutex_exit(&mech_entry
->me_mutex
);
555 case CRYPTO_SW_PROVIDER
:
556 mutex_enter(&mech_entry
->me_mutex
);
557 if (mech_entry
->me_sw_prov
!= NULL
) {
559 * There is already a SW provider for this mechanism.
560 * Since we allow only one SW provider per mechanism,
561 * report this condition.
563 cmn_err(CE_WARN
, "The cryptographic software provider "
564 "\"%s\" will not be used for %s. The provider "
565 "\"%s\" will be used for this mechanism "
566 "instead.", prov_desc
->pd_description
,
567 mech_info
->cm_mech_name
,
568 mech_entry
->me_sw_prov
->pm_prov_desc
->
570 KCF_PROV_REFRELE(prov_desc
);
571 kmem_free(prov_mech
, sizeof (kcf_prov_mech_desc_t
));
575 * Set the provider as the software provider for
578 mech_entry
->me_sw_prov
= prov_mech
;
580 /* We'll wrap around after 4 billion registrations! */
581 mech_entry
->me_gen_swprov
= kcf_gen_swprov
++;
583 mutex_exit(&mech_entry
->me_mutex
);
591 return (KCF_SUCCESS
);
595 * kcf_remove_mech_provider()
598 * . mech_name: the name of the mechanism.
599 * . prov_desc: The provider descriptor
602 * Removes a provider from chain of provider descriptors.
603 * The provider is made unavailable to kernel consumers for the specified
610 kcf_remove_mech_provider(char *mech_name
, kcf_provider_desc_t
*prov_desc
)
612 crypto_mech_type_t mech_type
;
613 kcf_prov_mech_desc_t
*prov_mech
= NULL
, *prov_chain
;
614 kcf_prov_mech_desc_t
**prev_entry_next
;
615 kcf_mech_entry_t
*mech_entry
;
616 crypto_mech_info_list_t
*mil
, *mil2
, *next
, **prev_next
;
618 ASSERT(prov_desc
->pd_prov_type
!= CRYPTO_LOGICAL_PROVIDER
);
620 /* get the KCF mech type that was assigned to the mechanism */
621 if ((mech_type
= kcf_mech_hash_find(mech_name
)) ==
622 CRYPTO_MECH_INVALID
) {
624 * Provider was not allowed for this mech due to policy or
630 /* get a ptr to the mech_entry that was created */
631 if (kcf_get_mech_entry(mech_type
, &mech_entry
) != KCF_SUCCESS
) {
633 * Provider was not allowed for this mech due to policy or
639 mutex_enter(&mech_entry
->me_mutex
);
641 switch (prov_desc
->pd_prov_type
) {
643 case CRYPTO_HW_PROVIDER
:
644 /* find the provider in the mech_entry chain */
645 prev_entry_next
= &mech_entry
->me_hw_prov_chain
;
646 prov_mech
= mech_entry
->me_hw_prov_chain
;
647 while (prov_mech
!= NULL
&&
648 prov_mech
->pm_prov_desc
!= prov_desc
) {
649 prev_entry_next
= &prov_mech
->pm_next
;
650 prov_mech
= prov_mech
->pm_next
;
653 if (prov_mech
== NULL
) {
654 /* entry not found, simply return */
655 mutex_exit(&mech_entry
->me_mutex
);
659 /* remove provider entry from mech_entry chain */
660 *prev_entry_next
= prov_mech
->pm_next
;
661 ASSERT(mech_entry
->me_num_hwprov
> 0);
662 mech_entry
->me_num_hwprov
--;
665 case CRYPTO_SW_PROVIDER
:
666 if (mech_entry
->me_sw_prov
== NULL
||
667 mech_entry
->me_sw_prov
->pm_prov_desc
!= prov_desc
) {
668 /* not the software provider for this mechanism */
669 mutex_exit(&mech_entry
->me_mutex
);
672 prov_mech
= mech_entry
->me_sw_prov
;
673 mech_entry
->me_sw_prov
= NULL
;
676 /* unexpected crypto_provider_type_t */
677 mutex_exit(&mech_entry
->me_mutex
);
681 mutex_exit(&mech_entry
->me_mutex
);
683 /* Free the dual ops cross-reference lists */
684 mil
= prov_mech
->pm_mi_list
;
685 while (mil
!= NULL
) {
687 if (kcf_get_mech_entry(mil
->ml_kcf_mechid
,
688 &mech_entry
) != KCF_SUCCESS
) {
693 mutex_enter(&mech_entry
->me_mutex
);
694 if (prov_desc
->pd_prov_type
== CRYPTO_HW_PROVIDER
)
695 prov_chain
= mech_entry
->me_hw_prov_chain
;
697 prov_chain
= mech_entry
->me_sw_prov
;
699 while (prov_chain
!= NULL
) {
700 if (prov_chain
->pm_prov_desc
== prov_desc
) {
701 prev_next
= &prov_chain
->pm_mi_list
;
702 mil2
= prov_chain
->pm_mi_list
;
703 while (mil2
!= NULL
&&
704 mil2
->ml_kcf_mechid
!= mech_type
) {
705 prev_next
= &mil2
->ml_next
;
706 mil2
= mil2
->ml_next
;
709 *prev_next
= mil2
->ml_next
;
710 kmem_free(mil2
, sizeof (*mil2
));
714 prov_chain
= prov_chain
->pm_next
;
717 mutex_exit(&mech_entry
->me_mutex
);
718 kmem_free(mil
, sizeof (crypto_mech_info_list_t
));
723 KCF_PROV_REFRELE(prov_mech
->pm_prov_desc
);
724 KCF_PROV_IREFRELE(prov_mech
->pm_prov_desc
);
725 kmem_free(prov_mech
, sizeof (kcf_prov_mech_desc_t
));
729 * kcf_get_mech_entry()
732 * . The framework mechanism type
733 * . Storage for the mechanism entry
736 * Retrieves the mechanism entry for the mech.
739 * User and interrupt contexts.
742 * KCF_MECHANISM_XXX appropriate error code.
743 * KCF_SUCCESS otherwise.
746 kcf_get_mech_entry(crypto_mech_type_t mech_type
, kcf_mech_entry_t
**mep
)
748 kcf_ops_class_t
class;
750 kcf_mech_entry_tab_t
*me_tab
;
754 class = KCF_MECH2CLASS(mech_type
);
756 if ((class < KCF_FIRST_OPSCLASS
) || (class > KCF_LAST_OPSCLASS
)) {
757 /* the caller won't need to know it's an invalid class */
758 return (KCF_INVALID_MECH_NUMBER
);
761 me_tab
= &kcf_mech_tabs_tab
[class];
762 index
= KCF_MECH2INDEX(mech_type
);
764 if ((index
< 0) || (index
>= me_tab
->met_size
)) {
765 return (KCF_INVALID_MECH_NUMBER
);
768 *mep
= &((me_tab
->met_tab
)[index
]);
770 return (KCF_SUCCESS
);
773 /* CURRENTLY UNSUPPORTED: attempting to load the module if it isn't found */
775 * Lookup the hash table for an entry that matches the mechname.
776 * If there are no hardware or software providers for the mechanism,
777 * but there is an unloaded software provider, this routine will attempt
780 * If the MOD_NOAUTOUNLOAD flag is not set, a software provider is
781 * in constant danger of being unloaded. For consumers that call
782 * crypto_mech2id() only once, the provider will not be reloaded
783 * if it becomes unloaded. If a provider gets loaded elsewhere
784 * without the MOD_NOAUTOUNLOAD flag being set, we set it now.
787 crypto_mech2id_common(char *mechname
, boolean_t load_module
)
789 crypto_mech_type_t mt
= kcf_mech_hash_find(mechname
);