17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*d3a28a55Sdinak * Common Development and Distribution License (the "License").
6*d3a28a55Sdinak * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*d3a28a55Sdinak * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate * Mechanism Manager - centralized knowledge of mechanisms.
307c478bd9Sstevel@tonic-gate *
317c478bd9Sstevel@tonic-gate * The core of the mechmanager is the "mechlist" data structure. It contains
327c478bd9Sstevel@tonic-gate * information about all mechanisms available from providers that have been
337c478bd9Sstevel@tonic-gate * exposed to the application.
347c478bd9Sstevel@tonic-gate *
357c478bd9Sstevel@tonic-gate * Each element in the array represents a particular mechanism type. The
367c478bd9Sstevel@tonic-gate * array is sorted by type, so that searching by mechanism can be done
377c478bd9Sstevel@tonic-gate * quickly. Each element also contains the mechanism data for each slot.
387c478bd9Sstevel@tonic-gate *
397c478bd9Sstevel@tonic-gate * The mechlist is constructed on an as-needed basis, entries are not added
407c478bd9Sstevel@tonic-gate * until the application triggers an action that requires an entry to be
417c478bd9Sstevel@tonic-gate * added (or updated).
427c478bd9Sstevel@tonic-gate *
437c478bd9Sstevel@tonic-gate */
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate #include <string.h>
467c478bd9Sstevel@tonic-gate #include <strings.h>
477c478bd9Sstevel@tonic-gate #include "pkcs11Conf.h"
487c478bd9Sstevel@tonic-gate #include "metaGlobal.h"
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate /* Global data... */
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate #define INITIAL_MECHLIST_SIZE 256
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate typedef struct mechliststruct {
567c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE type;
577c478bd9Sstevel@tonic-gate mechinfo_t *slots;
587c478bd9Sstevel@tonic-gate } mechlist_t;
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate static pthread_rwlock_t mechlist_lock = PTHREAD_RWLOCK_INITIALIZER;
617c478bd9Sstevel@tonic-gate static mechlist_t *mechlist;
627c478bd9Sstevel@tonic-gate static unsigned long num_mechs;
637c478bd9Sstevel@tonic-gate static unsigned long true_mechlist_size;
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate /* Prototypes... */
677c478bd9Sstevel@tonic-gate static CK_RV meta_mechManager_update_mech(CK_MECHANISM_TYPE, boolean_t);
687c478bd9Sstevel@tonic-gate static CK_RV meta_mechManager_update_slot(CK_ULONG);
697c478bd9Sstevel@tonic-gate static CK_RV update_slotmech(CK_MECHANISM_TYPE, CK_ULONG, unsigned long);
707c478bd9Sstevel@tonic-gate static CK_RV meta_mechManager_allocmechs(CK_MECHANISM_TYPE *, unsigned long,
717c478bd9Sstevel@tonic-gate unsigned long *);
727c478bd9Sstevel@tonic-gate static boolean_t find_mech_index(CK_MECHANISM_TYPE, unsigned long *);
737c478bd9Sstevel@tonic-gate static int qsort_mechtypes(const void *, const void *);
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate /*
777c478bd9Sstevel@tonic-gate * meta_mechManager_initialize
787c478bd9Sstevel@tonic-gate *
797c478bd9Sstevel@tonic-gate * Called from C_Initialize. Allocates and initializes storage needed
807c478bd9Sstevel@tonic-gate * by the slot manager.
817c478bd9Sstevel@tonic-gate */
827c478bd9Sstevel@tonic-gate CK_RV
meta_mechManager_initialize()837c478bd9Sstevel@tonic-gate meta_mechManager_initialize()
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate /* The mechlist can dynamically grow, but let's preallocate space. */
867c478bd9Sstevel@tonic-gate mechlist = calloc(INITIAL_MECHLIST_SIZE, sizeof (mechlist_t));
877c478bd9Sstevel@tonic-gate if (mechlist == NULL)
887c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate true_mechlist_size = INITIAL_MECHLIST_SIZE;
917c478bd9Sstevel@tonic-gate num_mechs = 0;
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate return (CKR_OK);
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate * meta_mechManager_finalize
997c478bd9Sstevel@tonic-gate *
1007c478bd9Sstevel@tonic-gate * Called from C_Finalize. Deallocates any storage held by the slot manager.
1017c478bd9Sstevel@tonic-gate */
1027c478bd9Sstevel@tonic-gate void
meta_mechManager_finalize()1037c478bd9Sstevel@tonic-gate meta_mechManager_finalize()
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate int i;
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate /* No need to lock list, we assume all sessions are closed. */
1087c478bd9Sstevel@tonic-gate for (i = 0; i < num_mechs; i++) {
1097c478bd9Sstevel@tonic-gate free(mechlist[i].slots);
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate free(mechlist);
1137c478bd9Sstevel@tonic-gate mechlist = NULL;
1147c478bd9Sstevel@tonic-gate num_mechs = 0;
1157c478bd9Sstevel@tonic-gate true_mechlist_size = 0;
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate /*
1207c478bd9Sstevel@tonic-gate * meta_mechManager_get_mechs
1217c478bd9Sstevel@tonic-gate *
1227c478bd9Sstevel@tonic-gate * Get list of all available mechanisms.
1237c478bd9Sstevel@tonic-gate *
1247c478bd9Sstevel@tonic-gate * Follows PKCS#11 semantics, where list may be NULL to only request a
1257c478bd9Sstevel@tonic-gate * count of available mechanisms.
1267c478bd9Sstevel@tonic-gate */
1277c478bd9Sstevel@tonic-gate CK_RV
meta_mechManager_get_mechs(CK_MECHANISM_TYPE * list,CK_ULONG * listsize)1287c478bd9Sstevel@tonic-gate meta_mechManager_get_mechs(CK_MECHANISM_TYPE *list, CK_ULONG *listsize)
1297c478bd9Sstevel@tonic-gate {
1307c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
1317c478bd9Sstevel@tonic-gate CK_ULONG num_found = 0;
1327c478bd9Sstevel@tonic-gate CK_ULONG slotnum, num_slots;
1337c478bd9Sstevel@tonic-gate unsigned long i;
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate /* get number of slots */
1367c478bd9Sstevel@tonic-gate num_slots = meta_slotManager_get_slotcount();
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate * Update slot info. Ignore any errors.
1407c478bd9Sstevel@tonic-gate *
1417c478bd9Sstevel@tonic-gate * NOTE: Due to the PKCS#11 convention of calling C_GetMechanismList
1427c478bd9Sstevel@tonic-gate * twice (once to get the count, again to get the actual list), this
1437c478bd9Sstevel@tonic-gate * is somewhat inefficient... However, I don't see an easy way to fix
1447c478bd9Sstevel@tonic-gate * that without impacting other cases (eg, when the first call contains
1457c478bd9Sstevel@tonic-gate * an "optimistic" pre-allocated buffer).
1467c478bd9Sstevel@tonic-gate */
1477c478bd9Sstevel@tonic-gate for (slotnum = 0; slotnum < num_slots; slotnum++) {
1487c478bd9Sstevel@tonic-gate (void) meta_mechManager_update_slot(slotnum);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate /*
1537c478bd9Sstevel@tonic-gate * Count the number of mechanisms. We can't just use num_mechs,
1547c478bd9Sstevel@tonic-gate * because some mechs may not currently be supported on any slot.
1557c478bd9Sstevel@tonic-gate * Also, it may not be allowed based on the mechanism policy.
1567c478bd9Sstevel@tonic-gate */
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&mechlist_lock);
1597c478bd9Sstevel@tonic-gate for (i = 0; i < num_mechs; i++) {
1607c478bd9Sstevel@tonic-gate CK_ULONG j;
1617c478bd9Sstevel@tonic-gate boolean_t supported;
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate if (pkcs11_is_dismech(METASLOT_FRAMEWORK_ID,
1647c478bd9Sstevel@tonic-gate mechlist[i].type)) {
1657c478bd9Sstevel@tonic-gate /* skip mechs disabled by policy */
1667c478bd9Sstevel@tonic-gate continue;
1677c478bd9Sstevel@tonic-gate }
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate supported = FALSE;
1707c478bd9Sstevel@tonic-gate for (j = 0; j < num_slots; j++) {
1717c478bd9Sstevel@tonic-gate if (!mechlist[i].slots[j].initialized)
1727c478bd9Sstevel@tonic-gate continue;
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate if (mechlist[i].slots[j].supported) {
1757c478bd9Sstevel@tonic-gate supported = B_TRUE;
1767c478bd9Sstevel@tonic-gate break;
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate if (supported) {
1817c478bd9Sstevel@tonic-gate num_found++;
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate if (list && *listsize >= num_found) {
1847c478bd9Sstevel@tonic-gate list[num_found - 1] = mechlist[i].type;
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&mechlist_lock);
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate if (num_found > *listsize)
1917c478bd9Sstevel@tonic-gate rv = CKR_BUFFER_TOO_SMALL;
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate *listsize = num_found;
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate return (rv);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate /*
2007c478bd9Sstevel@tonic-gate * meta_mechManager_get_slots
2017c478bd9Sstevel@tonic-gate *
2027c478bd9Sstevel@tonic-gate * Get list of all slots supporting the specified mechanism.
2037c478bd9Sstevel@tonic-gate *
2047c478bd9Sstevel@tonic-gate * The "mech_support_info" argument should have allocated enough
2057c478bd9Sstevel@tonic-gate * space to accomodate the list of slots that supports the
2067c478bd9Sstevel@tonic-gate * specified mechanism. The "num_supporting_slots" field
2077c478bd9Sstevel@tonic-gate * in the "mech_support_info" structure will indicate how
2087c478bd9Sstevel@tonic-gate * many slots are found to support the mechanism.
2097c478bd9Sstevel@tonic-gate *
2107c478bd9Sstevel@tonic-gate * If any error occurred in getting the list, info in
2117c478bd9Sstevel@tonic-gate * mech_support_info argument is not updated.
2127c478bd9Sstevel@tonic-gate *
2137c478bd9Sstevel@tonic-gate */
2147c478bd9Sstevel@tonic-gate CK_RV
meta_mechManager_get_slots(mech_support_info_t * mech_support_info,boolean_t force_update,CK_MECHANISM_INFO * mech_info)2157c478bd9Sstevel@tonic-gate meta_mechManager_get_slots(mech_support_info_t *mech_support_info,
216*d3a28a55Sdinak boolean_t force_update, CK_MECHANISM_INFO *mech_info)
2177c478bd9Sstevel@tonic-gate {
2187c478bd9Sstevel@tonic-gate CK_RV rv;
2197c478bd9Sstevel@tonic-gate boolean_t found;
2207c478bd9Sstevel@tonic-gate CK_ULONG i, num_slots;
2217c478bd9Sstevel@tonic-gate unsigned long index, num_found = 0;
222*d3a28a55Sdinak CK_MECHANISM_INFO info;
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate rv = meta_mechManager_update_mech(mech_support_info->mech,
2257c478bd9Sstevel@tonic-gate force_update);
2267c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
2277c478bd9Sstevel@tonic-gate return (rv);
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&mechlist_lock);
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate found = find_mech_index(mech_support_info->mech, &index);
2337c478bd9Sstevel@tonic-gate if (!found) {
2347c478bd9Sstevel@tonic-gate goto finish;
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate num_slots = meta_slotManager_get_slotcount();
2387c478bd9Sstevel@tonic-gate for (i = 0; i < num_slots; i++) {
2397c478bd9Sstevel@tonic-gate if (!mechlist[index].slots[i].initialized ||
2407c478bd9Sstevel@tonic-gate !mechlist[index].slots[i].supported)
2417c478bd9Sstevel@tonic-gate continue;
2427c478bd9Sstevel@tonic-gate
243*d3a28a55Sdinak if (mech_info) {
244*d3a28a55Sdinak info = mechlist[index].slots[i].mechanism_info;
245*d3a28a55Sdinak if (!(info.flags & mech_info->flags)) {
246*d3a28a55Sdinak continue;
247*d3a28a55Sdinak }
248*d3a28a55Sdinak }
249*d3a28a55Sdinak
2507c478bd9Sstevel@tonic-gate num_found++;
2517c478bd9Sstevel@tonic-gate (mech_support_info->supporting_slots)[num_found - 1]
2527c478bd9Sstevel@tonic-gate = &mechlist[index].slots[i];
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate finish:
2567c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&mechlist_lock);
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate if (num_found == 0) {
2597c478bd9Sstevel@tonic-gate rv = CKR_MECHANISM_INVALID;
2607c478bd9Sstevel@tonic-gate } else {
2617c478bd9Sstevel@tonic-gate mech_support_info->num_supporting_slots = num_found;
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate return (rv);
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate /*
2697c478bd9Sstevel@tonic-gate * meta_mechManager_update_mech
2707c478bd9Sstevel@tonic-gate *
2717c478bd9Sstevel@tonic-gate * Updates a mechanism in the mechlist. If the mechanism is not
2727c478bd9Sstevel@tonic-gate * listed, all providers will be queried. If the mechanism
2737c478bd9Sstevel@tonic-gate * is present, but not initialized for some providers, those providers
2747c478bd9Sstevel@tonic-gate * will be queried. Existing entries will not be updated unless the
2757c478bd9Sstevel@tonic-gate * force_refresh flag is set.
2767c478bd9Sstevel@tonic-gate *
2777c478bd9Sstevel@tonic-gate * The force_refresh flag is used by C_GetMechanismInfo, to force an
2787c478bd9Sstevel@tonic-gate * update. Updates are not forced during the common usage by operations
2797c478bd9Sstevel@tonic-gate * [eg C_EncryptInit] to avoid poor performance.
2807c478bd9Sstevel@tonic-gate */
2817c478bd9Sstevel@tonic-gate static CK_RV
meta_mechManager_update_mech(CK_MECHANISM_TYPE mech,boolean_t force_refresh)2827c478bd9Sstevel@tonic-gate meta_mechManager_update_mech(CK_MECHANISM_TYPE mech, boolean_t force_refresh)
2837c478bd9Sstevel@tonic-gate {
2847c478bd9Sstevel@tonic-gate CK_RV rv;
2857c478bd9Sstevel@tonic-gate CK_ULONG slot, num_slots;
2867c478bd9Sstevel@tonic-gate unsigned long index = 0;
2877c478bd9Sstevel@tonic-gate boolean_t found;
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate /* Ensure list contains the mechanism. */
2907c478bd9Sstevel@tonic-gate rv = meta_mechManager_allocmechs(&mech, 1, &index);
2917c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
2927c478bd9Sstevel@tonic-gate return (rv);
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(&mechlist_lock);
2957c478bd9Sstevel@tonic-gate /*
2967c478bd9Sstevel@tonic-gate * We didn't retain a lock after the first search, so it's possible
2977c478bd9Sstevel@tonic-gate * that the mechlist was updated. Search again, but use the last
2987c478bd9Sstevel@tonic-gate * index as a hint to quickly find the mechanism.
2997c478bd9Sstevel@tonic-gate */
3007c478bd9Sstevel@tonic-gate found = find_mech_index(mech, &index);
3017c478bd9Sstevel@tonic-gate if (!found) {
3027c478bd9Sstevel@tonic-gate /* Shouldn't happen - entries are not removed from list. */
3037c478bd9Sstevel@tonic-gate rv = CKR_GENERAL_ERROR;
3047c478bd9Sstevel@tonic-gate goto finish;
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate num_slots = meta_slotManager_get_slotcount();
3087c478bd9Sstevel@tonic-gate for (slot = 0; slot < num_slots; slot++) {
3097c478bd9Sstevel@tonic-gate if (force_refresh || !mechlist[index].slots[slot].initialized) {
3107c478bd9Sstevel@tonic-gate rv = update_slotmech(mech, slot, index);
3117c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
3127c478bd9Sstevel@tonic-gate /* Ignore error and continue with next slot. */
3137c478bd9Sstevel@tonic-gate rv = CKR_OK;
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate finish:
3197c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&mechlist_lock);
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate return (rv);
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate * meta_mechManager_update_slot
3277c478bd9Sstevel@tonic-gate *
3287c478bd9Sstevel@tonic-gate * Updates a slot in the mechlist. Called by C_GetMechanismList
3297c478bd9Sstevel@tonic-gate * [by way of meta_mechManager_get_mechs()]. Unlike
3307c478bd9Sstevel@tonic-gate * meta_mechManager_get_slots(), the context is always to force a refresh
3317c478bd9Sstevel@tonic-gate * of the mechlist.
3327c478bd9Sstevel@tonic-gate *
3337c478bd9Sstevel@tonic-gate */
3347c478bd9Sstevel@tonic-gate static CK_RV
meta_mechManager_update_slot(CK_ULONG slotnum)3357c478bd9Sstevel@tonic-gate meta_mechManager_update_slot(CK_ULONG slotnum)
3367c478bd9Sstevel@tonic-gate {
3377c478bd9Sstevel@tonic-gate unsigned long index = 0;
3387c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE *slot_mechlist = NULL, *tmp_slot_mechlist = NULL;
3397c478bd9Sstevel@tonic-gate CK_ULONG slot_mechlistsize, mechnum, tmp_mechlistsize;
3407c478bd9Sstevel@tonic-gate CK_RV rv;
3417c478bd9Sstevel@tonic-gate boolean_t found;
3427c478bd9Sstevel@tonic-gate CK_SLOT_ID fw_st_id, true_id;
3437c478bd9Sstevel@tonic-gate int i;
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate fw_st_id = meta_slotManager_get_framework_table_id(slotnum);
3467c478bd9Sstevel@tonic-gate true_id = TRUEID(fw_st_id);
3477c478bd9Sstevel@tonic-gate
3487c478bd9Sstevel@tonic-gate /* First, get the count. */
3497c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_GetMechanismList(true_id, NULL,
3507c478bd9Sstevel@tonic-gate &slot_mechlistsize);
3517c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
3527c478bd9Sstevel@tonic-gate goto finish;
3537c478bd9Sstevel@tonic-gate }
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate tmp_slot_mechlist = malloc(
3567c478bd9Sstevel@tonic-gate slot_mechlistsize * sizeof (CK_MECHANISM_TYPE));
3577c478bd9Sstevel@tonic-gate if (tmp_slot_mechlist == NULL) {
3587c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
3597c478bd9Sstevel@tonic-gate goto finish;
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate /* Next, get the actual list. */
3637c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_GetMechanismList(true_id,
3647c478bd9Sstevel@tonic-gate tmp_slot_mechlist, &slot_mechlistsize);
3657c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
3667c478bd9Sstevel@tonic-gate goto finish;
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate /*
3707c478bd9Sstevel@tonic-gate * filter the list of mechanisms returned by the underlying slot
3717c478bd9Sstevel@tonic-gate * to remove any mechanisms that are explicitly disabled
3727c478bd9Sstevel@tonic-gate * in the configuration file.
3737c478bd9Sstevel@tonic-gate */
3747c478bd9Sstevel@tonic-gate slot_mechlist = malloc(slot_mechlistsize * sizeof (CK_MECHANISM_TYPE));
3757c478bd9Sstevel@tonic-gate if (slot_mechlist == NULL) {
3767c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
3777c478bd9Sstevel@tonic-gate goto finish;
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate tmp_mechlistsize = 0;
3817c478bd9Sstevel@tonic-gate for (i = 0; i < slot_mechlistsize; i++) {
3827c478bd9Sstevel@tonic-gate /* filter out the disabled mechanisms */
3837c478bd9Sstevel@tonic-gate if (pkcs11_is_dismech(fw_st_id, tmp_slot_mechlist[i])) {
3847c478bd9Sstevel@tonic-gate continue;
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate slot_mechlist[tmp_mechlistsize] = tmp_slot_mechlist[i];
3887c478bd9Sstevel@tonic-gate tmp_mechlistsize++;
3897c478bd9Sstevel@tonic-gate }
3907c478bd9Sstevel@tonic-gate slot_mechlistsize = tmp_mechlistsize;
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate /* Sort the mechanisms by value. */
3937c478bd9Sstevel@tonic-gate qsort(slot_mechlist, slot_mechlistsize, sizeof (CK_MECHANISM_TYPE),
3947c478bd9Sstevel@tonic-gate qsort_mechtypes);
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate /* Ensure list contains the mechanisms. */
3977c478bd9Sstevel@tonic-gate rv = meta_mechManager_allocmechs(slot_mechlist, slot_mechlistsize,
3987c478bd9Sstevel@tonic-gate &index);
3997c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
4007c478bd9Sstevel@tonic-gate goto finish;
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate /* Update the mechanism info. */
4037c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(&mechlist_lock);
4047c478bd9Sstevel@tonic-gate for (mechnum = 0; mechnum < slot_mechlistsize; mechnum++) {
4057c478bd9Sstevel@tonic-gate found = find_mech_index(slot_mechlist[mechnum], &index);
4067c478bd9Sstevel@tonic-gate if (!found) {
4077c478bd9Sstevel@tonic-gate /* This shouldn't happen. */
4087c478bd9Sstevel@tonic-gate rv = CKR_GENERAL_ERROR;
4097c478bd9Sstevel@tonic-gate goto finish;
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate rv = update_slotmech(slot_mechlist[mechnum], slotnum, index);
4137c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
4147c478bd9Sstevel@tonic-gate /* Ignore error, make best effort to finish update. */
4157c478bd9Sstevel@tonic-gate rv = CKR_OK;
4167c478bd9Sstevel@tonic-gate continue;
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&mechlist_lock);
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate finish:
4227c478bd9Sstevel@tonic-gate if (slot_mechlist) {
4237c478bd9Sstevel@tonic-gate free(slot_mechlist);
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate if (tmp_slot_mechlist) {
4277c478bd9Sstevel@tonic-gate free(tmp_slot_mechlist);
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate return (rv);
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate
4347c478bd9Sstevel@tonic-gate /*
4357c478bd9Sstevel@tonic-gate * update_slotmech
4367c478bd9Sstevel@tonic-gate *
4377c478bd9Sstevel@tonic-gate * Updates the information for a particular mechanism for a particular slot.
4387c478bd9Sstevel@tonic-gate * (ie, slotlist[foo].slots[bar])
4397c478bd9Sstevel@tonic-gate *
4407c478bd9Sstevel@tonic-gate * It is assumed that the caller to this function (all of which are
4417c478bd9Sstevel@tonic-gate * in this file) holds the write-lock to "mechlist_lock".
4427c478bd9Sstevel@tonic-gate *
4437c478bd9Sstevel@tonic-gate */
4447c478bd9Sstevel@tonic-gate static CK_RV
update_slotmech(CK_MECHANISM_TYPE mech,CK_ULONG slotnum,unsigned long index)4457c478bd9Sstevel@tonic-gate update_slotmech(CK_MECHANISM_TYPE mech, CK_ULONG slotnum,
4467c478bd9Sstevel@tonic-gate unsigned long index)
4477c478bd9Sstevel@tonic-gate {
4487c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
4497c478bd9Sstevel@tonic-gate CK_MECHANISM_INFO info;
4507c478bd9Sstevel@tonic-gate CK_SLOT_ID fw_st_id, true_id;
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate mechlist[index].slots[slotnum].slotnum = slotnum;
4537c478bd9Sstevel@tonic-gate fw_st_id = meta_slotManager_get_framework_table_id(slotnum);
4547c478bd9Sstevel@tonic-gate true_id = TRUEID(fw_st_id);
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate /*
4577c478bd9Sstevel@tonic-gate * Check if the specified mechanism is in the disabled list
4587c478bd9Sstevel@tonic-gate * of the specified slot. If so, we can immediately conclude
4597c478bd9Sstevel@tonic-gate * that it is not supported by the specified slot.
4607c478bd9Sstevel@tonic-gate */
4617c478bd9Sstevel@tonic-gate if (pkcs11_is_dismech(fw_st_id, mech)) {
4627c478bd9Sstevel@tonic-gate /*
4637c478bd9Sstevel@tonic-gate * we mark this as initialized so that we won't try
4647c478bd9Sstevel@tonic-gate * to do this check later
4657c478bd9Sstevel@tonic-gate */
4667c478bd9Sstevel@tonic-gate mechlist[index].slots[slotnum].initialized = B_TRUE;
4677c478bd9Sstevel@tonic-gate mechlist[index].slots[slotnum].supported = B_FALSE;
4687c478bd9Sstevel@tonic-gate bzero(&mechlist[index].slots[slotnum].mechanism_info,
4697c478bd9Sstevel@tonic-gate sizeof (CK_MECHANISM_INFO));
4707c478bd9Sstevel@tonic-gate goto finish;
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate
4737c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_GetMechanismInfo(true_id, mech, &info);
4747c478bd9Sstevel@tonic-gate if (rv == CKR_OK) {
4757c478bd9Sstevel@tonic-gate mechlist[index].slots[slotnum].initialized = B_TRUE;
4767c478bd9Sstevel@tonic-gate mechlist[index].slots[slotnum].supported = B_TRUE;
4777c478bd9Sstevel@tonic-gate mechlist[index].slots[slotnum].mechanism_info = info;
4787c478bd9Sstevel@tonic-gate } else {
4797c478bd9Sstevel@tonic-gate /* record that the mechanism isn't supported for the slot */
4807c478bd9Sstevel@tonic-gate mechlist[index].slots[slotnum].initialized = B_TRUE;
4817c478bd9Sstevel@tonic-gate mechlist[index].slots[slotnum].supported = B_FALSE;
4827c478bd9Sstevel@tonic-gate bzero(&mechlist[index].slots[slotnum].mechanism_info,
4837c478bd9Sstevel@tonic-gate sizeof (CK_MECHANISM_INFO));
4847c478bd9Sstevel@tonic-gate }
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate finish:
4877c478bd9Sstevel@tonic-gate return (rv);
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate /*
4927c478bd9Sstevel@tonic-gate * meta_mechManager_allocmechs
4937c478bd9Sstevel@tonic-gate *
4947c478bd9Sstevel@tonic-gate * Ensures that all of the specified mechanisms are present in the
4957c478bd9Sstevel@tonic-gate * mechlist. If a mechanism is not present, an uninitialized entry is
4967c478bd9Sstevel@tonic-gate * added for it.
4977c478bd9Sstevel@tonic-gate *
4987c478bd9Sstevel@tonic-gate * The returned index can be used by the caller as a hint to where the
4997c478bd9Sstevel@tonic-gate * first mechanism was located.
5007c478bd9Sstevel@tonic-gate */
5017c478bd9Sstevel@tonic-gate static CK_RV
meta_mechManager_allocmechs(CK_MECHANISM_TYPE * new_mechs,unsigned long num_new_mechs,unsigned long * index_hint)5027c478bd9Sstevel@tonic-gate meta_mechManager_allocmechs(CK_MECHANISM_TYPE *new_mechs,
5037c478bd9Sstevel@tonic-gate unsigned long num_new_mechs, unsigned long *index_hint)
5047c478bd9Sstevel@tonic-gate {
5057c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
5067c478bd9Sstevel@tonic-gate unsigned long i, index = 0;
5077c478bd9Sstevel@tonic-gate boolean_t found;
5087c478bd9Sstevel@tonic-gate
5097c478bd9Sstevel@tonic-gate /* The optimistic assumption is that the mech is already present. */
5107c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&mechlist_lock);
5117c478bd9Sstevel@tonic-gate for (i = 0; i < num_new_mechs; i++) {
5127c478bd9Sstevel@tonic-gate found = find_mech_index(new_mechs[i], &index);
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate if (i == 0)
5157c478bd9Sstevel@tonic-gate *index_hint = index;
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gate if (!found)
5187c478bd9Sstevel@tonic-gate break;
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&mechlist_lock);
5217c478bd9Sstevel@tonic-gate
5227c478bd9Sstevel@tonic-gate if (found) {
5237c478bd9Sstevel@tonic-gate return (CKR_OK);
5247c478bd9Sstevel@tonic-gate }
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate /*
5277c478bd9Sstevel@tonic-gate * We stopped searching when the first unknown mech was found. Now
5287c478bd9Sstevel@tonic-gate * obtain a write-lock, and continue from where we left off, inserting
5297c478bd9Sstevel@tonic-gate * unknown mechanisms.
5307c478bd9Sstevel@tonic-gate */
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(&mechlist_lock);
5337c478bd9Sstevel@tonic-gate for (; i < num_new_mechs; i++) {
5347c478bd9Sstevel@tonic-gate found = find_mech_index(new_mechs[i], &index);
5357c478bd9Sstevel@tonic-gate
5367c478bd9Sstevel@tonic-gate if (!found) {
5377c478bd9Sstevel@tonic-gate mechinfo_t *new_mechinfos;
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate new_mechinfos = calloc(meta_slotManager_get_slotcount(),
5407c478bd9Sstevel@tonic-gate sizeof (mechinfo_t));
5417c478bd9Sstevel@tonic-gate if (new_mechinfos == NULL) {
5427c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
5437c478bd9Sstevel@tonic-gate goto finish;
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate /*
5477c478bd9Sstevel@tonic-gate * If the current storage for the mechlist is too
5487c478bd9Sstevel@tonic-gate * small, allocate a new list twice as large.
5497c478bd9Sstevel@tonic-gate */
5507c478bd9Sstevel@tonic-gate if (num_mechs == true_mechlist_size) {
5517c478bd9Sstevel@tonic-gate mechlist_t *newmechlist;
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate newmechlist = realloc(mechlist,
5547c478bd9Sstevel@tonic-gate 2 * true_mechlist_size *
5557c478bd9Sstevel@tonic-gate sizeof (mechlist_t));
5567c478bd9Sstevel@tonic-gate
5577c478bd9Sstevel@tonic-gate if (newmechlist == NULL) {
5587c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
5597c478bd9Sstevel@tonic-gate free(new_mechinfos);
5607c478bd9Sstevel@tonic-gate goto finish;
5617c478bd9Sstevel@tonic-gate }
5627c478bd9Sstevel@tonic-gate
5637c478bd9Sstevel@tonic-gate mechlist = newmechlist;
5647c478bd9Sstevel@tonic-gate true_mechlist_size *= 2;
5657c478bd9Sstevel@tonic-gate }
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate /* Shift existing entries to make space. */
5687c478bd9Sstevel@tonic-gate (void) memmove(&mechlist[index+1], &mechlist[index],
5697c478bd9Sstevel@tonic-gate (num_mechs - index) * sizeof (mechlist_t));
5707c478bd9Sstevel@tonic-gate num_mechs++;
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate mechlist[index].type = new_mechs[i];
5737c478bd9Sstevel@tonic-gate mechlist[index].slots = new_mechinfos;
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate }
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate finish:
5787c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&mechlist_lock);
5797c478bd9Sstevel@tonic-gate
5807c478bd9Sstevel@tonic-gate return (rv);
5817c478bd9Sstevel@tonic-gate }
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate /*
5857c478bd9Sstevel@tonic-gate * find_mech_index
5867c478bd9Sstevel@tonic-gate *
5877c478bd9Sstevel@tonic-gate * Performs a search of mechlist for the specified mechanism, and
5887c478bd9Sstevel@tonic-gate * returns if the mechanism was found or not. The value of the "index"
5897c478bd9Sstevel@tonic-gate * argument will be where the mech is (if found), or where it should
5907c478bd9Sstevel@tonic-gate * be (if not found).
5917c478bd9Sstevel@tonic-gate *
5927c478bd9Sstevel@tonic-gate * The current value of "index" will be used as a starting point, if the
5937c478bd9Sstevel@tonic-gate * caller already knows where the mechanism is likely to be.
5947c478bd9Sstevel@tonic-gate *
5957c478bd9Sstevel@tonic-gate * The caller is assumed to have a lock on the mechlist, preventing it
5967c478bd9Sstevel@tonic-gate * from being changed while searching (also to ensure the returned index
5977c478bd9Sstevel@tonic-gate * will remain valid until the list is unlocked).
5987c478bd9Sstevel@tonic-gate *
5997c478bd9Sstevel@tonic-gate * FUTURE: convert to binary search [from O(N) to a O(log(N))].
6007c478bd9Sstevel@tonic-gate *
6017c478bd9Sstevel@tonic-gate * NOTES:
6027c478bd9Sstevel@tonic-gate * 1) This function assumes that mechMap is a sorted list.
6037c478bd9Sstevel@tonic-gate */
6047c478bd9Sstevel@tonic-gate static boolean_t
find_mech_index(CK_MECHANISM_TYPE mechanism,unsigned long * index)6057c478bd9Sstevel@tonic-gate find_mech_index(CK_MECHANISM_TYPE mechanism, unsigned long *index)
6067c478bd9Sstevel@tonic-gate {
6077c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE;
6087c478bd9Sstevel@tonic-gate unsigned long i;
6097c478bd9Sstevel@tonic-gate
6107c478bd9Sstevel@tonic-gate for (i = 0; i < num_mechs; i++) {
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate if (mechlist[i].type == mechanism) {
6137c478bd9Sstevel@tonic-gate found = B_TRUE;
6147c478bd9Sstevel@tonic-gate break;
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate
6177c478bd9Sstevel@tonic-gate if (mechlist[i].type > mechanism)
6187c478bd9Sstevel@tonic-gate break;
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate *index = i;
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate return (found);
6247c478bd9Sstevel@tonic-gate }
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate static int
qsort_mechtypes(const void * arg1,const void * arg2)6277c478bd9Sstevel@tonic-gate qsort_mechtypes(const void *arg1, const void *arg2)
6287c478bd9Sstevel@tonic-gate {
6297c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE mech1 = *((CK_MECHANISM_TYPE *)arg1);
6307c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE mech2 = *((CK_MECHANISM_TYPE *)arg2);
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate if (mech1 > mech2)
6337c478bd9Sstevel@tonic-gate return (1);
6347c478bd9Sstevel@tonic-gate if (mech1 < mech2)
6357c478bd9Sstevel@tonic-gate return (-1);
6367c478bd9Sstevel@tonic-gate return (0);
6377c478bd9Sstevel@tonic-gate }
6387c478bd9Sstevel@tonic-gate
6397c478bd9Sstevel@tonic-gate /*
6407c478bd9Sstevel@tonic-gate * Check if the specified mechanism is supported by the specified slot.
6417c478bd9Sstevel@tonic-gate * The result is returned in the "supports" argument. If the "slot_info"
6427c478bd9Sstevel@tonic-gate * argument is not NULL, it will be filled with information about
6437c478bd9Sstevel@tonic-gate * the slot.
6447c478bd9Sstevel@tonic-gate */
6457c478bd9Sstevel@tonic-gate CK_RV
meta_mechManager_slot_supports_mech(CK_MECHANISM_TYPE mechanism,CK_ULONG slotnum,boolean_t * supports,mechinfo_t ** slot_info,boolean_t force_update,CK_MECHANISM_INFO * mech_info)6467c478bd9Sstevel@tonic-gate meta_mechManager_slot_supports_mech(CK_MECHANISM_TYPE mechanism,
6477c478bd9Sstevel@tonic-gate CK_ULONG slotnum, boolean_t *supports, mechinfo_t **slot_info,
648*d3a28a55Sdinak boolean_t force_update, CK_MECHANISM_INFO *mech_info)
6497c478bd9Sstevel@tonic-gate {
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate boolean_t found;
6527c478bd9Sstevel@tonic-gate CK_RV rv;
6537c478bd9Sstevel@tonic-gate unsigned long index;
654*d3a28a55Sdinak CK_MECHANISM_INFO info;
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate *supports = B_FALSE;
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate rv = meta_mechManager_update_mech(mechanism, force_update);
6597c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
6607c478bd9Sstevel@tonic-gate return (rv);
6617c478bd9Sstevel@tonic-gate
6627c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&mechlist_lock);
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate found = find_mech_index(mechanism, &index);
6657c478bd9Sstevel@tonic-gate if (!found) {
6667c478bd9Sstevel@tonic-gate goto finish;
6677c478bd9Sstevel@tonic-gate }
6687c478bd9Sstevel@tonic-gate
6697c478bd9Sstevel@tonic-gate if ((mechlist[index].slots[slotnum].initialized) &&
6707c478bd9Sstevel@tonic-gate (mechlist[index].slots[slotnum].supported)) {
671*d3a28a55Sdinak if (mech_info) {
672*d3a28a55Sdinak info = mechlist[index].slots[slotnum].mechanism_info;
673*d3a28a55Sdinak if (!(info.flags & mech_info->flags)) {
674*d3a28a55Sdinak goto finish;
675*d3a28a55Sdinak }
676*d3a28a55Sdinak }
6777c478bd9Sstevel@tonic-gate *supports = B_TRUE;
6787c478bd9Sstevel@tonic-gate if (slot_info) {
6797c478bd9Sstevel@tonic-gate *slot_info = &(mechlist[index].slots[slotnum]);
6807c478bd9Sstevel@tonic-gate }
6817c478bd9Sstevel@tonic-gate }
6827c478bd9Sstevel@tonic-gate
6837c478bd9Sstevel@tonic-gate finish:
6847c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&mechlist_lock);
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate return (rv);
6877c478bd9Sstevel@tonic-gate }
688