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
5fb27b1cdSmcpowers  * Common Development and Distribution License (the "License").
6fb27b1cdSmcpowers  * 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*9b009fc1SValerie Bubb Fenwick  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate  * This file contains routines which call into a provider's
277c478bd9Sstevel@tonic-gate  * entry points and do other related work.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <sys/systm.h>
327c478bd9Sstevel@tonic-gate #include <sys/taskq_impl.h>
337c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <sys/crypto/common.h>
367c478bd9Sstevel@tonic-gate #include <sys/crypto/impl.h>
377c478bd9Sstevel@tonic-gate #include <sys/crypto/sched_impl.h>
387c478bd9Sstevel@tonic-gate 
39436935a1SVladimir Kotal #include <sys/sdt.h>
40436935a1SVladimir Kotal 
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate  * Return B_TRUE if the specified entry point is NULL. We rely on the
437c478bd9Sstevel@tonic-gate  * caller to provide, with offset_1 and offset_2, information to calculate
447c478bd9Sstevel@tonic-gate  * the location of the entry point. The ops argument is a temporary local
457c478bd9Sstevel@tonic-gate  * variable defined as caddr_t *.
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate #define	KCF_PROV_NULL_ENTRY_POINT(pd, o1, o2, ops)			\
4895014fbbSDan OpenSolaris Anderson 	(ops = (caddr_t *)(void *)((caddr_t)(pd)->pd_ops_vector + (o1)), \
4995014fbbSDan OpenSolaris Anderson 	(*ops == NULL || *(caddr_t *)(void *)((caddr_t)(*ops) + (o2)) == NULL))
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate static int kcf_emulate_dual(kcf_provider_desc_t *, crypto_ctx_t *,
537c478bd9Sstevel@tonic-gate     kcf_req_params_t *);
54ef56a3c5SKrishna Yenduri 
557c478bd9Sstevel@tonic-gate void
kcf_free_triedlist(kcf_prov_tried_t * list)567c478bd9Sstevel@tonic-gate kcf_free_triedlist(kcf_prov_tried_t *list)
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate 	kcf_prov_tried_t *l;
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate 	while ((l = list) != NULL) {
617c478bd9Sstevel@tonic-gate 		list = list->pt_next;
627c478bd9Sstevel@tonic-gate 		KCF_PROV_REFRELE(l->pt_pd);
637c478bd9Sstevel@tonic-gate 		kmem_free(l, sizeof (kcf_prov_tried_t));
647c478bd9Sstevel@tonic-gate 	}
657c478bd9Sstevel@tonic-gate }
667c478bd9Sstevel@tonic-gate 
67ef56a3c5SKrishna Yenduri /*
68ef56a3c5SKrishna Yenduri  * The typical caller of this routine does a kcf_get_mech_provider()
69ef56a3c5SKrishna Yenduri  * which holds the provider and then calls this routine. So, for the
70ef56a3c5SKrishna Yenduri  * common case (no KCF_HOLD_PROV flag) we skip doing a KCF_PROV_REFHOLD.
71ef56a3c5SKrishna Yenduri  */
727c478bd9Sstevel@tonic-gate kcf_prov_tried_t *
kcf_insert_triedlist(kcf_prov_tried_t ** list,kcf_provider_desc_t * pd,int flags)737c478bd9Sstevel@tonic-gate kcf_insert_triedlist(kcf_prov_tried_t **list, kcf_provider_desc_t *pd,
74ef56a3c5SKrishna Yenduri     int flags)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate 	kcf_prov_tried_t *l;
777c478bd9Sstevel@tonic-gate 
78ef56a3c5SKrishna Yenduri 	l = kmem_alloc(sizeof (kcf_prov_tried_t),
79ef56a3c5SKrishna Yenduri 	    flags & (KM_SLEEP | KM_NOSLEEP));
807c478bd9Sstevel@tonic-gate 	if (l == NULL)
817c478bd9Sstevel@tonic-gate 		return (NULL);
827c478bd9Sstevel@tonic-gate 
83ef56a3c5SKrishna Yenduri 	if (flags & KCF_HOLD_PROV)
84ef56a3c5SKrishna Yenduri 		KCF_PROV_REFHOLD(pd);
857c478bd9Sstevel@tonic-gate 	l->pt_pd = pd;
867c478bd9Sstevel@tonic-gate 	l->pt_next = *list;
877c478bd9Sstevel@tonic-gate 	*list = l;
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	return (l);
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate static boolean_t
is_in_triedlist(kcf_provider_desc_t * pd,kcf_prov_tried_t * triedl)937c478bd9Sstevel@tonic-gate is_in_triedlist(kcf_provider_desc_t *pd, kcf_prov_tried_t *triedl)
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate 	while (triedl != NULL) {
967c478bd9Sstevel@tonic-gate 		if (triedl->pt_pd == pd)
977c478bd9Sstevel@tonic-gate 			return (B_TRUE);
987c478bd9Sstevel@tonic-gate 		triedl = triedl->pt_next;
997c478bd9Sstevel@tonic-gate 	};
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	return (B_FALSE);
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate 
104436935a1SVladimir Kotal /*
105436935a1SVladimir Kotal  * Check if the key/attribute length is within the limits of given provider
106436935a1SVladimir Kotal  * and mechanism. Return 0 if the key length is off the limits, 1 otherwise.
107436935a1SVladimir Kotal  * In the latter case, this either means the key length is within the limits
108436935a1SVladimir Kotal  * or we are not able to perform check for a key type.
109436935a1SVladimir Kotal  */
110436935a1SVladimir Kotal static int
kcf_check_prov_mech_keylen(kcf_provider_desc_t * provider,crypto_mech_type_t mech_type,crypto_key_t * key)111436935a1SVladimir Kotal kcf_check_prov_mech_keylen(kcf_provider_desc_t *provider,
112436935a1SVladimir Kotal 	crypto_mech_type_t mech_type,
113436935a1SVladimir Kotal 	crypto_key_t *key)
114436935a1SVladimir Kotal {
115436935a1SVladimir Kotal 	crypto_mech_info_t *mech_info = NULL;
1166033a792SVladimir Kotal 	size_t keylen = 0;
117436935a1SVladimir Kotal 	ssize_t attr_len;
118436935a1SVladimir Kotal 	uchar_t *attr;
119436935a1SVladimir Kotal 
120436935a1SVladimir Kotal 	mech_info = &(KCF_TO_PROV_MECHINFO(provider, mech_type));
121436935a1SVladimir Kotal 	switch (key->ck_format) {
122436935a1SVladimir Kotal 		case CRYPTO_KEY_RAW:
123436935a1SVladimir Kotal 			/* ck_length is always in bits */
124436935a1SVladimir Kotal 			if (mech_info->cm_mech_flags &
125436935a1SVladimir Kotal 			    CRYPTO_KEYSIZE_UNIT_IN_BYTES)
126436935a1SVladimir Kotal 				keylen = CRYPTO_BITS2BYTES(key->ck_length);
127436935a1SVladimir Kotal 			else
128436935a1SVladimir Kotal 				keylen = key->ck_length;
129436935a1SVladimir Kotal 			break;
130436935a1SVladimir Kotal 
131436935a1SVladimir Kotal 		case CRYPTO_KEY_ATTR_LIST:
132436935a1SVladimir Kotal 			/* Check modulus for RSA operations. */
133436935a1SVladimir Kotal 			if ((crypto_get_key_attr(key, SUN_CKA_MODULUS,
134436935a1SVladimir Kotal 			    &attr, &attr_len)) == CRYPTO_SUCCESS) {
135436935a1SVladimir Kotal 				/* modulus length is returned in bytes */
136436935a1SVladimir Kotal 				if (mech_info->cm_mech_flags &
137436935a1SVladimir Kotal 				    CRYPTO_KEYSIZE_UNIT_IN_BITS)
13895014fbbSDan OpenSolaris Anderson 					keylen = CRYPTO_BYTES2BITS(attr_len);
139436935a1SVladimir Kotal 				else
140436935a1SVladimir Kotal 					keylen = attr_len;
141436935a1SVladimir Kotal 			/* Check prime for DH/DSA operations. */
142436935a1SVladimir Kotal 			} else if ((crypto_get_key_attr(key, SUN_CKA_PRIME,
143436935a1SVladimir Kotal 			    &attr, &attr_len)) == CRYPTO_SUCCESS) {
144436935a1SVladimir Kotal 				/* prime length is returned in bytes */
145436935a1SVladimir Kotal 				if (mech_info->cm_mech_flags &
146436935a1SVladimir Kotal 				    CRYPTO_KEYSIZE_UNIT_IN_BITS)
14795014fbbSDan OpenSolaris Anderson 					keylen = CRYPTO_BYTES2BITS(attr_len);
148436935a1SVladimir Kotal 				else
149436935a1SVladimir Kotal 					keylen = attr_len;
150436935a1SVladimir Kotal 			}
151436935a1SVladimir Kotal 
152436935a1SVladimir Kotal 			/*
153436935a1SVladimir Kotal 			 * If the attribute is not found we cannot do
154436935a1SVladimir Kotal 			 * the check so return with success and let
155436935a1SVladimir Kotal 			 * the actual provider do the check.
156436935a1SVladimir Kotal 			 */
157436935a1SVladimir Kotal 			if (keylen == 0)
158436935a1SVladimir Kotal 				return (1);
159436935a1SVladimir Kotal 			break;
160436935a1SVladimir Kotal 
161436935a1SVladimir Kotal 		default:
162436935a1SVladimir Kotal 			/*
163436935a1SVladimir Kotal 			 * We are not able to check CRYPTO_KEY_REFERENCE
164436935a1SVladimir Kotal 			 * or other key types here.
165436935a1SVladimir Kotal 			 */
166436935a1SVladimir Kotal 			return (1);
167436935a1SVladimir Kotal 	}
168436935a1SVladimir Kotal 
169436935a1SVladimir Kotal 	DTRACE_PROBE4(keylen__check,
170436935a1SVladimir Kotal 	    crypto_mech_type_t, mech_type,
1716033a792SVladimir Kotal 	    size_t, keylen,
172436935a1SVladimir Kotal 	    ssize_t, mech_info->cm_min_key_length,
173436935a1SVladimir Kotal 	    ssize_t, mech_info->cm_max_key_length);
174436935a1SVladimir Kotal 	/* Do the actual check. */
175436935a1SVladimir Kotal 	if ((keylen > mech_info->cm_max_key_length) ||
176436935a1SVladimir Kotal 	    (keylen < mech_info->cm_min_key_length)) {
177436935a1SVladimir Kotal 		return (0);
178436935a1SVladimir Kotal 	}
179436935a1SVladimir Kotal 
180436935a1SVladimir Kotal 	return (1);
181436935a1SVladimir Kotal }
182436935a1SVladimir Kotal 
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate  * Search a mech entry's hardware provider list for the specified
1857c478bd9Sstevel@tonic-gate  * provider. Return true if found.
1867c478bd9Sstevel@tonic-gate  */
1877c478bd9Sstevel@tonic-gate static boolean_t
is_valid_provider_for_mech(kcf_provider_desc_t * pd,kcf_mech_entry_t * me,crypto_func_group_t fg)18872eff6e2Smcpowers is_valid_provider_for_mech(kcf_provider_desc_t *pd, kcf_mech_entry_t *me,
18972eff6e2Smcpowers     crypto_func_group_t fg)
1907c478bd9Sstevel@tonic-gate {
1917c478bd9Sstevel@tonic-gate 	kcf_prov_mech_desc_t *prov_chain;
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	prov_chain = me->me_hw_prov_chain;
1947c478bd9Sstevel@tonic-gate 	if (prov_chain != NULL) {
1957c478bd9Sstevel@tonic-gate 		ASSERT(me->me_num_hwprov > 0);
1967c478bd9Sstevel@tonic-gate 		for (; prov_chain != NULL; prov_chain = prov_chain->pm_next) {
19772eff6e2Smcpowers 			if (prov_chain->pm_prov_desc == pd &&
19872eff6e2Smcpowers 			    IS_FG_SUPPORTED(prov_chain, fg)) {
1997c478bd9Sstevel@tonic-gate 				return (B_TRUE);
2007c478bd9Sstevel@tonic-gate 			}
2017c478bd9Sstevel@tonic-gate 		}
2027c478bd9Sstevel@tonic-gate 	}
2037c478bd9Sstevel@tonic-gate 	return (B_FALSE);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate /*
2077c478bd9Sstevel@tonic-gate  * This routine, given a logical provider, returns the least loaded
2087c478bd9Sstevel@tonic-gate  * provider belonging to the logical provider. The provider must be
2097c478bd9Sstevel@tonic-gate  * able to do the specified mechanism, i.e. check that the mechanism
2107c478bd9Sstevel@tonic-gate  * hasn't been disabled. In addition, just in case providers are not
2117c478bd9Sstevel@tonic-gate  * entirely equivalent, the provider's entry point is checked for
2127c478bd9Sstevel@tonic-gate  * non-nullness. This is accomplished by having the caller pass, as
2137c478bd9Sstevel@tonic-gate  * arguments, the offset of the function group (offset_1), and the
2147c478bd9Sstevel@tonic-gate  * offset of the function within the function group (offset_2).
215436935a1SVladimir Kotal  *
216436935a1SVladimir Kotal  * If a non-NULL key structure is supplied, the provider will be checked
217436935a1SVladimir Kotal  * to see if the key length falls into the limits of given mechanism
218436935a1SVladimir Kotal  * for that provider. This is done for both key structures and mechanisms.
219436935a1SVladimir Kotal  *
2207c478bd9Sstevel@tonic-gate  * Returns NULL if no provider can be found.
2217c478bd9Sstevel@tonic-gate  */
2227c478bd9Sstevel@tonic-gate int
kcf_get_hardware_provider(crypto_mech_type_t mech_type_1,crypto_key_t * key1,crypto_mech_type_t mech_type_2,crypto_key_t * key2,kcf_provider_desc_t * old,kcf_provider_desc_t ** new,crypto_func_group_t fg)223436935a1SVladimir Kotal kcf_get_hardware_provider(crypto_mech_type_t mech_type_1, crypto_key_t *key1,
224*9b009fc1SValerie Bubb Fenwick     crypto_mech_type_t mech_type_2, crypto_key_t *key2,
22572eff6e2Smcpowers     kcf_provider_desc_t *old, kcf_provider_desc_t **new, crypto_func_group_t fg)
2267c478bd9Sstevel@tonic-gate {
22772eff6e2Smcpowers 	kcf_provider_desc_t *provider, *real_pd = old;
22872eff6e2Smcpowers 	kcf_provider_desc_t *gpd = NULL;	/* good provider */
22972eff6e2Smcpowers 	kcf_provider_desc_t *bpd = NULL;	/* busy provider */
2307c478bd9Sstevel@tonic-gate 	kcf_provider_list_t *p;
2317c478bd9Sstevel@tonic-gate 	kcf_ops_class_t class;
2327c478bd9Sstevel@tonic-gate 	kcf_mech_entry_t *me;
2337c478bd9Sstevel@tonic-gate 	kcf_mech_entry_tab_t *me_tab;
2347c478bd9Sstevel@tonic-gate 	int index, len, gqlen = INT_MAX, rv = CRYPTO_SUCCESS;
235ef56a3c5SKrishna Yenduri 	kcf_lock_withpad_t *mp;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	/* get the mech entry for the specified mechanism */
238894b2776Smcpowers 	class = KCF_MECH2CLASS(mech_type_1);
2397c478bd9Sstevel@tonic-gate 	if ((class < KCF_FIRST_OPSCLASS) || (class > KCF_LAST_OPSCLASS)) {
2407c478bd9Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
2417c478bd9Sstevel@tonic-gate 	}
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	me_tab = &kcf_mech_tabs_tab[class];
244894b2776Smcpowers 	index = KCF_MECH2INDEX(mech_type_1);
2457c478bd9Sstevel@tonic-gate 	if ((index < 0) || (index >= me_tab->met_size)) {
2467c478bd9Sstevel@tonic-gate 		return (CRYPTO_MECHANISM_INVALID);
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	me = &((me_tab->met_tab)[index]);
250ef56a3c5SKrishna Yenduri 	mp = &me_mutexes[CPU_SEQID];
251ef56a3c5SKrishna Yenduri 	mutex_enter(&mp->kl_lock);
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	/*
2547c478bd9Sstevel@tonic-gate 	 * We assume the provider descriptor will not go away because
2557c478bd9Sstevel@tonic-gate 	 * it is being held somewhere, i.e. its reference count has been
2567c478bd9Sstevel@tonic-gate 	 * incremented. In the case of the crypto module, the provider
2577c478bd9Sstevel@tonic-gate 	 * descriptor is held by the session structure.
2587c478bd9Sstevel@tonic-gate 	 */
2597c478bd9Sstevel@tonic-gate 	if (old->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
2607c478bd9Sstevel@tonic-gate 		if (old->pd_provider_list == NULL) {
2617c478bd9Sstevel@tonic-gate 			real_pd = NULL;
2627c478bd9Sstevel@tonic-gate 			rv = CRYPTO_DEVICE_ERROR;
2637c478bd9Sstevel@tonic-gate 			goto out;
2647c478bd9Sstevel@tonic-gate 		}
2657c478bd9Sstevel@tonic-gate 		/*
266c41e7ccaSkrishna 		 * Find the least loaded real provider. KCF_PROV_LOAD gives
267c41e7ccaSkrishna 		 * the load (number of pending requests) of the provider.
2687c478bd9Sstevel@tonic-gate 		 */
2697c478bd9Sstevel@tonic-gate 		mutex_enter(&old->pd_lock);
2707c478bd9Sstevel@tonic-gate 		p = old->pd_provider_list;
2717c478bd9Sstevel@tonic-gate 		while (p != NULL) {
2727c478bd9Sstevel@tonic-gate 			provider = p->pl_provider;
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 			ASSERT(provider->pd_prov_type !=
2757c478bd9Sstevel@tonic-gate 			    CRYPTO_LOGICAL_PROVIDER);
2767c478bd9Sstevel@tonic-gate 
27772eff6e2Smcpowers 			if (!is_valid_provider_for_mech(provider, me, fg)) {
2787c478bd9Sstevel@tonic-gate 				p = p->pl_next;
2797c478bd9Sstevel@tonic-gate 				continue;
2807c478bd9Sstevel@tonic-gate 			}
2817c478bd9Sstevel@tonic-gate 
282436935a1SVladimir Kotal 			if ((key1 != NULL) &&
283436935a1SVladimir Kotal 			    !kcf_check_prov_mech_keylen(provider, mech_type_1,
284436935a1SVladimir Kotal 			    key1)) {
285436935a1SVladimir Kotal 				p = p->pl_next;
286436935a1SVladimir Kotal 				rv = CRYPTO_KEY_SIZE_RANGE;
287436935a1SVladimir Kotal 				continue;
288436935a1SVladimir Kotal 			}
289436935a1SVladimir Kotal 
290894b2776Smcpowers 			/* provider does second mech */
291894b2776Smcpowers 			if (mech_type_2 != CRYPTO_MECH_INVALID) {
292894b2776Smcpowers 				int i;
293894b2776Smcpowers 
2946a1073f8Skrishna 				i = KCF_TO_PROV_MECH_INDX(provider,
2956a1073f8Skrishna 				    mech_type_2);
2966a1073f8Skrishna 				if (i == KCF_INVALID_INDX) {
297894b2776Smcpowers 					p = p->pl_next;
298894b2776Smcpowers 					continue;
299894b2776Smcpowers 				}
300436935a1SVladimir Kotal 
301436935a1SVladimir Kotal 				if ((key2 != NULL) &&
302436935a1SVladimir Kotal 				    !kcf_check_prov_mech_keylen(provider,
303436935a1SVladimir Kotal 				    mech_type_2, key2)) {
304436935a1SVladimir Kotal 					p = p->pl_next;
305436935a1SVladimir Kotal 					rv = CRYPTO_KEY_SIZE_RANGE;
306436935a1SVladimir Kotal 					continue;
307436935a1SVladimir Kotal 				}
308894b2776Smcpowers 			}
309894b2776Smcpowers 
31072eff6e2Smcpowers 			if (provider->pd_state != KCF_PROV_READY) {
31172eff6e2Smcpowers 				/* choose BUSY if no READY providers */
31272eff6e2Smcpowers 				if (provider->pd_state == KCF_PROV_BUSY)
31372eff6e2Smcpowers 					bpd = provider;
3147c478bd9Sstevel@tonic-gate 				p = p->pl_next;
3157c478bd9Sstevel@tonic-gate 				continue;
3167c478bd9Sstevel@tonic-gate 			}
3177c478bd9Sstevel@tonic-gate 
318ef56a3c5SKrishna Yenduri 			/* Do load calculation only if needed */
319ef56a3c5SKrishna Yenduri 			if ((p = p->pl_next) == NULL && gpd == NULL) {
3207c478bd9Sstevel@tonic-gate 				gpd = provider;
321ef56a3c5SKrishna Yenduri 			} else {
322ef56a3c5SKrishna Yenduri 				len = KCF_PROV_LOAD(provider);
323ef56a3c5SKrishna Yenduri 				if (len < gqlen) {
324ef56a3c5SKrishna Yenduri 					gqlen = len;
325ef56a3c5SKrishna Yenduri 					gpd = provider;
326ef56a3c5SKrishna Yenduri 				}
3277c478bd9Sstevel@tonic-gate 			}
3287c478bd9Sstevel@tonic-gate 		}
3297c478bd9Sstevel@tonic-gate 
330894b2776Smcpowers 		if (gpd != NULL) {
3317c478bd9Sstevel@tonic-gate 			real_pd = gpd;
332436935a1SVladimir Kotal 			rv = CRYPTO_SUCCESS;
333894b2776Smcpowers 			KCF_PROV_REFHOLD(real_pd);
33472eff6e2Smcpowers 		} else if (bpd != NULL) {
33572eff6e2Smcpowers 			real_pd = bpd;
336436935a1SVladimir Kotal 			rv = CRYPTO_SUCCESS;
33772eff6e2Smcpowers 			KCF_PROV_REFHOLD(real_pd);
338894b2776Smcpowers 		} else {
3397c478bd9Sstevel@tonic-gate 			/* can't find provider */
3407c478bd9Sstevel@tonic-gate 			real_pd = NULL;
341436935a1SVladimir Kotal 			if (rv == CRYPTO_SUCCESS)
342436935a1SVladimir Kotal 				rv = CRYPTO_MECHANISM_INVALID;
3437c478bd9Sstevel@tonic-gate 		}
344894b2776Smcpowers 		mutex_exit(&old->pd_lock);
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	} else {
347*9b009fc1SValerie Bubb Fenwick 		if (!KCF_IS_PROV_USABLE(old)) {
3487c478bd9Sstevel@tonic-gate 			real_pd = NULL;
3497c478bd9Sstevel@tonic-gate 			rv = CRYPTO_DEVICE_ERROR;
3507c478bd9Sstevel@tonic-gate 			goto out;
3517c478bd9Sstevel@tonic-gate 		}
3527c478bd9Sstevel@tonic-gate 
35372eff6e2Smcpowers 		if (!is_valid_provider_for_mech(old, me, fg)) {
3547c478bd9Sstevel@tonic-gate 			real_pd = NULL;
3557c478bd9Sstevel@tonic-gate 			rv = CRYPTO_MECHANISM_INVALID;
3567c478bd9Sstevel@tonic-gate 			goto out;
3577c478bd9Sstevel@tonic-gate 		}
3587c478bd9Sstevel@tonic-gate 
359436935a1SVladimir Kotal 		if ((key1 != NULL) &&
360436935a1SVladimir Kotal 		    !kcf_check_prov_mech_keylen(old, mech_type_1, key1)) {
361436935a1SVladimir Kotal 			real_pd = NULL;
362436935a1SVladimir Kotal 			rv = CRYPTO_KEY_SIZE_RANGE;
363436935a1SVladimir Kotal 			goto out;
364436935a1SVladimir Kotal 		}
365436935a1SVladimir Kotal 
366894b2776Smcpowers 		KCF_PROV_REFHOLD(real_pd);
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate out:
369ef56a3c5SKrishna Yenduri 	mutex_exit(&mp->kl_lock);
3707c478bd9Sstevel@tonic-gate 	*new = real_pd;
3717c478bd9Sstevel@tonic-gate 	return (rv);
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate /*
3757c478bd9Sstevel@tonic-gate  * This routine, given a logical provider, returns the least loaded
3767c478bd9Sstevel@tonic-gate  * provider belonging to the logical provider. Just in case providers
3777c478bd9Sstevel@tonic-gate  * are not entirely equivalent, the provider's entry point is checked
3787c478bd9Sstevel@tonic-gate  * for non-nullness. This is accomplished by having the caller pass, as
3797c478bd9Sstevel@tonic-gate  * arguments, the offset of the function group (offset_1), and the
3807c478bd9Sstevel@tonic-gate  * offset of the function within the function group (offset_2).
3817c478bd9Sstevel@tonic-gate  * Returns NULL if no provider can be found.
3827c478bd9Sstevel@tonic-gate  */
3837c478bd9Sstevel@tonic-gate int
kcf_get_hardware_provider_nomech(offset_t offset_1,offset_t offset_2,kcf_provider_desc_t * old,kcf_provider_desc_t ** new)3847c478bd9Sstevel@tonic-gate kcf_get_hardware_provider_nomech(offset_t offset_1, offset_t offset_2,
385*9b009fc1SValerie Bubb Fenwick     kcf_provider_desc_t *old, kcf_provider_desc_t **new)
3867c478bd9Sstevel@tonic-gate {
38772eff6e2Smcpowers 	kcf_provider_desc_t *provider, *real_pd = old;
38872eff6e2Smcpowers 	kcf_provider_desc_t *gpd = NULL;	/* good provider */
38972eff6e2Smcpowers 	kcf_provider_desc_t *bpd = NULL;	/* busy provider */
3907c478bd9Sstevel@tonic-gate 	kcf_provider_list_t *p;
3917c478bd9Sstevel@tonic-gate 	caddr_t *ops;
3927c478bd9Sstevel@tonic-gate 	int len, gqlen = INT_MAX, rv = CRYPTO_SUCCESS;
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 	/*
3957c478bd9Sstevel@tonic-gate 	 * We assume the provider descriptor will not go away because
3967c478bd9Sstevel@tonic-gate 	 * it is being held somewhere, i.e. its reference count has been
3977c478bd9Sstevel@tonic-gate 	 * incremented. In the case of the crypto module, the provider
3987c478bd9Sstevel@tonic-gate 	 * descriptor is held by the session structure.
3997c478bd9Sstevel@tonic-gate 	 */
4007c478bd9Sstevel@tonic-gate 	if (old->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
4017c478bd9Sstevel@tonic-gate 		if (old->pd_provider_list == NULL) {
4027c478bd9Sstevel@tonic-gate 			real_pd = NULL;
4037c478bd9Sstevel@tonic-gate 			rv = CRYPTO_DEVICE_ERROR;
4047c478bd9Sstevel@tonic-gate 			goto out;
4057c478bd9Sstevel@tonic-gate 		}
4067c478bd9Sstevel@tonic-gate 		/*
407c41e7ccaSkrishna 		 * Find the least loaded real provider. KCF_PROV_LOAD gives
408c41e7ccaSkrishna 		 * the load (number of pending requests) of the provider.
4097c478bd9Sstevel@tonic-gate 		 */
4107c478bd9Sstevel@tonic-gate 		mutex_enter(&old->pd_lock);
4117c478bd9Sstevel@tonic-gate 		p = old->pd_provider_list;
4127c478bd9Sstevel@tonic-gate 		while (p != NULL) {
4137c478bd9Sstevel@tonic-gate 			provider = p->pl_provider;
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 			ASSERT(provider->pd_prov_type !=
4167c478bd9Sstevel@tonic-gate 			    CRYPTO_LOGICAL_PROVIDER);
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 			if (KCF_PROV_NULL_ENTRY_POINT(provider, offset_1,
4197c478bd9Sstevel@tonic-gate 			    offset_2, ops)) {
4207c478bd9Sstevel@tonic-gate 				p = p->pl_next;
4217c478bd9Sstevel@tonic-gate 				continue;
4227c478bd9Sstevel@tonic-gate 			}
4237c478bd9Sstevel@tonic-gate 
42472eff6e2Smcpowers 			if (provider->pd_state != KCF_PROV_READY) {
42572eff6e2Smcpowers 				/* choose BUSY if no READY providers */
42672eff6e2Smcpowers 				if (provider->pd_state == KCF_PROV_BUSY)
42772eff6e2Smcpowers 					bpd = provider;
42872eff6e2Smcpowers 				p = p->pl_next;
42972eff6e2Smcpowers 				continue;
43072eff6e2Smcpowers 			}
43172eff6e2Smcpowers 
432ef56a3c5SKrishna Yenduri 			/* Do load calculation only if needed */
433ef56a3c5SKrishna Yenduri 			if ((p = p->pl_next) == NULL && gpd == NULL) {
4347c478bd9Sstevel@tonic-gate 				gpd = provider;
435ef56a3c5SKrishna Yenduri 			} else {
436ef56a3c5SKrishna Yenduri 				len = KCF_PROV_LOAD(provider);
437ef56a3c5SKrishna Yenduri 				if (len < gqlen) {
438ef56a3c5SKrishna Yenduri 					gqlen = len;
439ef56a3c5SKrishna Yenduri 					gpd = provider;
440ef56a3c5SKrishna Yenduri 				}
4417c478bd9Sstevel@tonic-gate 			}
4427c478bd9Sstevel@tonic-gate 		}
4437c478bd9Sstevel@tonic-gate 		mutex_exit(&old->pd_lock);
4447c478bd9Sstevel@tonic-gate 
445894b2776Smcpowers 		if (gpd != NULL) {
4467c478bd9Sstevel@tonic-gate 			real_pd = gpd;
447894b2776Smcpowers 			KCF_PROV_REFHOLD(real_pd);
44872eff6e2Smcpowers 		} else if (bpd != NULL) {
44972eff6e2Smcpowers 			real_pd = bpd;
45072eff6e2Smcpowers 			KCF_PROV_REFHOLD(real_pd);
451894b2776Smcpowers 		} else {
4527c478bd9Sstevel@tonic-gate 			/* can't find provider */
4537c478bd9Sstevel@tonic-gate 			real_pd = NULL;
4547c478bd9Sstevel@tonic-gate 			rv = CRYPTO_DEVICE_ERROR;
4557c478bd9Sstevel@tonic-gate 		}
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	} else {
458*9b009fc1SValerie Bubb Fenwick 		if (!KCF_IS_PROV_USABLE(old)) {
4597c478bd9Sstevel@tonic-gate 			real_pd = NULL;
4607c478bd9Sstevel@tonic-gate 			rv = CRYPTO_DEVICE_ERROR;
4617c478bd9Sstevel@tonic-gate 			goto out;
4627c478bd9Sstevel@tonic-gate 		}
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 		if (KCF_PROV_NULL_ENTRY_POINT(old, offset_1, offset_2, ops)) {
4657c478bd9Sstevel@tonic-gate 			real_pd = NULL;
4667c478bd9Sstevel@tonic-gate 			rv = CRYPTO_NOT_SUPPORTED;
467894b2776Smcpowers 			goto out;
4687c478bd9Sstevel@tonic-gate 		}
469894b2776Smcpowers 		KCF_PROV_REFHOLD(real_pd);
4707c478bd9Sstevel@tonic-gate 	}
4717c478bd9Sstevel@tonic-gate out:
4727c478bd9Sstevel@tonic-gate 	*new = real_pd;
4737c478bd9Sstevel@tonic-gate 	return (rv);
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate /*
4777c478bd9Sstevel@tonic-gate  * Return the next member of a logical provider, given the previous
4787c478bd9Sstevel@tonic-gate  * member. The function returns true if the next member is found and
4797c478bd9Sstevel@tonic-gate  * bumps its refcnt before returning.
4807c478bd9Sstevel@tonic-gate  */
4817c478bd9Sstevel@tonic-gate boolean_t
kcf_get_next_logical_provider_member(kcf_provider_desc_t * logical_provider,kcf_provider_desc_t * prev,kcf_provider_desc_t ** pd)4827c478bd9Sstevel@tonic-gate kcf_get_next_logical_provider_member(kcf_provider_desc_t *logical_provider,
4837c478bd9Sstevel@tonic-gate     kcf_provider_desc_t *prev, kcf_provider_desc_t **pd)
4847c478bd9Sstevel@tonic-gate {
4857c478bd9Sstevel@tonic-gate 	kcf_provider_list_t *p;
4867c478bd9Sstevel@tonic-gate 	kcf_provider_desc_t *next;
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&logical_provider->pd_lock));
4897c478bd9Sstevel@tonic-gate 	p = logical_provider->pd_provider_list;
4907c478bd9Sstevel@tonic-gate 	while (p != NULL) {
4917c478bd9Sstevel@tonic-gate 		/* start the search */
4927c478bd9Sstevel@tonic-gate 		if (prev == NULL) {
4937c478bd9Sstevel@tonic-gate 			next = p->pl_provider;
4947c478bd9Sstevel@tonic-gate 			goto found;
4957c478bd9Sstevel@tonic-gate 		} else {
4967c478bd9Sstevel@tonic-gate 			/* find where we were before */
4977c478bd9Sstevel@tonic-gate 			if (p->pl_provider == prev) {
4987c478bd9Sstevel@tonic-gate 				if (p->pl_next != NULL) {
4997c478bd9Sstevel@tonic-gate 					next = p->pl_next->pl_provider;
5007c478bd9Sstevel@tonic-gate 					goto found;
5017c478bd9Sstevel@tonic-gate 				}
5027c478bd9Sstevel@tonic-gate 			}
5037c478bd9Sstevel@tonic-gate 		}
5047c478bd9Sstevel@tonic-gate 		p = p->pl_next;
5057c478bd9Sstevel@tonic-gate 	}
5067c478bd9Sstevel@tonic-gate 	return (B_FALSE);
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate found:
5097c478bd9Sstevel@tonic-gate 	KCF_PROV_REFHOLD(next);
5107c478bd9Sstevel@tonic-gate 	*pd = next;
5117c478bd9Sstevel@tonic-gate 	return (B_TRUE);
5127c478bd9Sstevel@tonic-gate }
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate /*
5157c478bd9Sstevel@tonic-gate  * Return the best provider for the specified mechanism. The provider
5167c478bd9Sstevel@tonic-gate  * is held and it is the caller's responsibility to release it when done.
5177c478bd9Sstevel@tonic-gate  * The fg input argument is used as a search criterion to pick a provider.
518436935a1SVladimir Kotal  * A provider has to support this function group to be picked. If a non-NULL
519436935a1SVladimir Kotal  * key structure is supplied, the provider will be checked to see if the key
520436935a1SVladimir Kotal  * length falls into the limits of given mechanism for that provider.
5217c478bd9Sstevel@tonic-gate  *
5227c478bd9Sstevel@tonic-gate  * Find the least loaded provider in the list of providers. We do a linear
5237c478bd9Sstevel@tonic-gate  * search to find one. This is fine as we assume there are only a few
5247c478bd9Sstevel@tonic-gate  * number of providers in this list. If this assumption ever changes,
5257c478bd9Sstevel@tonic-gate  * we should revisit this.
5267c478bd9Sstevel@tonic-gate  *
5277c478bd9Sstevel@tonic-gate  */
5287c478bd9Sstevel@tonic-gate kcf_provider_desc_t *
kcf_get_mech_provider(crypto_mech_type_t mech_type,crypto_key_t * key,kcf_mech_entry_t ** mepp,int * error,kcf_prov_tried_t * triedl,crypto_func_group_t fg,size_t data_size)529436935a1SVladimir Kotal kcf_get_mech_provider(crypto_mech_type_t mech_type, crypto_key_t *key,
530436935a1SVladimir Kotal     kcf_mech_entry_t **mepp, int *error, kcf_prov_tried_t *triedl,
531*9b009fc1SValerie Bubb Fenwick     crypto_func_group_t fg, size_t data_size)
5327c478bd9Sstevel@tonic-gate {
5337c478bd9Sstevel@tonic-gate 	kcf_provider_desc_t *pd = NULL, *gpd = NULL;
5347c478bd9Sstevel@tonic-gate 	kcf_prov_mech_desc_t *prov_chain, *mdesc;
5357c478bd9Sstevel@tonic-gate 	int len, gqlen = INT_MAX;
5367c478bd9Sstevel@tonic-gate 	kcf_ops_class_t class;
5377c478bd9Sstevel@tonic-gate 	int index;
5387c478bd9Sstevel@tonic-gate 	kcf_mech_entry_t *me;
5397c478bd9Sstevel@tonic-gate 	kcf_mech_entry_tab_t *me_tab;
540ef56a3c5SKrishna Yenduri 	kcf_lock_withpad_t *mp;
541436935a1SVladimir Kotal 	int error_val = CRYPTO_MECH_NOT_SUPPORTED; /* default error value */
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	class = KCF_MECH2CLASS(mech_type);
5447c478bd9Sstevel@tonic-gate 	if ((class < KCF_FIRST_OPSCLASS) || (class > KCF_LAST_OPSCLASS)) {
5457c478bd9Sstevel@tonic-gate 		*error = CRYPTO_MECHANISM_INVALID;
5467c478bd9Sstevel@tonic-gate 		return (NULL);
5477c478bd9Sstevel@tonic-gate 	}
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 	me_tab = &kcf_mech_tabs_tab[class];
5507c478bd9Sstevel@tonic-gate 	index = KCF_MECH2INDEX(mech_type);
5517c478bd9Sstevel@tonic-gate 	if ((index < 0) || (index >= me_tab->met_size)) {
5527c478bd9Sstevel@tonic-gate 		*error = CRYPTO_MECHANISM_INVALID;
5537c478bd9Sstevel@tonic-gate 		return (NULL);
5547c478bd9Sstevel@tonic-gate 	}
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	me = &((me_tab->met_tab)[index]);
5577c478bd9Sstevel@tonic-gate 	if (mepp != NULL)
5587c478bd9Sstevel@tonic-gate 		*mepp = me;
5597c478bd9Sstevel@tonic-gate 
560ef56a3c5SKrishna Yenduri 	mp = &me_mutexes[CPU_SEQID];
561ef56a3c5SKrishna Yenduri 	mutex_enter(&mp->kl_lock);
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	prov_chain = me->me_hw_prov_chain;
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	/*
566ef56a3c5SKrishna Yenduri 	 * We check for the threshold for using a hardware provider for
5677c478bd9Sstevel@tonic-gate 	 * this amount of data. If there is no software provider available
5687c478bd9Sstevel@tonic-gate 	 * for the mechanism, then the threshold is ignored.
5697c478bd9Sstevel@tonic-gate 	 */
5707c478bd9Sstevel@tonic-gate 	if ((prov_chain != NULL) &&
5717c478bd9Sstevel@tonic-gate 	    ((data_size == 0) || (me->me_threshold == 0) ||
5726a1073f8Skrishna 	    (data_size >= me->me_threshold) ||
5737c478bd9Sstevel@tonic-gate 	    ((mdesc = me->me_sw_prov) == NULL) ||
5747c478bd9Sstevel@tonic-gate 	    (!IS_FG_SUPPORTED(mdesc, fg)) ||
5757c478bd9Sstevel@tonic-gate 	    (!KCF_IS_PROV_USABLE(mdesc->pm_prov_desc)))) {
5767c478bd9Sstevel@tonic-gate 		ASSERT(me->me_num_hwprov > 0);
5777c478bd9Sstevel@tonic-gate 		/* there is at least one provider */
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 		/*
580c41e7ccaSkrishna 		 * Find the least loaded real provider. KCF_PROV_LOAD gives
581c41e7ccaSkrishna 		 * the load (number of pending requests) of the provider.
5827c478bd9Sstevel@tonic-gate 		 */
5837c478bd9Sstevel@tonic-gate 		while (prov_chain != NULL) {
5847c478bd9Sstevel@tonic-gate 			pd = prov_chain->pm_prov_desc;
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 			if (!IS_FG_SUPPORTED(prov_chain, fg) ||
5877c478bd9Sstevel@tonic-gate 			    !KCF_IS_PROV_USABLE(pd) ||
588*9b009fc1SValerie Bubb Fenwick 			    IS_PROVIDER_TRIED(pd, triedl)) {
5897c478bd9Sstevel@tonic-gate 				prov_chain = prov_chain->pm_next;
5907c478bd9Sstevel@tonic-gate 				continue;
5917c478bd9Sstevel@tonic-gate 			}
5927c478bd9Sstevel@tonic-gate 
593436935a1SVladimir Kotal 			if ((key != NULL) && !kcf_check_prov_mech_keylen(pd,
594436935a1SVladimir Kotal 			    mech_type, key)) {
595436935a1SVladimir Kotal 				prov_chain = prov_chain->pm_next;
596436935a1SVladimir Kotal 				error_val = CRYPTO_KEY_SIZE_RANGE;
597436935a1SVladimir Kotal 				continue;
598436935a1SVladimir Kotal 			}
599436935a1SVladimir Kotal 
600ef56a3c5SKrishna Yenduri 			/* Do load calculation only if needed */
601ef56a3c5SKrishna Yenduri 			if ((prov_chain = prov_chain->pm_next) == NULL &&
602ef56a3c5SKrishna Yenduri 			    gpd == NULL) {
6037c478bd9Sstevel@tonic-gate 				gpd = pd;
604ef56a3c5SKrishna Yenduri 			} else {
605ef56a3c5SKrishna Yenduri 				len = KCF_PROV_LOAD(pd);
606ef56a3c5SKrishna Yenduri 				if (len < gqlen) {
607ef56a3c5SKrishna Yenduri 					gqlen = len;
608ef56a3c5SKrishna Yenduri 					gpd = pd;
609ef56a3c5SKrishna Yenduri 				}
6107c478bd9Sstevel@tonic-gate 			}
6117c478bd9Sstevel@tonic-gate 		}
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 		pd = gpd;
6147c478bd9Sstevel@tonic-gate 	}
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	/* No HW provider for this mech, is there a SW provider? */
6177c478bd9Sstevel@tonic-gate 	if (pd == NULL && (mdesc = me->me_sw_prov) != NULL) {
6187c478bd9Sstevel@tonic-gate 		pd = mdesc->pm_prov_desc;
6197c478bd9Sstevel@tonic-gate 		if (!IS_FG_SUPPORTED(mdesc, fg) ||
6207c478bd9Sstevel@tonic-gate 		    !KCF_IS_PROV_USABLE(pd) ||
621*9b009fc1SValerie Bubb Fenwick 		    IS_PROVIDER_TRIED(pd, triedl))
6227c478bd9Sstevel@tonic-gate 			pd = NULL;
6237c478bd9Sstevel@tonic-gate 	}
6247c478bd9Sstevel@tonic-gate 
625436935a1SVladimir Kotal 	/* No provider found */
6267c478bd9Sstevel@tonic-gate 	if (pd == NULL) {
6277c478bd9Sstevel@tonic-gate 		/*
6287c478bd9Sstevel@tonic-gate 		 * We do not want to report CRYPTO_MECH_NOT_SUPPORTED, when
6297c478bd9Sstevel@tonic-gate 		 * we are in the "fallback to the next provider" case. Rather
6307c478bd9Sstevel@tonic-gate 		 * we preserve the error, so that the client gets the right
6317c478bd9Sstevel@tonic-gate 		 * error code.
6327c478bd9Sstevel@tonic-gate 		 */
6337c478bd9Sstevel@tonic-gate 		if (triedl == NULL)
634436935a1SVladimir Kotal 			*error = error_val;
635ef56a3c5SKrishna Yenduri 	} else {
6367c478bd9Sstevel@tonic-gate 		KCF_PROV_REFHOLD(pd);
637ef56a3c5SKrishna Yenduri 	}
6387c478bd9Sstevel@tonic-gate 
639ef56a3c5SKrishna Yenduri 	mutex_exit(&mp->kl_lock);
6407c478bd9Sstevel@tonic-gate 	return (pd);
6417c478bd9Sstevel@tonic-gate }
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate /*
6447c478bd9Sstevel@tonic-gate  * Very similar to kcf_get_mech_provider(). Finds the best provider capable of
6457c478bd9Sstevel@tonic-gate  * a dual operation with both me1 and me2.
646436935a1SVladimir Kotal  *
647436935a1SVladimir Kotal  * If a non-NULL key structure is supplied, the provider will be checked
648436935a1SVladimir Kotal  * to see if the key length falls into the limits of given mechanism
649436935a1SVladimir Kotal  * for that provider. This is done for both key structures and mechanisms.
650436935a1SVladimir Kotal  *
6517c478bd9Sstevel@tonic-gate  * When no dual-ops capable providers are available, return the best provider
6527c478bd9Sstevel@tonic-gate  * for me1 only, and sets *prov_mt2 to CRYPTO_INVALID_MECHID;
6537c478bd9Sstevel@tonic-gate  * We assume/expect that a slower HW capable of the dual is still
6547c478bd9Sstevel@tonic-gate  * faster than the 2 fastest providers capable of the individual ops
6557c478bd9Sstevel@tonic-gate  * separately.
6567c478bd9Sstevel@tonic-gate  */
6577c478bd9Sstevel@tonic-gate kcf_provider_desc_t *
kcf_get_dual_provider(crypto_mechanism_t * mech1,crypto_key_t * key1,crypto_mechanism_t * mech2,crypto_key_t * key2,kcf_mech_entry_t ** mepp,crypto_mech_type_t * prov_mt1,crypto_mech_type_t * prov_mt2,int * error,kcf_prov_tried_t * triedl,crypto_func_group_t fg1,crypto_func_group_t fg2,size_t data_size)658436935a1SVladimir Kotal kcf_get_dual_provider(crypto_mechanism_t *mech1, crypto_key_t *key1,
659436935a1SVladimir Kotal     crypto_mechanism_t *mech2, crypto_key_t *key2,
6607c478bd9Sstevel@tonic-gate     kcf_mech_entry_t **mepp, crypto_mech_type_t *prov_mt1,
6617c478bd9Sstevel@tonic-gate     crypto_mech_type_t *prov_mt2, int *error, kcf_prov_tried_t *triedl,
662*9b009fc1SValerie Bubb Fenwick     crypto_func_group_t fg1, crypto_func_group_t fg2,
6637c478bd9Sstevel@tonic-gate     size_t data_size)
6647c478bd9Sstevel@tonic-gate {
6657c478bd9Sstevel@tonic-gate 	kcf_provider_desc_t *pd = NULL, *pdm1 = NULL, *pdm1m2 = NULL;
6667c478bd9Sstevel@tonic-gate 	kcf_prov_mech_desc_t *prov_chain, *mdesc;
6677c478bd9Sstevel@tonic-gate 	int len, gqlen = INT_MAX, dgqlen = INT_MAX;
6687c478bd9Sstevel@tonic-gate 	crypto_mech_info_list_t *mil;
6697c478bd9Sstevel@tonic-gate 	crypto_mech_type_t m2id =  mech2->cm_type;
6707c478bd9Sstevel@tonic-gate 	kcf_mech_entry_t *me;
671ef56a3c5SKrishna Yenduri 	kcf_lock_withpad_t *mp;
672436935a1SVladimir Kotal 	int error_val = CRYPTO_MECH_NOT_SUPPORTED; /* default error value */
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 	/* when mech is a valid mechanism, me will be its mech_entry */
6757c478bd9Sstevel@tonic-gate 	if (kcf_get_mech_entry(mech1->cm_type, &me) != KCF_SUCCESS) {
6767c478bd9Sstevel@tonic-gate 		*error = CRYPTO_MECHANISM_INVALID;
6777c478bd9Sstevel@tonic-gate 		return (NULL);
6787c478bd9Sstevel@tonic-gate 	}
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 	*prov_mt2 = CRYPTO_MECH_INVALID;
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	if (mepp != NULL)
6837c478bd9Sstevel@tonic-gate 		*mepp = me;
684ef56a3c5SKrishna Yenduri 
685ef56a3c5SKrishna Yenduri 	mp = &me_mutexes[CPU_SEQID];
686ef56a3c5SKrishna Yenduri 	mutex_enter(&mp->kl_lock);
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 	prov_chain = me->me_hw_prov_chain;
6897c478bd9Sstevel@tonic-gate 	/*
6907c478bd9Sstevel@tonic-gate 	 * We check the threshold for using a hardware provider for
6917c478bd9Sstevel@tonic-gate 	 * this amount of data. If there is no software provider available
6927c478bd9Sstevel@tonic-gate 	 * for the first mechanism, then the threshold is ignored.
6937c478bd9Sstevel@tonic-gate 	 */
6947c478bd9Sstevel@tonic-gate 	if ((prov_chain != NULL) &&
6957c478bd9Sstevel@tonic-gate 	    ((data_size == 0) || (me->me_threshold == 0) ||
6966a1073f8Skrishna 	    (data_size >= me->me_threshold) ||
6977c478bd9Sstevel@tonic-gate 	    ((mdesc = me->me_sw_prov) == NULL) ||
6987c478bd9Sstevel@tonic-gate 	    (!IS_FG_SUPPORTED(mdesc, fg1)) ||
6997c478bd9Sstevel@tonic-gate 	    (!KCF_IS_PROV_USABLE(mdesc->pm_prov_desc)))) {
7007c478bd9Sstevel@tonic-gate 		/* there is at least one provider */
7017c478bd9Sstevel@tonic-gate 		ASSERT(me->me_num_hwprov > 0);
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 		/*
7047c478bd9Sstevel@tonic-gate 		 * Find the least loaded provider capable of the combo
7057c478bd9Sstevel@tonic-gate 		 * me1 + me2, and save a pointer to the least loaded
7067c478bd9Sstevel@tonic-gate 		 * provider capable of me1 only.
7077c478bd9Sstevel@tonic-gate 		 */
7087c478bd9Sstevel@tonic-gate 		while (prov_chain != NULL) {
7097c478bd9Sstevel@tonic-gate 			pd = prov_chain->pm_prov_desc;
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 			if (!IS_FG_SUPPORTED(prov_chain, fg1) ||
7127c478bd9Sstevel@tonic-gate 			    !KCF_IS_PROV_USABLE(pd) ||
713*9b009fc1SValerie Bubb Fenwick 			    IS_PROVIDER_TRIED(pd, triedl)) {
7147c478bd9Sstevel@tonic-gate 				prov_chain = prov_chain->pm_next;
7157c478bd9Sstevel@tonic-gate 				continue;
7167c478bd9Sstevel@tonic-gate 			}
7177c478bd9Sstevel@tonic-gate 
718436935a1SVladimir Kotal 			if ((key1 != NULL) && !kcf_check_prov_mech_keylen(pd,
719436935a1SVladimir Kotal 			    mech1->cm_type, key1)) {
720436935a1SVladimir Kotal 				prov_chain = prov_chain->pm_next;
721436935a1SVladimir Kotal 				error_val = CRYPTO_KEY_SIZE_RANGE;
722436935a1SVladimir Kotal 				continue;
723436935a1SVladimir Kotal 			}
724436935a1SVladimir Kotal 
725ef56a3c5SKrishna Yenduri #define	PMD_MECH_NUM(pmdp)	(pmdp)->pm_mech_info.cm_mech_number
726ef56a3c5SKrishna Yenduri 
727ef56a3c5SKrishna Yenduri 			/* Do load calculation only if needed */
728ef56a3c5SKrishna Yenduri 			if (prov_chain->pm_next == NULL && pdm1 == NULL) {
729ef56a3c5SKrishna Yenduri 				*prov_mt1 = PMD_MECH_NUM(prov_chain);
7307c478bd9Sstevel@tonic-gate 				pdm1 = pd;
731ef56a3c5SKrishna Yenduri 			} else {
732ef56a3c5SKrishna Yenduri 				len = KCF_PROV_LOAD(pd);
733ef56a3c5SKrishna Yenduri 
734ef56a3c5SKrishna Yenduri 				/* Save the best provider capable of m1 */
735ef56a3c5SKrishna Yenduri 				if (len < gqlen) {
736ef56a3c5SKrishna Yenduri 					*prov_mt1 = PMD_MECH_NUM(prov_chain);
737ef56a3c5SKrishna Yenduri 					gqlen = len;
738ef56a3c5SKrishna Yenduri 					pdm1 = pd;
739ef56a3c5SKrishna Yenduri 				}
7407c478bd9Sstevel@tonic-gate 			}
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 			/* See if pd can do me2 too */
7437c478bd9Sstevel@tonic-gate 			for (mil = prov_chain->pm_mi_list;
7447c478bd9Sstevel@tonic-gate 			    mil != NULL; mil = mil->ml_next) {
7457c478bd9Sstevel@tonic-gate 				if ((mil->ml_mech_info.cm_func_group_mask &
7467c478bd9Sstevel@tonic-gate 				    fg2) == 0)
7477c478bd9Sstevel@tonic-gate 					continue;
7487c478bd9Sstevel@tonic-gate 
749436935a1SVladimir Kotal 				if ((key2 != NULL) &&
750436935a1SVladimir Kotal 				    !kcf_check_prov_mech_keylen(pd,
751436935a1SVladimir Kotal 				    mech2->cm_type, key2)) {
752436935a1SVladimir Kotal 					error_val = CRYPTO_KEY_SIZE_RANGE;
753436935a1SVladimir Kotal 					continue;
754436935a1SVladimir Kotal 				}
755436935a1SVladimir Kotal 
756ef56a3c5SKrishna Yenduri #define	MIL_MECH_NUM(mil)	(mil)->ml_mech_info.cm_mech_number
757ef56a3c5SKrishna Yenduri 
758ef56a3c5SKrishna Yenduri 				if (mil->ml_kcf_mechid == m2id) { /* Bingo! */
759ef56a3c5SKrishna Yenduri 
760ef56a3c5SKrishna Yenduri 					/* Do load calculation only if needed */
761ef56a3c5SKrishna Yenduri 					if (prov_chain->pm_next == NULL &&
762ef56a3c5SKrishna Yenduri 					    pdm1m2 == NULL) {
763ef56a3c5SKrishna Yenduri 						pdm1m2 = pd;
764ef56a3c5SKrishna Yenduri 						*prov_mt2 = MIL_MECH_NUM(mil);
765ef56a3c5SKrishna Yenduri 					} else {
766ef56a3c5SKrishna Yenduri 						if (len < dgqlen) {
767ef56a3c5SKrishna Yenduri 							dgqlen = len;
768ef56a3c5SKrishna Yenduri 							pdm1m2 = pd;
769ef56a3c5SKrishna Yenduri 							*prov_mt2 =
770ef56a3c5SKrishna Yenduri 							    MIL_MECH_NUM(mil);
771ef56a3c5SKrishna Yenduri 						}
772ef56a3c5SKrishna Yenduri 					}
7737c478bd9Sstevel@tonic-gate 					break;
7747c478bd9Sstevel@tonic-gate 				}
7757c478bd9Sstevel@tonic-gate 			}
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 			prov_chain = prov_chain->pm_next;
7787c478bd9Sstevel@tonic-gate 		}
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 		pd =  (pdm1m2 != NULL) ? pdm1m2 : pdm1;
7817c478bd9Sstevel@tonic-gate 	}
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 	/* no HW provider for this mech, is there a SW provider? */
7847c478bd9Sstevel@tonic-gate 	if (pd == NULL && (mdesc = me->me_sw_prov) != NULL) {
7857c478bd9Sstevel@tonic-gate 		pd = mdesc->pm_prov_desc;
7867c478bd9Sstevel@tonic-gate 		if (!IS_FG_SUPPORTED(mdesc, fg1) ||
7877c478bd9Sstevel@tonic-gate 		    !KCF_IS_PROV_USABLE(pd) ||
788*9b009fc1SValerie Bubb Fenwick 		    IS_PROVIDER_TRIED(pd, triedl))
7897c478bd9Sstevel@tonic-gate 			pd = NULL;
7907c478bd9Sstevel@tonic-gate 		else {
7917c478bd9Sstevel@tonic-gate 			/* See if pd can do me2 too */
7927c478bd9Sstevel@tonic-gate 			for (mil = me->me_sw_prov->pm_mi_list;
7937c478bd9Sstevel@tonic-gate 			    mil != NULL; mil = mil->ml_next) {
7947c478bd9Sstevel@tonic-gate 				if ((mil->ml_mech_info.cm_func_group_mask &
7957c478bd9Sstevel@tonic-gate 				    fg2) == 0)
7967c478bd9Sstevel@tonic-gate 					continue;
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate 				if (mil->ml_kcf_mechid == m2id) {
7997c478bd9Sstevel@tonic-gate 					/* Bingo! */
8007c478bd9Sstevel@tonic-gate 					*prov_mt2 =
8017c478bd9Sstevel@tonic-gate 					    mil->ml_mech_info.cm_mech_number;
8027c478bd9Sstevel@tonic-gate 					break;
8037c478bd9Sstevel@tonic-gate 				}
8047c478bd9Sstevel@tonic-gate 			}
8057c478bd9Sstevel@tonic-gate 			*prov_mt1 = me->me_sw_prov->pm_mech_info.cm_mech_number;
8067c478bd9Sstevel@tonic-gate 		}
8077c478bd9Sstevel@tonic-gate 	}
8087c478bd9Sstevel@tonic-gate 
809436935a1SVladimir Kotal 	/* No provider found */
810436935a1SVladimir Kotal 	if (pd == NULL) {
811436935a1SVladimir Kotal 		/*
812436935a1SVladimir Kotal 		 * We do not want to report CRYPTO_MECH_NOT_SUPPORTED, when
813436935a1SVladimir Kotal 		 * we are in the "fallback to the next provider" case. Rather
814436935a1SVladimir Kotal 		 * we preserve the error, so that the client gets the right
815436935a1SVladimir Kotal 		 * error code.
816436935a1SVladimir Kotal 		 */
817436935a1SVladimir Kotal 		if (triedl == NULL)
818436935a1SVladimir Kotal 			*error = error_val;
819436935a1SVladimir Kotal 	} else
8207c478bd9Sstevel@tonic-gate 		KCF_PROV_REFHOLD(pd);
8217c478bd9Sstevel@tonic-gate 
822ef56a3c5SKrishna Yenduri 	mutex_exit(&mp->kl_lock);
8237c478bd9Sstevel@tonic-gate 	return (pd);
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate /*
8277c478bd9Sstevel@tonic-gate  * Do the actual work of calling the provider routines.
8287c478bd9Sstevel@tonic-gate  *
8297c478bd9Sstevel@tonic-gate  * pd - Provider structure
8307c478bd9Sstevel@tonic-gate  * ctx - Context for this operation
8317c478bd9Sstevel@tonic-gate  * params - Parameters for this operation
8327c478bd9Sstevel@tonic-gate  * rhndl - Request handle to use for notification
8337c478bd9Sstevel@tonic-gate  *
8347c478bd9Sstevel@tonic-gate  * The return values are the same as that of the respective SPI.
8357c478bd9Sstevel@tonic-gate  */
8367c478bd9Sstevel@tonic-gate int
common_submit_request(kcf_provider_desc_t * pd,crypto_ctx_t * ctx,kcf_req_params_t * params,crypto_req_handle_t rhndl)8377c478bd9Sstevel@tonic-gate common_submit_request(kcf_provider_desc_t *pd, crypto_ctx_t *ctx,
8387c478bd9Sstevel@tonic-gate     kcf_req_params_t *params, crypto_req_handle_t rhndl)
8397c478bd9Sstevel@tonic-gate {
8407c478bd9Sstevel@tonic-gate 	int err = CRYPTO_ARGUMENTS_BAD;
8417c478bd9Sstevel@tonic-gate 	kcf_op_type_t optype;
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 	optype = params->rp_optype;
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 	switch (params->rp_opgrp) {
8467c478bd9Sstevel@tonic-gate 	case KCF_OG_DIGEST: {
8477c478bd9Sstevel@tonic-gate 		kcf_digest_ops_params_t *dops = &params->rp_u.digest_params;
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 		switch (optype) {
8507c478bd9Sstevel@tonic-gate 		case KCF_OP_INIT:
8517c478bd9Sstevel@tonic-gate 			/*
8527c478bd9Sstevel@tonic-gate 			 * We should do this only here and not in KCF_WRAP_*
8537c478bd9Sstevel@tonic-gate 			 * macros. This is because we may want to try other
8547c478bd9Sstevel@tonic-gate 			 * providers, in case we recover from a failure.
8557c478bd9Sstevel@tonic-gate 			 */
8567c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(dops->do_framework_mechtype,
8577c478bd9Sstevel@tonic-gate 			    pd, &dops->do_mech);
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 			err = KCF_PROV_DIGEST_INIT(pd, ctx, &dops->do_mech,
8607c478bd9Sstevel@tonic-gate 			    rhndl);
8617c478bd9Sstevel@tonic-gate 			break;
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 		case KCF_OP_SINGLE:
8647c478bd9Sstevel@tonic-gate 			err = KCF_PROV_DIGEST(pd, ctx, dops->do_data,
8657c478bd9Sstevel@tonic-gate 			    dops->do_digest, rhndl);
8667c478bd9Sstevel@tonic-gate 			break;
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate 		case KCF_OP_UPDATE:
8697c478bd9Sstevel@tonic-gate 			err = KCF_PROV_DIGEST_UPDATE(pd, ctx,
8707c478bd9Sstevel@tonic-gate 			    dops->do_data, rhndl);
8717c478bd9Sstevel@tonic-gate 			break;
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate 		case KCF_OP_FINAL:
8747c478bd9Sstevel@tonic-gate 			err = KCF_PROV_DIGEST_FINAL(pd, ctx,
8757c478bd9Sstevel@tonic-gate 			    dops->do_digest, rhndl);
8767c478bd9Sstevel@tonic-gate 			break;
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 		case KCF_OP_ATOMIC:
8797c478bd9Sstevel@tonic-gate 			ASSERT(ctx == NULL);
8807c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(dops->do_framework_mechtype,
8817c478bd9Sstevel@tonic-gate 			    pd, &dops->do_mech);
8827c478bd9Sstevel@tonic-gate 			err = KCF_PROV_DIGEST_ATOMIC(pd, dops->do_sid,
8837c478bd9Sstevel@tonic-gate 			    &dops->do_mech, dops->do_data, dops->do_digest,
8847c478bd9Sstevel@tonic-gate 			    rhndl);
8857c478bd9Sstevel@tonic-gate 			break;
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 		case KCF_OP_DIGEST_KEY:
8887c478bd9Sstevel@tonic-gate 			err = KCF_PROV_DIGEST_KEY(pd, ctx, dops->do_digest_key,
8897c478bd9Sstevel@tonic-gate 			    rhndl);
8907c478bd9Sstevel@tonic-gate 			break;
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 		default:
8937c478bd9Sstevel@tonic-gate 			break;
8947c478bd9Sstevel@tonic-gate 		}
8957c478bd9Sstevel@tonic-gate 		break;
8967c478bd9Sstevel@tonic-gate 	}
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 	case KCF_OG_MAC: {
8997c478bd9Sstevel@tonic-gate 		kcf_mac_ops_params_t *mops = &params->rp_u.mac_params;
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 		switch (optype) {
9027c478bd9Sstevel@tonic-gate 		case KCF_OP_INIT:
9037c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(mops->mo_framework_mechtype,
9047c478bd9Sstevel@tonic-gate 			    pd, &mops->mo_mech);
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 			err = KCF_PROV_MAC_INIT(pd, ctx, &mops->mo_mech,
9077c478bd9Sstevel@tonic-gate 			    mops->mo_key, mops->mo_templ, rhndl);
9087c478bd9Sstevel@tonic-gate 			break;
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate 		case KCF_OP_SINGLE:
9117c478bd9Sstevel@tonic-gate 			err = KCF_PROV_MAC(pd, ctx, mops->mo_data,
9127c478bd9Sstevel@tonic-gate 			    mops->mo_mac, rhndl);
9137c478bd9Sstevel@tonic-gate 			break;
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 		case KCF_OP_UPDATE:
9167c478bd9Sstevel@tonic-gate 			err = KCF_PROV_MAC_UPDATE(pd, ctx, mops->mo_data,
9177c478bd9Sstevel@tonic-gate 			    rhndl);
9187c478bd9Sstevel@tonic-gate 			break;
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 		case KCF_OP_FINAL:
9217c478bd9Sstevel@tonic-gate 			err = KCF_PROV_MAC_FINAL(pd, ctx, mops->mo_mac, rhndl);
9227c478bd9Sstevel@tonic-gate 			break;
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 		case KCF_OP_ATOMIC:
9257c478bd9Sstevel@tonic-gate 			ASSERT(ctx == NULL);
9267c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(mops->mo_framework_mechtype,
9277c478bd9Sstevel@tonic-gate 			    pd, &mops->mo_mech);
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 			err = KCF_PROV_MAC_ATOMIC(pd, mops->mo_sid,
9307c478bd9Sstevel@tonic-gate 			    &mops->mo_mech, mops->mo_key, mops->mo_data,
9317c478bd9Sstevel@tonic-gate 			    mops->mo_mac, mops->mo_templ, rhndl);
9327c478bd9Sstevel@tonic-gate 			break;
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 		case KCF_OP_MAC_VERIFY_ATOMIC:
9357c478bd9Sstevel@tonic-gate 			ASSERT(ctx == NULL);
9367c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(mops->mo_framework_mechtype,
9377c478bd9Sstevel@tonic-gate 			    pd, &mops->mo_mech);
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate 			err = KCF_PROV_MAC_VERIFY_ATOMIC(pd, mops->mo_sid,
9407c478bd9Sstevel@tonic-gate 			    &mops->mo_mech, mops->mo_key, mops->mo_data,
9417c478bd9Sstevel@tonic-gate 			    mops->mo_mac, mops->mo_templ, rhndl);
9427c478bd9Sstevel@tonic-gate 			break;
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 		default:
9457c478bd9Sstevel@tonic-gate 			break;
9467c478bd9Sstevel@tonic-gate 		}
9477c478bd9Sstevel@tonic-gate 		break;
9487c478bd9Sstevel@tonic-gate 	}
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 	case KCF_OG_ENCRYPT: {
9517c478bd9Sstevel@tonic-gate 		kcf_encrypt_ops_params_t *eops = &params->rp_u.encrypt_params;
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 		switch (optype) {
9547c478bd9Sstevel@tonic-gate 		case KCF_OP_INIT:
9557c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(eops->eo_framework_mechtype,
9567c478bd9Sstevel@tonic-gate 			    pd, &eops->eo_mech);
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 			err = KCF_PROV_ENCRYPT_INIT(pd, ctx, &eops->eo_mech,
9597c478bd9Sstevel@tonic-gate 			    eops->eo_key, eops->eo_templ, rhndl);
9607c478bd9Sstevel@tonic-gate 			break;
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate 		case KCF_OP_SINGLE:
9637c478bd9Sstevel@tonic-gate 			err = KCF_PROV_ENCRYPT(pd, ctx, eops->eo_plaintext,
9647c478bd9Sstevel@tonic-gate 			    eops->eo_ciphertext, rhndl);
9657c478bd9Sstevel@tonic-gate 			break;
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 		case KCF_OP_UPDATE:
9687c478bd9Sstevel@tonic-gate 			err = KCF_PROV_ENCRYPT_UPDATE(pd, ctx,
9697c478bd9Sstevel@tonic-gate 			    eops->eo_plaintext, eops->eo_ciphertext, rhndl);
9707c478bd9Sstevel@tonic-gate 			break;
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 		case KCF_OP_FINAL:
9737c478bd9Sstevel@tonic-gate 			err = KCF_PROV_ENCRYPT_FINAL(pd, ctx,
9747c478bd9Sstevel@tonic-gate 			    eops->eo_ciphertext, rhndl);
9757c478bd9Sstevel@tonic-gate 			break;
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 		case KCF_OP_ATOMIC:
9787c478bd9Sstevel@tonic-gate 			ASSERT(ctx == NULL);
9797c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(eops->eo_framework_mechtype,
9807c478bd9Sstevel@tonic-gate 			    pd, &eops->eo_mech);
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 			err = KCF_PROV_ENCRYPT_ATOMIC(pd, eops->eo_sid,
9837c478bd9Sstevel@tonic-gate 			    &eops->eo_mech, eops->eo_key, eops->eo_plaintext,
9847c478bd9Sstevel@tonic-gate 			    eops->eo_ciphertext, eops->eo_templ, rhndl);
9857c478bd9Sstevel@tonic-gate 			break;
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 		default:
9887c478bd9Sstevel@tonic-gate 			break;
9897c478bd9Sstevel@tonic-gate 		}
9907c478bd9Sstevel@tonic-gate 		break;
9917c478bd9Sstevel@tonic-gate 	}
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate 	case KCF_OG_DECRYPT: {
9947c478bd9Sstevel@tonic-gate 		kcf_decrypt_ops_params_t *dcrops = &params->rp_u.decrypt_params;
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 		switch (optype) {
9977c478bd9Sstevel@tonic-gate 		case KCF_OP_INIT:
9987c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(dcrops->dop_framework_mechtype,
9997c478bd9Sstevel@tonic-gate 			    pd, &dcrops->dop_mech);
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 			err = KCF_PROV_DECRYPT_INIT(pd, ctx, &dcrops->dop_mech,
10027c478bd9Sstevel@tonic-gate 			    dcrops->dop_key, dcrops->dop_templ, rhndl);
10037c478bd9Sstevel@tonic-gate 			break;
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 		case KCF_OP_SINGLE:
10067c478bd9Sstevel@tonic-gate 			err = KCF_PROV_DECRYPT(pd, ctx, dcrops->dop_ciphertext,
10077c478bd9Sstevel@tonic-gate 			    dcrops->dop_plaintext, rhndl);
10087c478bd9Sstevel@tonic-gate 			break;
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 		case KCF_OP_UPDATE:
10117c478bd9Sstevel@tonic-gate 			err = KCF_PROV_DECRYPT_UPDATE(pd, ctx,
10127c478bd9Sstevel@tonic-gate 			    dcrops->dop_ciphertext, dcrops->dop_plaintext,
10137c478bd9Sstevel@tonic-gate 			    rhndl);
10147c478bd9Sstevel@tonic-gate 			break;
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 		case KCF_OP_FINAL:
10177c478bd9Sstevel@tonic-gate 			err = KCF_PROV_DECRYPT_FINAL(pd, ctx,
10187c478bd9Sstevel@tonic-gate 			    dcrops->dop_plaintext, rhndl);
10197c478bd9Sstevel@tonic-gate 			break;
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate 		case KCF_OP_ATOMIC:
10227c478bd9Sstevel@tonic-gate 			ASSERT(ctx == NULL);
10237c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(dcrops->dop_framework_mechtype,
10247c478bd9Sstevel@tonic-gate 			    pd, &dcrops->dop_mech);
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate 			err = KCF_PROV_DECRYPT_ATOMIC(pd, dcrops->dop_sid,
10277c478bd9Sstevel@tonic-gate 			    &dcrops->dop_mech, dcrops->dop_key,
10287c478bd9Sstevel@tonic-gate 			    dcrops->dop_ciphertext, dcrops->dop_plaintext,
10297c478bd9Sstevel@tonic-gate 			    dcrops->dop_templ, rhndl);
10307c478bd9Sstevel@tonic-gate 			break;
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 		default:
10337c478bd9Sstevel@tonic-gate 			break;
10347c478bd9Sstevel@tonic-gate 		}
10357c478bd9Sstevel@tonic-gate 		break;
10367c478bd9Sstevel@tonic-gate 	}
10377c478bd9Sstevel@tonic-gate 
10387c478bd9Sstevel@tonic-gate 	case KCF_OG_SIGN: {
10397c478bd9Sstevel@tonic-gate 		kcf_sign_ops_params_t *sops = &params->rp_u.sign_params;
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate 		switch (optype) {
10427c478bd9Sstevel@tonic-gate 		case KCF_OP_INIT:
10437c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(sops->so_framework_mechtype,
10447c478bd9Sstevel@tonic-gate 			    pd, &sops->so_mech);
10457c478bd9Sstevel@tonic-gate 
10467c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SIGN_INIT(pd, ctx, &sops->so_mech,
10477c478bd9Sstevel@tonic-gate 			    sops->so_key, sops->so_templ, rhndl);
10487c478bd9Sstevel@tonic-gate 			break;
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate 		case KCF_OP_SIGN_RECOVER_INIT:
10517c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(sops->so_framework_mechtype,
10527c478bd9Sstevel@tonic-gate 			    pd, &sops->so_mech);
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SIGN_RECOVER_INIT(pd, ctx,
10557c478bd9Sstevel@tonic-gate 			    &sops->so_mech, sops->so_key, sops->so_templ,
10567c478bd9Sstevel@tonic-gate 			    rhndl);
10577c478bd9Sstevel@tonic-gate 			break;
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate 		case KCF_OP_SINGLE:
10607c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SIGN(pd, ctx, sops->so_data,
10617c478bd9Sstevel@tonic-gate 			    sops->so_signature, rhndl);
10627c478bd9Sstevel@tonic-gate 			break;
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate 		case KCF_OP_SIGN_RECOVER:
10657c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SIGN_RECOVER(pd, ctx,
10667c478bd9Sstevel@tonic-gate 			    sops->so_data, sops->so_signature, rhndl);
10677c478bd9Sstevel@tonic-gate 			break;
10687c478bd9Sstevel@tonic-gate 
10697c478bd9Sstevel@tonic-gate 		case KCF_OP_UPDATE:
10707c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SIGN_UPDATE(pd, ctx, sops->so_data,
10717c478bd9Sstevel@tonic-gate 			    rhndl);
10727c478bd9Sstevel@tonic-gate 			break;
10737c478bd9Sstevel@tonic-gate 
10747c478bd9Sstevel@tonic-gate 		case KCF_OP_FINAL:
10757c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SIGN_FINAL(pd, ctx, sops->so_signature,
10767c478bd9Sstevel@tonic-gate 			    rhndl);
10777c478bd9Sstevel@tonic-gate 			break;
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 		case KCF_OP_ATOMIC:
10807c478bd9Sstevel@tonic-gate 			ASSERT(ctx == NULL);
10817c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(sops->so_framework_mechtype,
10827c478bd9Sstevel@tonic-gate 			    pd, &sops->so_mech);
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SIGN_ATOMIC(pd, sops->so_sid,
10857c478bd9Sstevel@tonic-gate 			    &sops->so_mech, sops->so_key, sops->so_data,
10867c478bd9Sstevel@tonic-gate 			    sops->so_templ, sops->so_signature, rhndl);
10877c478bd9Sstevel@tonic-gate 			break;
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate 		case KCF_OP_SIGN_RECOVER_ATOMIC:
10907c478bd9Sstevel@tonic-gate 			ASSERT(ctx == NULL);
10917c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(sops->so_framework_mechtype,
10927c478bd9Sstevel@tonic-gate 			    pd, &sops->so_mech);
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SIGN_RECOVER_ATOMIC(pd, sops->so_sid,
10957c478bd9Sstevel@tonic-gate 			    &sops->so_mech, sops->so_key, sops->so_data,
10967c478bd9Sstevel@tonic-gate 			    sops->so_templ, sops->so_signature, rhndl);
10977c478bd9Sstevel@tonic-gate 			break;
10987c478bd9Sstevel@tonic-gate 
10997c478bd9Sstevel@tonic-gate 		default:
11007c478bd9Sstevel@tonic-gate 			break;
11017c478bd9Sstevel@tonic-gate 		}
11027c478bd9Sstevel@tonic-gate 		break;
11037c478bd9Sstevel@tonic-gate 	}
11047c478bd9Sstevel@tonic-gate 
11057c478bd9Sstevel@tonic-gate 	case KCF_OG_VERIFY: {
11067c478bd9Sstevel@tonic-gate 		kcf_verify_ops_params_t *vops = &params->rp_u.verify_params;
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 		switch (optype) {
11097c478bd9Sstevel@tonic-gate 		case KCF_OP_INIT:
11107c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(vops->vo_framework_mechtype,
11117c478bd9Sstevel@tonic-gate 			    pd, &vops->vo_mech);
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate 			err = KCF_PROV_VERIFY_INIT(pd, ctx, &vops->vo_mech,
11147c478bd9Sstevel@tonic-gate 			    vops->vo_key, vops->vo_templ, rhndl);
11157c478bd9Sstevel@tonic-gate 			break;
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 		case KCF_OP_VERIFY_RECOVER_INIT:
11187c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(vops->vo_framework_mechtype,
11197c478bd9Sstevel@tonic-gate 			    pd, &vops->vo_mech);
11207c478bd9Sstevel@tonic-gate 
11217c478bd9Sstevel@tonic-gate 			err = KCF_PROV_VERIFY_RECOVER_INIT(pd, ctx,
11227c478bd9Sstevel@tonic-gate 			    &vops->vo_mech, vops->vo_key, vops->vo_templ,
11237c478bd9Sstevel@tonic-gate 			    rhndl);
11247c478bd9Sstevel@tonic-gate 			break;
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate 		case KCF_OP_SINGLE:
11277c478bd9Sstevel@tonic-gate 			err = KCF_PROV_VERIFY(pd, ctx, vops->vo_data,
11287c478bd9Sstevel@tonic-gate 			    vops->vo_signature, rhndl);
11297c478bd9Sstevel@tonic-gate 			break;
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate 		case KCF_OP_VERIFY_RECOVER:
11327c478bd9Sstevel@tonic-gate 			err = KCF_PROV_VERIFY_RECOVER(pd, ctx,
11337c478bd9Sstevel@tonic-gate 			    vops->vo_signature, vops->vo_data, rhndl);
11347c478bd9Sstevel@tonic-gate 			break;
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate 		case KCF_OP_UPDATE:
11377c478bd9Sstevel@tonic-gate 			err = KCF_PROV_VERIFY_UPDATE(pd, ctx, vops->vo_data,
11387c478bd9Sstevel@tonic-gate 			    rhndl);
11397c478bd9Sstevel@tonic-gate 			break;
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 		case KCF_OP_FINAL:
11427c478bd9Sstevel@tonic-gate 			err = KCF_PROV_VERIFY_FINAL(pd, ctx, vops->vo_signature,
11437c478bd9Sstevel@tonic-gate 			    rhndl);
11447c478bd9Sstevel@tonic-gate 			break;
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate 		case KCF_OP_ATOMIC:
11477c478bd9Sstevel@tonic-gate 			ASSERT(ctx == NULL);
11487c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(vops->vo_framework_mechtype,
11497c478bd9Sstevel@tonic-gate 			    pd, &vops->vo_mech);
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 			err = KCF_PROV_VERIFY_ATOMIC(pd, vops->vo_sid,
11527c478bd9Sstevel@tonic-gate 			    &vops->vo_mech, vops->vo_key, vops->vo_data,
11537c478bd9Sstevel@tonic-gate 			    vops->vo_templ, vops->vo_signature, rhndl);
11547c478bd9Sstevel@tonic-gate 			break;
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate 		case KCF_OP_VERIFY_RECOVER_ATOMIC:
11577c478bd9Sstevel@tonic-gate 			ASSERT(ctx == NULL);
11587c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(vops->vo_framework_mechtype,
11597c478bd9Sstevel@tonic-gate 			    pd, &vops->vo_mech);
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 			err = KCF_PROV_VERIFY_RECOVER_ATOMIC(pd, vops->vo_sid,
11627c478bd9Sstevel@tonic-gate 			    &vops->vo_mech, vops->vo_key, vops->vo_signature,
11637c478bd9Sstevel@tonic-gate 			    vops->vo_templ, vops->vo_data, rhndl);
11647c478bd9Sstevel@tonic-gate 			break;
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate 		default:
11677c478bd9Sstevel@tonic-gate 			break;
11687c478bd9Sstevel@tonic-gate 		}
11697c478bd9Sstevel@tonic-gate 		break;
11707c478bd9Sstevel@tonic-gate 	}
11717c478bd9Sstevel@tonic-gate 
11727c478bd9Sstevel@tonic-gate 	case KCF_OG_ENCRYPT_MAC: {
11737c478bd9Sstevel@tonic-gate 		kcf_encrypt_mac_ops_params_t *eops =
11747c478bd9Sstevel@tonic-gate 		    &params->rp_u.encrypt_mac_params;
11757c478bd9Sstevel@tonic-gate 		kcf_context_t *kcf_secondctx;
11767c478bd9Sstevel@tonic-gate 
11777c478bd9Sstevel@tonic-gate 		switch (optype) {
11787c478bd9Sstevel@tonic-gate 		case KCF_OP_INIT:
11797c478bd9Sstevel@tonic-gate 			kcf_secondctx = ((kcf_context_t *)
11807c478bd9Sstevel@tonic-gate 			    (ctx->cc_framework_private))->kc_secondctx;
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 			if (kcf_secondctx != NULL) {
11837c478bd9Sstevel@tonic-gate 				err = kcf_emulate_dual(pd, ctx, params);
11847c478bd9Sstevel@tonic-gate 				break;
11857c478bd9Sstevel@tonic-gate 			}
11867c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(
11877c478bd9Sstevel@tonic-gate 			    eops->em_framework_encr_mechtype,
11887c478bd9Sstevel@tonic-gate 			    pd, &eops->em_encr_mech);
11897c478bd9Sstevel@tonic-gate 
11907c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(
11917c478bd9Sstevel@tonic-gate 			    eops->em_framework_mac_mechtype,
11927c478bd9Sstevel@tonic-gate 			    pd, &eops->em_mac_mech);
11937c478bd9Sstevel@tonic-gate 
11947c478bd9Sstevel@tonic-gate 			err = KCF_PROV_ENCRYPT_MAC_INIT(pd, ctx,
11957c478bd9Sstevel@tonic-gate 			    &eops->em_encr_mech, eops->em_encr_key,
11967c478bd9Sstevel@tonic-gate 			    &eops->em_mac_mech, eops->em_mac_key,
11977c478bd9Sstevel@tonic-gate 			    eops->em_encr_templ, eops->em_mac_templ,
11987c478bd9Sstevel@tonic-gate 			    rhndl);
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 			break;
12017c478bd9Sstevel@tonic-gate 
12027c478bd9Sstevel@tonic-gate 		case KCF_OP_SINGLE:
12037c478bd9Sstevel@tonic-gate 			err = KCF_PROV_ENCRYPT_MAC(pd, ctx,
12047c478bd9Sstevel@tonic-gate 			    eops->em_plaintext, eops->em_ciphertext,
12057c478bd9Sstevel@tonic-gate 			    eops->em_mac, rhndl);
12067c478bd9Sstevel@tonic-gate 			break;
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate 		case KCF_OP_UPDATE:
12097c478bd9Sstevel@tonic-gate 			kcf_secondctx = ((kcf_context_t *)
12107c478bd9Sstevel@tonic-gate 			    (ctx->cc_framework_private))->kc_secondctx;
12117c478bd9Sstevel@tonic-gate 			if (kcf_secondctx != NULL) {
12127c478bd9Sstevel@tonic-gate 				err = kcf_emulate_dual(pd, ctx, params);
12137c478bd9Sstevel@tonic-gate 				break;
12147c478bd9Sstevel@tonic-gate 			}
12157c478bd9Sstevel@tonic-gate 			err = KCF_PROV_ENCRYPT_MAC_UPDATE(pd, ctx,
12167c478bd9Sstevel@tonic-gate 			    eops->em_plaintext, eops->em_ciphertext, rhndl);
12177c478bd9Sstevel@tonic-gate 			break;
12187c478bd9Sstevel@tonic-gate 
12197c478bd9Sstevel@tonic-gate 		case KCF_OP_FINAL:
12207c478bd9Sstevel@tonic-gate 			kcf_secondctx = ((kcf_context_t *)
12217c478bd9Sstevel@tonic-gate 			    (ctx->cc_framework_private))->kc_secondctx;
12227c478bd9Sstevel@tonic-gate 			if (kcf_secondctx != NULL) {
12237c478bd9Sstevel@tonic-gate 				err = kcf_emulate_dual(pd, ctx, params);
12247c478bd9Sstevel@tonic-gate 				break;
12257c478bd9Sstevel@tonic-gate 			}
12267c478bd9Sstevel@tonic-gate 			err = KCF_PROV_ENCRYPT_MAC_FINAL(pd, ctx,
12277c478bd9Sstevel@tonic-gate 			    eops->em_ciphertext, eops->em_mac, rhndl);
12287c478bd9Sstevel@tonic-gate 			break;
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate 		case KCF_OP_ATOMIC:
12317c478bd9Sstevel@tonic-gate 			ASSERT(ctx == NULL);
12327c478bd9Sstevel@tonic-gate 
12337c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(
12347c478bd9Sstevel@tonic-gate 			    eops->em_framework_encr_mechtype,
12357c478bd9Sstevel@tonic-gate 			    pd, &eops->em_encr_mech);
12367c478bd9Sstevel@tonic-gate 
12377c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(
12387c478bd9Sstevel@tonic-gate 			    eops->em_framework_mac_mechtype,
12397c478bd9Sstevel@tonic-gate 			    pd, &eops->em_mac_mech);
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate 			err = KCF_PROV_ENCRYPT_MAC_ATOMIC(pd, eops->em_sid,
12427c478bd9Sstevel@tonic-gate 			    &eops->em_encr_mech, eops->em_encr_key,
12437c478bd9Sstevel@tonic-gate 			    &eops->em_mac_mech, eops->em_mac_key,
12447c478bd9Sstevel@tonic-gate 			    eops->em_plaintext, eops->em_ciphertext,
12457c478bd9Sstevel@tonic-gate 			    eops->em_mac,
12467c478bd9Sstevel@tonic-gate 			    eops->em_encr_templ, eops->em_mac_templ,
12477c478bd9Sstevel@tonic-gate 			    rhndl);
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 			break;
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 		default:
12527c478bd9Sstevel@tonic-gate 			break;
12537c478bd9Sstevel@tonic-gate 		}
12547c478bd9Sstevel@tonic-gate 		break;
12557c478bd9Sstevel@tonic-gate 	}
12567c478bd9Sstevel@tonic-gate 
12577c478bd9Sstevel@tonic-gate 	case KCF_OG_MAC_DECRYPT: {
12587c478bd9Sstevel@tonic-gate 		kcf_mac_decrypt_ops_params_t *dops =
12597c478bd9Sstevel@tonic-gate 		    &params->rp_u.mac_decrypt_params;
12607c478bd9Sstevel@tonic-gate 		kcf_context_t *kcf_secondctx;
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate 		switch (optype) {
12637c478bd9Sstevel@tonic-gate 		case KCF_OP_INIT:
12647c478bd9Sstevel@tonic-gate 			kcf_secondctx = ((kcf_context_t *)
12657c478bd9Sstevel@tonic-gate 			    (ctx->cc_framework_private))->kc_secondctx;
12667c478bd9Sstevel@tonic-gate 
12677c478bd9Sstevel@tonic-gate 			if (kcf_secondctx != NULL) {
12687c478bd9Sstevel@tonic-gate 				err = kcf_emulate_dual(pd, ctx, params);
12697c478bd9Sstevel@tonic-gate 				break;
12707c478bd9Sstevel@tonic-gate 			}
12717c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(
12727c478bd9Sstevel@tonic-gate 			    dops->md_framework_mac_mechtype,
12737c478bd9Sstevel@tonic-gate 			    pd, &dops->md_mac_mech);
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(
12767c478bd9Sstevel@tonic-gate 			    dops->md_framework_decr_mechtype,
12777c478bd9Sstevel@tonic-gate 			    pd, &dops->md_decr_mech);
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate 			err = KCF_PROV_MAC_DECRYPT_INIT(pd, ctx,
12807c478bd9Sstevel@tonic-gate 			    &dops->md_mac_mech, dops->md_mac_key,
12817c478bd9Sstevel@tonic-gate 			    &dops->md_decr_mech, dops->md_decr_key,
12827c478bd9Sstevel@tonic-gate 			    dops->md_mac_templ, dops->md_decr_templ,
12837c478bd9Sstevel@tonic-gate 			    rhndl);
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 			break;
12867c478bd9Sstevel@tonic-gate 
12877c478bd9Sstevel@tonic-gate 		case KCF_OP_SINGLE:
12887c478bd9Sstevel@tonic-gate 			err = KCF_PROV_MAC_DECRYPT(pd, ctx,
12897c478bd9Sstevel@tonic-gate 			    dops->md_ciphertext, dops->md_mac,
12907c478bd9Sstevel@tonic-gate 			    dops->md_plaintext, rhndl);
12917c478bd9Sstevel@tonic-gate 			break;
12927c478bd9Sstevel@tonic-gate 
12937c478bd9Sstevel@tonic-gate 		case KCF_OP_UPDATE:
12947c478bd9Sstevel@tonic-gate 			kcf_secondctx = ((kcf_context_t *)
12957c478bd9Sstevel@tonic-gate 			    (ctx->cc_framework_private))->kc_secondctx;
12967c478bd9Sstevel@tonic-gate 			if (kcf_secondctx != NULL) {
12977c478bd9Sstevel@tonic-gate 				err = kcf_emulate_dual(pd, ctx, params);
12987c478bd9Sstevel@tonic-gate 				break;
12997c478bd9Sstevel@tonic-gate 			}
13007c478bd9Sstevel@tonic-gate 			err = KCF_PROV_MAC_DECRYPT_UPDATE(pd, ctx,
13017c478bd9Sstevel@tonic-gate 			    dops->md_ciphertext, dops->md_plaintext, rhndl);
13027c478bd9Sstevel@tonic-gate 			break;
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 		case KCF_OP_FINAL:
13057c478bd9Sstevel@tonic-gate 			kcf_secondctx = ((kcf_context_t *)
13067c478bd9Sstevel@tonic-gate 			    (ctx->cc_framework_private))->kc_secondctx;
13077c478bd9Sstevel@tonic-gate 			if (kcf_secondctx != NULL) {
13087c478bd9Sstevel@tonic-gate 				err = kcf_emulate_dual(pd, ctx, params);
13097c478bd9Sstevel@tonic-gate 				break;
13107c478bd9Sstevel@tonic-gate 			}
13117c478bd9Sstevel@tonic-gate 			err = KCF_PROV_MAC_DECRYPT_FINAL(pd, ctx,
13127c478bd9Sstevel@tonic-gate 			    dops->md_mac, dops->md_plaintext, rhndl);
13137c478bd9Sstevel@tonic-gate 			break;
13147c478bd9Sstevel@tonic-gate 
13157c478bd9Sstevel@tonic-gate 		case KCF_OP_ATOMIC:
13167c478bd9Sstevel@tonic-gate 			ASSERT(ctx == NULL);
13177c478bd9Sstevel@tonic-gate 
13187c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(
13197c478bd9Sstevel@tonic-gate 			    dops->md_framework_mac_mechtype,
13207c478bd9Sstevel@tonic-gate 			    pd, &dops->md_mac_mech);
13217c478bd9Sstevel@tonic-gate 
13227c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(
13237c478bd9Sstevel@tonic-gate 			    dops->md_framework_decr_mechtype,
13247c478bd9Sstevel@tonic-gate 			    pd, &dops->md_decr_mech);
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate 			err = KCF_PROV_MAC_DECRYPT_ATOMIC(pd, dops->md_sid,
13277c478bd9Sstevel@tonic-gate 			    &dops->md_mac_mech, dops->md_mac_key,
13287c478bd9Sstevel@tonic-gate 			    &dops->md_decr_mech, dops->md_decr_key,
13297c478bd9Sstevel@tonic-gate 			    dops->md_ciphertext, dops->md_mac,
13307c478bd9Sstevel@tonic-gate 			    dops->md_plaintext,
13317c478bd9Sstevel@tonic-gate 			    dops->md_mac_templ, dops->md_decr_templ,
13327c478bd9Sstevel@tonic-gate 			    rhndl);
13337c478bd9Sstevel@tonic-gate 
13347c478bd9Sstevel@tonic-gate 			break;
13357c478bd9Sstevel@tonic-gate 
13367c478bd9Sstevel@tonic-gate 		case KCF_OP_MAC_VERIFY_DECRYPT_ATOMIC:
13377c478bd9Sstevel@tonic-gate 			ASSERT(ctx == NULL);
13387c478bd9Sstevel@tonic-gate 
13397c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(
13407c478bd9Sstevel@tonic-gate 			    dops->md_framework_mac_mechtype,
13417c478bd9Sstevel@tonic-gate 			    pd, &dops->md_mac_mech);
13427c478bd9Sstevel@tonic-gate 
13437c478bd9Sstevel@tonic-gate 			KCF_SET_PROVIDER_MECHNUM(
13447c478bd9Sstevel@tonic-gate 			    dops->md_framework_decr_mechtype,
13457c478bd9Sstevel@tonic-gate 			    pd, &dops->md_decr_mech);
13467c478bd9Sstevel@tonic-gate 
13477c478bd9Sstevel@tonic-gate 			err = KCF_PROV_MAC_VERIFY_DECRYPT_ATOMIC(pd,
13487c478bd9Sstevel@tonic-gate 			    dops->md_sid, &dops->md_mac_mech, dops->md_mac_key,
13497c478bd9Sstevel@tonic-gate 			    &dops->md_decr_mech, dops->md_decr_key,
13507c478bd9Sstevel@tonic-gate 			    dops->md_ciphertext, dops->md_mac,
13517c478bd9Sstevel@tonic-gate 			    dops->md_plaintext,
13527c478bd9Sstevel@tonic-gate 			    dops->md_mac_templ, dops->md_decr_templ,
13537c478bd9Sstevel@tonic-gate 			    rhndl);
13547c478bd9Sstevel@tonic-gate 
13557c478bd9Sstevel@tonic-gate 			break;
13567c478bd9Sstevel@tonic-gate 
13577c478bd9Sstevel@tonic-gate 		default:
13587c478bd9Sstevel@tonic-gate 			break;
13597c478bd9Sstevel@tonic-gate 		}
13607c478bd9Sstevel@tonic-gate 		break;
13617c478bd9Sstevel@tonic-gate 	}
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate 	case KCF_OG_KEY: {
13647c478bd9Sstevel@tonic-gate 		kcf_key_ops_params_t *kops = &params->rp_u.key_params;
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 		ASSERT(ctx == NULL);
13677c478bd9Sstevel@tonic-gate 		KCF_SET_PROVIDER_MECHNUM(kops->ko_framework_mechtype, pd,
13687c478bd9Sstevel@tonic-gate 		    &kops->ko_mech);
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate 		switch (optype) {
13717c478bd9Sstevel@tonic-gate 		case KCF_OP_KEY_GENERATE:
13727c478bd9Sstevel@tonic-gate 			err = KCF_PROV_KEY_GENERATE(pd, kops->ko_sid,
13737c478bd9Sstevel@tonic-gate 			    &kops->ko_mech,
13747c478bd9Sstevel@tonic-gate 			    kops->ko_key_template, kops->ko_key_attribute_count,
13757c478bd9Sstevel@tonic-gate 			    kops->ko_key_object_id_ptr, rhndl);
13767c478bd9Sstevel@tonic-gate 			break;
13777c478bd9Sstevel@tonic-gate 
13787c478bd9Sstevel@tonic-gate 		case KCF_OP_KEY_GENERATE_PAIR:
13797c478bd9Sstevel@tonic-gate 			err = KCF_PROV_KEY_GENERATE_PAIR(pd, kops->ko_sid,
13807c478bd9Sstevel@tonic-gate 			    &kops->ko_mech,
13817c478bd9Sstevel@tonic-gate 			    kops->ko_key_template, kops->ko_key_attribute_count,
13827c478bd9Sstevel@tonic-gate 			    kops->ko_private_key_template,
13837c478bd9Sstevel@tonic-gate 			    kops->ko_private_key_attribute_count,
13847c478bd9Sstevel@tonic-gate 			    kops->ko_key_object_id_ptr,
13857c478bd9Sstevel@tonic-gate 			    kops->ko_private_key_object_id_ptr, rhndl);
13867c478bd9Sstevel@tonic-gate 			break;
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate 		case KCF_OP_KEY_WRAP:
13897c478bd9Sstevel@tonic-gate 			err = KCF_PROV_KEY_WRAP(pd, kops->ko_sid,
13907c478bd9Sstevel@tonic-gate 			    &kops->ko_mech,
13917c478bd9Sstevel@tonic-gate 			    kops->ko_key, kops->ko_key_object_id_ptr,
13927c478bd9Sstevel@tonic-gate 			    kops->ko_wrapped_key, kops->ko_wrapped_key_len_ptr,
13937c478bd9Sstevel@tonic-gate 			    rhndl);
13947c478bd9Sstevel@tonic-gate 			break;
13957c478bd9Sstevel@tonic-gate 
13967c478bd9Sstevel@tonic-gate 		case KCF_OP_KEY_UNWRAP:
13977c478bd9Sstevel@tonic-gate 			err = KCF_PROV_KEY_UNWRAP(pd, kops->ko_sid,
13987c478bd9Sstevel@tonic-gate 			    &kops->ko_mech,
13997c478bd9Sstevel@tonic-gate 			    kops->ko_key, kops->ko_wrapped_key,
14007c478bd9Sstevel@tonic-gate 			    kops->ko_wrapped_key_len_ptr,
14017c478bd9Sstevel@tonic-gate 			    kops->ko_key_template, kops->ko_key_attribute_count,
14027c478bd9Sstevel@tonic-gate 			    kops->ko_key_object_id_ptr, rhndl);
14037c478bd9Sstevel@tonic-gate 			break;
14047c478bd9Sstevel@tonic-gate 
14057c478bd9Sstevel@tonic-gate 		case KCF_OP_KEY_DERIVE:
14067c478bd9Sstevel@tonic-gate 			err = KCF_PROV_KEY_DERIVE(pd, kops->ko_sid,
14077c478bd9Sstevel@tonic-gate 			    &kops->ko_mech,
14087c478bd9Sstevel@tonic-gate 			    kops->ko_key, kops->ko_key_template,
14097c478bd9Sstevel@tonic-gate 			    kops->ko_key_attribute_count,
14107c478bd9Sstevel@tonic-gate 			    kops->ko_key_object_id_ptr, rhndl);
14117c478bd9Sstevel@tonic-gate 			break;
14127c478bd9Sstevel@tonic-gate 
14137c478bd9Sstevel@tonic-gate 		default:
14147c478bd9Sstevel@tonic-gate 			break;
14157c478bd9Sstevel@tonic-gate 		}
14167c478bd9Sstevel@tonic-gate 		break;
14177c478bd9Sstevel@tonic-gate 	}
14187c478bd9Sstevel@tonic-gate 
14197c478bd9Sstevel@tonic-gate 	case KCF_OG_RANDOM: {
14207c478bd9Sstevel@tonic-gate 		kcf_random_number_ops_params_t *rops =
14217c478bd9Sstevel@tonic-gate 		    &params->rp_u.random_number_params;
14227c478bd9Sstevel@tonic-gate 
14237c478bd9Sstevel@tonic-gate 		ASSERT(ctx == NULL);
14247c478bd9Sstevel@tonic-gate 
14257c478bd9Sstevel@tonic-gate 		switch (optype) {
14267c478bd9Sstevel@tonic-gate 		case KCF_OP_RANDOM_SEED:
14277c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SEED_RANDOM(pd, rops->rn_sid,
14288047c9fbSmcpowers 			    rops->rn_buf, rops->rn_buflen, rops->rn_entropy_est,
14298047c9fbSmcpowers 			    rops->rn_flags, rhndl);
14307c478bd9Sstevel@tonic-gate 			break;
14317c478bd9Sstevel@tonic-gate 
14327c478bd9Sstevel@tonic-gate 		case KCF_OP_RANDOM_GENERATE:
14337c478bd9Sstevel@tonic-gate 			err = KCF_PROV_GENERATE_RANDOM(pd, rops->rn_sid,
14347c478bd9Sstevel@tonic-gate 			    rops->rn_buf, rops->rn_buflen, rhndl);
14357c478bd9Sstevel@tonic-gate 			break;
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate 		default:
14387c478bd9Sstevel@tonic-gate 			break;
14397c478bd9Sstevel@tonic-gate 		}
14407c478bd9Sstevel@tonic-gate 		break;
14417c478bd9Sstevel@tonic-gate 	}
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 	case KCF_OG_SESSION: {
14447c478bd9Sstevel@tonic-gate 		kcf_session_ops_params_t *sops = &params->rp_u.session_params;
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate 		ASSERT(ctx == NULL);
14477c478bd9Sstevel@tonic-gate 		switch (optype) {
14487c478bd9Sstevel@tonic-gate 		case KCF_OP_SESSION_OPEN:
1449fb27b1cdSmcpowers 			/*
1450fb27b1cdSmcpowers 			 * so_pd may be a logical provider, in which case
1451fb27b1cdSmcpowers 			 * we need to check whether it has been removed.
1452fb27b1cdSmcpowers 			 */
1453fb27b1cdSmcpowers 			if (KCF_IS_PROV_REMOVED(sops->so_pd)) {
1454fb27b1cdSmcpowers 				err = CRYPTO_DEVICE_ERROR;
1455fb27b1cdSmcpowers 				break;
1456fb27b1cdSmcpowers 			}
14577c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SESSION_OPEN(pd, sops->so_sid_ptr,
14587c478bd9Sstevel@tonic-gate 			    rhndl, sops->so_pd);
14597c478bd9Sstevel@tonic-gate 			break;
14607c478bd9Sstevel@tonic-gate 
14617c478bd9Sstevel@tonic-gate 		case KCF_OP_SESSION_CLOSE:
1462fb27b1cdSmcpowers 			/*
1463fb27b1cdSmcpowers 			 * so_pd may be a logical provider, in which case
1464fb27b1cdSmcpowers 			 * we need to check whether it has been removed.
1465fb27b1cdSmcpowers 			 */
1466fb27b1cdSmcpowers 			if (KCF_IS_PROV_REMOVED(sops->so_pd)) {
1467fb27b1cdSmcpowers 				err = CRYPTO_DEVICE_ERROR;
1468fb27b1cdSmcpowers 				break;
1469fb27b1cdSmcpowers 			}
14707c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SESSION_CLOSE(pd, sops->so_sid,
14717c478bd9Sstevel@tonic-gate 			    rhndl, sops->so_pd);
14727c478bd9Sstevel@tonic-gate 			break;
14737c478bd9Sstevel@tonic-gate 
14747c478bd9Sstevel@tonic-gate 		case KCF_OP_SESSION_LOGIN:
14757c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SESSION_LOGIN(pd, sops->so_sid,
14767c478bd9Sstevel@tonic-gate 			    sops->so_user_type, sops->so_pin,
14777c478bd9Sstevel@tonic-gate 			    sops->so_pin_len, rhndl);
14787c478bd9Sstevel@tonic-gate 			break;
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 		case KCF_OP_SESSION_LOGOUT:
14817c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SESSION_LOGOUT(pd, sops->so_sid, rhndl);
14827c478bd9Sstevel@tonic-gate 			break;
14837c478bd9Sstevel@tonic-gate 
14847c478bd9Sstevel@tonic-gate 		default:
14857c478bd9Sstevel@tonic-gate 			break;
14867c478bd9Sstevel@tonic-gate 		}
14877c478bd9Sstevel@tonic-gate 		break;
14887c478bd9Sstevel@tonic-gate 	}
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate 	case KCF_OG_OBJECT: {
14917c478bd9Sstevel@tonic-gate 		kcf_object_ops_params_t *jops = &params->rp_u.object_params;
14927c478bd9Sstevel@tonic-gate 
14937c478bd9Sstevel@tonic-gate 		ASSERT(ctx == NULL);
14947c478bd9Sstevel@tonic-gate 		switch (optype) {
14957c478bd9Sstevel@tonic-gate 		case KCF_OP_OBJECT_CREATE:
14967c478bd9Sstevel@tonic-gate 			err = KCF_PROV_OBJECT_CREATE(pd, jops->oo_sid,
14977c478bd9Sstevel@tonic-gate 			    jops->oo_template, jops->oo_attribute_count,
14987c478bd9Sstevel@tonic-gate 			    jops->oo_object_id_ptr, rhndl);
14997c478bd9Sstevel@tonic-gate 			break;
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 		case KCF_OP_OBJECT_COPY:
15027c478bd9Sstevel@tonic-gate 			err = KCF_PROV_OBJECT_COPY(pd, jops->oo_sid,
15037c478bd9Sstevel@tonic-gate 			    jops->oo_object_id,
15047c478bd9Sstevel@tonic-gate 			    jops->oo_template, jops->oo_attribute_count,
15057c478bd9Sstevel@tonic-gate 			    jops->oo_object_id_ptr, rhndl);
15067c478bd9Sstevel@tonic-gate 			break;
15077c478bd9Sstevel@tonic-gate 
15087c478bd9Sstevel@tonic-gate 		case KCF_OP_OBJECT_DESTROY:
15097c478bd9Sstevel@tonic-gate 			err = KCF_PROV_OBJECT_DESTROY(pd, jops->oo_sid,
15107c478bd9Sstevel@tonic-gate 			    jops->oo_object_id, rhndl);
15117c478bd9Sstevel@tonic-gate 			break;
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate 		case KCF_OP_OBJECT_GET_SIZE:
15147c478bd9Sstevel@tonic-gate 			err = KCF_PROV_OBJECT_GET_SIZE(pd, jops->oo_sid,
15157c478bd9Sstevel@tonic-gate 			    jops->oo_object_id, jops->oo_object_size, rhndl);
15167c478bd9Sstevel@tonic-gate 			break;
15177c478bd9Sstevel@tonic-gate 
15187c478bd9Sstevel@tonic-gate 		case KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE:
15197c478bd9Sstevel@tonic-gate 			err = KCF_PROV_OBJECT_GET_ATTRIBUTE_VALUE(pd,
15207c478bd9Sstevel@tonic-gate 			    jops->oo_sid, jops->oo_object_id,
15217c478bd9Sstevel@tonic-gate 			    jops->oo_template, jops->oo_attribute_count, rhndl);
15227c478bd9Sstevel@tonic-gate 			break;
15237c478bd9Sstevel@tonic-gate 
15247c478bd9Sstevel@tonic-gate 		case KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE:
15257c478bd9Sstevel@tonic-gate 			err = KCF_PROV_OBJECT_SET_ATTRIBUTE_VALUE(pd,
15267c478bd9Sstevel@tonic-gate 			    jops->oo_sid, jops->oo_object_id,
15277c478bd9Sstevel@tonic-gate 			    jops->oo_template, jops->oo_attribute_count, rhndl);
15287c478bd9Sstevel@tonic-gate 			break;
15297c478bd9Sstevel@tonic-gate 
15307c478bd9Sstevel@tonic-gate 		case KCF_OP_OBJECT_FIND_INIT:
15317c478bd9Sstevel@tonic-gate 			err = KCF_PROV_OBJECT_FIND_INIT(pd, jops->oo_sid,
15327c478bd9Sstevel@tonic-gate 			    jops->oo_template, jops->oo_attribute_count,
15337c478bd9Sstevel@tonic-gate 			    jops->oo_find_init_pp_ptr, rhndl);
15347c478bd9Sstevel@tonic-gate 			break;
15357c478bd9Sstevel@tonic-gate 
15367c478bd9Sstevel@tonic-gate 		case KCF_OP_OBJECT_FIND:
15377c478bd9Sstevel@tonic-gate 			err = KCF_PROV_OBJECT_FIND(pd, jops->oo_find_pp,
15387c478bd9Sstevel@tonic-gate 			    jops->oo_object_id_ptr, jops->oo_max_object_count,
15397c478bd9Sstevel@tonic-gate 			    jops->oo_object_count_ptr, rhndl);
15407c478bd9Sstevel@tonic-gate 			break;
15417c478bd9Sstevel@tonic-gate 
15427c478bd9Sstevel@tonic-gate 		case KCF_OP_OBJECT_FIND_FINAL:
15437c478bd9Sstevel@tonic-gate 			err = KCF_PROV_OBJECT_FIND_FINAL(pd, jops->oo_find_pp,
15447c478bd9Sstevel@tonic-gate 			    rhndl);
15457c478bd9Sstevel@tonic-gate 			break;
15467c478bd9Sstevel@tonic-gate 
15477c478bd9Sstevel@tonic-gate 		default:
15487c478bd9Sstevel@tonic-gate 			break;
15497c478bd9Sstevel@tonic-gate 		}
15507c478bd9Sstevel@tonic-gate 		break;
15517c478bd9Sstevel@tonic-gate 	}
15527c478bd9Sstevel@tonic-gate 
15537c478bd9Sstevel@tonic-gate 	case KCF_OG_PROVMGMT: {
15547c478bd9Sstevel@tonic-gate 		kcf_provmgmt_ops_params_t *pops = &params->rp_u.provmgmt_params;
15557c478bd9Sstevel@tonic-gate 
15567c478bd9Sstevel@tonic-gate 		ASSERT(ctx == NULL);
15577c478bd9Sstevel@tonic-gate 		switch (optype) {
15587c478bd9Sstevel@tonic-gate 		case KCF_OP_MGMT_EXTINFO:
1559fb27b1cdSmcpowers 			/*
1560fb27b1cdSmcpowers 			 * po_pd may be a logical provider, in which case
1561fb27b1cdSmcpowers 			 * we need to check whether it has been removed.
1562fb27b1cdSmcpowers 			 */
1563fb27b1cdSmcpowers 			if (KCF_IS_PROV_REMOVED(pops->po_pd)) {
1564fb27b1cdSmcpowers 				err = CRYPTO_DEVICE_ERROR;
1565fb27b1cdSmcpowers 				break;
1566fb27b1cdSmcpowers 			}
15677c478bd9Sstevel@tonic-gate 			err = KCF_PROV_EXT_INFO(pd, pops->po_ext_info, rhndl,
15687c478bd9Sstevel@tonic-gate 			    pops->po_pd);
15697c478bd9Sstevel@tonic-gate 			break;
15707c478bd9Sstevel@tonic-gate 
15717c478bd9Sstevel@tonic-gate 		case KCF_OP_MGMT_INITTOKEN:
15727c478bd9Sstevel@tonic-gate 			err = KCF_PROV_INIT_TOKEN(pd, pops->po_pin,
15737c478bd9Sstevel@tonic-gate 			    pops->po_pin_len, pops->po_label, rhndl);
15747c478bd9Sstevel@tonic-gate 			break;
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate 		case KCF_OP_MGMT_INITPIN:
15777c478bd9Sstevel@tonic-gate 			err = KCF_PROV_INIT_PIN(pd, pops->po_sid, pops->po_pin,
15787c478bd9Sstevel@tonic-gate 			    pops->po_pin_len, rhndl);
15797c478bd9Sstevel@tonic-gate 			break;
15807c478bd9Sstevel@tonic-gate 
15817c478bd9Sstevel@tonic-gate 		case KCF_OP_MGMT_SETPIN:
15827c478bd9Sstevel@tonic-gate 			err = KCF_PROV_SET_PIN(pd, pops->po_sid,
15837c478bd9Sstevel@tonic-gate 			    pops->po_old_pin, pops->po_old_pin_len,
15847c478bd9Sstevel@tonic-gate 			    pops->po_pin, pops->po_pin_len, rhndl);
15857c478bd9Sstevel@tonic-gate 			break;
15867c478bd9Sstevel@tonic-gate 
15877c478bd9Sstevel@tonic-gate 		default:
15887c478bd9Sstevel@tonic-gate 			break;
15897c478bd9Sstevel@tonic-gate 		}
15907c478bd9Sstevel@tonic-gate 		break;
15917c478bd9Sstevel@tonic-gate 	}
15927c478bd9Sstevel@tonic-gate 
1593034448feSmcpowers 	case KCF_OG_NOSTORE_KEY: {
1594034448feSmcpowers 		kcf_key_ops_params_t *kops = &params->rp_u.key_params;
1595034448feSmcpowers 
1596034448feSmcpowers 		ASSERT(ctx == NULL);
1597034448feSmcpowers 		KCF_SET_PROVIDER_MECHNUM(kops->ko_framework_mechtype, pd,
1598034448feSmcpowers 		    &kops->ko_mech);
1599034448feSmcpowers 
1600034448feSmcpowers 		switch (optype) {
1601034448feSmcpowers 		case KCF_OP_KEY_GENERATE:
1602034448feSmcpowers 			err = KCF_PROV_NOSTORE_KEY_GENERATE(pd, kops->ko_sid,
1603034448feSmcpowers 			    &kops->ko_mech, kops->ko_key_template,
1604034448feSmcpowers 			    kops->ko_key_attribute_count,
1605034448feSmcpowers 			    kops->ko_out_template1,
1606034448feSmcpowers 			    kops->ko_out_attribute_count1, rhndl);
1607034448feSmcpowers 			break;
1608034448feSmcpowers 
1609034448feSmcpowers 		case KCF_OP_KEY_GENERATE_PAIR:
1610034448feSmcpowers 			err = KCF_PROV_NOSTORE_KEY_GENERATE_PAIR(pd,
1611034448feSmcpowers 			    kops->ko_sid, &kops->ko_mech,
1612034448feSmcpowers 			    kops->ko_key_template, kops->ko_key_attribute_count,
1613034448feSmcpowers 			    kops->ko_private_key_template,
1614034448feSmcpowers 			    kops->ko_private_key_attribute_count,
1615034448feSmcpowers 			    kops->ko_out_template1,
1616034448feSmcpowers 			    kops->ko_out_attribute_count1,
1617034448feSmcpowers 			    kops->ko_out_template2,
1618034448feSmcpowers 			    kops->ko_out_attribute_count2,
1619034448feSmcpowers 			    rhndl);
1620034448feSmcpowers 			break;
1621034448feSmcpowers 
1622034448feSmcpowers 		case KCF_OP_KEY_DERIVE:
1623034448feSmcpowers 			err = KCF_PROV_NOSTORE_KEY_DERIVE(pd, kops->ko_sid,
1624034448feSmcpowers 			    &kops->ko_mech, kops->ko_key,
1625034448feSmcpowers 			    kops->ko_key_template,
1626034448feSmcpowers 			    kops->ko_key_attribute_count,
1627034448feSmcpowers 			    kops->ko_out_template1,
1628034448feSmcpowers 			    kops->ko_out_attribute_count1, rhndl);
1629034448feSmcpowers 			break;
1630034448feSmcpowers 
1631034448feSmcpowers 		default:
1632034448feSmcpowers 			break;
1633034448feSmcpowers 		}
1634034448feSmcpowers 		break;
1635034448feSmcpowers 	}
16367c478bd9Sstevel@tonic-gate 	default:
16377c478bd9Sstevel@tonic-gate 		break;
16387c478bd9Sstevel@tonic-gate 	}		/* end of switch(params->rp_opgrp) */
16397c478bd9Sstevel@tonic-gate 
16407c478bd9Sstevel@tonic-gate 	KCF_PROV_INCRSTATS(pd, err);
16417c478bd9Sstevel@tonic-gate 	return (err);
16427c478bd9Sstevel@tonic-gate }
16437c478bd9Sstevel@tonic-gate 
16447c478bd9Sstevel@tonic-gate /*
16457c478bd9Sstevel@tonic-gate  * Emulate the call for a multipart dual ops with 2 single steps.
16467c478bd9Sstevel@tonic-gate  * This routine is always called in the context of a working thread
16477c478bd9Sstevel@tonic-gate  * running kcf_svc_do_run().
16487c478bd9Sstevel@tonic-gate  * The single steps are submitted in a pure synchronous way (blocking).
16497c478bd9Sstevel@tonic-gate  * When this routine returns, kcf_svc_do_run() will call kcf_aop_done()
16507c478bd9Sstevel@tonic-gate  * so the originating consumer's callback gets invoked. kcf_aop_done()
16517c478bd9Sstevel@tonic-gate  * takes care of freeing the operation context. So, this routine does
16527c478bd9Sstevel@tonic-gate  * not free the operation context.
16537c478bd9Sstevel@tonic-gate  *
16547c478bd9Sstevel@tonic-gate  * The provider descriptor is assumed held by the callers.
16557c478bd9Sstevel@tonic-gate  */
16567c478bd9Sstevel@tonic-gate static int
kcf_emulate_dual(kcf_provider_desc_t * pd,crypto_ctx_t * ctx,kcf_req_params_t * params)16577c478bd9Sstevel@tonic-gate kcf_emulate_dual(kcf_provider_desc_t *pd, crypto_ctx_t *ctx,
16587c478bd9Sstevel@tonic-gate     kcf_req_params_t *params)
16597c478bd9Sstevel@tonic-gate {
16607c478bd9Sstevel@tonic-gate 	int err = CRYPTO_ARGUMENTS_BAD;
16617c478bd9Sstevel@tonic-gate 	kcf_op_type_t optype;
16627c478bd9Sstevel@tonic-gate 	size_t save_len;
16637c478bd9Sstevel@tonic-gate 	off_t save_offset;
16647c478bd9Sstevel@tonic-gate 
16657c478bd9Sstevel@tonic-gate 	optype = params->rp_optype;
16667c478bd9Sstevel@tonic-gate 
16677c478bd9Sstevel@tonic-gate 	switch (params->rp_opgrp) {
16687c478bd9Sstevel@tonic-gate 	case KCF_OG_ENCRYPT_MAC: {
16697c478bd9Sstevel@tonic-gate 		kcf_encrypt_mac_ops_params_t *cmops =
16707c478bd9Sstevel@tonic-gate 		    &params->rp_u.encrypt_mac_params;
16717c478bd9Sstevel@tonic-gate 		kcf_context_t *encr_kcf_ctx;
16727c478bd9Sstevel@tonic-gate 		crypto_ctx_t *mac_ctx;
16737c478bd9Sstevel@tonic-gate 		kcf_req_params_t encr_params;
16747c478bd9Sstevel@tonic-gate 
16757c478bd9Sstevel@tonic-gate 		encr_kcf_ctx = (kcf_context_t *)(ctx->cc_framework_private);
16767c478bd9Sstevel@tonic-gate 
16777c478bd9Sstevel@tonic-gate 		switch (optype) {
16787c478bd9Sstevel@tonic-gate 		case KCF_OP_INIT: {
16797c478bd9Sstevel@tonic-gate 			encr_kcf_ctx->kc_secondctx = NULL;
16807c478bd9Sstevel@tonic-gate 
16817c478bd9Sstevel@tonic-gate 			KCF_WRAP_ENCRYPT_OPS_PARAMS(&encr_params, KCF_OP_INIT,
16827c478bd9Sstevel@tonic-gate 			    pd->pd_sid, &cmops->em_encr_mech,
16837c478bd9Sstevel@tonic-gate 			    cmops->em_encr_key, NULL, NULL,
16847c478bd9Sstevel@tonic-gate 			    cmops->em_encr_templ);
16857c478bd9Sstevel@tonic-gate 
16867c478bd9Sstevel@tonic-gate 			err = kcf_submit_request(pd, ctx, NULL, &encr_params,
16877c478bd9Sstevel@tonic-gate 			    B_FALSE);
16887c478bd9Sstevel@tonic-gate 
16897c478bd9Sstevel@tonic-gate 			/* It can't be CRYPTO_QUEUED */
16907c478bd9Sstevel@tonic-gate 			if (err != CRYPTO_SUCCESS) {
16917c478bd9Sstevel@tonic-gate 				break;
16927c478bd9Sstevel@tonic-gate 			}
16937c478bd9Sstevel@tonic-gate 
16947c478bd9Sstevel@tonic-gate 			err = crypto_mac_init(&cmops->em_mac_mech,
16957c478bd9Sstevel@tonic-gate 			    cmops->em_mac_key, cmops->em_mac_templ,
16967c478bd9Sstevel@tonic-gate 			    (crypto_context_t *)&mac_ctx, NULL);
16977c478bd9Sstevel@tonic-gate 
16987c478bd9Sstevel@tonic-gate 			if (err == CRYPTO_SUCCESS) {
16997c478bd9Sstevel@tonic-gate 				encr_kcf_ctx->kc_secondctx = (kcf_context_t *)
17007c478bd9Sstevel@tonic-gate 				    mac_ctx->cc_framework_private;
17017c478bd9Sstevel@tonic-gate 				KCF_CONTEXT_REFHOLD((kcf_context_t *)
17027c478bd9Sstevel@tonic-gate 				    mac_ctx->cc_framework_private);
17037c478bd9Sstevel@tonic-gate 			}
17047c478bd9Sstevel@tonic-gate 
17057c478bd9Sstevel@tonic-gate 			break;
17067c478bd9Sstevel@tonic-gate 
17077c478bd9Sstevel@tonic-gate 		}
17087c478bd9Sstevel@tonic-gate 		case KCF_OP_UPDATE: {
17097c478bd9Sstevel@tonic-gate 			crypto_dual_data_t *ct = cmops->em_ciphertext;
17107c478bd9Sstevel@tonic-gate 			crypto_data_t *pt = cmops->em_plaintext;
17117c478bd9Sstevel@tonic-gate 			kcf_context_t *mac_kcf_ctx = encr_kcf_ctx->kc_secondctx;
17127c478bd9Sstevel@tonic-gate 			crypto_ctx_t *mac_ctx = &mac_kcf_ctx->kc_glbl_ctx;
17137c478bd9Sstevel@tonic-gate 
17147c478bd9Sstevel@tonic-gate 			KCF_WRAP_ENCRYPT_OPS_PARAMS(&encr_params, KCF_OP_UPDATE,
17157c478bd9Sstevel@tonic-gate 			    pd->pd_sid, NULL, NULL, pt, (crypto_data_t *)ct,
17167c478bd9Sstevel@tonic-gate 			    NULL);
17177c478bd9Sstevel@tonic-gate 
17187c478bd9Sstevel@tonic-gate 			err = kcf_submit_request(pd, ctx, NULL, &encr_params,
17197c478bd9Sstevel@tonic-gate 			    B_FALSE);
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate 			/* It can't be CRYPTO_QUEUED */
17227c478bd9Sstevel@tonic-gate 			if (err != CRYPTO_SUCCESS) {
17237c478bd9Sstevel@tonic-gate 				break;
17247c478bd9Sstevel@tonic-gate 			}
17257c478bd9Sstevel@tonic-gate 
17267c478bd9Sstevel@tonic-gate 			save_offset = ct->dd_offset1;
17277c478bd9Sstevel@tonic-gate 			save_len = ct->dd_len1;
17287c478bd9Sstevel@tonic-gate 			if (ct->dd_len2 == 0) {
17297c478bd9Sstevel@tonic-gate 				/*
17307c478bd9Sstevel@tonic-gate 				 * The previous encrypt step was an
17317c478bd9Sstevel@tonic-gate 				 * accumulation only and didn't produce any
17327c478bd9Sstevel@tonic-gate 				 * partial output
17337c478bd9Sstevel@tonic-gate 				 */
17347c478bd9Sstevel@tonic-gate 				if (ct->dd_len1 == 0)
17357c478bd9Sstevel@tonic-gate 					break;
17367c478bd9Sstevel@tonic-gate 
17377c478bd9Sstevel@tonic-gate 			} else {
17387c478bd9Sstevel@tonic-gate 				ct->dd_offset1 = ct->dd_offset2;
17397c478bd9Sstevel@tonic-gate 				ct->dd_len1 = ct->dd_len2;
17407c478bd9Sstevel@tonic-gate 			}
17417c478bd9Sstevel@tonic-gate 			err = crypto_mac_update((crypto_context_t)mac_ctx,
17427c478bd9Sstevel@tonic-gate 			    (crypto_data_t *)ct, NULL);
17437c478bd9Sstevel@tonic-gate 
17447c478bd9Sstevel@tonic-gate 			ct->dd_offset1 = save_offset;
17457c478bd9Sstevel@tonic-gate 			ct->dd_len1 = save_len;
17467c478bd9Sstevel@tonic-gate 
17477c478bd9Sstevel@tonic-gate 			break;
17487c478bd9Sstevel@tonic-gate 		}
17497c478bd9Sstevel@tonic-gate 		case KCF_OP_FINAL: {
17507c478bd9Sstevel@tonic-gate 			crypto_dual_data_t *ct = cmops->em_ciphertext;
17517c478bd9Sstevel@tonic-gate 			crypto_data_t *mac = cmops->em_mac;
17527c478bd9Sstevel@tonic-gate 			kcf_context_t *mac_kcf_ctx = encr_kcf_ctx->kc_secondctx;
17537c478bd9Sstevel@tonic-gate 			crypto_ctx_t *mac_ctx = &mac_kcf_ctx->kc_glbl_ctx;
17547c478bd9Sstevel@tonic-gate 			crypto_context_t mac_context = mac_ctx;
17557c478bd9Sstevel@tonic-gate 
17567c478bd9Sstevel@tonic-gate 			KCF_WRAP_ENCRYPT_OPS_PARAMS(&encr_params, KCF_OP_FINAL,
17577c478bd9Sstevel@tonic-gate 			    pd->pd_sid, NULL, NULL, NULL, (crypto_data_t *)ct,
17587c478bd9Sstevel@tonic-gate 			    NULL);
17597c478bd9Sstevel@tonic-gate 
17607c478bd9Sstevel@tonic-gate 			err = kcf_submit_request(pd, ctx, NULL, &encr_params,
17617c478bd9Sstevel@tonic-gate 			    B_FALSE);
17627c478bd9Sstevel@tonic-gate 
17637c478bd9Sstevel@tonic-gate 			/* It can't be CRYPTO_QUEUED */
17647c478bd9Sstevel@tonic-gate 			if (err != CRYPTO_SUCCESS) {
17657c478bd9Sstevel@tonic-gate 				crypto_cancel_ctx(mac_context);
17667c478bd9Sstevel@tonic-gate 				break;
17677c478bd9Sstevel@tonic-gate 			}
17687c478bd9Sstevel@tonic-gate 
17697c478bd9Sstevel@tonic-gate 			if (ct->dd_len2 > 0) {
17707c478bd9Sstevel@tonic-gate 				save_offset = ct->dd_offset1;
17717c478bd9Sstevel@tonic-gate 				save_len = ct->dd_len1;
17727c478bd9Sstevel@tonic-gate 				ct->dd_offset1 = ct->dd_offset2;
17737c478bd9Sstevel@tonic-gate 				ct->dd_len1 = ct->dd_len2;
17747c478bd9Sstevel@tonic-gate 
17757c478bd9Sstevel@tonic-gate 				err = crypto_mac_update(mac_context,
17767c478bd9Sstevel@tonic-gate 				    (crypto_data_t *)ct, NULL);
17777c478bd9Sstevel@tonic-gate 
17787c478bd9Sstevel@tonic-gate 				ct->dd_offset1 = save_offset;
17797c478bd9Sstevel@tonic-gate 				ct->dd_len1 = save_len;
17807c478bd9Sstevel@tonic-gate 
17817c478bd9Sstevel@tonic-gate 				if (err != CRYPTO_SUCCESS)  {
17827c478bd9Sstevel@tonic-gate 					crypto_cancel_ctx(mac_context);
17837c478bd9Sstevel@tonic-gate 					return (err);
17847c478bd9Sstevel@tonic-gate 				}
17857c478bd9Sstevel@tonic-gate 			}
17867c478bd9Sstevel@tonic-gate 
17877c478bd9Sstevel@tonic-gate 			/* and finally, collect the MAC */
17887c478bd9Sstevel@tonic-gate 			err = crypto_mac_final(mac_context, mac, NULL);
17897c478bd9Sstevel@tonic-gate 			break;
17907c478bd9Sstevel@tonic-gate 		}
17917c478bd9Sstevel@tonic-gate 
17927c478bd9Sstevel@tonic-gate 		default:
17937c478bd9Sstevel@tonic-gate 			break;
17947c478bd9Sstevel@tonic-gate 		}
17957c478bd9Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, err);
17967c478bd9Sstevel@tonic-gate 		break;
17977c478bd9Sstevel@tonic-gate 	}
17987c478bd9Sstevel@tonic-gate 	case KCF_OG_MAC_DECRYPT: {
17997c478bd9Sstevel@tonic-gate 		kcf_mac_decrypt_ops_params_t *mdops =
18007c478bd9Sstevel@tonic-gate 		    &params->rp_u.mac_decrypt_params;
18017c478bd9Sstevel@tonic-gate 		kcf_context_t *decr_kcf_ctx;
18027c478bd9Sstevel@tonic-gate 		crypto_ctx_t *mac_ctx;
18037c478bd9Sstevel@tonic-gate 		kcf_req_params_t decr_params;
18047c478bd9Sstevel@tonic-gate 
18057c478bd9Sstevel@tonic-gate 		decr_kcf_ctx = (kcf_context_t *)(ctx->cc_framework_private);
18067c478bd9Sstevel@tonic-gate 
18077c478bd9Sstevel@tonic-gate 		switch (optype) {
18087c478bd9Sstevel@tonic-gate 		case KCF_OP_INIT: {
18097c478bd9Sstevel@tonic-gate 			decr_kcf_ctx->kc_secondctx = NULL;
18107c478bd9Sstevel@tonic-gate 
18117c478bd9Sstevel@tonic-gate 			err = crypto_mac_init(&mdops->md_mac_mech,
18127c478bd9Sstevel@tonic-gate 			    mdops->md_mac_key, mdops->md_mac_templ,
18137c478bd9Sstevel@tonic-gate 			    (crypto_context_t *)&mac_ctx, NULL);
18147c478bd9Sstevel@tonic-gate 
18157c478bd9Sstevel@tonic-gate 			/* It can't be CRYPTO_QUEUED */
18167c478bd9Sstevel@tonic-gate 			if (err != CRYPTO_SUCCESS) {
18177c478bd9Sstevel@tonic-gate 				break;
18187c478bd9Sstevel@tonic-gate 			}
18197c478bd9Sstevel@tonic-gate 
18207c478bd9Sstevel@tonic-gate 			KCF_WRAP_DECRYPT_OPS_PARAMS(&decr_params, KCF_OP_INIT,
18217c478bd9Sstevel@tonic-gate 			    pd->pd_sid, &mdops->md_decr_mech,
18227c478bd9Sstevel@tonic-gate 			    mdops->md_decr_key, NULL, NULL,
18237c478bd9Sstevel@tonic-gate 			    mdops->md_decr_templ);
18247c478bd9Sstevel@tonic-gate 
18257c478bd9Sstevel@tonic-gate 			err = kcf_submit_request(pd, ctx, NULL, &decr_params,
18267c478bd9Sstevel@tonic-gate 			    B_FALSE);
18277c478bd9Sstevel@tonic-gate 
18287c478bd9Sstevel@tonic-gate 			/* It can't be CRYPTO_QUEUED */
18297c478bd9Sstevel@tonic-gate 			if (err != CRYPTO_SUCCESS) {
18307c478bd9Sstevel@tonic-gate 				crypto_cancel_ctx((crypto_context_t)mac_ctx);
18317c478bd9Sstevel@tonic-gate 				break;
18327c478bd9Sstevel@tonic-gate 			}
18337c478bd9Sstevel@tonic-gate 
18347c478bd9Sstevel@tonic-gate 			decr_kcf_ctx->kc_secondctx = (kcf_context_t *)
18357c478bd9Sstevel@tonic-gate 			    mac_ctx->cc_framework_private;
18367c478bd9Sstevel@tonic-gate 			KCF_CONTEXT_REFHOLD((kcf_context_t *)
18377c478bd9Sstevel@tonic-gate 			    mac_ctx->cc_framework_private);
18387c478bd9Sstevel@tonic-gate 
18397c478bd9Sstevel@tonic-gate 			break;
18407c478bd9Sstevel@tonic-gate 
18417c478bd9Sstevel@tonic-gate 		}
18427c478bd9Sstevel@tonic-gate 		case KCF_OP_UPDATE: {
18437c478bd9Sstevel@tonic-gate 			crypto_dual_data_t *ct = mdops->md_ciphertext;
18447c478bd9Sstevel@tonic-gate 			crypto_data_t *pt = mdops->md_plaintext;
18457c478bd9Sstevel@tonic-gate 			kcf_context_t *mac_kcf_ctx = decr_kcf_ctx->kc_secondctx;
18467c478bd9Sstevel@tonic-gate 			crypto_ctx_t *mac_ctx = &mac_kcf_ctx->kc_glbl_ctx;
18477c478bd9Sstevel@tonic-gate 
18487c478bd9Sstevel@tonic-gate 			err = crypto_mac_update((crypto_context_t)mac_ctx,
18497c478bd9Sstevel@tonic-gate 			    (crypto_data_t *)ct, NULL);
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 			if (err != CRYPTO_SUCCESS)
18527c478bd9Sstevel@tonic-gate 				break;
18537c478bd9Sstevel@tonic-gate 
18547c478bd9Sstevel@tonic-gate 			save_offset = ct->dd_offset1;
18557c478bd9Sstevel@tonic-gate 			save_len = ct->dd_len1;
18567c478bd9Sstevel@tonic-gate 
18577c478bd9Sstevel@tonic-gate 			/* zero ct->dd_len2 means decrypt everything */
18587c478bd9Sstevel@tonic-gate 			if (ct->dd_len2 > 0) {
18597c478bd9Sstevel@tonic-gate 				ct->dd_offset1 = ct->dd_offset2;
18607c478bd9Sstevel@tonic-gate 				ct->dd_len1 = ct->dd_len2;
18617c478bd9Sstevel@tonic-gate 			}
18627c478bd9Sstevel@tonic-gate 
18637c478bd9Sstevel@tonic-gate 			err = crypto_decrypt_update((crypto_context_t)ctx,
18647c478bd9Sstevel@tonic-gate 			    (crypto_data_t *)ct, pt, NULL);
18657c478bd9Sstevel@tonic-gate 
18667c478bd9Sstevel@tonic-gate 			ct->dd_offset1 = save_offset;
18677c478bd9Sstevel@tonic-gate 			ct->dd_len1 = save_len;
18687c478bd9Sstevel@tonic-gate 
18697c478bd9Sstevel@tonic-gate 			break;
18707c478bd9Sstevel@tonic-gate 		}
18717c478bd9Sstevel@tonic-gate 		case KCF_OP_FINAL: {
18727c478bd9Sstevel@tonic-gate 			crypto_data_t *pt = mdops->md_plaintext;
18737c478bd9Sstevel@tonic-gate 			crypto_data_t *mac = mdops->md_mac;
18747c478bd9Sstevel@tonic-gate 			kcf_context_t *mac_kcf_ctx = decr_kcf_ctx->kc_secondctx;
18757c478bd9Sstevel@tonic-gate 			crypto_ctx_t *mac_ctx = &mac_kcf_ctx->kc_glbl_ctx;
18767c478bd9Sstevel@tonic-gate 
18777c478bd9Sstevel@tonic-gate 			err = crypto_mac_final((crypto_context_t)mac_ctx,
18787c478bd9Sstevel@tonic-gate 			    mac, NULL);
18797c478bd9Sstevel@tonic-gate 
18807c478bd9Sstevel@tonic-gate 			if (err != CRYPTO_SUCCESS) {
18817c478bd9Sstevel@tonic-gate 				crypto_cancel_ctx(ctx);
18827c478bd9Sstevel@tonic-gate 				break;
18837c478bd9Sstevel@tonic-gate 			}
18847c478bd9Sstevel@tonic-gate 
18857c478bd9Sstevel@tonic-gate 			/* Get the last chunk of plaintext */
18867c478bd9Sstevel@tonic-gate 			KCF_CONTEXT_REFHOLD(decr_kcf_ctx);
18877c478bd9Sstevel@tonic-gate 			err = crypto_decrypt_final((crypto_context_t)ctx, pt,
18887c478bd9Sstevel@tonic-gate 			    NULL);
18897c478bd9Sstevel@tonic-gate 
18907c478bd9Sstevel@tonic-gate 			break;
18917c478bd9Sstevel@tonic-gate 		}
18927c478bd9Sstevel@tonic-gate 		}
18937c478bd9Sstevel@tonic-gate 		break;
18947c478bd9Sstevel@tonic-gate 	}
18957c478bd9Sstevel@tonic-gate 	default:
18967c478bd9Sstevel@tonic-gate 
18977c478bd9Sstevel@tonic-gate 		break;
18987c478bd9Sstevel@tonic-gate 	}		/* end of switch(params->rp_opgrp) */
18997c478bd9Sstevel@tonic-gate 
19007c478bd9Sstevel@tonic-gate 	return (err);
19017c478bd9Sstevel@tonic-gate }
1902