xref: /onnv-gate/usr/src/uts/common/crypto/api/kcf_dual.c (revision 10444:713f936eb685)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51808Smcpowers  * Common Development and Distribution License (the "License").
61808Smcpowers  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*10444SVladimir.Kotal@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/errno.h>
270Sstevel@tonic-gate #include <sys/types.h>
280Sstevel@tonic-gate #include <sys/kmem.h>
29904Smcpowers #include <sys/sysmacros.h>
300Sstevel@tonic-gate #include <sys/crypto/common.h>
310Sstevel@tonic-gate #include <sys/crypto/impl.h>
320Sstevel@tonic-gate #include <sys/crypto/api.h>
330Sstevel@tonic-gate #include <sys/crypto/spi.h>
340Sstevel@tonic-gate #include <sys/crypto/sched_impl.h>
350Sstevel@tonic-gate 
36904Smcpowers #define	CRYPTO_OPS_OFFSET(f)		offsetof(crypto_ops_t, co_##f)
37904Smcpowers #define	CRYPTO_CIPHER_MAC_OFFSET(f) offsetof(crypto_dual_cipher_mac_ops_t, f)
380Sstevel@tonic-gate 
390Sstevel@tonic-gate static int crypto_mac_decrypt_common(crypto_mechanism_t *,
400Sstevel@tonic-gate     crypto_mechanism_t *, crypto_dual_data_t *, crypto_key_t *, crypto_key_t *,
410Sstevel@tonic-gate     crypto_ctx_template_t, crypto_ctx_template_t, crypto_data_t *,
420Sstevel@tonic-gate     crypto_data_t *, crypto_call_req_t *, boolean_t);
430Sstevel@tonic-gate 
44904Smcpowers static int crypto_mac_decrypt_common_prov(crypto_provider_t provider,
45904Smcpowers     crypto_session_id_t sid, crypto_mechanism_t *, crypto_mechanism_t *,
46904Smcpowers     crypto_dual_data_t *, crypto_key_t *, crypto_key_t *,
47904Smcpowers     crypto_ctx_template_t, crypto_ctx_template_t, crypto_data_t *,
48904Smcpowers     crypto_data_t *, crypto_call_req_t *, boolean_t);
49904Smcpowers 
50904Smcpowers int
51904Smcpowers crypto_encrypt_mac_prov(crypto_provider_t provider, crypto_session_id_t sid,
52904Smcpowers     crypto_mechanism_t *encr_mech, crypto_mechanism_t *mac_mech,
53904Smcpowers     crypto_data_t *pt, crypto_key_t *encr_key, crypto_key_t *mac_key,
54904Smcpowers     crypto_ctx_template_t encr_tmpl, crypto_ctx_template_t mac_tmpl,
55904Smcpowers     crypto_dual_data_t *ct, crypto_data_t *mac, crypto_call_req_t *crq)
56904Smcpowers {
57904Smcpowers 	/*
58904Smcpowers 	 * First try to find a provider for the encryption mechanism, that
59904Smcpowers 	 * is also capable of the MAC mechanism.
60904Smcpowers 	 */
61904Smcpowers 	int rv;
62904Smcpowers 	kcf_mech_entry_t *me;
63904Smcpowers 	kcf_provider_desc_t *pd = provider;
64904Smcpowers 	kcf_provider_desc_t *real_provider = pd;
65904Smcpowers 	kcf_ctx_template_t *ctx_encr_tmpl, *ctx_mac_tmpl;
66904Smcpowers 	kcf_req_params_t params;
67904Smcpowers 	kcf_encrypt_mac_ops_params_t *cmops;
68904Smcpowers 	crypto_spi_ctx_template_t spi_encr_tmpl = NULL, spi_mac_tmpl = NULL;
69904Smcpowers 
70904Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
71904Smcpowers 
72904Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
73*10444SVladimir.Kotal@Sun.COM 		rv = kcf_get_hardware_provider(encr_mech->cm_type, encr_key,
74*10444SVladimir.Kotal@Sun.COM 		    mac_mech->cm_type, mac_key, CHECK_RESTRICT(crq), pd,
751808Smcpowers 		    &real_provider, CRYPTO_FG_ENCRYPT_MAC_ATOMIC);
76904Smcpowers 
77904Smcpowers 		if (rv != CRYPTO_SUCCESS)
78904Smcpowers 			return (rv);
79904Smcpowers 	}
80904Smcpowers 
81904Smcpowers 	/*
82904Smcpowers 	 * For SW providers, check the validity of the context template
83904Smcpowers 	 * It is very rare that the generation number mis-matches, so
84904Smcpowers 	 * is acceptable to fail here, and let the consumer recover by
85904Smcpowers 	 * freeing this tmpl and create a new one for the key and new SW
86904Smcpowers 	 * provider
87904Smcpowers 	 * Warning! will need to change when multiple software providers
88904Smcpowers 	 * per mechanism are supported.
89904Smcpowers 	 */
90904Smcpowers 
91904Smcpowers 	if (real_provider->pd_prov_type == CRYPTO_SW_PROVIDER) {
92904Smcpowers 		if (encr_tmpl != NULL) {
93904Smcpowers 			if (kcf_get_mech_entry(encr_mech->cm_type, &me) !=
94904Smcpowers 			    KCF_SUCCESS) {
95904Smcpowers 				rv = CRYPTO_MECHANISM_INVALID;
96904Smcpowers 				goto out;
97904Smcpowers 			}
98904Smcpowers 			ctx_encr_tmpl = (kcf_ctx_template_t *)encr_tmpl;
99904Smcpowers 			if (ctx_encr_tmpl->ct_generation != me->me_gen_swprov) {
100904Smcpowers 				rv = CRYPTO_OLD_CTX_TEMPLATE;
101904Smcpowers 				goto out;
102904Smcpowers 			}
103904Smcpowers 			spi_encr_tmpl = ctx_encr_tmpl->ct_prov_tmpl;
104904Smcpowers 		}
105904Smcpowers 
106904Smcpowers 		if (mac_tmpl != NULL) {
107904Smcpowers 			if (kcf_get_mech_entry(mac_mech->cm_type, &me) !=
108904Smcpowers 			    KCF_SUCCESS) {
109904Smcpowers 				rv = CRYPTO_MECHANISM_INVALID;
110904Smcpowers 				goto out;
111904Smcpowers 			}
112904Smcpowers 			ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
113904Smcpowers 			if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
114904Smcpowers 				rv = CRYPTO_OLD_CTX_TEMPLATE;
115904Smcpowers 				goto out;
116904Smcpowers 			}
117904Smcpowers 			spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
118904Smcpowers 		}
119904Smcpowers 	}
120904Smcpowers 
121904Smcpowers 	/* The fast path for SW providers. */
122904Smcpowers 	if (CHECK_FASTPATH(crq, real_provider)) {
123904Smcpowers 		crypto_mechanism_t lencr_mech;
124904Smcpowers 		crypto_mechanism_t lmac_mech;
125904Smcpowers 
126904Smcpowers 		/* careful! structs assignments */
127904Smcpowers 		lencr_mech = *encr_mech;
128904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(encr_mech->cm_type, real_provider,
129904Smcpowers 		    &lencr_mech);
130904Smcpowers 
131904Smcpowers 		lmac_mech = *mac_mech;
132904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
133904Smcpowers 		    &lmac_mech);
134904Smcpowers 
135904Smcpowers 		rv = KCF_PROV_ENCRYPT_MAC_ATOMIC(real_provider, sid,
136904Smcpowers 		    &lencr_mech, encr_key, &lmac_mech, mac_key, pt, ct,
137904Smcpowers 		    mac, spi_encr_tmpl, spi_mac_tmpl, KCF_SWFP_RHNDL(crq));
138904Smcpowers 
139904Smcpowers 		KCF_PROV_INCRSTATS(pd, rv);
140904Smcpowers 	} else {
141904Smcpowers 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_ATOMIC,
142904Smcpowers 		    sid, encr_key, mac_key, pt, ct, mac, spi_encr_tmpl,
143904Smcpowers 		    spi_mac_tmpl);
144904Smcpowers 
145904Smcpowers 		cmops = &(params.rp_u.encrypt_mac_params);
146904Smcpowers 
147904Smcpowers 		/* careful! structs assignments */
148904Smcpowers 		cmops->em_encr_mech = *encr_mech;
149904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(encr_mech->cm_type, real_provider,
150904Smcpowers 		    &cmops->em_encr_mech);
151904Smcpowers 		cmops->em_framework_encr_mechtype = encr_mech->cm_type;
152904Smcpowers 
153904Smcpowers 		cmops->em_mac_mech = *mac_mech;
154904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
155904Smcpowers 		    &cmops->em_mac_mech);
156904Smcpowers 		cmops->em_framework_mac_mechtype = mac_mech->cm_type;
157904Smcpowers 
158904Smcpowers 		rv = kcf_submit_request(real_provider, NULL, crq, &params,
159904Smcpowers 		    B_FALSE);
160904Smcpowers 	}
161904Smcpowers 
162904Smcpowers out:
163904Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
164904Smcpowers 		KCF_PROV_REFRELE(real_provider);
165904Smcpowers 	return (rv);
166904Smcpowers }
167904Smcpowers 
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate  * Performs a dual encrypt/mac atomic operation. The provider and session
1700Sstevel@tonic-gate  * to use are determined by the KCF dispatcher.
1710Sstevel@tonic-gate  */
1720Sstevel@tonic-gate int
1730Sstevel@tonic-gate crypto_encrypt_mac(crypto_mechanism_t *encr_mech,
1740Sstevel@tonic-gate     crypto_mechanism_t *mac_mech, crypto_data_t *pt,
1750Sstevel@tonic-gate     crypto_key_t *encr_key, crypto_key_t *mac_key,
1760Sstevel@tonic-gate     crypto_ctx_template_t encr_tmpl, crypto_ctx_template_t mac_tmpl,
1770Sstevel@tonic-gate     crypto_dual_data_t *ct, crypto_data_t *mac, crypto_call_req_t *crq)
1780Sstevel@tonic-gate {
1790Sstevel@tonic-gate 	/*
1800Sstevel@tonic-gate 	 * First try to find a provider for the encryption mechanism, that
1810Sstevel@tonic-gate 	 * is also capable of the MAC mechanism.
1820Sstevel@tonic-gate 	 */
1830Sstevel@tonic-gate 	int error;
1840Sstevel@tonic-gate 	kcf_mech_entry_t *me;
1850Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
1860Sstevel@tonic-gate 	kcf_ctx_template_t *ctx_encr_tmpl, *ctx_mac_tmpl;
1870Sstevel@tonic-gate 	kcf_req_params_t params;
1880Sstevel@tonic-gate 	kcf_encrypt_mac_ops_params_t *cmops;
1890Sstevel@tonic-gate 	crypto_spi_ctx_template_t spi_encr_tmpl = NULL, spi_mac_tmpl = NULL;
1900Sstevel@tonic-gate 	crypto_mech_type_t prov_encr_mechid, prov_mac_mechid;
1910Sstevel@tonic-gate 	kcf_prov_tried_t *list = NULL;
1920Sstevel@tonic-gate 	boolean_t encr_tmpl_checked = B_FALSE;
1930Sstevel@tonic-gate 	boolean_t mac_tmpl_checked = B_FALSE;
1940Sstevel@tonic-gate 	kcf_dual_req_t *next_req = NULL;
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate retry:
1970Sstevel@tonic-gate 	/* pd is returned held on success */
198*10444SVladimir.Kotal@Sun.COM 	pd = kcf_get_dual_provider(encr_mech, encr_key, mac_mech, mac_key,
199*10444SVladimir.Kotal@Sun.COM 	    &me, &prov_encr_mechid,
2000Sstevel@tonic-gate 	    &prov_mac_mechid, &error, list,
2010Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC,
2020Sstevel@tonic-gate 	    CRYPTO_FG_MAC_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC,
2030Sstevel@tonic-gate 	    CHECK_RESTRICT(crq), ct->dd_len1);
2040Sstevel@tonic-gate 	if (pd == NULL) {
2050Sstevel@tonic-gate 		if (list != NULL)
2060Sstevel@tonic-gate 			kcf_free_triedlist(list);
2070Sstevel@tonic-gate 		if (next_req != NULL)
2080Sstevel@tonic-gate 			kmem_free(next_req, sizeof (kcf_dual_req_t));
2090Sstevel@tonic-gate 		return (error);
2100Sstevel@tonic-gate 	}
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	/*
2130Sstevel@tonic-gate 	 * For SW providers, check the validity of the context template
2140Sstevel@tonic-gate 	 * It is very rare that the generation number mis-matches, so
2150Sstevel@tonic-gate 	 * is acceptable to fail here, and let the consumer recover by
2160Sstevel@tonic-gate 	 * freeing this tmpl and create a new one for the key and new SW
2170Sstevel@tonic-gate 	 * provider
2180Sstevel@tonic-gate 	 * Warning! will need to change when multiple software providers
2190Sstevel@tonic-gate 	 * per mechanism are supported.
2200Sstevel@tonic-gate 	 */
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	if ((!encr_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
2230Sstevel@tonic-gate 		if (encr_tmpl != NULL) {
2240Sstevel@tonic-gate 			ctx_encr_tmpl = (kcf_ctx_template_t *)encr_tmpl;
2250Sstevel@tonic-gate 			if (ctx_encr_tmpl->ct_generation != me->me_gen_swprov) {
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 				if (next_req != NULL)
2280Sstevel@tonic-gate 					kmem_free(next_req,
2290Sstevel@tonic-gate 					    sizeof (kcf_dual_req_t));
2300Sstevel@tonic-gate 				if (list != NULL)
2310Sstevel@tonic-gate 					kcf_free_triedlist(list);
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
2340Sstevel@tonic-gate 				/* Which one is the the old one ? */
2350Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
2360Sstevel@tonic-gate 			}
2370Sstevel@tonic-gate 			spi_encr_tmpl = ctx_encr_tmpl->ct_prov_tmpl;
2380Sstevel@tonic-gate 		}
2390Sstevel@tonic-gate 		encr_tmpl_checked = B_TRUE;
2400Sstevel@tonic-gate 	}
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	if (prov_mac_mechid == CRYPTO_MECH_INVALID) {
2430Sstevel@tonic-gate 		crypto_call_req_t encr_req;
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 		/* Need to emulate with 2 internal calls */
2460Sstevel@tonic-gate 		/* Allocate and initialize the MAC req for the callback */
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 		if (crq != NULL) {
2490Sstevel@tonic-gate 			if (next_req == NULL) {
2500Sstevel@tonic-gate 				next_req = kcf_alloc_req(crq);
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 				if (next_req == NULL) {
2530Sstevel@tonic-gate 					KCF_PROV_REFRELE(pd);
2540Sstevel@tonic-gate 					if (list != NULL)
2550Sstevel@tonic-gate 						kcf_free_triedlist(list);
2560Sstevel@tonic-gate 					return (CRYPTO_HOST_MEMORY);
2570Sstevel@tonic-gate 				}
2580Sstevel@tonic-gate 				/*
2590Sstevel@tonic-gate 				 * Careful! we're wrapping-in mac_tmpl instead
2600Sstevel@tonic-gate 				 * of an spi_mac_tmpl. The callback routine will
2610Sstevel@tonic-gate 				 * have to validate mac_tmpl, and use the
2620Sstevel@tonic-gate 				 * mac_ctx_tmpl, once it picks a MAC provider.
2630Sstevel@tonic-gate 				 */
2640Sstevel@tonic-gate 				KCF_WRAP_MAC_OPS_PARAMS(&(next_req->kr_params),
2650Sstevel@tonic-gate 				    KCF_OP_ATOMIC, NULL, mac_mech, mac_key,
2660Sstevel@tonic-gate 				    (crypto_data_t *)ct, mac, mac_tmpl);
2670Sstevel@tonic-gate 			}
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 			encr_req.cr_flag = crq->cr_flag;
2700Sstevel@tonic-gate 			encr_req.cr_callback_func = kcf_next_req;
2710Sstevel@tonic-gate 			encr_req.cr_callback_arg = next_req;
2720Sstevel@tonic-gate 		}
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 		if (pt == NULL) {
2750Sstevel@tonic-gate 			KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_ATOMIC,
2760Sstevel@tonic-gate 			    pd->pd_sid, encr_mech, encr_key,
2770Sstevel@tonic-gate 			    (crypto_data_t *)ct, NULL, spi_encr_tmpl);
2780Sstevel@tonic-gate 		} else {
2790Sstevel@tonic-gate 			KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_ATOMIC,
2800Sstevel@tonic-gate 			    pd->pd_sid, encr_mech, encr_key, pt,
2810Sstevel@tonic-gate 			    (crypto_data_t *)ct, spi_encr_tmpl);
2820Sstevel@tonic-gate 		}
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 		error = kcf_submit_request(pd, NULL, (crq == NULL) ? NULL :
2850Sstevel@tonic-gate 		    &encr_req, &params, B_TRUE);
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 		switch (error) {
2880Sstevel@tonic-gate 		case CRYPTO_SUCCESS: {
2890Sstevel@tonic-gate 			off_t saveoffset;
2900Sstevel@tonic-gate 			size_t savelen;
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 			/*
2930Sstevel@tonic-gate 			 * The encryption step is done. Reuse the encr_req
2940Sstevel@tonic-gate 			 * for submitting the MAC step.
2950Sstevel@tonic-gate 			 */
2960Sstevel@tonic-gate 			if (next_req == NULL) {
2970Sstevel@tonic-gate 				saveoffset = ct->dd_offset1;
2980Sstevel@tonic-gate 				savelen = ct->dd_len1;
2990Sstevel@tonic-gate 			} else {
3000Sstevel@tonic-gate 				saveoffset = next_req->kr_saveoffset =
3010Sstevel@tonic-gate 				    ct->dd_offset1;
3020Sstevel@tonic-gate 				savelen = next_req->kr_savelen = ct->dd_len1;
3030Sstevel@tonic-gate 				encr_req.cr_callback_func = kcf_last_req;
3040Sstevel@tonic-gate 			}
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 			ct->dd_offset1 = ct->dd_offset2;
3070Sstevel@tonic-gate 			ct->dd_len1 = ct->dd_len2;
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 			error = crypto_mac(mac_mech, (crypto_data_t *)ct,
3100Sstevel@tonic-gate 			    mac_key, mac_tmpl, mac, (crq == NULL) ? NULL :
3110Sstevel@tonic-gate 			    &encr_req);
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 			if (error != CRYPTO_QUEUED) {
3140Sstevel@tonic-gate 				ct->dd_offset1 = saveoffset;
3150Sstevel@tonic-gate 				ct->dd_len1 = savelen;
3160Sstevel@tonic-gate 			}
3170Sstevel@tonic-gate 			break;
3180Sstevel@tonic-gate 		}
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 		case CRYPTO_QUEUED:
3210Sstevel@tonic-gate 			if ((crq != NULL) &&
3220Sstevel@tonic-gate 			    !(crq->cr_flag & CRYPTO_SKIP_REQID))
3230Sstevel@tonic-gate 				crq->cr_reqid = encr_req.cr_reqid;
3240Sstevel@tonic-gate 			break;
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 		default:
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 			/* Add pd to the linked list of providers tried. */
3290Sstevel@tonic-gate 			if (IS_RECOVERABLE(error)) {
3300Sstevel@tonic-gate 				if (kcf_insert_triedlist(&list, pd,
3310Sstevel@tonic-gate 				    KCF_KMFLAG(crq)) != NULL)
3320Sstevel@tonic-gate 					goto retry;
3330Sstevel@tonic-gate 			}
3340Sstevel@tonic-gate 		}
3350Sstevel@tonic-gate 		if (error != CRYPTO_QUEUED && next_req != NULL)
3360Sstevel@tonic-gate 			kmem_free(next_req, sizeof (kcf_dual_req_t));
3370Sstevel@tonic-gate 		if (list != NULL)
3380Sstevel@tonic-gate 			kcf_free_triedlist(list);
3390Sstevel@tonic-gate 		KCF_PROV_REFRELE(pd);
3400Sstevel@tonic-gate 		return (error);
3410Sstevel@tonic-gate 	}
3420Sstevel@tonic-gate 	if ((!mac_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
3430Sstevel@tonic-gate 		if ((mac_tmpl != NULL) &&
3440Sstevel@tonic-gate 		    (prov_mac_mechid != CRYPTO_MECH_INVALID)) {
3450Sstevel@tonic-gate 			ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
3460Sstevel@tonic-gate 			if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 				if (next_req != NULL)
3490Sstevel@tonic-gate 					kmem_free(next_req,
3500Sstevel@tonic-gate 					    sizeof (kcf_dual_req_t));
3510Sstevel@tonic-gate 				if (list != NULL)
3520Sstevel@tonic-gate 					kcf_free_triedlist(list);
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
3550Sstevel@tonic-gate 				/* Which one is the the old one ? */
3560Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
3570Sstevel@tonic-gate 			}
3580Sstevel@tonic-gate 			spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
3590Sstevel@tonic-gate 		}
3600Sstevel@tonic-gate 		mac_tmpl_checked = B_TRUE;
3610Sstevel@tonic-gate 	}
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 	/* The fast path for SW providers. */
3640Sstevel@tonic-gate 	if (CHECK_FASTPATH(crq, pd)) {
3650Sstevel@tonic-gate 		crypto_mechanism_t lencr_mech;
3660Sstevel@tonic-gate 		crypto_mechanism_t lmac_mech;
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 		/* careful! structs assignments */
3690Sstevel@tonic-gate 		lencr_mech = *encr_mech;
3700Sstevel@tonic-gate 		lencr_mech.cm_type = prov_encr_mechid;
3710Sstevel@tonic-gate 		lmac_mech = *mac_mech;
3720Sstevel@tonic-gate 		lmac_mech.cm_type = prov_mac_mechid;
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 		error = KCF_PROV_ENCRYPT_MAC_ATOMIC(pd, pd->pd_sid,
3750Sstevel@tonic-gate 		    &lencr_mech, encr_key, &lmac_mech, mac_key, pt, ct,
3760Sstevel@tonic-gate 		    mac, spi_encr_tmpl, spi_mac_tmpl, KCF_SWFP_RHNDL(crq));
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
3790Sstevel@tonic-gate 	} else {
3800Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_ATOMIC,
3810Sstevel@tonic-gate 		    pd->pd_sid, encr_key, mac_key, pt, ct, mac, spi_encr_tmpl,
3820Sstevel@tonic-gate 		    spi_mac_tmpl);
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 		cmops = &(params.rp_u.encrypt_mac_params);
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 		/* careful! structs assignments */
3870Sstevel@tonic-gate 		cmops->em_encr_mech = *encr_mech;
3880Sstevel@tonic-gate 		cmops->em_encr_mech.cm_type = prov_encr_mechid;
3890Sstevel@tonic-gate 		cmops->em_framework_encr_mechtype = encr_mech->cm_type;
3900Sstevel@tonic-gate 		cmops->em_mac_mech = *mac_mech;
3910Sstevel@tonic-gate 		cmops->em_mac_mech.cm_type = prov_mac_mechid;
3920Sstevel@tonic-gate 		cmops->em_framework_mac_mechtype = mac_mech->cm_type;
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 		error = kcf_submit_request(pd, NULL, crq, &params, B_FALSE);
3950Sstevel@tonic-gate 	}
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED &&
3980Sstevel@tonic-gate 	    IS_RECOVERABLE(error)) {
3990Sstevel@tonic-gate 		/* Add pd to the linked list of providers tried. */
4000Sstevel@tonic-gate 		if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL)
4010Sstevel@tonic-gate 			goto retry;
4020Sstevel@tonic-gate 	}
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	if (next_req != NULL)
4050Sstevel@tonic-gate 		kmem_free(next_req, sizeof (kcf_dual_req_t));
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 	if (list != NULL)
4080Sstevel@tonic-gate 		kcf_free_triedlist(list);
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	KCF_PROV_REFRELE(pd);
4110Sstevel@tonic-gate 	return (error);
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate 
414904Smcpowers int
415904Smcpowers crypto_encrypt_mac_init_prov(crypto_provider_t provider,
416904Smcpowers     crypto_session_id_t sid, crypto_mechanism_t *encr_mech,
417904Smcpowers     crypto_mechanism_t *mac_mech, crypto_key_t *encr_key,
418904Smcpowers     crypto_key_t *mac_key, crypto_ctx_template_t encr_tmpl,
419904Smcpowers     crypto_ctx_template_t mac_tmpl, crypto_context_t *ctxp,
420904Smcpowers     crypto_call_req_t *cr)
421904Smcpowers {
422904Smcpowers 	/*
423904Smcpowers 	 * First try to find a provider for the encryption mechanism, that
424904Smcpowers 	 * is also capable of the MAC mechanism.
425904Smcpowers 	 */
426904Smcpowers 	int rv;
427904Smcpowers 	kcf_mech_entry_t *me;
428904Smcpowers 	kcf_provider_desc_t *pd = provider;
429904Smcpowers 	kcf_provider_desc_t *real_provider = pd;
430904Smcpowers 	kcf_ctx_template_t *ctx_encr_tmpl, *ctx_mac_tmpl;
431904Smcpowers 	kcf_req_params_t params;
432904Smcpowers 	kcf_encrypt_mac_ops_params_t *cmops;
433904Smcpowers 	crypto_spi_ctx_template_t spi_encr_tmpl = NULL, spi_mac_tmpl = NULL;
434904Smcpowers 	crypto_ctx_t *ctx;
435904Smcpowers 	kcf_context_t *encr_kcf_context = NULL;
436904Smcpowers 
437904Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
438904Smcpowers 
439904Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
440*10444SVladimir.Kotal@Sun.COM 		rv = kcf_get_hardware_provider(encr_mech->cm_type, encr_key,
441*10444SVladimir.Kotal@Sun.COM 		    mac_mech->cm_type, mac_key, CHECK_RESTRICT(cr), pd,
442*10444SVladimir.Kotal@Sun.COM 		    &real_provider, CRYPTO_FG_ENCRYPT_MAC);
443904Smcpowers 
444904Smcpowers 		if (rv != CRYPTO_SUCCESS)
445904Smcpowers 			return (rv);
446904Smcpowers 	}
447904Smcpowers 
448904Smcpowers 	/*
449904Smcpowers 	 * For SW providers, check the validity of the context template
450904Smcpowers 	 * It is very rare that the generation number mis-matches, so
451904Smcpowers 	 * is acceptable to fail here, and let the consumer recover by
452904Smcpowers 	 * freeing this tmpl and create a new one for the key and new SW
453904Smcpowers 	 * provider
454904Smcpowers 	 * Warning! will need to change when multiple software providers
455904Smcpowers 	 * per mechanism are supported.
456904Smcpowers 	 */
457904Smcpowers 
458904Smcpowers 	if (real_provider->pd_prov_type == CRYPTO_SW_PROVIDER) {
459904Smcpowers 		if (encr_tmpl != NULL) {
460904Smcpowers 			if (kcf_get_mech_entry(encr_mech->cm_type, &me) !=
461904Smcpowers 			    KCF_SUCCESS) {
462904Smcpowers 				rv = CRYPTO_MECHANISM_INVALID;
463904Smcpowers 				goto out;
464904Smcpowers 			}
465904Smcpowers 			ctx_encr_tmpl = (kcf_ctx_template_t *)encr_tmpl;
466904Smcpowers 			if (ctx_encr_tmpl->ct_generation != me->me_gen_swprov) {
467904Smcpowers 				rv = CRYPTO_OLD_CTX_TEMPLATE;
468904Smcpowers 				goto out;
469904Smcpowers 			}
470904Smcpowers 			spi_encr_tmpl = ctx_encr_tmpl->ct_prov_tmpl;
471904Smcpowers 		}
472904Smcpowers 
473904Smcpowers 		if (mac_tmpl != NULL) {
474904Smcpowers 			if (kcf_get_mech_entry(mac_mech->cm_type, &me) !=
475904Smcpowers 			    KCF_SUCCESS) {
476904Smcpowers 				rv = CRYPTO_MECHANISM_INVALID;
477904Smcpowers 				goto out;
478904Smcpowers 			}
479904Smcpowers 			ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
480904Smcpowers 			if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
481904Smcpowers 				rv = CRYPTO_OLD_CTX_TEMPLATE;
482904Smcpowers 				goto out;
483904Smcpowers 			}
484904Smcpowers 			spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
485904Smcpowers 		}
486904Smcpowers 	}
487904Smcpowers 
488904Smcpowers 	ctx = kcf_new_ctx(cr, real_provider, sid);
489904Smcpowers 	if (ctx == NULL) {
490904Smcpowers 		rv = CRYPTO_HOST_MEMORY;
491904Smcpowers 		goto out;
492904Smcpowers 	}
493904Smcpowers 	encr_kcf_context = (kcf_context_t *)ctx->cc_framework_private;
494904Smcpowers 
495904Smcpowers 	/* The fast path for SW providers. */
496904Smcpowers 	if (CHECK_FASTPATH(cr, real_provider)) {
497904Smcpowers 		crypto_mechanism_t lencr_mech;
498904Smcpowers 		crypto_mechanism_t lmac_mech;
499904Smcpowers 
500904Smcpowers 		/* careful! structs assignments */
501904Smcpowers 		lencr_mech = *encr_mech;
502904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(encr_mech->cm_type, real_provider,
503904Smcpowers 		    &lencr_mech);
504904Smcpowers 
505904Smcpowers 		lmac_mech = *mac_mech;
506904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
507904Smcpowers 		    &lmac_mech);
508904Smcpowers 
509904Smcpowers 		rv = KCF_PROV_ENCRYPT_MAC_INIT(real_provider, ctx, &lencr_mech,
510904Smcpowers 		    encr_key, &lmac_mech, mac_key, spi_encr_tmpl, spi_mac_tmpl,
511904Smcpowers 		    KCF_SWFP_RHNDL(cr));
512904Smcpowers 
513904Smcpowers 		KCF_PROV_INCRSTATS(pd, rv);
514904Smcpowers 	} else {
515904Smcpowers 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_INIT,
516904Smcpowers 		    sid, encr_key, mac_key, NULL, NULL, NULL,
517904Smcpowers 		    spi_encr_tmpl, spi_mac_tmpl);
518904Smcpowers 
519904Smcpowers 		cmops = &(params.rp_u.encrypt_mac_params);
520904Smcpowers 
521904Smcpowers 		/* careful! structs assignments */
522904Smcpowers 		cmops->em_encr_mech = *encr_mech;
523904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(encr_mech->cm_type, real_provider,
524904Smcpowers 		    &cmops->em_encr_mech);
525904Smcpowers 		cmops->em_framework_encr_mechtype = encr_mech->cm_type;
526904Smcpowers 
527904Smcpowers 		cmops->em_mac_mech = *mac_mech;
528904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
529904Smcpowers 		    &cmops->em_mac_mech);
530904Smcpowers 		cmops->em_framework_mac_mechtype = mac_mech->cm_type;
531904Smcpowers 
532904Smcpowers 		rv = kcf_submit_request(real_provider, ctx, cr, &params,
533904Smcpowers 		    B_FALSE);
534904Smcpowers 	}
535904Smcpowers 
536904Smcpowers 	if (rv != CRYPTO_SUCCESS && rv != CRYPTO_QUEUED) {
537904Smcpowers 		KCF_CONTEXT_REFRELE(encr_kcf_context);
538904Smcpowers 	} else
539904Smcpowers 		*ctxp = (crypto_context_t)ctx;
540904Smcpowers 
541904Smcpowers out:
542904Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
543904Smcpowers 		KCF_PROV_REFRELE(real_provider);
544904Smcpowers 	return (rv);
545904Smcpowers }
546904Smcpowers 
5470Sstevel@tonic-gate /*
5480Sstevel@tonic-gate  * Starts a multi-part dual encrypt/mac operation. The provider and session
5490Sstevel@tonic-gate  * to use are determined by the KCF dispatcher.
5500Sstevel@tonic-gate  */
5510Sstevel@tonic-gate /* ARGSUSED */
5520Sstevel@tonic-gate int
5530Sstevel@tonic-gate crypto_encrypt_mac_init(crypto_mechanism_t *encr_mech,
5540Sstevel@tonic-gate     crypto_mechanism_t *mac_mech, crypto_key_t *encr_key,
5550Sstevel@tonic-gate     crypto_key_t *mac_key, crypto_ctx_template_t encr_tmpl,
5560Sstevel@tonic-gate     crypto_ctx_template_t mac_tmpl, crypto_context_t *ctxp,
5570Sstevel@tonic-gate     crypto_call_req_t *cr)
5580Sstevel@tonic-gate {
5590Sstevel@tonic-gate 	/*
5600Sstevel@tonic-gate 	 * First try to find a provider for the encryption mechanism, that
5610Sstevel@tonic-gate 	 * is also capable of the MAC mechanism.
5620Sstevel@tonic-gate 	 */
5630Sstevel@tonic-gate 	int error;
5640Sstevel@tonic-gate 	kcf_mech_entry_t *me;
5650Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
5660Sstevel@tonic-gate 	kcf_ctx_template_t *ctx_encr_tmpl, *ctx_mac_tmpl;
5670Sstevel@tonic-gate 	kcf_req_params_t params;
5680Sstevel@tonic-gate 	kcf_encrypt_mac_ops_params_t *cmops;
5690Sstevel@tonic-gate 	crypto_spi_ctx_template_t spi_encr_tmpl = NULL, spi_mac_tmpl = NULL;
5700Sstevel@tonic-gate 	crypto_mech_type_t prov_encr_mechid, prov_mac_mechid;
5710Sstevel@tonic-gate 	kcf_prov_tried_t *list = NULL;
5720Sstevel@tonic-gate 	boolean_t encr_tmpl_checked = B_FALSE;
5730Sstevel@tonic-gate 	boolean_t mac_tmpl_checked = B_FALSE;
5740Sstevel@tonic-gate 	crypto_ctx_t *ctx = NULL;
5750Sstevel@tonic-gate 	kcf_context_t *encr_kcf_context = NULL, *mac_kcf_context;
5760Sstevel@tonic-gate 	crypto_call_flag_t save_flag;
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate retry:
5790Sstevel@tonic-gate 	/* pd is returned held on success */
580*10444SVladimir.Kotal@Sun.COM 	pd = kcf_get_dual_provider(encr_mech, encr_key, mac_mech, mac_key,
581*10444SVladimir.Kotal@Sun.COM 	    &me, &prov_encr_mechid,
5820Sstevel@tonic-gate 	    &prov_mac_mechid, &error, list,
5830Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_MAC, CRYPTO_FG_MAC,
5840Sstevel@tonic-gate 	    CHECK_RESTRICT(cr), 0);
5850Sstevel@tonic-gate 	if (pd == NULL) {
5860Sstevel@tonic-gate 		if (list != NULL)
5870Sstevel@tonic-gate 			kcf_free_triedlist(list);
5880Sstevel@tonic-gate 		return (error);
5890Sstevel@tonic-gate 	}
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	/*
5920Sstevel@tonic-gate 	 * For SW providers, check the validity of the context template
5930Sstevel@tonic-gate 	 * It is very rare that the generation number mis-matches, so
5940Sstevel@tonic-gate 	 * is acceptable to fail here, and let the consumer recover by
5950Sstevel@tonic-gate 	 * freeing this tmpl and create a new one for the key and new SW
5960Sstevel@tonic-gate 	 * provider
5970Sstevel@tonic-gate 	 * Warning! will need to change when multiple software providers
5980Sstevel@tonic-gate 	 * per mechanism are supported.
5990Sstevel@tonic-gate 	 */
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 	if ((!encr_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
6020Sstevel@tonic-gate 		if (encr_tmpl != NULL) {
6030Sstevel@tonic-gate 			ctx_encr_tmpl = (kcf_ctx_template_t *)encr_tmpl;
6040Sstevel@tonic-gate 			if (ctx_encr_tmpl->ct_generation != me->me_gen_swprov) {
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate 				if (list != NULL)
6070Sstevel@tonic-gate 					kcf_free_triedlist(list);
6080Sstevel@tonic-gate 				if (encr_kcf_context != NULL)
6090Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(encr_kcf_context);
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
6120Sstevel@tonic-gate 				/* Which one is the the old one ? */
6130Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
6140Sstevel@tonic-gate 			}
6150Sstevel@tonic-gate 			spi_encr_tmpl = ctx_encr_tmpl->ct_prov_tmpl;
6160Sstevel@tonic-gate 		}
6170Sstevel@tonic-gate 		encr_tmpl_checked = B_TRUE;
6180Sstevel@tonic-gate 	}
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 	if (prov_mac_mechid == CRYPTO_MECH_INVALID) {
6210Sstevel@tonic-gate 		/* Need to emulate with 2 internal calls */
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 		/*
6240Sstevel@tonic-gate 		 * We avoid code complexity by limiting the pure async.
6250Sstevel@tonic-gate 		 * case to be done using only a SW provider.
6260Sstevel@tonic-gate 		 * XXX - Redo the emulation code below so that we can
6270Sstevel@tonic-gate 		 * remove this limitation.
6280Sstevel@tonic-gate 		 */
6290Sstevel@tonic-gate 		if (cr != NULL && pd->pd_prov_type == CRYPTO_HW_PROVIDER) {
6300Sstevel@tonic-gate 			if ((kcf_insert_triedlist(&list, pd, KCF_KMFLAG(cr))
6310Sstevel@tonic-gate 			    != NULL))
6320Sstevel@tonic-gate 				goto retry;
6330Sstevel@tonic-gate 			if (list != NULL)
6340Sstevel@tonic-gate 				kcf_free_triedlist(list);
6350Sstevel@tonic-gate 			if (encr_kcf_context != NULL)
6360Sstevel@tonic-gate 				KCF_CONTEXT_REFRELE(encr_kcf_context);
6370Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
6380Sstevel@tonic-gate 			return (CRYPTO_HOST_MEMORY);
6390Sstevel@tonic-gate 		}
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 		if (ctx == NULL && pd->pd_prov_type == CRYPTO_SW_PROVIDER) {
6420Sstevel@tonic-gate 			ctx = kcf_new_ctx(cr, pd, pd->pd_sid);
6430Sstevel@tonic-gate 			if (ctx == NULL) {
6440Sstevel@tonic-gate 				if (list != NULL)
6450Sstevel@tonic-gate 					kcf_free_triedlist(list);
6460Sstevel@tonic-gate 				if (encr_kcf_context != NULL)
6470Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(encr_kcf_context);
6480Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
6490Sstevel@tonic-gate 				return (CRYPTO_HOST_MEMORY);
6500Sstevel@tonic-gate 			}
6510Sstevel@tonic-gate 			encr_kcf_context = (kcf_context_t *)
6520Sstevel@tonic-gate 			    ctx->cc_framework_private;
6530Sstevel@tonic-gate 		}
6540Sstevel@tonic-gate 		/*
6550Sstevel@tonic-gate 		 * Trade-off speed vs avoidance of code complexity and
6560Sstevel@tonic-gate 		 * duplication:
6570Sstevel@tonic-gate 		 * Could do all the combinations of fastpath / synch / asynch
6580Sstevel@tonic-gate 		 * for the encryption and the mac steps. Early attempts
6590Sstevel@tonic-gate 		 * showed the code grew wild and bug-prone, for little gain.
6600Sstevel@tonic-gate 		 * Therefore, the adaptative asynch case is not implemented.
6610Sstevel@tonic-gate 		 * It's either pure synchronous, or pure asynchronous.
6620Sstevel@tonic-gate 		 * We still preserve a fastpath for the pure synchronous
6630Sstevel@tonic-gate 		 * requests to SW providers.
6640Sstevel@tonic-gate 		 */
6650Sstevel@tonic-gate 		if (cr == NULL) {
6660Sstevel@tonic-gate 			crypto_context_t mac_context;
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 			if (pd->pd_prov_type == CRYPTO_SW_PROVIDER) {
6690Sstevel@tonic-gate 				crypto_mechanism_t lmech = *encr_mech;
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate 				lmech.cm_type = prov_encr_mechid;
6720Sstevel@tonic-gate 
6730Sstevel@tonic-gate 				error = KCF_PROV_ENCRYPT_INIT(pd, ctx, &lmech,
6740Sstevel@tonic-gate 				    encr_key, spi_encr_tmpl,
6750Sstevel@tonic-gate 				    KCF_RHNDL(KM_SLEEP));
6760Sstevel@tonic-gate 			} else {
6770Sstevel@tonic-gate 				/*
6780Sstevel@tonic-gate 				 * If we did the 'goto retry' then ctx may not
6790Sstevel@tonic-gate 				 * be NULL.  In general, we can't reuse another
6800Sstevel@tonic-gate 				 * provider's context, so we free it now so
6810Sstevel@tonic-gate 				 * we don't leak it.
6820Sstevel@tonic-gate 				 */
6830Sstevel@tonic-gate 				if (ctx != NULL) {
6840Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE((kcf_context_t *)
6850Sstevel@tonic-gate 					    ctx->cc_framework_private);
6860Sstevel@tonic-gate 					encr_kcf_context = NULL;
6870Sstevel@tonic-gate 				}
6880Sstevel@tonic-gate 				error = crypto_encrypt_init_prov(pd, pd->pd_sid,
6890Sstevel@tonic-gate 				    encr_mech, encr_key, &encr_tmpl,
6900Sstevel@tonic-gate 				    (crypto_context_t *)&ctx, NULL);
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate 				if (error == CRYPTO_SUCCESS) {
6930Sstevel@tonic-gate 					encr_kcf_context = (kcf_context_t *)
6940Sstevel@tonic-gate 					    ctx->cc_framework_private;
6950Sstevel@tonic-gate 				}
6960Sstevel@tonic-gate 			}
6970Sstevel@tonic-gate 			KCF_PROV_INCRSTATS(pd, error);
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS) {
7020Sstevel@tonic-gate 				/* Can't be CRYPTO_QUEUED. return the failure */
7030Sstevel@tonic-gate 				if (list != NULL)
7040Sstevel@tonic-gate 					kcf_free_triedlist(list);
7050Sstevel@tonic-gate 				if (encr_kcf_context != NULL)
7060Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(encr_kcf_context);
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 				return (error);
7090Sstevel@tonic-gate 			}
7100Sstevel@tonic-gate 			error = crypto_mac_init(mac_mech, mac_key, mac_tmpl,
7110Sstevel@tonic-gate 			    &mac_context, NULL);
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate 			if (list != NULL)
7140Sstevel@tonic-gate 				kcf_free_triedlist(list);
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS) {
7170Sstevel@tonic-gate 				/* Should this be an ASSERT() ? */
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate 				KCF_CONTEXT_REFRELE(encr_kcf_context);
7200Sstevel@tonic-gate 			} else {
7210Sstevel@tonic-gate 				encr_kcf_context = (kcf_context_t *)
7220Sstevel@tonic-gate 				    ctx->cc_framework_private;
7230Sstevel@tonic-gate 				mac_kcf_context = (kcf_context_t *)
7240Sstevel@tonic-gate 				    ((crypto_ctx_t *)mac_context)->
7250Sstevel@tonic-gate 				    cc_framework_private;
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 				encr_kcf_context->kc_secondctx =
7280Sstevel@tonic-gate 				    mac_kcf_context;
7290Sstevel@tonic-gate 				KCF_CONTEXT_REFHOLD(mac_kcf_context);
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate 				*ctxp = (crypto_context_t)ctx;
7320Sstevel@tonic-gate 			}
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 			return (error);
7350Sstevel@tonic-gate 		}
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate 		/* submit a pure asynchronous request. */
7380Sstevel@tonic-gate 		save_flag = cr->cr_flag;
7390Sstevel@tonic-gate 		cr->cr_flag |= CRYPTO_ALWAYS_QUEUE;
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_INIT,
7420Sstevel@tonic-gate 		    pd->pd_sid, encr_key, mac_key, NULL, NULL, NULL,
7430Sstevel@tonic-gate 		    spi_encr_tmpl, spi_mac_tmpl);
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 		cmops = &(params.rp_u.encrypt_mac_params);
7460Sstevel@tonic-gate 
7470Sstevel@tonic-gate 		/* careful! structs assignments */
7480Sstevel@tonic-gate 		cmops->em_encr_mech = *encr_mech;
7490Sstevel@tonic-gate 		/*
7500Sstevel@tonic-gate 		 * cmops->em_encr_mech.cm_type will be set when we get to
7510Sstevel@tonic-gate 		 * kcf_emulate_dual() routine.
7520Sstevel@tonic-gate 		 */
7530Sstevel@tonic-gate 		cmops->em_framework_encr_mechtype = encr_mech->cm_type;
7540Sstevel@tonic-gate 		cmops->em_mac_mech = *mac_mech;
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 		/*
7570Sstevel@tonic-gate 		 * cmops->em_mac_mech.cm_type will be set when we know the
7580Sstevel@tonic-gate 		 * MAC provider.
7590Sstevel@tonic-gate 		 */
7600Sstevel@tonic-gate 		cmops->em_framework_mac_mechtype = mac_mech->cm_type;
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate 		/*
7630Sstevel@tonic-gate 		 * non-NULL ctx->kc_secondctx tells common_submit_request
7640Sstevel@tonic-gate 		 * that this request uses separate cipher and MAC contexts.
7650Sstevel@tonic-gate 		 * That function will set ctx->kc_secondctx to the new
7660Sstevel@tonic-gate 		 * MAC context, once it gets one.
7670Sstevel@tonic-gate 		 */
7680Sstevel@tonic-gate 		encr_kcf_context->kc_secondctx = encr_kcf_context;
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 		cr->cr_flag = save_flag;
7730Sstevel@tonic-gate 
7740Sstevel@tonic-gate 		if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED) {
7750Sstevel@tonic-gate 			KCF_CONTEXT_REFRELE(encr_kcf_context);
7760Sstevel@tonic-gate 		}
7770Sstevel@tonic-gate 		if (list != NULL)
7780Sstevel@tonic-gate 			kcf_free_triedlist(list);
7790Sstevel@tonic-gate 		*ctxp = (crypto_context_t)ctx;
7800Sstevel@tonic-gate 		KCF_PROV_REFRELE(pd);
7810Sstevel@tonic-gate 		return (error);
7820Sstevel@tonic-gate 	}
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 	if ((!mac_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
7850Sstevel@tonic-gate 		if ((mac_tmpl != NULL) &&
7860Sstevel@tonic-gate 		    (prov_mac_mechid != CRYPTO_MECH_INVALID)) {
7870Sstevel@tonic-gate 			ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
7880Sstevel@tonic-gate 			if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 				if (list != NULL)
7910Sstevel@tonic-gate 					kcf_free_triedlist(list);
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
7940Sstevel@tonic-gate 				/* Which one is the the old one ? */
7950Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
7960Sstevel@tonic-gate 			}
7970Sstevel@tonic-gate 			spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
7980Sstevel@tonic-gate 		}
7990Sstevel@tonic-gate 		mac_tmpl_checked = B_TRUE;
8000Sstevel@tonic-gate 	}
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 	if (ctx == NULL) {
8030Sstevel@tonic-gate 		ctx = kcf_new_ctx(cr, pd, pd->pd_sid);
8040Sstevel@tonic-gate 		if (ctx == NULL) {
8050Sstevel@tonic-gate 			if (list != NULL)
8060Sstevel@tonic-gate 				kcf_free_triedlist(list);
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
8090Sstevel@tonic-gate 			return (CRYPTO_HOST_MEMORY);
8100Sstevel@tonic-gate 		}
8110Sstevel@tonic-gate 		encr_kcf_context = (kcf_context_t *)ctx->cc_framework_private;
8120Sstevel@tonic-gate 	}
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate 	/* The fast path for SW providers. */
8150Sstevel@tonic-gate 	if (CHECK_FASTPATH(cr, pd)) {
8160Sstevel@tonic-gate 		crypto_mechanism_t lencr_mech;
8170Sstevel@tonic-gate 		crypto_mechanism_t lmac_mech;
8180Sstevel@tonic-gate 
8190Sstevel@tonic-gate 		/* careful! structs assignments */
8200Sstevel@tonic-gate 		lencr_mech = *encr_mech;
8210Sstevel@tonic-gate 		lencr_mech.cm_type = prov_encr_mechid;
8220Sstevel@tonic-gate 		lmac_mech = *mac_mech;
8230Sstevel@tonic-gate 		lmac_mech.cm_type = prov_mac_mechid;
8240Sstevel@tonic-gate 
8250Sstevel@tonic-gate 		error = KCF_PROV_ENCRYPT_MAC_INIT(pd, ctx, &lencr_mech,
8260Sstevel@tonic-gate 		    encr_key, &lmac_mech, mac_key, spi_encr_tmpl, spi_mac_tmpl,
8270Sstevel@tonic-gate 		    KCF_SWFP_RHNDL(cr));
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
8300Sstevel@tonic-gate 	} else {
8310Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_INIT,
8320Sstevel@tonic-gate 		    pd->pd_sid, encr_key, mac_key, NULL, NULL, NULL,
8330Sstevel@tonic-gate 		    spi_encr_tmpl, spi_mac_tmpl);
8340Sstevel@tonic-gate 
8350Sstevel@tonic-gate 		cmops = &(params.rp_u.encrypt_mac_params);
8360Sstevel@tonic-gate 
8370Sstevel@tonic-gate 		/* careful! structs assignments */
8380Sstevel@tonic-gate 		cmops->em_encr_mech = *encr_mech;
8390Sstevel@tonic-gate 		cmops->em_encr_mech.cm_type = prov_encr_mechid;
8400Sstevel@tonic-gate 		cmops->em_framework_encr_mechtype = encr_mech->cm_type;
8410Sstevel@tonic-gate 		cmops->em_mac_mech = *mac_mech;
8420Sstevel@tonic-gate 		cmops->em_mac_mech.cm_type = prov_mac_mechid;
8430Sstevel@tonic-gate 		cmops->em_framework_mac_mechtype = mac_mech->cm_type;
8440Sstevel@tonic-gate 
8450Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
8460Sstevel@tonic-gate 	}
8470Sstevel@tonic-gate 
8480Sstevel@tonic-gate 	if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED) {
8490Sstevel@tonic-gate 		if ((IS_RECOVERABLE(error)) &&
8500Sstevel@tonic-gate 		    (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(cr)) != NULL))
8510Sstevel@tonic-gate 			goto retry;
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 		KCF_CONTEXT_REFRELE(encr_kcf_context);
8540Sstevel@tonic-gate 	} else
8550Sstevel@tonic-gate 		*ctxp = (crypto_context_t)ctx;
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate 	if (list != NULL)
8580Sstevel@tonic-gate 		kcf_free_triedlist(list);
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	KCF_PROV_REFRELE(pd);
8610Sstevel@tonic-gate 	return (error);
8620Sstevel@tonic-gate }
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate /*
8650Sstevel@tonic-gate  * Continues a multi-part dual encrypt/mac operation.
8660Sstevel@tonic-gate  */
8670Sstevel@tonic-gate /* ARGSUSED */
8680Sstevel@tonic-gate int
8690Sstevel@tonic-gate crypto_encrypt_mac_update(crypto_context_t context,
8700Sstevel@tonic-gate     crypto_data_t *pt, crypto_dual_data_t *ct, crypto_call_req_t *cr)
8710Sstevel@tonic-gate {
8720Sstevel@tonic-gate 	crypto_ctx_t *ctx = (crypto_ctx_t *)context, *mac_ctx;
8730Sstevel@tonic-gate 	kcf_context_t *kcf_ctx, *kcf_mac_ctx;
8740Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
8750Sstevel@tonic-gate 	int error;
8760Sstevel@tonic-gate 	kcf_req_params_t params;
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 	if ((ctx == NULL) ||
8790Sstevel@tonic-gate 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
8800Sstevel@tonic-gate 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
8810Sstevel@tonic-gate 		return (CRYPTO_INVALID_CONTEXT);
8820Sstevel@tonic-gate 	}
8830Sstevel@tonic-gate 
884904Smcpowers 	ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate 	if ((kcf_mac_ctx = kcf_ctx->kc_secondctx) != NULL) {
8870Sstevel@tonic-gate 		off_t save_offset;
8880Sstevel@tonic-gate 		size_t save_len;
8890Sstevel@tonic-gate 		crypto_call_flag_t save_flag;
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 		if (kcf_mac_ctx->kc_prov_desc == NULL) {
8920Sstevel@tonic-gate 			error = CRYPTO_INVALID_CONTEXT;
8930Sstevel@tonic-gate 			goto out;
8940Sstevel@tonic-gate 		}
8950Sstevel@tonic-gate 		mac_ctx = &kcf_mac_ctx->kc_glbl_ctx;
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 		/* First we submit the encryption request */
8980Sstevel@tonic-gate 		if (cr == NULL) {
8990Sstevel@tonic-gate 			/*
9000Sstevel@tonic-gate 			 * 'ct' is always not NULL.
9010Sstevel@tonic-gate 			 * A NULL 'pt' means in-place.
9020Sstevel@tonic-gate 			 */
9030Sstevel@tonic-gate 			if (pt == NULL)
9040Sstevel@tonic-gate 				error = crypto_encrypt_update(context,
9050Sstevel@tonic-gate 				    (crypto_data_t *)ct, NULL, NULL);
9060Sstevel@tonic-gate 			else
9070Sstevel@tonic-gate 				error = crypto_encrypt_update(context, pt,
9080Sstevel@tonic-gate 				    (crypto_data_t *)ct, NULL);
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS)
9110Sstevel@tonic-gate 				goto out;
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 			/*
9140Sstevel@tonic-gate 			 * call  mac_update when there is data to throw in
9150Sstevel@tonic-gate 			 * the mix. Either an explicitly non-zero ct->dd_len2,
9160Sstevel@tonic-gate 			 * or the last ciphertext portion.
9170Sstevel@tonic-gate 			 */
9180Sstevel@tonic-gate 			save_offset = ct->dd_offset1;
9190Sstevel@tonic-gate 			save_len = ct->dd_len1;
9200Sstevel@tonic-gate 			if (ct->dd_len2 == 0) {
9210Sstevel@tonic-gate 				/*
9220Sstevel@tonic-gate 				 * The previous encrypt step was an
9230Sstevel@tonic-gate 				 * accumulation only and didn't produce any
9240Sstevel@tonic-gate 				 * partial output
9250Sstevel@tonic-gate 				 */
9260Sstevel@tonic-gate 				if (ct->dd_len1 == 0)
9270Sstevel@tonic-gate 					goto out;
9280Sstevel@tonic-gate 			} else {
9290Sstevel@tonic-gate 				ct->dd_offset1 = ct->dd_offset2;
9300Sstevel@tonic-gate 				ct->dd_len1 = ct->dd_len2;
9310Sstevel@tonic-gate 			}
9320Sstevel@tonic-gate 			error = crypto_mac_update((crypto_context_t)mac_ctx,
9330Sstevel@tonic-gate 			    (crypto_data_t *)ct, NULL);
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 			ct->dd_offset1 = save_offset;
9360Sstevel@tonic-gate 			ct->dd_len1 = save_len;
9370Sstevel@tonic-gate 
9380Sstevel@tonic-gate 			goto out;
9390Sstevel@tonic-gate 		}
9400Sstevel@tonic-gate 		/* submit a pure asynchronous request. */
9410Sstevel@tonic-gate 		save_flag = cr->cr_flag;
9420Sstevel@tonic-gate 		cr->cr_flag |= CRYPTO_ALWAYS_QUEUE;
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_UPDATE,
9450Sstevel@tonic-gate 		    pd->pd_sid, NULL, NULL, pt, ct, NULL, NULL, NULL)
9460Sstevel@tonic-gate 
9470Sstevel@tonic-gate 
9480Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 		cr->cr_flag = save_flag;
9510Sstevel@tonic-gate 		goto out;
9520Sstevel@tonic-gate 	}
9530Sstevel@tonic-gate 
9540Sstevel@tonic-gate 	/* The fast path for SW providers. */
9550Sstevel@tonic-gate 	if (CHECK_FASTPATH(cr, pd)) {
9560Sstevel@tonic-gate 		error = KCF_PROV_ENCRYPT_MAC_UPDATE(pd, ctx, pt, ct, NULL);
9570Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
9580Sstevel@tonic-gate 	} else {
9590Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_UPDATE,
960904Smcpowers 		    ctx->cc_session, NULL, NULL, pt, ct, NULL, NULL, NULL);
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
9630Sstevel@tonic-gate 	}
9640Sstevel@tonic-gate out:
9650Sstevel@tonic-gate 	return (error);
9660Sstevel@tonic-gate }
9670Sstevel@tonic-gate 
9680Sstevel@tonic-gate /*
9690Sstevel@tonic-gate  * Terminates a multi-part dual encrypt/mac operation.
9700Sstevel@tonic-gate  */
9710Sstevel@tonic-gate /* ARGSUSED */
9720Sstevel@tonic-gate int crypto_encrypt_mac_final(crypto_context_t context, crypto_dual_data_t *ct,
9730Sstevel@tonic-gate     crypto_data_t *mac, crypto_call_req_t *cr)
9740Sstevel@tonic-gate {
9750Sstevel@tonic-gate 	crypto_ctx_t *ctx = (crypto_ctx_t *)context, *mac_ctx;
9760Sstevel@tonic-gate 	kcf_context_t *kcf_ctx, *kcf_mac_ctx;
9770Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
9780Sstevel@tonic-gate 	int error;
9790Sstevel@tonic-gate 	kcf_req_params_t params;
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate 	if ((ctx == NULL) ||
9820Sstevel@tonic-gate 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
9830Sstevel@tonic-gate 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
9840Sstevel@tonic-gate 		return (CRYPTO_INVALID_CONTEXT);
9850Sstevel@tonic-gate 	}
9860Sstevel@tonic-gate 
987904Smcpowers 	ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
9880Sstevel@tonic-gate 
9890Sstevel@tonic-gate 	if ((kcf_mac_ctx = kcf_ctx->kc_secondctx) != NULL) {
9900Sstevel@tonic-gate 		off_t save_offset;
9910Sstevel@tonic-gate 		size_t save_len;
9920Sstevel@tonic-gate 		crypto_context_t mac_context;
9930Sstevel@tonic-gate 		crypto_call_flag_t save_flag;
9940Sstevel@tonic-gate 
9950Sstevel@tonic-gate 		if (kcf_mac_ctx->kc_prov_desc == NULL) {
9960Sstevel@tonic-gate 			return (CRYPTO_INVALID_CONTEXT);
9970Sstevel@tonic-gate 		}
9980Sstevel@tonic-gate 		mac_ctx = &kcf_mac_ctx->kc_glbl_ctx;
9990Sstevel@tonic-gate 		mac_context = (crypto_context_t)mac_ctx;
10000Sstevel@tonic-gate 
10010Sstevel@tonic-gate 		if (cr == NULL) {
10020Sstevel@tonic-gate 			/* Get the last chunk of ciphertext */
10030Sstevel@tonic-gate 			error = crypto_encrypt_final(context,
10040Sstevel@tonic-gate 			    (crypto_data_t *)ct, NULL);
10050Sstevel@tonic-gate 
10060Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS)  {
10070Sstevel@tonic-gate 				/*
10080Sstevel@tonic-gate 				 * Needed here, because the caller of
10090Sstevel@tonic-gate 				 * crypto_encrypt_mac_final() lost all
10100Sstevel@tonic-gate 				 * refs to the mac_ctx.
10110Sstevel@tonic-gate 				 */
10120Sstevel@tonic-gate 				crypto_cancel_ctx(mac_context);
10130Sstevel@tonic-gate 				return (error);
10140Sstevel@tonic-gate 			}
10150Sstevel@tonic-gate 			if (ct->dd_len2 > 0) {
10160Sstevel@tonic-gate 				save_offset = ct->dd_offset1;
10170Sstevel@tonic-gate 				save_len = ct->dd_len1;
10180Sstevel@tonic-gate 				ct->dd_offset1 = ct->dd_offset2;
10190Sstevel@tonic-gate 				ct->dd_len1 = ct->dd_len2;
10200Sstevel@tonic-gate 
10210Sstevel@tonic-gate 				error = crypto_mac_update(mac_context,
10220Sstevel@tonic-gate 				    (crypto_data_t *)ct, NULL);
10230Sstevel@tonic-gate 
10240Sstevel@tonic-gate 				ct->dd_offset1 = save_offset;
10250Sstevel@tonic-gate 				ct->dd_len1 = save_len;
10260Sstevel@tonic-gate 
10270Sstevel@tonic-gate 				if (error != CRYPTO_SUCCESS)  {
10280Sstevel@tonic-gate 					crypto_cancel_ctx(mac_context);
10290Sstevel@tonic-gate 					return (error);
10300Sstevel@tonic-gate 				}
10310Sstevel@tonic-gate 			}
10320Sstevel@tonic-gate 
10330Sstevel@tonic-gate 			/* and finally, collect the MAC */
10340Sstevel@tonic-gate 			error = crypto_mac_final(mac_context, mac, NULL);
10350Sstevel@tonic-gate 
10360Sstevel@tonic-gate 			return (error);
10370Sstevel@tonic-gate 		}
10380Sstevel@tonic-gate 		/* submit a pure asynchronous request. */
10390Sstevel@tonic-gate 		save_flag = cr->cr_flag;
10400Sstevel@tonic-gate 		cr->cr_flag |= CRYPTO_ALWAYS_QUEUE;
10410Sstevel@tonic-gate 
10420Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_FINAL,
10430Sstevel@tonic-gate 		    pd->pd_sid, NULL, NULL, NULL, ct, mac, NULL, NULL)
10440Sstevel@tonic-gate 
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate 		cr->cr_flag = save_flag;
10490Sstevel@tonic-gate 		return (error);
10500Sstevel@tonic-gate 	}
10510Sstevel@tonic-gate 	/* The fast path for SW providers. */
10520Sstevel@tonic-gate 	if (CHECK_FASTPATH(cr, pd)) {
10530Sstevel@tonic-gate 		error = KCF_PROV_ENCRYPT_MAC_FINAL(pd, ctx, ct, mac, NULL);
10540Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
10550Sstevel@tonic-gate 	} else {
10560Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_FINAL,
1057904Smcpowers 		    ctx->cc_session, NULL, NULL, NULL, ct, mac, NULL, NULL);
10580Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
10590Sstevel@tonic-gate 	}
10600Sstevel@tonic-gate out:
10610Sstevel@tonic-gate 	/* Release the hold done in kcf_new_ctx() during init step. */
10620Sstevel@tonic-gate 	KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
10630Sstevel@tonic-gate 	return (error);
10640Sstevel@tonic-gate }
10650Sstevel@tonic-gate 
10660Sstevel@tonic-gate /*
10670Sstevel@tonic-gate  * Performs an atomic dual mac/decrypt operation. The provider to use
10680Sstevel@tonic-gate  * is determined by the KCF dispatcher.
10690Sstevel@tonic-gate  */
10700Sstevel@tonic-gate int
10710Sstevel@tonic-gate crypto_mac_decrypt(crypto_mechanism_t *mac_mech,
10720Sstevel@tonic-gate     crypto_mechanism_t *decr_mech, crypto_dual_data_t *ct,
10730Sstevel@tonic-gate     crypto_key_t *mac_key, crypto_key_t *decr_key,
10740Sstevel@tonic-gate     crypto_ctx_template_t mac_tmpl, crypto_ctx_template_t decr_tmpl,
10750Sstevel@tonic-gate     crypto_data_t *mac, crypto_data_t *pt, crypto_call_req_t *crq)
10760Sstevel@tonic-gate {
10770Sstevel@tonic-gate 	return (crypto_mac_decrypt_common(mac_mech, decr_mech, ct, mac_key,
10780Sstevel@tonic-gate 	    decr_key, mac_tmpl, decr_tmpl, mac, pt, crq, B_FALSE));
10790Sstevel@tonic-gate }
10800Sstevel@tonic-gate 
1081904Smcpowers int
1082904Smcpowers crypto_mac_decrypt_prov(crypto_provider_t provider, crypto_session_id_t sid,
1083904Smcpowers     crypto_mechanism_t *mac_mech, crypto_mechanism_t *decr_mech,
1084904Smcpowers     crypto_dual_data_t *ct, crypto_key_t *mac_key, crypto_key_t *decr_key,
1085904Smcpowers     crypto_ctx_template_t mac_tmpl, crypto_ctx_template_t decr_tmpl,
1086904Smcpowers     crypto_data_t *mac, crypto_data_t *pt, crypto_call_req_t *crq)
1087904Smcpowers {
1088904Smcpowers 	return (crypto_mac_decrypt_common_prov(provider, sid, mac_mech,
1089904Smcpowers 	    decr_mech, ct, mac_key, decr_key, mac_tmpl, decr_tmpl, mac, pt,
1090904Smcpowers 	    crq, B_FALSE));
1091904Smcpowers }
1092904Smcpowers 
10930Sstevel@tonic-gate /*
10940Sstevel@tonic-gate  * Performs an atomic dual mac/decrypt operation. The provider to use
10950Sstevel@tonic-gate  * is determined by the KCF dispatcher. 'mac' specifies the expected
10960Sstevel@tonic-gate  * value for the MAC. The decryption is not performed if the computed
10970Sstevel@tonic-gate  * MAC does not match the expected MAC.
10980Sstevel@tonic-gate  */
10990Sstevel@tonic-gate int
11000Sstevel@tonic-gate crypto_mac_verify_decrypt(crypto_mechanism_t *mac_mech,
11010Sstevel@tonic-gate     crypto_mechanism_t *decr_mech, crypto_dual_data_t *ct,
11020Sstevel@tonic-gate     crypto_key_t *mac_key, crypto_key_t *decr_key,
11030Sstevel@tonic-gate     crypto_ctx_template_t mac_tmpl, crypto_ctx_template_t decr_tmpl,
11040Sstevel@tonic-gate     crypto_data_t *mac, crypto_data_t *pt, crypto_call_req_t *crq)
11050Sstevel@tonic-gate {
11060Sstevel@tonic-gate 	return (crypto_mac_decrypt_common(mac_mech, decr_mech, ct, mac_key,
11070Sstevel@tonic-gate 	    decr_key, mac_tmpl, decr_tmpl, mac, pt, crq, B_TRUE));
11080Sstevel@tonic-gate }
11090Sstevel@tonic-gate 
1110904Smcpowers int
1111904Smcpowers crypto_mac_verify_decrypt_prov(crypto_provider_t provider,
1112904Smcpowers     crypto_session_id_t sid, crypto_mechanism_t *mac_mech,
1113904Smcpowers     crypto_mechanism_t *decr_mech, crypto_dual_data_t *ct,
1114904Smcpowers     crypto_key_t *mac_key, crypto_key_t *decr_key,
1115904Smcpowers     crypto_ctx_template_t mac_tmpl, crypto_ctx_template_t decr_tmpl,
1116904Smcpowers     crypto_data_t *mac, crypto_data_t *pt, crypto_call_req_t *crq)
1117904Smcpowers {
1118904Smcpowers 	return (crypto_mac_decrypt_common_prov(provider, sid, mac_mech,
1119904Smcpowers 	    decr_mech, ct, mac_key, decr_key, mac_tmpl, decr_tmpl, mac, pt,
1120904Smcpowers 	    crq, B_TRUE));
1121904Smcpowers }
1122904Smcpowers 
11230Sstevel@tonic-gate /*
11240Sstevel@tonic-gate  * Called by both crypto_mac_decrypt() and crypto_mac_verify_decrypt().
11250Sstevel@tonic-gate  * optionally verified if the MACs match before calling the decryption step.
11260Sstevel@tonic-gate  */
11270Sstevel@tonic-gate static int
11280Sstevel@tonic-gate crypto_mac_decrypt_common(crypto_mechanism_t *mac_mech,
11290Sstevel@tonic-gate     crypto_mechanism_t *decr_mech, crypto_dual_data_t *ct,
11300Sstevel@tonic-gate     crypto_key_t *mac_key, crypto_key_t *decr_key,
11310Sstevel@tonic-gate     crypto_ctx_template_t mac_tmpl, crypto_ctx_template_t decr_tmpl,
11320Sstevel@tonic-gate     crypto_data_t *mac, crypto_data_t *pt, crypto_call_req_t *crq,
11330Sstevel@tonic-gate     boolean_t do_verify)
11340Sstevel@tonic-gate {
11350Sstevel@tonic-gate 	/*
11360Sstevel@tonic-gate 	 * First try to find a provider for the decryption mechanism, that
11370Sstevel@tonic-gate 	 * is also capable of the MAC mechanism.
11380Sstevel@tonic-gate 	 * We still favor optimizing the costlier decryption.
11390Sstevel@tonic-gate 	 */
11400Sstevel@tonic-gate 	int error;
11410Sstevel@tonic-gate 	kcf_mech_entry_t *me;
11420Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
11430Sstevel@tonic-gate 	kcf_ctx_template_t *ctx_decr_tmpl, *ctx_mac_tmpl;
11440Sstevel@tonic-gate 	kcf_req_params_t params;
11450Sstevel@tonic-gate 	kcf_mac_decrypt_ops_params_t *cmops;
11460Sstevel@tonic-gate 	crypto_spi_ctx_template_t spi_decr_tmpl = NULL, spi_mac_tmpl = NULL;
11470Sstevel@tonic-gate 	crypto_mech_type_t prov_decr_mechid, prov_mac_mechid;
11480Sstevel@tonic-gate 	kcf_prov_tried_t *list = NULL;
11490Sstevel@tonic-gate 	boolean_t decr_tmpl_checked = B_FALSE;
11500Sstevel@tonic-gate 	boolean_t mac_tmpl_checked = B_FALSE;
11510Sstevel@tonic-gate 	kcf_dual_req_t *next_req = NULL;
11520Sstevel@tonic-gate 	crypto_call_req_t mac_req, *mac_reqp = NULL;
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate retry:
11550Sstevel@tonic-gate 	/* pd is returned held on success */
1156*10444SVladimir.Kotal@Sun.COM 	pd = kcf_get_dual_provider(decr_mech, decr_key, mac_mech, mac_key,
1157*10444SVladimir.Kotal@Sun.COM 	    &me, &prov_decr_mechid,
11580Sstevel@tonic-gate 	    &prov_mac_mechid, &error, list,
11590Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
11600Sstevel@tonic-gate 	    CRYPTO_FG_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
11610Sstevel@tonic-gate 	    CHECK_RESTRICT(crq), ct->dd_len2);
11620Sstevel@tonic-gate 	if (pd == NULL) {
11630Sstevel@tonic-gate 		if (list != NULL)
11640Sstevel@tonic-gate 			kcf_free_triedlist(list);
11650Sstevel@tonic-gate 		if (next_req != NULL)
11660Sstevel@tonic-gate 			kmem_free(next_req, sizeof (kcf_dual_req_t));
11670Sstevel@tonic-gate 		return (CRYPTO_MECH_NOT_SUPPORTED);
11680Sstevel@tonic-gate 	}
11690Sstevel@tonic-gate 
11700Sstevel@tonic-gate 	/*
11710Sstevel@tonic-gate 	 * For SW providers, check the validity of the context template
11720Sstevel@tonic-gate 	 * It is very rare that the generation number mis-matches, so
11730Sstevel@tonic-gate 	 * is acceptable to fail here, and let the consumer recover by
11740Sstevel@tonic-gate 	 * freeing this tmpl and create a new one for the key and new SW
11750Sstevel@tonic-gate 	 * provider
11760Sstevel@tonic-gate 	 */
11770Sstevel@tonic-gate 
11780Sstevel@tonic-gate 	if ((!decr_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
11790Sstevel@tonic-gate 		if (decr_tmpl != NULL) {
11800Sstevel@tonic-gate 			ctx_decr_tmpl = (kcf_ctx_template_t *)decr_tmpl;
11810Sstevel@tonic-gate 			if (ctx_decr_tmpl->ct_generation != me->me_gen_swprov) {
11820Sstevel@tonic-gate 				if (next_req != NULL)
11830Sstevel@tonic-gate 					kmem_free(next_req,
11840Sstevel@tonic-gate 					    sizeof (kcf_dual_req_t));
11850Sstevel@tonic-gate 				if (list != NULL)
11860Sstevel@tonic-gate 					kcf_free_triedlist(list);
11870Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 				/* Which one is the the old one ? */
11900Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
11910Sstevel@tonic-gate 			}
11920Sstevel@tonic-gate 			spi_decr_tmpl = ctx_decr_tmpl->ct_prov_tmpl;
11930Sstevel@tonic-gate 		}
11940Sstevel@tonic-gate 		decr_tmpl_checked = B_TRUE;
11950Sstevel@tonic-gate 	}
11960Sstevel@tonic-gate 	if (prov_mac_mechid == CRYPTO_MECH_INVALID) {
11970Sstevel@tonic-gate 		/* Need to emulate with 2 internal calls */
11980Sstevel@tonic-gate 
11990Sstevel@tonic-gate 		/* Prepare the call_req to be submitted for the MAC step */
12000Sstevel@tonic-gate 
12010Sstevel@tonic-gate 		if (crq != NULL) {
12020Sstevel@tonic-gate 
12030Sstevel@tonic-gate 			if (next_req == NULL) {
12040Sstevel@tonic-gate 				/*
12050Sstevel@tonic-gate 				 * allocate, initialize and prepare the
12060Sstevel@tonic-gate 				 * params for the next step only in the
12070Sstevel@tonic-gate 				 * first pass (not on every retry).
12080Sstevel@tonic-gate 				 */
12090Sstevel@tonic-gate 				next_req = kcf_alloc_req(crq);
12100Sstevel@tonic-gate 
12110Sstevel@tonic-gate 				if (next_req == NULL) {
12120Sstevel@tonic-gate 					KCF_PROV_REFRELE(pd);
12130Sstevel@tonic-gate 					if (list != NULL)
12140Sstevel@tonic-gate 						kcf_free_triedlist(list);
12150Sstevel@tonic-gate 					return (CRYPTO_HOST_MEMORY);
12160Sstevel@tonic-gate 				}
12170Sstevel@tonic-gate 				KCF_WRAP_DECRYPT_OPS_PARAMS(
12180Sstevel@tonic-gate 				    &(next_req->kr_params), KCF_OP_ATOMIC,
12190Sstevel@tonic-gate 				    NULL, decr_mech, decr_key,
12200Sstevel@tonic-gate 				    (crypto_data_t *)ct, pt, spi_decr_tmpl);
12210Sstevel@tonic-gate 			}
12220Sstevel@tonic-gate 
12230Sstevel@tonic-gate 			mac_req.cr_flag = (crq != NULL) ? crq->cr_flag : 0;
12240Sstevel@tonic-gate 			mac_req.cr_flag |= CRYPTO_SETDUAL;
12250Sstevel@tonic-gate 			mac_req.cr_callback_func = kcf_next_req;
12260Sstevel@tonic-gate 			mac_req.cr_callback_arg = next_req;
12270Sstevel@tonic-gate 			mac_reqp = &mac_req;
12280Sstevel@tonic-gate 		}
12290Sstevel@tonic-gate 
12300Sstevel@tonic-gate 		/* 'pd' is the decryption provider. */
12310Sstevel@tonic-gate 
12320Sstevel@tonic-gate 		if (do_verify)
12330Sstevel@tonic-gate 			error = crypto_mac_verify(mac_mech, (crypto_data_t *)ct,
12340Sstevel@tonic-gate 			    mac_key, mac_tmpl, mac,
12350Sstevel@tonic-gate 			    (crq == NULL) ? NULL : mac_reqp);
12360Sstevel@tonic-gate 		else
12370Sstevel@tonic-gate 			error = crypto_mac(mac_mech, (crypto_data_t *)ct,
12380Sstevel@tonic-gate 			    mac_key, mac_tmpl, mac,
12390Sstevel@tonic-gate 			    (crq == NULL) ? NULL : mac_reqp);
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate 		switch (error) {
12420Sstevel@tonic-gate 		case CRYPTO_SUCCESS: {
12430Sstevel@tonic-gate 			off_t saveoffset;
12440Sstevel@tonic-gate 			size_t savelen;
12450Sstevel@tonic-gate 
12460Sstevel@tonic-gate 			if (next_req == NULL) {
12470Sstevel@tonic-gate 				saveoffset = ct->dd_offset1;
12480Sstevel@tonic-gate 				savelen = ct->dd_len1;
12490Sstevel@tonic-gate 			} else {
12500Sstevel@tonic-gate 				saveoffset = next_req->kr_saveoffset =
12510Sstevel@tonic-gate 				    ct->dd_offset1;
12520Sstevel@tonic-gate 				savelen = next_req->kr_savelen = ct->dd_len1;
12530Sstevel@tonic-gate 
12540Sstevel@tonic-gate 				ASSERT(mac_reqp != NULL);
12550Sstevel@tonic-gate 				mac_req.cr_flag &= ~CRYPTO_SETDUAL;
12560Sstevel@tonic-gate 				mac_req.cr_callback_func = kcf_last_req;
12570Sstevel@tonic-gate 			}
12580Sstevel@tonic-gate 			ct->dd_offset1 = ct->dd_offset2;
12590Sstevel@tonic-gate 			ct->dd_len1 = ct->dd_len2;
12600Sstevel@tonic-gate 
12610Sstevel@tonic-gate 			if (CHECK_FASTPATH(crq, pd)) {
12620Sstevel@tonic-gate 				crypto_mechanism_t lmech;
12630Sstevel@tonic-gate 
12640Sstevel@tonic-gate 				lmech = *decr_mech;
12650Sstevel@tonic-gate 				KCF_SET_PROVIDER_MECHNUM(decr_mech->cm_type,
12660Sstevel@tonic-gate 				    pd, &lmech);
12670Sstevel@tonic-gate 
12680Sstevel@tonic-gate 				error = KCF_PROV_DECRYPT_ATOMIC(pd, pd->pd_sid,
12690Sstevel@tonic-gate 				    &lmech, decr_key, (crypto_data_t *)ct,
12700Sstevel@tonic-gate 				    (crypto_data_t *)pt, spi_decr_tmpl,
12710Sstevel@tonic-gate 				    KCF_SWFP_RHNDL(mac_reqp));
12720Sstevel@tonic-gate 
12730Sstevel@tonic-gate 				KCF_PROV_INCRSTATS(pd, error);
12740Sstevel@tonic-gate 			} else {
12750Sstevel@tonic-gate 				KCF_WRAP_DECRYPT_OPS_PARAMS(&params,
12760Sstevel@tonic-gate 				    KCF_OP_ATOMIC, pd->pd_sid, decr_mech,
12770Sstevel@tonic-gate 				    decr_key, (crypto_data_t *)ct, pt,
12780Sstevel@tonic-gate 				    spi_decr_tmpl);
12790Sstevel@tonic-gate 
12800Sstevel@tonic-gate 				error = kcf_submit_request(pd, NULL,
12810Sstevel@tonic-gate 				    (crq == NULL) ? NULL : mac_reqp,
12820Sstevel@tonic-gate 				    &params, B_FALSE);
12830Sstevel@tonic-gate 			}
12840Sstevel@tonic-gate 			if (error != CRYPTO_QUEUED) {
12850Sstevel@tonic-gate 				KCF_PROV_INCRSTATS(pd, error);
12860Sstevel@tonic-gate 				ct->dd_offset1 = saveoffset;
12870Sstevel@tonic-gate 				ct->dd_len1 = savelen;
12880Sstevel@tonic-gate 			}
12890Sstevel@tonic-gate 			break;
12900Sstevel@tonic-gate 		}
12910Sstevel@tonic-gate 
12920Sstevel@tonic-gate 		case CRYPTO_QUEUED:
12930Sstevel@tonic-gate 			if ((crq != NULL) && (crq->cr_flag & CRYPTO_SKIP_REQID))
12940Sstevel@tonic-gate 				crq->cr_reqid = mac_req.cr_reqid;
12950Sstevel@tonic-gate 			break;
12960Sstevel@tonic-gate 
12970Sstevel@tonic-gate 		default:
12980Sstevel@tonic-gate 			if (IS_RECOVERABLE(error)) {
12990Sstevel@tonic-gate 				if (kcf_insert_triedlist(&list, pd,
13000Sstevel@tonic-gate 				    KCF_KMFLAG(crq)) != NULL)
13010Sstevel@tonic-gate 					goto retry;
13020Sstevel@tonic-gate 			}
13030Sstevel@tonic-gate 		}
13040Sstevel@tonic-gate 		if (error != CRYPTO_QUEUED && next_req != NULL)
13050Sstevel@tonic-gate 			kmem_free(next_req, sizeof (kcf_dual_req_t));
13060Sstevel@tonic-gate 		if (list != NULL)
13070Sstevel@tonic-gate 			kcf_free_triedlist(list);
13080Sstevel@tonic-gate 		KCF_PROV_REFRELE(pd);
13090Sstevel@tonic-gate 		return (error);
13100Sstevel@tonic-gate 	}
13110Sstevel@tonic-gate 
13120Sstevel@tonic-gate 	if ((!mac_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
13130Sstevel@tonic-gate 		if ((mac_tmpl != NULL) &&
13140Sstevel@tonic-gate 		    (prov_mac_mechid != CRYPTO_MECH_INVALID)) {
13150Sstevel@tonic-gate 			ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
13160Sstevel@tonic-gate 			if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
13170Sstevel@tonic-gate 				if (next_req != NULL)
13180Sstevel@tonic-gate 					kmem_free(next_req,
13190Sstevel@tonic-gate 					    sizeof (kcf_dual_req_t));
13200Sstevel@tonic-gate 				if (list != NULL)
13210Sstevel@tonic-gate 					kcf_free_triedlist(list);
13220Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
13230Sstevel@tonic-gate 
13240Sstevel@tonic-gate 				/* Which one is the the old one ? */
13250Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
13260Sstevel@tonic-gate 			}
13270Sstevel@tonic-gate 			spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
13280Sstevel@tonic-gate 		}
13290Sstevel@tonic-gate 		mac_tmpl_checked = B_TRUE;
13300Sstevel@tonic-gate 	}
13310Sstevel@tonic-gate 
13320Sstevel@tonic-gate 	/* The fast path for SW providers. */
13330Sstevel@tonic-gate 	if (CHECK_FASTPATH(crq, pd)) {
13340Sstevel@tonic-gate 		crypto_mechanism_t lmac_mech;
13350Sstevel@tonic-gate 		crypto_mechanism_t ldecr_mech;
13360Sstevel@tonic-gate 
13370Sstevel@tonic-gate 		/* careful! structs assignments */
13380Sstevel@tonic-gate 		ldecr_mech = *decr_mech;
13390Sstevel@tonic-gate 		ldecr_mech.cm_type = prov_decr_mechid;
13400Sstevel@tonic-gate 		lmac_mech = *mac_mech;
13410Sstevel@tonic-gate 		lmac_mech.cm_type = prov_mac_mechid;
13420Sstevel@tonic-gate 
13430Sstevel@tonic-gate 		if (do_verify)
13440Sstevel@tonic-gate 			error = KCF_PROV_MAC_VERIFY_DECRYPT_ATOMIC(pd,
13450Sstevel@tonic-gate 			    pd->pd_sid, &lmac_mech, mac_key, &ldecr_mech,
13460Sstevel@tonic-gate 			    decr_key, ct, mac, pt, spi_mac_tmpl, spi_decr_tmpl,
13470Sstevel@tonic-gate 			    KCF_SWFP_RHNDL(crq));
13480Sstevel@tonic-gate 		else
13490Sstevel@tonic-gate 			error = KCF_PROV_MAC_DECRYPT_ATOMIC(pd, pd->pd_sid,
13500Sstevel@tonic-gate 			    &lmac_mech, mac_key, &ldecr_mech, decr_key,
13510Sstevel@tonic-gate 			    ct, mac, pt, spi_mac_tmpl, spi_decr_tmpl,
13520Sstevel@tonic-gate 			    KCF_SWFP_RHNDL(crq));
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
13550Sstevel@tonic-gate 	} else {
13560Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params,
13570Sstevel@tonic-gate 		    (do_verify) ? KCF_OP_MAC_VERIFY_DECRYPT_ATOMIC :
13580Sstevel@tonic-gate 		    KCF_OP_ATOMIC, pd->pd_sid, mac_key, decr_key, ct, mac, pt,
13590Sstevel@tonic-gate 		    spi_mac_tmpl, spi_decr_tmpl);
13600Sstevel@tonic-gate 
13610Sstevel@tonic-gate 		cmops = &(params.rp_u.mac_decrypt_params);
13620Sstevel@tonic-gate 
13630Sstevel@tonic-gate 		/* careful! structs assignments */
13640Sstevel@tonic-gate 		cmops->md_decr_mech = *decr_mech;
13650Sstevel@tonic-gate 		cmops->md_decr_mech.cm_type = prov_decr_mechid;
13660Sstevel@tonic-gate 		cmops->md_framework_decr_mechtype = decr_mech->cm_type;
13670Sstevel@tonic-gate 		cmops->md_mac_mech = *mac_mech;
13680Sstevel@tonic-gate 		cmops->md_mac_mech.cm_type = prov_mac_mechid;
13690Sstevel@tonic-gate 		cmops->md_framework_mac_mechtype = mac_mech->cm_type;
13700Sstevel@tonic-gate 
13710Sstevel@tonic-gate 		error = kcf_submit_request(pd, NULL, crq, &params, B_FALSE);
13720Sstevel@tonic-gate 	}
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate 	if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED &&
13750Sstevel@tonic-gate 	    IS_RECOVERABLE(error)) {
13760Sstevel@tonic-gate 		/* Add pd to the linked list of providers tried. */
13770Sstevel@tonic-gate 		if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL)
13780Sstevel@tonic-gate 			goto retry;
13790Sstevel@tonic-gate 	}
13800Sstevel@tonic-gate 
13810Sstevel@tonic-gate 	if (list != NULL)
13820Sstevel@tonic-gate 		kcf_free_triedlist(list);
13830Sstevel@tonic-gate 
13840Sstevel@tonic-gate 	if (next_req != NULL)
13850Sstevel@tonic-gate 		kmem_free(next_req, sizeof (kcf_dual_req_t));
13860Sstevel@tonic-gate 	KCF_PROV_REFRELE(pd);
13870Sstevel@tonic-gate 	return (error);
13880Sstevel@tonic-gate }
13890Sstevel@tonic-gate 
1390904Smcpowers static int
1391904Smcpowers crypto_mac_decrypt_common_prov(crypto_provider_t provider,
1392904Smcpowers     crypto_session_id_t sid, crypto_mechanism_t *mac_mech,
1393904Smcpowers     crypto_mechanism_t *decr_mech, crypto_dual_data_t *ct,
1394904Smcpowers     crypto_key_t *mac_key, crypto_key_t *decr_key,
1395904Smcpowers     crypto_ctx_template_t mac_tmpl, crypto_ctx_template_t decr_tmpl,
1396904Smcpowers     crypto_data_t *mac, crypto_data_t *pt, crypto_call_req_t *crq,
1397904Smcpowers     boolean_t do_verify)
1398904Smcpowers {
1399904Smcpowers 	/*
1400904Smcpowers 	 * First try to find a provider for the decryption mechanism, that
1401904Smcpowers 	 * is also capable of the MAC mechanism.
1402904Smcpowers 	 * We still favor optimizing the costlier decryption.
1403904Smcpowers 	 */
1404904Smcpowers 	int error;
1405904Smcpowers 	kcf_mech_entry_t *me;
1406904Smcpowers 	kcf_provider_desc_t *pd = provider;
1407904Smcpowers 	kcf_provider_desc_t *real_provider = pd;
1408904Smcpowers 	kcf_ctx_template_t *ctx_decr_tmpl, *ctx_mac_tmpl;
1409904Smcpowers 	kcf_req_params_t params;
1410904Smcpowers 	kcf_mac_decrypt_ops_params_t *cmops;
1411904Smcpowers 	crypto_spi_ctx_template_t spi_decr_tmpl = NULL, spi_mac_tmpl = NULL;
1412904Smcpowers 
1413904Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
1414904Smcpowers 
1415904Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
1416*10444SVladimir.Kotal@Sun.COM 		error = kcf_get_hardware_provider(decr_mech->cm_type, decr_key,
1417*10444SVladimir.Kotal@Sun.COM 		    mac_mech->cm_type, mac_key, CHECK_RESTRICT(crq), pd,
14181808Smcpowers 		    &real_provider, CRYPTO_FG_MAC_DECRYPT_ATOMIC);
1419904Smcpowers 
1420904Smcpowers 		if (error != CRYPTO_SUCCESS)
1421904Smcpowers 			return (error);
1422904Smcpowers 	}
1423904Smcpowers 
1424904Smcpowers 	/*
1425904Smcpowers 	 * For SW providers, check the validity of the context template
1426904Smcpowers 	 * It is very rare that the generation number mis-matches, so
1427904Smcpowers 	 * is acceptable to fail here, and let the consumer recover by
1428904Smcpowers 	 * freeing this tmpl and create a new one for the key and new SW
1429904Smcpowers 	 * provider
1430904Smcpowers 	 */
1431904Smcpowers 
1432904Smcpowers 	if (real_provider->pd_prov_type == CRYPTO_SW_PROVIDER) {
1433904Smcpowers 		if (decr_tmpl != NULL) {
1434904Smcpowers 			if (kcf_get_mech_entry(decr_mech->cm_type, &me) !=
1435904Smcpowers 			    KCF_SUCCESS) {
1436904Smcpowers 				error = CRYPTO_MECHANISM_INVALID;
1437904Smcpowers 				goto out;
1438904Smcpowers 			}
1439904Smcpowers 			ctx_decr_tmpl = (kcf_ctx_template_t *)decr_tmpl;
1440904Smcpowers 			if (ctx_decr_tmpl->ct_generation != me->me_gen_swprov) {
1441904Smcpowers 				error = CRYPTO_OLD_CTX_TEMPLATE;
1442904Smcpowers 				goto out;
1443904Smcpowers 			}
1444904Smcpowers 			spi_decr_tmpl = ctx_decr_tmpl->ct_prov_tmpl;
1445904Smcpowers 		}
1446904Smcpowers 
1447904Smcpowers 		if (mac_tmpl != NULL) {
1448904Smcpowers 			if (kcf_get_mech_entry(mac_mech->cm_type, &me) !=
1449904Smcpowers 			    KCF_SUCCESS) {
1450904Smcpowers 				error = CRYPTO_MECHANISM_INVALID;
1451904Smcpowers 				goto out;
1452904Smcpowers 			}
1453904Smcpowers 			ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
1454904Smcpowers 			if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
1455904Smcpowers 				error = CRYPTO_OLD_CTX_TEMPLATE;
1456904Smcpowers 				goto out;
1457904Smcpowers 			}
1458904Smcpowers 			spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
1459904Smcpowers 		}
1460904Smcpowers 	}
1461904Smcpowers 
1462904Smcpowers 	/* The fast path for SW providers. */
1463904Smcpowers 	if (CHECK_FASTPATH(crq, pd)) {
1464904Smcpowers 		crypto_mechanism_t lmac_mech;
1465904Smcpowers 		crypto_mechanism_t ldecr_mech;
1466904Smcpowers 
1467904Smcpowers 		/* careful! structs assignments */
1468904Smcpowers 		ldecr_mech = *decr_mech;
1469904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(decr_mech->cm_type, real_provider,
1470904Smcpowers 		    &ldecr_mech);
1471904Smcpowers 
1472904Smcpowers 		lmac_mech = *mac_mech;
1473904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
1474904Smcpowers 		    &lmac_mech);
1475904Smcpowers 
1476904Smcpowers 		if (do_verify)
1477904Smcpowers 			error = KCF_PROV_MAC_VERIFY_DECRYPT_ATOMIC(
1478904Smcpowers 			    real_provider, sid, &lmac_mech, mac_key,
1479904Smcpowers 			    &ldecr_mech, decr_key, ct, mac, pt, spi_mac_tmpl,
1480904Smcpowers 			    spi_decr_tmpl, KCF_SWFP_RHNDL(crq));
1481904Smcpowers 		else
1482904Smcpowers 			error = KCF_PROV_MAC_DECRYPT_ATOMIC(real_provider, sid,
1483904Smcpowers 			    &lmac_mech, mac_key, &ldecr_mech, decr_key,
1484904Smcpowers 			    ct, mac, pt, spi_mac_tmpl, spi_decr_tmpl,
1485904Smcpowers 			    KCF_SWFP_RHNDL(crq));
1486904Smcpowers 
1487904Smcpowers 		KCF_PROV_INCRSTATS(pd, error);
1488904Smcpowers 	} else {
1489904Smcpowers 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params,
1490904Smcpowers 		    (do_verify) ? KCF_OP_MAC_VERIFY_DECRYPT_ATOMIC :
1491904Smcpowers 		    KCF_OP_ATOMIC, sid, mac_key, decr_key, ct, mac, pt,
1492904Smcpowers 		    spi_mac_tmpl, spi_decr_tmpl);
1493904Smcpowers 
1494904Smcpowers 		cmops = &(params.rp_u.mac_decrypt_params);
1495904Smcpowers 
1496904Smcpowers 		/* careful! structs assignments */
1497904Smcpowers 		cmops->md_decr_mech = *decr_mech;
1498904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(decr_mech->cm_type, real_provider,
1499904Smcpowers 		    &cmops->md_decr_mech);
1500904Smcpowers 		cmops->md_framework_decr_mechtype = decr_mech->cm_type;
1501904Smcpowers 
1502904Smcpowers 		cmops->md_mac_mech = *mac_mech;
1503904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
1504904Smcpowers 		    &cmops->md_mac_mech);
1505904Smcpowers 		cmops->md_framework_mac_mechtype = mac_mech->cm_type;
1506904Smcpowers 
1507904Smcpowers 		error = kcf_submit_request(real_provider, NULL, crq, &params,
1508904Smcpowers 		    B_FALSE);
1509904Smcpowers 	}
1510904Smcpowers 
1511904Smcpowers out:
1512904Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
1513904Smcpowers 		KCF_PROV_REFRELE(real_provider);
1514904Smcpowers 	return (error);
1515904Smcpowers }
1516904Smcpowers 
15170Sstevel@tonic-gate /*
15180Sstevel@tonic-gate  * Starts a multi-part dual mac/decrypt operation. The provider to
15190Sstevel@tonic-gate  * use is determined by the KCF dispatcher.
15200Sstevel@tonic-gate  */
15210Sstevel@tonic-gate /* ARGSUSED */
15220Sstevel@tonic-gate int
15230Sstevel@tonic-gate crypto_mac_decrypt_init(crypto_mechanism_t *mac_mech,
15240Sstevel@tonic-gate     crypto_mechanism_t *decr_mech, crypto_key_t *mac_key,
15250Sstevel@tonic-gate     crypto_key_t *decr_key, crypto_ctx_template_t mac_tmpl,
15260Sstevel@tonic-gate     crypto_ctx_template_t decr_tmpl, crypto_context_t *ctxp,
15270Sstevel@tonic-gate     crypto_call_req_t *cr)
15280Sstevel@tonic-gate {
15290Sstevel@tonic-gate 	/*
15300Sstevel@tonic-gate 	 * First try to find a provider for the decryption mechanism, that
15310Sstevel@tonic-gate 	 * is also capable of the MAC mechanism.
15320Sstevel@tonic-gate 	 * We still favor optimizing the costlier decryption.
15330Sstevel@tonic-gate 	 */
15340Sstevel@tonic-gate 	int error;
15350Sstevel@tonic-gate 	kcf_mech_entry_t *me;
15360Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
15370Sstevel@tonic-gate 	kcf_ctx_template_t *ctx_decr_tmpl, *ctx_mac_tmpl;
15380Sstevel@tonic-gate 	kcf_req_params_t params;
15390Sstevel@tonic-gate 	kcf_mac_decrypt_ops_params_t *mdops;
15400Sstevel@tonic-gate 	crypto_spi_ctx_template_t spi_decr_tmpl = NULL, spi_mac_tmpl = NULL;
15410Sstevel@tonic-gate 	crypto_mech_type_t prov_decr_mechid, prov_mac_mechid;
15420Sstevel@tonic-gate 	kcf_prov_tried_t *list = NULL;
15430Sstevel@tonic-gate 	boolean_t decr_tmpl_checked = B_FALSE;
15440Sstevel@tonic-gate 	boolean_t mac_tmpl_checked = B_FALSE;
15450Sstevel@tonic-gate 	crypto_ctx_t *ctx = NULL;
15460Sstevel@tonic-gate 	kcf_context_t *decr_kcf_context = NULL, *mac_kcf_context = NULL;
15470Sstevel@tonic-gate 	crypto_call_flag_t save_flag;
15480Sstevel@tonic-gate 
15490Sstevel@tonic-gate retry:
15500Sstevel@tonic-gate 	/* pd is returned held on success */
1551*10444SVladimir.Kotal@Sun.COM 	pd = kcf_get_dual_provider(decr_mech, decr_key, mac_mech, mac_key,
1552*10444SVladimir.Kotal@Sun.COM 	    &me, &prov_decr_mechid,
15530Sstevel@tonic-gate 	    &prov_mac_mechid, &error, list,
15540Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_MAC_DECRYPT, CRYPTO_FG_MAC,
15550Sstevel@tonic-gate 	    CHECK_RESTRICT(cr), 0);
15560Sstevel@tonic-gate 	if (pd == NULL) {
15570Sstevel@tonic-gate 		if (list != NULL)
15580Sstevel@tonic-gate 			kcf_free_triedlist(list);
15590Sstevel@tonic-gate 		return (error);
15600Sstevel@tonic-gate 	}
15610Sstevel@tonic-gate 
15620Sstevel@tonic-gate 	/*
15630Sstevel@tonic-gate 	 * For SW providers, check the validity of the context template
15640Sstevel@tonic-gate 	 * It is very rare that the generation number mis-matches, so
15650Sstevel@tonic-gate 	 * is acceptable to fail here, and let the consumer recover by
15660Sstevel@tonic-gate 	 * freeing this tmpl and create a new one for the key and new SW
15670Sstevel@tonic-gate 	 * provider
15680Sstevel@tonic-gate 	 * Warning! will need to change when multiple software providers
15690Sstevel@tonic-gate 	 * per mechanism are supported.
15700Sstevel@tonic-gate 	 */
15710Sstevel@tonic-gate 
15720Sstevel@tonic-gate 	if ((!decr_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
15730Sstevel@tonic-gate 		if (decr_tmpl != NULL) {
15740Sstevel@tonic-gate 			ctx_decr_tmpl = (kcf_ctx_template_t *)decr_tmpl;
15750Sstevel@tonic-gate 			if (ctx_decr_tmpl->ct_generation != me->me_gen_swprov) {
15760Sstevel@tonic-gate 
15770Sstevel@tonic-gate 				if (list != NULL)
15780Sstevel@tonic-gate 					kcf_free_triedlist(list);
15790Sstevel@tonic-gate 				if (decr_kcf_context != NULL)
15800Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(decr_kcf_context);
15810Sstevel@tonic-gate 
15820Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
15830Sstevel@tonic-gate 				/* Which one is the the old one ? */
15840Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
15850Sstevel@tonic-gate 			}
15860Sstevel@tonic-gate 			spi_decr_tmpl = ctx_decr_tmpl->ct_prov_tmpl;
15870Sstevel@tonic-gate 		}
15880Sstevel@tonic-gate 		decr_tmpl_checked = B_TRUE;
15890Sstevel@tonic-gate 	}
15900Sstevel@tonic-gate 
15910Sstevel@tonic-gate 	if (prov_mac_mechid == CRYPTO_MECH_INVALID) {
15920Sstevel@tonic-gate 		/* Need to emulate with 2 internal calls */
15930Sstevel@tonic-gate 
15940Sstevel@tonic-gate 		/*
15950Sstevel@tonic-gate 		 * We avoid code complexity by limiting the pure async.
15960Sstevel@tonic-gate 		 * case to be done using only a SW provider.
15970Sstevel@tonic-gate 		 * XXX - Redo the emulation code below so that we can
15980Sstevel@tonic-gate 		 * remove this limitation.
15990Sstevel@tonic-gate 		 */
16000Sstevel@tonic-gate 		if (cr != NULL && pd->pd_prov_type == CRYPTO_HW_PROVIDER) {
16010Sstevel@tonic-gate 			if ((kcf_insert_triedlist(&list, pd, KCF_KMFLAG(cr))
16020Sstevel@tonic-gate 			    != NULL))
16030Sstevel@tonic-gate 				goto retry;
16040Sstevel@tonic-gate 			if (list != NULL)
16050Sstevel@tonic-gate 				kcf_free_triedlist(list);
16060Sstevel@tonic-gate 			if (decr_kcf_context != NULL)
16070Sstevel@tonic-gate 				KCF_CONTEXT_REFRELE(decr_kcf_context);
16080Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
16090Sstevel@tonic-gate 			return (CRYPTO_HOST_MEMORY);
16100Sstevel@tonic-gate 		}
16110Sstevel@tonic-gate 
16120Sstevel@tonic-gate 		if (ctx == NULL && pd->pd_prov_type == CRYPTO_SW_PROVIDER) {
16130Sstevel@tonic-gate 			ctx = kcf_new_ctx(cr, pd, pd->pd_sid);
16140Sstevel@tonic-gate 			if (ctx == NULL) {
16150Sstevel@tonic-gate 				if (list != NULL)
16160Sstevel@tonic-gate 					kcf_free_triedlist(list);
16170Sstevel@tonic-gate 				if (decr_kcf_context != NULL)
16180Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(decr_kcf_context);
16190Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
16200Sstevel@tonic-gate 				return (CRYPTO_HOST_MEMORY);
16210Sstevel@tonic-gate 			}
16220Sstevel@tonic-gate 			decr_kcf_context = (kcf_context_t *)
16230Sstevel@tonic-gate 			    ctx->cc_framework_private;
16240Sstevel@tonic-gate 		}
16250Sstevel@tonic-gate 		/*
16260Sstevel@tonic-gate 		 * Trade-off speed vs avoidance of code complexity and
16270Sstevel@tonic-gate 		 * duplication:
16280Sstevel@tonic-gate 		 * Could do all the combinations of fastpath / synch / asynch
16290Sstevel@tonic-gate 		 * for the decryption and the mac steps. Early attempts
16300Sstevel@tonic-gate 		 * showed the code grew wild and bug-prone, for little gain.
16310Sstevel@tonic-gate 		 * Therefore, the adaptative asynch case is not implemented.
16320Sstevel@tonic-gate 		 * It's either pure synchronous, or pure asynchronous.
16330Sstevel@tonic-gate 		 * We still preserve a fastpath for the pure synchronous
16340Sstevel@tonic-gate 		 * requests to SW providers.
16350Sstevel@tonic-gate 		 */
16360Sstevel@tonic-gate 		if (cr == NULL) {
16370Sstevel@tonic-gate 			crypto_context_t mac_context;
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate 			error = crypto_mac_init(mac_mech, mac_key, mac_tmpl,
16400Sstevel@tonic-gate 			    &mac_context, NULL);
16410Sstevel@tonic-gate 
16420Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS) {
16430Sstevel@tonic-gate 				/* Can't be CRYPTO_QUEUED. return the failure */
16440Sstevel@tonic-gate 				if (list != NULL)
16450Sstevel@tonic-gate 					kcf_free_triedlist(list);
16460Sstevel@tonic-gate 
16470Sstevel@tonic-gate 				if (decr_kcf_context != NULL)
16480Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(decr_kcf_context);
16490Sstevel@tonic-gate 				return (error);
16500Sstevel@tonic-gate 			}
16510Sstevel@tonic-gate 			if (pd->pd_prov_type == CRYPTO_SW_PROVIDER) {
16520Sstevel@tonic-gate 				crypto_mechanism_t lmech = *decr_mech;
16530Sstevel@tonic-gate 
16540Sstevel@tonic-gate 				lmech.cm_type = prov_decr_mechid;
16550Sstevel@tonic-gate 
16560Sstevel@tonic-gate 				error = KCF_PROV_DECRYPT_INIT(pd, ctx, &lmech,
16570Sstevel@tonic-gate 				    decr_key, spi_decr_tmpl,
16580Sstevel@tonic-gate 				    KCF_RHNDL(KM_SLEEP));
16590Sstevel@tonic-gate 			} else {
16600Sstevel@tonic-gate 				/*
16610Sstevel@tonic-gate 				 * If we did the 'goto retry' then ctx may not
16620Sstevel@tonic-gate 				 * be NULL.  In general, we can't reuse another
16630Sstevel@tonic-gate 				 * provider's context, so we free it now so
16640Sstevel@tonic-gate 				 * we don't leak it.
16650Sstevel@tonic-gate 				 */
16660Sstevel@tonic-gate 				if (ctx != NULL) {
16670Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE((kcf_context_t *)
16680Sstevel@tonic-gate 					    ctx->cc_framework_private);
16690Sstevel@tonic-gate 					decr_kcf_context = NULL;
16700Sstevel@tonic-gate 				}
16710Sstevel@tonic-gate 				error = crypto_decrypt_init_prov(pd, pd->pd_sid,
16720Sstevel@tonic-gate 				    decr_mech, decr_key, &decr_tmpl,
16730Sstevel@tonic-gate 				    (crypto_context_t *)&ctx, NULL);
16740Sstevel@tonic-gate 
16750Sstevel@tonic-gate 				if (error == CRYPTO_SUCCESS) {
16760Sstevel@tonic-gate 					decr_kcf_context = (kcf_context_t *)
16770Sstevel@tonic-gate 					    ctx->cc_framework_private;
16780Sstevel@tonic-gate 				}
16790Sstevel@tonic-gate 			}
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate 			KCF_PROV_INCRSTATS(pd, error);
16820Sstevel@tonic-gate 
16830Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
16840Sstevel@tonic-gate 
16850Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS) {
16860Sstevel@tonic-gate 				/* Can't be CRYPTO_QUEUED. return the failure */
16870Sstevel@tonic-gate 				if (list != NULL)
16880Sstevel@tonic-gate 					kcf_free_triedlist(list);
16890Sstevel@tonic-gate 				if (mac_kcf_context != NULL)
16900Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(mac_kcf_context);
16910Sstevel@tonic-gate 
16920Sstevel@tonic-gate 				return (error);
16930Sstevel@tonic-gate 			}
16940Sstevel@tonic-gate 			mac_kcf_context = (kcf_context_t *)
16950Sstevel@tonic-gate 			    ((crypto_ctx_t *)mac_context)->
16960Sstevel@tonic-gate 			    cc_framework_private;
16970Sstevel@tonic-gate 
16980Sstevel@tonic-gate 			decr_kcf_context = (kcf_context_t *)
16990Sstevel@tonic-gate 			    ctx->cc_framework_private;
17000Sstevel@tonic-gate 
17010Sstevel@tonic-gate 			/*
17020Sstevel@tonic-gate 			 * Here also, the mac context is second. The callback
17030Sstevel@tonic-gate 			 * case can't overwrite the context returned to
17040Sstevel@tonic-gate 			 * the caller.
17050Sstevel@tonic-gate 			 */
17060Sstevel@tonic-gate 			decr_kcf_context->kc_secondctx = mac_kcf_context;
17070Sstevel@tonic-gate 			KCF_CONTEXT_REFHOLD(mac_kcf_context);
17080Sstevel@tonic-gate 
17090Sstevel@tonic-gate 			*ctxp = (crypto_context_t)ctx;
17100Sstevel@tonic-gate 
17110Sstevel@tonic-gate 			return (error);
17120Sstevel@tonic-gate 		}
17130Sstevel@tonic-gate 		/* submit a pure asynchronous request. */
17140Sstevel@tonic-gate 		save_flag = cr->cr_flag;
17150Sstevel@tonic-gate 		cr->cr_flag |= CRYPTO_ALWAYS_QUEUE;
17160Sstevel@tonic-gate 
17170Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_INIT,
17180Sstevel@tonic-gate 		    pd->pd_sid, mac_key, decr_key, NULL, NULL, NULL,
17190Sstevel@tonic-gate 		    spi_mac_tmpl, spi_decr_tmpl);
17200Sstevel@tonic-gate 
17210Sstevel@tonic-gate 		mdops = &(params.rp_u.mac_decrypt_params);
17220Sstevel@tonic-gate 
17230Sstevel@tonic-gate 		/* careful! structs assignments */
17240Sstevel@tonic-gate 		mdops->md_decr_mech = *decr_mech;
17250Sstevel@tonic-gate 		/*
17260Sstevel@tonic-gate 		 * mdops->md_decr_mech.cm_type will be set when we get to
17270Sstevel@tonic-gate 		 * kcf_emulate_dual() routine.
17280Sstevel@tonic-gate 		 */
17290Sstevel@tonic-gate 		mdops->md_framework_decr_mechtype = decr_mech->cm_type;
17300Sstevel@tonic-gate 		mdops->md_mac_mech = *mac_mech;
17310Sstevel@tonic-gate 
17320Sstevel@tonic-gate 		/*
17330Sstevel@tonic-gate 		 * mdops->md_mac_mech.cm_type will be set when we know the
17340Sstevel@tonic-gate 		 * MAC provider.
17350Sstevel@tonic-gate 		 */
17360Sstevel@tonic-gate 		mdops->md_framework_mac_mechtype = mac_mech->cm_type;
17370Sstevel@tonic-gate 
17380Sstevel@tonic-gate 		/*
17390Sstevel@tonic-gate 		 * non-NULL ctx->kc_secondctx tells common_submit_request
17400Sstevel@tonic-gate 		 * that this request uses separate cipher and MAC contexts.
17410Sstevel@tonic-gate 		 * That function will set the MAC context's kc_secondctx to
17420Sstevel@tonic-gate 		 * this decrypt context.
17430Sstevel@tonic-gate 		 */
17440Sstevel@tonic-gate 		decr_kcf_context->kc_secondctx = decr_kcf_context;
17450Sstevel@tonic-gate 
17460Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
17470Sstevel@tonic-gate 
17480Sstevel@tonic-gate 		cr->cr_flag = save_flag;
17490Sstevel@tonic-gate 
17500Sstevel@tonic-gate 		if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED) {
17510Sstevel@tonic-gate 			KCF_CONTEXT_REFRELE(decr_kcf_context);
17520Sstevel@tonic-gate 		}
17530Sstevel@tonic-gate 		if (list != NULL)
17540Sstevel@tonic-gate 			kcf_free_triedlist(list);
17550Sstevel@tonic-gate 		*ctxp =  ctx;
17560Sstevel@tonic-gate 		KCF_PROV_REFRELE(pd);
17570Sstevel@tonic-gate 		return (error);
17580Sstevel@tonic-gate 	}
17590Sstevel@tonic-gate 
17600Sstevel@tonic-gate 	if ((!mac_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
17610Sstevel@tonic-gate 		if ((mac_tmpl != NULL) &&
17620Sstevel@tonic-gate 		    (prov_mac_mechid != CRYPTO_MECH_INVALID)) {
17630Sstevel@tonic-gate 			ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
17640Sstevel@tonic-gate 			if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
17650Sstevel@tonic-gate 
17660Sstevel@tonic-gate 				if (list != NULL)
17670Sstevel@tonic-gate 					kcf_free_triedlist(list);
17680Sstevel@tonic-gate 
17690Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
17700Sstevel@tonic-gate 				/* Which one is the the old one ? */
17710Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
17720Sstevel@tonic-gate 			}
17730Sstevel@tonic-gate 			spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
17740Sstevel@tonic-gate 		}
17750Sstevel@tonic-gate 		mac_tmpl_checked = B_TRUE;
17760Sstevel@tonic-gate 	}
17770Sstevel@tonic-gate 
17780Sstevel@tonic-gate 	if (ctx == NULL) {
17790Sstevel@tonic-gate 		ctx = kcf_new_ctx(cr, pd, pd->pd_sid);
17800Sstevel@tonic-gate 		if (ctx == NULL) {
17810Sstevel@tonic-gate 			error = CRYPTO_HOST_MEMORY;
17820Sstevel@tonic-gate 			if (list != NULL)
17830Sstevel@tonic-gate 				kcf_free_triedlist(list);
17840Sstevel@tonic-gate 			return (CRYPTO_HOST_MEMORY);
17850Sstevel@tonic-gate 		}
17860Sstevel@tonic-gate 		decr_kcf_context = (kcf_context_t *)ctx->cc_framework_private;
17870Sstevel@tonic-gate 	}
17880Sstevel@tonic-gate 
17890Sstevel@tonic-gate 	/* The fast path for SW providers. */
17900Sstevel@tonic-gate 	if (CHECK_FASTPATH(cr, pd)) {
17910Sstevel@tonic-gate 		crypto_mechanism_t ldecr_mech;
17920Sstevel@tonic-gate 		crypto_mechanism_t lmac_mech;
17930Sstevel@tonic-gate 
17940Sstevel@tonic-gate 		/* careful! structs assignments */
17950Sstevel@tonic-gate 		ldecr_mech = *decr_mech;
17960Sstevel@tonic-gate 		ldecr_mech.cm_type = prov_decr_mechid;
17970Sstevel@tonic-gate 		lmac_mech = *mac_mech;
17980Sstevel@tonic-gate 		lmac_mech.cm_type = prov_mac_mechid;
17990Sstevel@tonic-gate 
18000Sstevel@tonic-gate 		error = KCF_PROV_MAC_DECRYPT_INIT(pd, ctx, &lmac_mech,
18010Sstevel@tonic-gate 		    mac_key, &ldecr_mech, decr_key, spi_mac_tmpl, spi_decr_tmpl,
18020Sstevel@tonic-gate 		    KCF_SWFP_RHNDL(cr));
18030Sstevel@tonic-gate 
18040Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
18050Sstevel@tonic-gate 	} else {
18060Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_INIT,
18070Sstevel@tonic-gate 		    pd->pd_sid, mac_key, decr_key, NULL, NULL, NULL,
18080Sstevel@tonic-gate 		    spi_mac_tmpl, spi_decr_tmpl);
18090Sstevel@tonic-gate 
18100Sstevel@tonic-gate 		mdops = &(params.rp_u.mac_decrypt_params);
18110Sstevel@tonic-gate 
18120Sstevel@tonic-gate 		/* careful! structs assignments */
18130Sstevel@tonic-gate 		mdops->md_decr_mech = *decr_mech;
18140Sstevel@tonic-gate 		mdops->md_decr_mech.cm_type = prov_decr_mechid;
18150Sstevel@tonic-gate 		mdops->md_framework_decr_mechtype = decr_mech->cm_type;
18160Sstevel@tonic-gate 		mdops->md_mac_mech = *mac_mech;
18170Sstevel@tonic-gate 		mdops->md_mac_mech.cm_type = prov_mac_mechid;
18180Sstevel@tonic-gate 		mdops->md_framework_mac_mechtype = mac_mech->cm_type;
18190Sstevel@tonic-gate 
18200Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
18210Sstevel@tonic-gate 	}
18220Sstevel@tonic-gate 
18230Sstevel@tonic-gate 	if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED) {
18240Sstevel@tonic-gate 		if ((IS_RECOVERABLE(error)) &&
18250Sstevel@tonic-gate 		    (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(cr)) != NULL))
18260Sstevel@tonic-gate 			goto retry;
18270Sstevel@tonic-gate 
18280Sstevel@tonic-gate 		KCF_CONTEXT_REFRELE(decr_kcf_context);
18290Sstevel@tonic-gate 	} else
18300Sstevel@tonic-gate 		*ctxp = (crypto_context_t)ctx;
18310Sstevel@tonic-gate 
18320Sstevel@tonic-gate 	if (list != NULL)
18330Sstevel@tonic-gate 		kcf_free_triedlist(list);
18340Sstevel@tonic-gate 
18350Sstevel@tonic-gate 	KCF_PROV_REFRELE(pd);
18360Sstevel@tonic-gate 	return (error);
18370Sstevel@tonic-gate }
18380Sstevel@tonic-gate 
1839904Smcpowers int
1840904Smcpowers crypto_mac_decrypt_init_prov(crypto_provider_t provider,
1841904Smcpowers     crypto_session_id_t sid, crypto_mechanism_t *mac_mech,
1842904Smcpowers     crypto_mechanism_t *decr_mech, crypto_key_t *mac_key,
1843904Smcpowers     crypto_key_t *decr_key, crypto_ctx_template_t mac_tmpl,
1844904Smcpowers     crypto_ctx_template_t decr_tmpl, crypto_context_t *ctxp,
1845904Smcpowers     crypto_call_req_t *cr)
1846904Smcpowers {
1847904Smcpowers 	/*
1848904Smcpowers 	 * First try to find a provider for the decryption mechanism, that
1849904Smcpowers 	 * is also capable of the MAC mechanism.
1850904Smcpowers 	 * We still favor optimizing the costlier decryption.
1851904Smcpowers 	 */
1852904Smcpowers 	int rv;
1853904Smcpowers 	kcf_mech_entry_t *me;
1854904Smcpowers 	kcf_provider_desc_t *pd = provider;
1855904Smcpowers 	kcf_provider_desc_t *real_provider = pd;
1856904Smcpowers 	kcf_ctx_template_t *ctx_decr_tmpl, *ctx_mac_tmpl;
1857904Smcpowers 	kcf_req_params_t params;
1858904Smcpowers 	kcf_mac_decrypt_ops_params_t *mdops;
1859904Smcpowers 	crypto_spi_ctx_template_t spi_decr_tmpl = NULL, spi_mac_tmpl = NULL;
1860904Smcpowers 	crypto_ctx_t *ctx;
1861904Smcpowers 	kcf_context_t *decr_kcf_context = NULL;
1862904Smcpowers 
1863904Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
1864904Smcpowers 
1865904Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
1866*10444SVladimir.Kotal@Sun.COM 		rv = kcf_get_hardware_provider(decr_mech->cm_type, decr_key,
1867*10444SVladimir.Kotal@Sun.COM 		    mac_mech->cm_type, mac_key, CHECK_RESTRICT(cr), pd,
1868*10444SVladimir.Kotal@Sun.COM 		    &real_provider, CRYPTO_FG_MAC_DECRYPT);
1869904Smcpowers 
1870904Smcpowers 		if (rv != CRYPTO_SUCCESS)
1871904Smcpowers 			return (rv);
1872904Smcpowers 	}
1873904Smcpowers 
1874904Smcpowers 	/*
1875904Smcpowers 	 * For SW providers, check the validity of the context template
1876904Smcpowers 	 * It is very rare that the generation number mis-matches, so
1877904Smcpowers 	 * is acceptable to fail here, and let the consumer recover by
1878904Smcpowers 	 * freeing this tmpl and create a new one for the key and new SW
1879904Smcpowers 	 * provider
1880904Smcpowers 	 * Warning! will need to change when multiple software providers
1881904Smcpowers 	 * per mechanism are supported.
1882904Smcpowers 	 */
1883904Smcpowers 
1884904Smcpowers 	if (real_provider->pd_prov_type == CRYPTO_SW_PROVIDER) {
1885904Smcpowers 		if (decr_tmpl != NULL) {
1886904Smcpowers 			if (kcf_get_mech_entry(decr_mech->cm_type, &me) !=
1887904Smcpowers 			    KCF_SUCCESS) {
1888904Smcpowers 				rv = CRYPTO_MECHANISM_INVALID;
1889904Smcpowers 				goto out;
1890904Smcpowers 			}
1891904Smcpowers 			ctx_decr_tmpl = (kcf_ctx_template_t *)decr_tmpl;
1892904Smcpowers 			if (ctx_decr_tmpl->ct_generation != me->me_gen_swprov) {
1893904Smcpowers 				rv = CRYPTO_OLD_CTX_TEMPLATE;
1894904Smcpowers 				goto out;
1895904Smcpowers 			}
1896904Smcpowers 			spi_decr_tmpl = ctx_decr_tmpl->ct_prov_tmpl;
1897904Smcpowers 		}
1898904Smcpowers 
1899904Smcpowers 		if (mac_tmpl != NULL) {
1900904Smcpowers 			if (kcf_get_mech_entry(mac_mech->cm_type, &me) !=
1901904Smcpowers 			    KCF_SUCCESS) {
1902904Smcpowers 				rv = CRYPTO_MECHANISM_INVALID;
1903904Smcpowers 				goto out;
1904904Smcpowers 			}
1905904Smcpowers 			ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
1906904Smcpowers 			if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
1907904Smcpowers 				rv = CRYPTO_OLD_CTX_TEMPLATE;
1908904Smcpowers 				goto out;
1909904Smcpowers 			}
1910904Smcpowers 			spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
1911904Smcpowers 		}
1912904Smcpowers 	}
1913904Smcpowers 
1914904Smcpowers 	ctx = kcf_new_ctx(cr, real_provider, sid);
1915904Smcpowers 	if (ctx == NULL) {
1916904Smcpowers 		rv = CRYPTO_HOST_MEMORY;
1917904Smcpowers 		goto out;
1918904Smcpowers 	}
1919904Smcpowers 	decr_kcf_context = (kcf_context_t *)ctx->cc_framework_private;
1920904Smcpowers 
1921904Smcpowers 	/* The fast path for SW providers. */
1922904Smcpowers 	if (CHECK_FASTPATH(cr, pd)) {
1923904Smcpowers 		crypto_mechanism_t ldecr_mech;
1924904Smcpowers 		crypto_mechanism_t lmac_mech;
1925904Smcpowers 
1926904Smcpowers 		/* careful! structs assignments */
1927904Smcpowers 		ldecr_mech = *decr_mech;
1928904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(decr_mech->cm_type, real_provider,
1929904Smcpowers 		    &ldecr_mech);
1930904Smcpowers 
1931904Smcpowers 		lmac_mech = *mac_mech;
1932904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
1933904Smcpowers 		    &lmac_mech);
1934904Smcpowers 
1935904Smcpowers 		rv = KCF_PROV_MAC_DECRYPT_INIT(real_provider, ctx, &lmac_mech,
1936904Smcpowers 		    mac_key, &ldecr_mech, decr_key, spi_mac_tmpl, spi_decr_tmpl,
1937904Smcpowers 		    KCF_SWFP_RHNDL(cr));
1938904Smcpowers 
1939904Smcpowers 		KCF_PROV_INCRSTATS(pd, rv);
1940904Smcpowers 	} else {
1941904Smcpowers 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_INIT,
1942904Smcpowers 		    sid, mac_key, decr_key, NULL, NULL, NULL,
1943904Smcpowers 		    spi_mac_tmpl, spi_decr_tmpl);
1944904Smcpowers 
1945904Smcpowers 		mdops = &(params.rp_u.mac_decrypt_params);
1946904Smcpowers 
1947904Smcpowers 		/* careful! structs assignments */
1948904Smcpowers 		mdops->md_decr_mech = *decr_mech;
1949904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(decr_mech->cm_type, real_provider,
1950904Smcpowers 		    &mdops->md_decr_mech);
1951904Smcpowers 		mdops->md_framework_decr_mechtype = decr_mech->cm_type;
1952904Smcpowers 
1953904Smcpowers 		mdops->md_mac_mech = *mac_mech;
1954904Smcpowers 		KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
1955904Smcpowers 		    &mdops->md_mac_mech);
1956904Smcpowers 		mdops->md_framework_mac_mechtype = mac_mech->cm_type;
1957904Smcpowers 
1958904Smcpowers 		rv = kcf_submit_request(real_provider, ctx, cr, &params,
1959904Smcpowers 		    B_FALSE);
1960904Smcpowers 	}
1961904Smcpowers 
1962904Smcpowers 	if (rv != CRYPTO_SUCCESS && rv != CRYPTO_QUEUED) {
1963904Smcpowers 		KCF_CONTEXT_REFRELE(decr_kcf_context);
1964904Smcpowers 	} else
1965904Smcpowers 		*ctxp = (crypto_context_t)ctx;
1966904Smcpowers 
1967904Smcpowers out:
1968904Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
1969904Smcpowers 		KCF_PROV_REFRELE(real_provider);
1970904Smcpowers 	return (rv);
1971904Smcpowers }
19720Sstevel@tonic-gate /*
19730Sstevel@tonic-gate  * Continues a multi-part dual mac/decrypt operation.
19740Sstevel@tonic-gate  */
19750Sstevel@tonic-gate /* ARGSUSED */
19760Sstevel@tonic-gate int
19770Sstevel@tonic-gate crypto_mac_decrypt_update(crypto_context_t context,
19780Sstevel@tonic-gate     crypto_dual_data_t *ct, crypto_data_t *pt, crypto_call_req_t *cr)
19790Sstevel@tonic-gate {
19800Sstevel@tonic-gate 	crypto_ctx_t *ctx = (crypto_ctx_t *)context, *mac_ctx;
19810Sstevel@tonic-gate 	kcf_context_t *kcf_ctx, *kcf_mac_ctx;
19820Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
19830Sstevel@tonic-gate 	int error;
19840Sstevel@tonic-gate 	kcf_req_params_t params;
19850Sstevel@tonic-gate 
19860Sstevel@tonic-gate 	if ((ctx == NULL) ||
19870Sstevel@tonic-gate 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
19880Sstevel@tonic-gate 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
19890Sstevel@tonic-gate 		return (CRYPTO_INVALID_CONTEXT);
19900Sstevel@tonic-gate 	}
19910Sstevel@tonic-gate 
1992904Smcpowers 	ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
19930Sstevel@tonic-gate 
19940Sstevel@tonic-gate 	if ((kcf_mac_ctx = kcf_ctx->kc_secondctx) != NULL) {
19950Sstevel@tonic-gate 		off_t save_offset;
19960Sstevel@tonic-gate 		size_t save_len;
19970Sstevel@tonic-gate 		crypto_call_flag_t save_flag;
19980Sstevel@tonic-gate 
19990Sstevel@tonic-gate 		if (kcf_mac_ctx->kc_prov_desc == NULL) {
20000Sstevel@tonic-gate 			error = CRYPTO_INVALID_CONTEXT;
20010Sstevel@tonic-gate 			goto out;
20020Sstevel@tonic-gate 		}
20030Sstevel@tonic-gate 		mac_ctx = &kcf_mac_ctx->kc_glbl_ctx;
20040Sstevel@tonic-gate 
20050Sstevel@tonic-gate 		/* First we submit the MAC request */
20060Sstevel@tonic-gate 		if (cr == NULL) {
20070Sstevel@tonic-gate 			/*
20080Sstevel@tonic-gate 			 * 'ct' is always not NULL.
20090Sstevel@tonic-gate 			 */
20100Sstevel@tonic-gate 			error = crypto_mac_update((crypto_context_t)mac_ctx,
20110Sstevel@tonic-gate 			    (crypto_data_t *)ct, NULL);
20120Sstevel@tonic-gate 
20130Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS)
20140Sstevel@tonic-gate 				goto out;
20150Sstevel@tonic-gate 
20160Sstevel@tonic-gate 			/* Decrypt a different length only when told so */
20170Sstevel@tonic-gate 
20180Sstevel@tonic-gate 			save_offset = ct->dd_offset1;
20190Sstevel@tonic-gate 			save_len = ct->dd_len1;
20200Sstevel@tonic-gate 
20210Sstevel@tonic-gate 			if (ct->dd_len2 > 0) {
20220Sstevel@tonic-gate 				ct->dd_offset1 = ct->dd_offset2;
20230Sstevel@tonic-gate 				ct->dd_len1 = ct->dd_len2;
20240Sstevel@tonic-gate 			}
20250Sstevel@tonic-gate 
20260Sstevel@tonic-gate 			error = crypto_decrypt_update(context,
20270Sstevel@tonic-gate 			    (crypto_data_t *)ct, pt, NULL);
20280Sstevel@tonic-gate 
20290Sstevel@tonic-gate 			ct->dd_offset1 = save_offset;
20300Sstevel@tonic-gate 			ct->dd_len1 = save_len;
20310Sstevel@tonic-gate 
20320Sstevel@tonic-gate 			goto out;
20330Sstevel@tonic-gate 		}
20340Sstevel@tonic-gate 		/* submit a pure asynchronous request. */
20350Sstevel@tonic-gate 		save_flag = cr->cr_flag;
20360Sstevel@tonic-gate 		cr->cr_flag |= CRYPTO_ALWAYS_QUEUE;
20370Sstevel@tonic-gate 
20380Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE,
20390Sstevel@tonic-gate 		    pd->pd_sid, NULL, NULL, ct, NULL, pt, NULL, NULL)
20400Sstevel@tonic-gate 
20410Sstevel@tonic-gate 
20420Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
20430Sstevel@tonic-gate 
20440Sstevel@tonic-gate 		cr->cr_flag = save_flag;
20450Sstevel@tonic-gate 		goto out;
20460Sstevel@tonic-gate 	}
20470Sstevel@tonic-gate 
20480Sstevel@tonic-gate 	/* The fast path for SW providers. */
20490Sstevel@tonic-gate 	if (CHECK_FASTPATH(cr, pd)) {
20500Sstevel@tonic-gate 		error = KCF_PROV_MAC_DECRYPT_UPDATE(pd, ctx, ct, pt, NULL);
20510Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
20520Sstevel@tonic-gate 	} else {
20530Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE,
2054904Smcpowers 		    ctx->cc_session, NULL, NULL, ct, NULL, pt, NULL, NULL);
20550Sstevel@tonic-gate 
20560Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
20570Sstevel@tonic-gate 	}
20580Sstevel@tonic-gate out:
20590Sstevel@tonic-gate 	return (error);
20600Sstevel@tonic-gate }
20610Sstevel@tonic-gate 
20620Sstevel@tonic-gate /*
20630Sstevel@tonic-gate  * Terminates a multi-part dual mac/decrypt operation.
20640Sstevel@tonic-gate  */
20650Sstevel@tonic-gate /* ARGSUSED */
20660Sstevel@tonic-gate int
20670Sstevel@tonic-gate crypto_mac_decrypt_final(crypto_context_t context, crypto_data_t *mac,
20680Sstevel@tonic-gate     crypto_data_t *pt, crypto_call_req_t *cr)
20690Sstevel@tonic-gate {
20700Sstevel@tonic-gate 	crypto_ctx_t *ctx = (crypto_ctx_t *)context, *mac_ctx;
20710Sstevel@tonic-gate 	kcf_context_t *kcf_ctx, *kcf_mac_ctx;
20720Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
20730Sstevel@tonic-gate 	int error;
20740Sstevel@tonic-gate 	kcf_req_params_t params;
20750Sstevel@tonic-gate 
20760Sstevel@tonic-gate 	if ((ctx == NULL) ||
20770Sstevel@tonic-gate 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
20780Sstevel@tonic-gate 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
20790Sstevel@tonic-gate 		return (CRYPTO_INVALID_CONTEXT);
20800Sstevel@tonic-gate 	}
20810Sstevel@tonic-gate 
2082904Smcpowers 	ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
20830Sstevel@tonic-gate 
20840Sstevel@tonic-gate 	if ((kcf_mac_ctx = kcf_ctx->kc_secondctx) != NULL) {
20850Sstevel@tonic-gate 		crypto_call_flag_t save_flag;
20860Sstevel@tonic-gate 
20870Sstevel@tonic-gate 		if (kcf_mac_ctx->kc_prov_desc == NULL) {
20880Sstevel@tonic-gate 			error = CRYPTO_INVALID_CONTEXT;
20890Sstevel@tonic-gate 			goto out;
20900Sstevel@tonic-gate 		}
20910Sstevel@tonic-gate 		mac_ctx = &kcf_mac_ctx->kc_glbl_ctx;
20920Sstevel@tonic-gate 
20930Sstevel@tonic-gate 		/* First we collect the MAC */
20940Sstevel@tonic-gate 		if (cr == NULL) {
20950Sstevel@tonic-gate 
20960Sstevel@tonic-gate 			error = crypto_mac_final((crypto_context_t)mac_ctx,
20970Sstevel@tonic-gate 			    mac, NULL);
20980Sstevel@tonic-gate 
20990Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS) {
21000Sstevel@tonic-gate 				crypto_cancel_ctx(ctx);
21010Sstevel@tonic-gate 			} else {
21020Sstevel@tonic-gate 				/* Get the last chunk of plaintext */
21030Sstevel@tonic-gate 				error = crypto_decrypt_final(context, pt, NULL);
21040Sstevel@tonic-gate 			}
21050Sstevel@tonic-gate 
21060Sstevel@tonic-gate 			return (error);
21070Sstevel@tonic-gate 		}
21080Sstevel@tonic-gate 		/* submit a pure asynchronous request. */
21090Sstevel@tonic-gate 		save_flag = cr->cr_flag;
21100Sstevel@tonic-gate 		cr->cr_flag |= CRYPTO_ALWAYS_QUEUE;
21110Sstevel@tonic-gate 
21120Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_FINAL,
21130Sstevel@tonic-gate 		    pd->pd_sid, NULL, NULL, NULL, mac, pt, NULL, NULL)
21140Sstevel@tonic-gate 
21150Sstevel@tonic-gate 
21160Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
21170Sstevel@tonic-gate 
21180Sstevel@tonic-gate 		cr->cr_flag = save_flag;
21190Sstevel@tonic-gate 
21200Sstevel@tonic-gate 		return (error);
21210Sstevel@tonic-gate 	}
21220Sstevel@tonic-gate 
21230Sstevel@tonic-gate 	/* The fast path for SW providers. */
21240Sstevel@tonic-gate 	if (CHECK_FASTPATH(cr, pd)) {
21250Sstevel@tonic-gate 		error = KCF_PROV_MAC_DECRYPT_FINAL(pd, ctx, mac, pt, NULL);
21260Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
21270Sstevel@tonic-gate 	} else {
21280Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_FINAL,
2129904Smcpowers 		    ctx->cc_session, NULL, NULL, NULL, mac, pt, NULL, NULL);
21300Sstevel@tonic-gate 
21310Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
21320Sstevel@tonic-gate 	}
21330Sstevel@tonic-gate out:
21340Sstevel@tonic-gate 	/* Release the hold done in kcf_new_ctx() during init step. */
21350Sstevel@tonic-gate 	KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
21360Sstevel@tonic-gate 	return (error);
21370Sstevel@tonic-gate }
21380Sstevel@tonic-gate 
21390Sstevel@tonic-gate /*
21400Sstevel@tonic-gate  * Digest/Encrypt dual operation. Project-private entry point, not part of
21410Sstevel@tonic-gate  * the k-API.
21420Sstevel@tonic-gate  */
21430Sstevel@tonic-gate /* ARGSUSED */
21440Sstevel@tonic-gate int
21450Sstevel@tonic-gate crypto_digest_encrypt_update(crypto_context_t digest_ctx,
21460Sstevel@tonic-gate     crypto_context_t encrypt_ctx, crypto_data_t *plaintext,
21470Sstevel@tonic-gate     crypto_data_t *ciphertext, crypto_call_req_t *crq)
21480Sstevel@tonic-gate {
21490Sstevel@tonic-gate 	/*
21500Sstevel@tonic-gate 	 * RFE 4688647:
21510Sstevel@tonic-gate 	 * core functions needed by ioctl interface missing from impl.h
21520Sstevel@tonic-gate 	 */
21530Sstevel@tonic-gate 	return (CRYPTO_NOT_SUPPORTED);
21540Sstevel@tonic-gate }
21550Sstevel@tonic-gate 
21560Sstevel@tonic-gate /*
21570Sstevel@tonic-gate  * Decrypt/Digest dual operation. Project-private entry point, not part of
21580Sstevel@tonic-gate  * the k-API.
21590Sstevel@tonic-gate  */
21600Sstevel@tonic-gate /* ARGSUSED */
21610Sstevel@tonic-gate int
21620Sstevel@tonic-gate crypto_decrypt_digest_update(crypto_context_t decryptctx,
21630Sstevel@tonic-gate     crypto_context_t encrypt_ctx, crypto_data_t *ciphertext,
21640Sstevel@tonic-gate     crypto_data_t *plaintext, crypto_call_req_t *crq)
21650Sstevel@tonic-gate {
21660Sstevel@tonic-gate 	/*
21670Sstevel@tonic-gate 	 * RFE 4688647:
21680Sstevel@tonic-gate 	 * core functions needed by ioctl interface missing from impl.h
21690Sstevel@tonic-gate 	 */
21700Sstevel@tonic-gate 	return (CRYPTO_NOT_SUPPORTED);
21710Sstevel@tonic-gate }
21720Sstevel@tonic-gate 
21730Sstevel@tonic-gate /*
21740Sstevel@tonic-gate  * Sign/Encrypt dual operation. Project-private entry point, not part of
21750Sstevel@tonic-gate  * the k-API.
21760Sstevel@tonic-gate  */
21770Sstevel@tonic-gate /* ARGSUSED */
21780Sstevel@tonic-gate int
21790Sstevel@tonic-gate crypto_sign_encrypt_update(crypto_context_t sign_ctx,
21800Sstevel@tonic-gate     crypto_context_t encrypt_ctx, crypto_data_t *plaintext,
21810Sstevel@tonic-gate     crypto_data_t *ciphertext, crypto_call_req_t *crq)
21820Sstevel@tonic-gate {
21830Sstevel@tonic-gate 	/*
21840Sstevel@tonic-gate 	 * RFE 4688647:
21850Sstevel@tonic-gate 	 * core functions needed by ioctl interface missing from impl.h
21860Sstevel@tonic-gate 	 */
21870Sstevel@tonic-gate 	return (CRYPTO_NOT_SUPPORTED);
21880Sstevel@tonic-gate }
21890Sstevel@tonic-gate 
21900Sstevel@tonic-gate /*
21910Sstevel@tonic-gate  * Decrypt/Verify dual operation. Project-private entry point, not part of
21920Sstevel@tonic-gate  * the k-API.
21930Sstevel@tonic-gate  */
21940Sstevel@tonic-gate /* ARGSUSED */
21950Sstevel@tonic-gate int
21960Sstevel@tonic-gate crypto_decrypt_verify_update(crypto_context_t decrypt_ctx,
21970Sstevel@tonic-gate     crypto_context_t verify_ctx, crypto_data_t *ciphertext,
21980Sstevel@tonic-gate     crypto_data_t *plaintext, crypto_call_req_t *crq)
21990Sstevel@tonic-gate {
22000Sstevel@tonic-gate 	/*
22010Sstevel@tonic-gate 	 * RFE 4688647:
22020Sstevel@tonic-gate 	 * core functions needed by ioctl interface missing from impl.h
22030Sstevel@tonic-gate 	 */
22040Sstevel@tonic-gate 	return (CRYPTO_NOT_SUPPORTED);
22050Sstevel@tonic-gate }
2206