xref: /titanic_41/usr/src/lib/pkcs11/libpkcs11/common/metaMechManager.c (revision d3a28a554b9205bf55157ee542394fa7ee72fe4b)
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