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