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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/types.h>
26 #include <sys/sunddi.h>
28 #include <sys/modctl.h>
29 #include <sys/sysmacros.h>
30 #include <sys/crypto/common.h>
31 #include <sys/crypto/api.h>
32 #include <sys/crypto/impl.h>
33 #include <sys/crypto/sched_impl.h>
35 #define isspace(ch) (((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n') || \
36 ((ch) == '\t') || ((ch) == '\f'))
38 #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
39 #define CRYPTO_KEY_OFFSET(f) offsetof(crypto_key_ops_t, f)
40 #define CRYPTO_PROVIDER_OFFSET(f) \
41 offsetof(crypto_provider_management_ops_t, f)
43 /* Miscellaneous exported entry points */
46 * All event subscribers are put on a list. kcf_notify_list_lock
47 * protects changes to this list.
49 * The following locking order is maintained in the code - The
50 * global kcf_notify_list_lock followed by the individual lock
51 * in a kcf_ntfy_elem structure (kn_lock).
53 kmutex_t ntfy_list_lock
;
54 kcondvar_t ntfy_list_cv
; /* cv the service thread waits on */
55 static kcf_ntfy_elem_t
*ntfy_list_head
;
56 static kcf_ntfy_elem_t
*ntfy_list_tail
;
58 /* count all the hardware and software providers */
59 #define PROV_COUNT(me) \
60 (((me)->me_sw_prov != NULL ? 1 : 0) + (me)->me_num_hwprov)
66 * . mechname: A null-terminated string identifying the mechanism name.
69 * Walks the mechanisms tables, looking for an entry that matches the
70 * mechname. Once it find it, it builds the 64-bit mech_type and returns
71 * it. If there are no hardware or software providers for the mechanism,
72 * but there is an unloaded software provider, this routine will attempt
76 * Process and interruption.
79 * The unique mechanism identified by 'mechname', if found.
80 * CRYPTO_MECH_INVALID otherwise.
83 crypto_mech2id(char *mechname
)
85 return (crypto_mech2id_common(mechname
, B_TRUE
));
89 * crypto_get_mech_list()
92 * . countp: pointer to contain the number of mech names returned
93 * . kmflag: memory allocation flag.
96 * Allocates an array of crypto_mech_name_t containing all the mechanisms
97 * currently available on the system. Sets *countp with the number of
98 * mechanism names returned.
100 * We get a list of mech names which have a hardware provider by walking
101 * all the mechanism tables. We merge them with mech names obtained from
102 * the hint list. A mech name in the hint list is considered only if it
103 * is not disabled for the provider. Note that the hint list contains only
104 * software providers and the mech names supported by them.
107 * Process and interruption. kmflag should be KM_NOSLEEP when called
108 * from an interruption context.
111 * The array of the crypto_mech_t allocated.
115 crypto_get_mech_list(uint_t
*countp
, int kmflag
)
117 uint_t count
= 0, me_tab_size
, i
, j
;
119 kcf_mech_entry_t
*me
, *me_tab
;
120 crypto_mech_name_t
*mech_name_tab
, *tmp_mech_name_tab
;
121 char *mech_name
, *hint_mech
, *end
;
122 kcf_soft_conf_entry_t
*p
;
124 kcf_lock_withpad_t
*mp
;
127 * Count the maximum possible mechanisms that can come from the
130 mutex_enter(&soft_config_mutex
);
131 p
= soft_config_list
;
133 count
+= p
->ce_count
;
136 mutex_exit(&soft_config_mutex
);
138 /* First let's count'em, for mem allocation */
139 for (cl
= KCF_FIRST_OPSCLASS
; cl
<= KCF_LAST_OPSCLASS
; cl
++) {
140 me_tab_size
= kcf_mech_tabs_tab
[cl
].met_size
;
141 me_tab
= kcf_mech_tabs_tab
[cl
].met_tab
;
142 for (i
= 0; i
< me_tab_size
; i
++) {
144 mp
= &me_mutexes
[CPU_SEQID
];
145 mutex_enter(&mp
->kl_lock
);
146 if ((me
->me_name
[0] != 0) && (me
->me_num_hwprov
>= 1)) {
147 ASSERT(me
->me_hw_prov_chain
!= NULL
);
150 mutex_exit(&mp
->kl_lock
);
155 * Allocate a buffer to hold the mechanisms from
156 * mech tabs and mechanisms from the hint list.
158 n
= count
* CRYPTO_MAX_MECH_NAME
;
162 tmp_mech_name_tab
= kmem_zalloc(n
, kmflag
);
163 if (tmp_mech_name_tab
== NULL
) {
169 * Second round, fill in the table
172 mech_name
= (char *)tmp_mech_name_tab
;
175 for (cl
= KCF_FIRST_OPSCLASS
; cl
<= KCF_LAST_OPSCLASS
; cl
++) {
176 me_tab_size
= kcf_mech_tabs_tab
[cl
].met_size
;
177 me_tab
= kcf_mech_tabs_tab
[cl
].met_tab
;
178 for (i
= 0; i
< me_tab_size
; i
++) {
180 mp
= &me_mutexes
[CPU_SEQID
];
181 mutex_enter(&mp
->kl_lock
);
182 if ((me
->me_name
[0] != 0) && (me
->me_num_hwprov
>= 1)) {
183 ASSERT(me
->me_hw_prov_chain
!= NULL
);
184 if ((mech_name
+ CRYPTO_MAX_MECH_NAME
) > end
) {
185 mutex_exit(&mp
->kl_lock
);
186 kmem_free(tmp_mech_name_tab
, n
);
190 (void) strncpy(mech_name
, me
->me_name
,
191 CRYPTO_MAX_MECH_NAME
);
193 mech_name
+= CRYPTO_MAX_MECH_NAME
;
196 mutex_exit(&mp
->kl_lock
);
201 * Search tmp_mech_name_tab for each mechanism in the hint list. We
202 * have to add any new mechanisms found in the hint list. Note that we
203 * should not modload the providers here as it will be too early. It
204 * may be the case that the caller never uses a provider.
206 mutex_enter(&soft_config_mutex
);
207 p
= soft_config_list
;
209 for (i
= 0; i
< p
->ce_count
; i
++) {
210 hint_mech
= p
->ce_mechs
[i
];
212 /* Do not consider the mechanism if it is disabled. */
213 if (is_mech_disabled_byname(CRYPTO_SW_PROVIDER
,
214 p
->ce_name
, 0, hint_mech
))
218 * There may be duplicate mechanisms in the hint list.
219 * So, we need to search all the entries that have been
220 * added so far. That number would be count.
222 for (j
= 0; j
< count
; j
++) {
223 if (strcmp(hint_mech
,
224 tmp_mech_name_tab
[j
]) == 0)
228 if (j
== count
) { /* This is a new one. Add it. */
229 ASSERT((char *)&tmp_mech_name_tab
[count
] ==
231 if ((mech_name
+ CRYPTO_MAX_MECH_NAME
) > end
) {
232 mutex_exit(&soft_config_mutex
);
233 kmem_free(tmp_mech_name_tab
, n
);
237 (void) strncpy(tmp_mech_name_tab
[count
],
238 hint_mech
, CRYPTO_MAX_MECH_NAME
);
239 mech_name
+= CRYPTO_MAX_MECH_NAME
;
245 mutex_exit(&soft_config_mutex
);
248 * Check if we have consumed all of the space. We are done if
251 ASSERT(mech_name
<= end
);
252 if (mech_name
== end
) {
253 mech_name_tab
= tmp_mech_name_tab
;
258 * Allocate a buffer of the right size now that we have the
261 mech_name_tab
= kmem_zalloc(count
* CRYPTO_MAX_MECH_NAME
, kmflag
);
262 if (mech_name_tab
== NULL
) {
263 kmem_free(tmp_mech_name_tab
, n
);
268 bcopy(tmp_mech_name_tab
, mech_name_tab
, count
* CRYPTO_MAX_MECH_NAME
);
269 kmem_free(tmp_mech_name_tab
, n
);
273 return (mech_name_tab
);
277 * crypto_free_mech_list()
280 * . mech_names: An array of crypto_mech_name_t previously allocated by
281 * crypto_get_mech_list.
282 * . count: the number of mech names in mech_names
285 * Frees the the mech_names array.
288 * Process and interruption.
291 crypto_free_mech_list(crypto_mech_name_t
*mech_names
, uint_t count
)
293 if ((mech_names
!= NULL
) && (count
> 0))
294 kmem_free(mech_names
, count
* CRYPTO_MAX_MECH_NAME
);
298 * crypto_notify_events()
301 * . nf: Callback function to invoke when event occurs.
302 * . event_mask: Mask of events.
305 * Allocates a new element and inserts it in to the notification
312 * A handle is returned if the client is put on the notification list.
313 * NULL is returned otherwise.
315 crypto_notify_handle_t
316 crypto_notify_events(crypto_notify_callback_t nf
, uint32_t event_mask
)
318 kcf_ntfy_elem_t
*nep
;
319 crypto_notify_handle_t hndl
;
321 /* Check the input */
322 if (nf
== NULL
|| !(event_mask
& (CRYPTO_EVENT_MECHS_CHANGED
|
323 CRYPTO_EVENT_PROVIDER_REGISTERED
|
324 CRYPTO_EVENT_PROVIDER_UNREGISTERED
))) {
328 nep
= kmem_zalloc(sizeof (kcf_ntfy_elem_t
), KM_SLEEP
);
329 mutex_init(&nep
->kn_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
330 cv_init(&nep
->kn_cv
, NULL
, CV_DEFAULT
, NULL
);
331 nep
->kn_state
= NTFY_WAITING
;
333 nep
->kn_event_mask
= event_mask
;
335 mutex_enter(&ntfy_list_lock
);
336 if (ntfy_list_head
== NULL
) {
337 ntfy_list_head
= ntfy_list_tail
= nep
;
339 ntfy_list_tail
->kn_next
= nep
;
340 nep
->kn_prev
= ntfy_list_tail
;
341 ntfy_list_tail
= nep
;
344 hndl
= (crypto_notify_handle_t
)nep
;
345 mutex_exit(&ntfy_list_lock
);
351 * crypto_unnotify_events()
354 * . hndl - Handle returned from an earlier crypto_notify_events().
357 * Removes the element specified by hndl from the notification list.
358 * We wait for the notification routine to complete, if the routine
359 * is currently being called. We also free the element.
365 crypto_unnotify_events(crypto_notify_handle_t hndl
)
367 kcf_ntfy_elem_t
*nep
= (kcf_ntfy_elem_t
*)hndl
;
373 mutex_enter(&ntfy_list_lock
);
374 mutex_enter(&nep
->kn_lock
);
376 if (nep
->kn_state
== NTFY_WAITING
) {
377 kcf_ntfy_elem_t
*nextp
= nep
->kn_next
;
378 kcf_ntfy_elem_t
*prevp
= nep
->kn_prev
;
381 nextp
->kn_prev
= prevp
;
383 ntfy_list_tail
= prevp
;
386 prevp
->kn_next
= nextp
;
388 ntfy_list_head
= nextp
;
390 ASSERT(nep
->kn_state
== NTFY_RUNNING
);
393 * We have to drop this lock as the client might call
394 * crypto_notify_events() in the callback routine resulting
397 mutex_exit(&ntfy_list_lock
);
400 * Another thread is working on this element. We will wait
401 * for that thread to signal us when done. No other thread
402 * will free this element. So, we can be sure it stays valid
405 while (nep
->kn_state
== NTFY_RUNNING
)
406 cv_wait(&nep
->kn_cv
, &nep
->kn_lock
);
407 mutex_exit(&nep
->kn_lock
);
410 * We have to remove the element from the notification list.
411 * So, start over and do the work (acquire locks etc.). This is
412 * safe (i.e. We won't be in this routine forever) as the
413 * events do not happen frequently. We have to revisit this
414 * code if we add a new event that happens often.
419 mutex_exit(&nep
->kn_lock
);
421 /* Free the element */
422 mutex_destroy(&nep
->kn_lock
);
423 cv_destroy(&nep
->kn_cv
);
424 kmem_free(nep
, sizeof (kcf_ntfy_elem_t
));
426 mutex_exit(&ntfy_list_lock
);
430 * We walk the notification list and do the callbacks.
433 kcf_walk_ntfylist(uint32_t event
, void *event_arg
)
435 kcf_ntfy_elem_t
*nep
;
438 mutex_enter(&ntfy_list_lock
);
441 * Count how many clients are on the notification list. We need
442 * this count to ensure that clients which joined the list after we
443 * have started this walk, are not wrongly notified.
445 for (nep
= ntfy_list_head
; nep
!= NULL
; nep
= nep
->kn_next
)
448 for (nep
= ntfy_list_head
; (nep
!= NULL
&& nelem
); nep
= nep
->kn_next
) {
452 * Check if this client is interested in the
455 if (!(nep
->kn_event_mask
& event
))
458 mutex_enter(&nep
->kn_lock
);
459 nep
->kn_state
= NTFY_RUNNING
;
460 mutex_exit(&nep
->kn_lock
);
461 mutex_exit(&ntfy_list_lock
);
464 * We invoke the callback routine with no locks held. Another
465 * client could have joined the list meanwhile. This is fine
466 * as we maintain nelem as stated above. The NULL check in the
467 * for loop guards against shrinkage. Also, any callers of
468 * crypto_unnotify_events() at this point cv_wait till kn_state
469 * changes to NTFY_WAITING. Hence, nep is assured to be valid.
471 (*nep
->kn_func
)(event
, event_arg
);
473 mutex_enter(&nep
->kn_lock
);
474 nep
->kn_state
= NTFY_WAITING
;
475 cv_broadcast(&nep
->kn_cv
);
476 mutex_exit(&nep
->kn_lock
);
478 mutex_enter(&ntfy_list_lock
);
481 mutex_exit(&ntfy_list_lock
);
488 * . mech: the mechanism to check the key with.
489 * . key: the key to check for validity and weakness.
492 * Checks the validity and strength of the key for the mechanism.
493 * CRYPTO_KEY_REFERENCE is not supported for this routine.
494 * If more than one provider is capable of key checking for the mechanism,
495 * then run the key through them all.
496 * A conservative approach is adopted here: New weak keys may be
497 * discovered with more recent providers. If at least one provider is
498 * not happy with a key, then it is no good.
501 * Process and interruption.
504 crypto_key_check(crypto_mechanism_t
*mech
, crypto_key_t
*key
)
507 kcf_mech_entry_t
*me
;
508 kcf_provider_desc_t
*pd
;
509 kcf_prov_mech_desc_t
*prov_chain
;
510 kcf_lock_withpad_t
*mp
;
512 /* when mech is a valid mechanism, me will be its mech_entry */
513 if ((mech
== NULL
) || (key
== NULL
) ||
514 (key
->ck_format
== CRYPTO_KEY_REFERENCE
))
515 return (CRYPTO_ARGUMENTS_BAD
);
517 if ((error
= kcf_get_mech_entry(mech
->cm_type
, &me
)) != KCF_SUCCESS
) {
518 /* error is one of the KCF_INVALID_MECH_XXX's */
519 return (CRYPTO_MECHANISM_INVALID
);
522 mp
= &me_mutexes
[CPU_SEQID
];
523 mutex_enter(&mp
->kl_lock
);
525 /* First let the software provider check this key */
526 if (me
->me_sw_prov
!= NULL
) {
527 pd
= me
->me_sw_prov
->pm_prov_desc
;
528 KCF_PROV_REFHOLD(pd
);
530 if ((KCF_PROV_KEY_OPS(pd
) != NULL
) &&
531 (KCF_PROV_KEY_OPS(pd
)->key_check
!= NULL
)) {
532 crypto_mechanism_t lmech
;
534 mutex_exit(&mp
->kl_lock
);
536 KCF_SET_PROVIDER_MECHNUM(mech
->cm_type
, pd
, &lmech
);
537 error
= KCF_PROV_KEY_CHECK(pd
, &lmech
, key
);
539 if (error
!= CRYPTO_SUCCESS
) {
540 KCF_PROV_REFRELE(pd
);
544 mutex_enter(&mp
->kl_lock
);
546 KCF_PROV_REFRELE(pd
);
549 prov_chain
= me
->me_hw_prov_chain
;
550 while (prov_chain
!= NULL
) {
551 pd
= prov_chain
->pm_prov_desc
;
552 KCF_PROV_REFHOLD(pd
);
554 if ((KCF_PROV_KEY_OPS(pd
) != NULL
) &&
555 (KCF_PROV_KEY_OPS(pd
)->key_check
!= NULL
)) {
556 crypto_mechanism_t lmech
;
558 mutex_exit(&mp
->kl_lock
);
560 KCF_SET_PROVIDER_MECHNUM(mech
->cm_type
, pd
,
562 error
= KCF_PROV_KEY_CHECK(pd
, &lmech
, key
);
564 if (error
!= CRYPTO_SUCCESS
) {
565 KCF_PROV_REFRELE(pd
);
568 mutex_enter(&mp
->kl_lock
);
570 KCF_PROV_REFRELE(pd
);
571 prov_chain
= prov_chain
->pm_next
;
574 mutex_exit(&mp
->kl_lock
);
576 /* All are happy with this key */
577 return (CRYPTO_SUCCESS
);
581 crypto_key_check_prov(crypto_provider_t provider
, crypto_mechanism_t
*mech
,
584 kcf_provider_desc_t
*pd
= provider
;
585 kcf_provider_desc_t
*real_provider
= pd
;
586 crypto_mechanism_t lmech
;
589 ASSERT(KCF_PROV_REFHELD(pd
));
591 if ((mech
== NULL
) || (key
== NULL
) ||
592 (key
->ck_format
== CRYPTO_KEY_REFERENCE
))
593 return (CRYPTO_ARGUMENTS_BAD
);
595 /* no logical providers currently support the key check */
596 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
) {
597 return (CRYPTO_NOT_SUPPORTED
);
601 KCF_SET_PROVIDER_MECHNUM(mech
->cm_type
, real_provider
, &lmech
);
602 rv
= KCF_PROV_KEY_CHECK(real_provider
, &lmech
, key
);
603 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
604 KCF_PROV_REFRELE(real_provider
);
610 * Initialize the specified crypto_mechanism_info_t structure for
611 * the specified mechanism provider descriptor. Used by
612 * crypto_get_all_mech_info().
615 init_mechanism_info(crypto_mechanism_info_t
*mech_info
,
616 kcf_prov_mech_desc_t
*pmd
)
618 crypto_func_group_t fg
= pmd
->pm_mech_info
.cm_func_group_mask
;
620 /* min/max key sizes */
621 mech_info
->mi_keysize_unit
= pmd
->pm_mech_info
.cm_mech_flags
&
622 (CRYPTO_KEYSIZE_UNIT_IN_BITS
| CRYPTO_KEYSIZE_UNIT_IN_BYTES
);
623 mech_info
->mi_min_key_size
=
624 (size_t)pmd
->pm_mech_info
.cm_min_key_length
;
625 mech_info
->mi_max_key_size
=
626 (size_t)pmd
->pm_mech_info
.cm_max_key_length
;
629 mech_info
->mi_usage
= 0;
630 if (fg
& (CRYPTO_FG_ENCRYPT
| CRYPTO_FG_ENCRYPT_ATOMIC
))
631 mech_info
->mi_usage
|= CRYPTO_MECH_USAGE_ENCRYPT
;
632 if (fg
& (CRYPTO_FG_DECRYPT
| CRYPTO_FG_DECRYPT_ATOMIC
))
633 mech_info
->mi_usage
|= CRYPTO_MECH_USAGE_DECRYPT
;
634 if (fg
& (CRYPTO_FG_MAC
| CRYPTO_FG_MAC_ATOMIC
))
635 mech_info
->mi_usage
|= CRYPTO_MECH_USAGE_MAC
;
639 * Return the mechanism info for the specified mechanism.
642 crypto_get_all_mech_info(crypto_mech_type_t mech_type
,
643 crypto_mechanism_info_t
**mech_infos
, uint_t
*num_mech_infos
,
646 uint_t ninfos
, cur_info
;
647 kcf_mech_entry_t
*me
;
649 kcf_prov_mech_desc_t
*hwp
;
650 crypto_mechanism_info_t
*infos
;
652 kcf_lock_withpad_t
*mp
;
654 /* get to the mech entry corresponding to the specified mech type */
655 if ((rv
= kcf_get_mech_entry(mech_type
, &me
)) != CRYPTO_SUCCESS
) {
659 /* compute the number of key size ranges to return */
660 mp
= &me_mutexes
[CPU_SEQID
];
661 mutex_enter(&mp
->kl_lock
);
663 ninfos
= PROV_COUNT(me
);
664 mutex_exit(&mp
->kl_lock
);
671 infos_size
= ninfos
* sizeof (crypto_mechanism_info_t
);
672 infos
= kmem_alloc(infos_size
, km_flag
);
674 rv
= CRYPTO_HOST_MEMORY
;
678 mutex_enter(&mp
->kl_lock
);
679 if (ninfos
!= PROV_COUNT(me
)) {
680 kmem_free(infos
, infos_size
);
684 /* populate array of crypto mechanism infos */
687 /* software provider, if present */
688 if (me
->me_sw_prov
!= NULL
)
689 init_mechanism_info(&infos
[cur_info
++], me
->me_sw_prov
);
691 /* hardware providers */
692 for (hwp
= me
->me_hw_prov_chain
; hwp
!= NULL
; hwp
= hwp
->pm_next
)
693 init_mechanism_info(&infos
[cur_info
++], hwp
);
695 mutex_exit(&mp
->kl_lock
);
696 ASSERT(cur_info
== ninfos
);
699 *num_mech_infos
= ninfos
;
704 * Frees the array of mechanism infos previously allocated by
705 * crypto_get_all_mech_info().
708 crypto_free_all_mech_info(crypto_mechanism_info_t
*mech_infos
, uint_t count
)
710 if ((mech_infos
!= NULL
) && (count
> 0))
711 kmem_free(mech_infos
, count
* sizeof (crypto_mechanism_info_t
));
715 * memcmp_pad_max() is a specialized version of memcmp() which
716 * compares two pieces of data up to a maximum length. If the
717 * the two data match up the maximum length, they are considered
718 * matching. Trailing blanks do not cause the match to fail if
719 * one of the data is shorter.
721 * Examples of matches:
726 * "Number One | X" (X is beyond maximum length)
730 * Examples of mismatches:
739 memcmp_pad_max(void *d1
, uint_t d1_len
, void *d2
, uint_t d2_len
, uint_t max_sz
)
741 uint_t len
, extra_len
;
744 /* No point in comparing anything beyond max_sz */
750 /* Find shorter of the two data. */
751 if (d1_len
<= d2_len
) {
755 } else { /* d1_len > d2_len */
761 /* Have a match in the shortest length of data? */
762 if (memcmp(d1
, d2
, len
) != 0)
766 /* If the rest of longer data is nulls or blanks, call it a match. */
767 while (len
< extra_len
)
768 if (!isspace(marker
[len
++]))
775 * Obtain ext info for specified provider and see if it matches.
778 match_ext_info(kcf_provider_desc_t
*pd
, char *label
, char *manuf
, char *serial
,
779 crypto_provider_ext_info_t
*ext_info
)
783 rv
= crypto_get_provinfo(pd
, ext_info
);
784 ASSERT(rv
!= CRYPTO_NOT_SUPPORTED
);
785 if (rv
!= CRYPTO_SUCCESS
)
788 if (memcmp_pad_max(ext_info
->ei_label
, CRYPTO_EXT_SIZE_LABEL
,
789 label
, strlen(label
), CRYPTO_EXT_SIZE_LABEL
))
793 if (memcmp_pad_max(ext_info
->ei_manufacturerID
,
794 CRYPTO_EXT_SIZE_MANUF
, manuf
, strlen(manuf
),
795 CRYPTO_EXT_SIZE_MANUF
))
799 if (serial
!= NULL
) {
800 if (memcmp_pad_max(ext_info
->ei_serial_number
,
801 CRYPTO_EXT_SIZE_SERIAL
, serial
, strlen(serial
),
802 CRYPTO_EXT_SIZE_SERIAL
))
809 * Find a provider based on its label, manufacturer ID, and serial number.
812 crypto_get_provider(char *label
, char *manuf
, char *serial
)
814 kcf_provider_desc_t
**provider_array
, *pd
;
815 crypto_provider_ext_info_t
*ext_info
;
819 /* manuf and serial are optional */
823 if (kcf_get_slot_list(&count
, &provider_array
, B_FALSE
)
830 ext_info
= kmem_zalloc(sizeof (crypto_provider_ext_info_t
), KM_SLEEP
);
832 for (i
= 0; i
< count
; i
++) {
833 pd
= provider_array
[i
];
834 if (match_ext_info(pd
, label
, manuf
, serial
, ext_info
)) {
835 KCF_PROV_REFHOLD(pd
);
842 kcf_free_provider_tab(count
, provider_array
);
843 kmem_free(ext_info
, sizeof (crypto_provider_ext_info_t
));
848 * Get the provider information given a provider handle. The caller
849 * needs to allocate the space for the argument, info.
852 crypto_get_provinfo(crypto_provider_t hndl
, crypto_provider_ext_info_t
*info
)
855 kcf_req_params_t params
;
856 kcf_provider_desc_t
*pd
;
857 kcf_provider_desc_t
*real_provider
;
859 pd
= (kcf_provider_desc_t
*)hndl
;
860 rv
= kcf_get_hardware_provider_nomech(
861 CRYPTO_OPS_OFFSET(provider_ops
), CRYPTO_PROVIDER_OFFSET(ext_info
),
864 if (rv
== CRYPTO_SUCCESS
&& real_provider
!= NULL
) {
865 ASSERT(real_provider
== pd
||
866 pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
);
867 KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms
, KCF_OP_MGMT_EXTINFO
,
868 0, NULL
, 0, NULL
, 0, NULL
, info
, pd
);
869 rv
= kcf_submit_request(real_provider
, NULL
, NULL
, ¶ms
,
871 KCF_PROV_REFRELE(real_provider
);
878 crypto_release_provider(crypto_provider_t provider
)
880 KCF_PROV_REFRELE((kcf_provider_desc_t
*)provider
);