xref: /onnv-gate/usr/src/uts/common/crypto/api/kcf_dual.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/errno.h>
30*0Sstevel@tonic-gate #include <sys/types.h>
31*0Sstevel@tonic-gate #include <sys/kmem.h>
32*0Sstevel@tonic-gate #include <sys/crypto/common.h>
33*0Sstevel@tonic-gate #include <sys/crypto/impl.h>
34*0Sstevel@tonic-gate #include <sys/crypto/api.h>
35*0Sstevel@tonic-gate #include <sys/crypto/spi.h>
36*0Sstevel@tonic-gate #include <sys/crypto/sched_impl.h>
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate 
39*0Sstevel@tonic-gate static int crypto_mac_decrypt_common(crypto_mechanism_t *,
40*0Sstevel@tonic-gate     crypto_mechanism_t *, crypto_dual_data_t *, crypto_key_t *, crypto_key_t *,
41*0Sstevel@tonic-gate     crypto_ctx_template_t, crypto_ctx_template_t, crypto_data_t *,
42*0Sstevel@tonic-gate     crypto_data_t *, crypto_call_req_t *, boolean_t);
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate /*
45*0Sstevel@tonic-gate  * Performs a dual encrypt/mac atomic operation. The provider and session
46*0Sstevel@tonic-gate  * to use are determined by the KCF dispatcher.
47*0Sstevel@tonic-gate  */
48*0Sstevel@tonic-gate int
49*0Sstevel@tonic-gate crypto_encrypt_mac(crypto_mechanism_t *encr_mech,
50*0Sstevel@tonic-gate     crypto_mechanism_t *mac_mech, crypto_data_t *pt,
51*0Sstevel@tonic-gate     crypto_key_t *encr_key, crypto_key_t *mac_key,
52*0Sstevel@tonic-gate     crypto_ctx_template_t encr_tmpl, crypto_ctx_template_t mac_tmpl,
53*0Sstevel@tonic-gate     crypto_dual_data_t *ct, crypto_data_t *mac, crypto_call_req_t *crq)
54*0Sstevel@tonic-gate {
55*0Sstevel@tonic-gate 	/*
56*0Sstevel@tonic-gate 	 * First try to find a provider for the encryption mechanism, that
57*0Sstevel@tonic-gate 	 * is also capable of the MAC mechanism.
58*0Sstevel@tonic-gate 	 */
59*0Sstevel@tonic-gate 	int error;
60*0Sstevel@tonic-gate 	kcf_mech_entry_t *me;
61*0Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
62*0Sstevel@tonic-gate 	kcf_ctx_template_t *ctx_encr_tmpl, *ctx_mac_tmpl;
63*0Sstevel@tonic-gate 	kcf_req_params_t params;
64*0Sstevel@tonic-gate 	kcf_encrypt_mac_ops_params_t *cmops;
65*0Sstevel@tonic-gate 	crypto_spi_ctx_template_t spi_encr_tmpl = NULL, spi_mac_tmpl = NULL;
66*0Sstevel@tonic-gate 	crypto_mech_type_t prov_encr_mechid, prov_mac_mechid;
67*0Sstevel@tonic-gate 	kcf_prov_tried_t *list = NULL;
68*0Sstevel@tonic-gate 	boolean_t encr_tmpl_checked = B_FALSE;
69*0Sstevel@tonic-gate 	boolean_t mac_tmpl_checked = B_FALSE;
70*0Sstevel@tonic-gate 	kcf_dual_req_t *next_req = NULL;
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate retry:
73*0Sstevel@tonic-gate 	/* pd is returned held on success */
74*0Sstevel@tonic-gate 	pd = kcf_get_dual_provider(encr_mech, mac_mech, &me, &prov_encr_mechid,
75*0Sstevel@tonic-gate 	    &prov_mac_mechid, &error, list,
76*0Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC,
77*0Sstevel@tonic-gate 	    CRYPTO_FG_MAC_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC,
78*0Sstevel@tonic-gate 	    CHECK_RESTRICT(crq), ct->dd_len1);
79*0Sstevel@tonic-gate 	if (pd == NULL) {
80*0Sstevel@tonic-gate 		if (list != NULL)
81*0Sstevel@tonic-gate 			kcf_free_triedlist(list);
82*0Sstevel@tonic-gate 		if (next_req != NULL)
83*0Sstevel@tonic-gate 			kmem_free(next_req, sizeof (kcf_dual_req_t));
84*0Sstevel@tonic-gate 		return (error);
85*0Sstevel@tonic-gate 	}
86*0Sstevel@tonic-gate 
87*0Sstevel@tonic-gate 	/*
88*0Sstevel@tonic-gate 	 * For SW providers, check the validity of the context template
89*0Sstevel@tonic-gate 	 * It is very rare that the generation number mis-matches, so
90*0Sstevel@tonic-gate 	 * is acceptable to fail here, and let the consumer recover by
91*0Sstevel@tonic-gate 	 * freeing this tmpl and create a new one for the key and new SW
92*0Sstevel@tonic-gate 	 * provider
93*0Sstevel@tonic-gate 	 * Warning! will need to change when multiple software providers
94*0Sstevel@tonic-gate 	 * per mechanism are supported.
95*0Sstevel@tonic-gate 	 */
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	if ((!encr_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
98*0Sstevel@tonic-gate 		if (encr_tmpl != NULL) {
99*0Sstevel@tonic-gate 			ctx_encr_tmpl = (kcf_ctx_template_t *)encr_tmpl;
100*0Sstevel@tonic-gate 			if (ctx_encr_tmpl->ct_generation != me->me_gen_swprov) {
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 				if (next_req != NULL)
103*0Sstevel@tonic-gate 					kmem_free(next_req,
104*0Sstevel@tonic-gate 					    sizeof (kcf_dual_req_t));
105*0Sstevel@tonic-gate 				if (list != NULL)
106*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
109*0Sstevel@tonic-gate 				/* Which one is the the old one ? */
110*0Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
111*0Sstevel@tonic-gate 			}
112*0Sstevel@tonic-gate 			spi_encr_tmpl = ctx_encr_tmpl->ct_prov_tmpl;
113*0Sstevel@tonic-gate 		}
114*0Sstevel@tonic-gate 		encr_tmpl_checked = B_TRUE;
115*0Sstevel@tonic-gate 	}
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate 	if (prov_mac_mechid == CRYPTO_MECH_INVALID) {
118*0Sstevel@tonic-gate 		crypto_call_req_t encr_req;
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate 		/* Need to emulate with 2 internal calls */
121*0Sstevel@tonic-gate 		/* Allocate and initialize the MAC req for the callback */
122*0Sstevel@tonic-gate 
123*0Sstevel@tonic-gate 		if (crq != NULL) {
124*0Sstevel@tonic-gate 			if (next_req == NULL) {
125*0Sstevel@tonic-gate 				next_req = kcf_alloc_req(crq);
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate 				if (next_req == NULL) {
128*0Sstevel@tonic-gate 					KCF_PROV_REFRELE(pd);
129*0Sstevel@tonic-gate 					if (list != NULL)
130*0Sstevel@tonic-gate 						kcf_free_triedlist(list);
131*0Sstevel@tonic-gate 					return (CRYPTO_HOST_MEMORY);
132*0Sstevel@tonic-gate 				}
133*0Sstevel@tonic-gate 				/*
134*0Sstevel@tonic-gate 				 * Careful! we're wrapping-in mac_tmpl instead
135*0Sstevel@tonic-gate 				 * of an spi_mac_tmpl. The callback routine will
136*0Sstevel@tonic-gate 				 * have to validate mac_tmpl, and use the
137*0Sstevel@tonic-gate 				 * mac_ctx_tmpl, once it picks a MAC provider.
138*0Sstevel@tonic-gate 				 */
139*0Sstevel@tonic-gate 				KCF_WRAP_MAC_OPS_PARAMS(&(next_req->kr_params),
140*0Sstevel@tonic-gate 				    KCF_OP_ATOMIC, NULL, mac_mech, mac_key,
141*0Sstevel@tonic-gate 				    (crypto_data_t *)ct, mac, mac_tmpl);
142*0Sstevel@tonic-gate 			}
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate 			encr_req.cr_flag = crq->cr_flag;
145*0Sstevel@tonic-gate 			encr_req.cr_callback_func = kcf_next_req;
146*0Sstevel@tonic-gate 			encr_req.cr_callback_arg = next_req;
147*0Sstevel@tonic-gate 		}
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate 		if (pt == NULL) {
150*0Sstevel@tonic-gate 			KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_ATOMIC,
151*0Sstevel@tonic-gate 			    pd->pd_sid, encr_mech, encr_key,
152*0Sstevel@tonic-gate 			    (crypto_data_t *)ct, NULL, spi_encr_tmpl);
153*0Sstevel@tonic-gate 		} else {
154*0Sstevel@tonic-gate 			KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_ATOMIC,
155*0Sstevel@tonic-gate 			    pd->pd_sid, encr_mech, encr_key, pt,
156*0Sstevel@tonic-gate 			    (crypto_data_t *)ct, spi_encr_tmpl);
157*0Sstevel@tonic-gate 		}
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, NULL, (crq == NULL) ? NULL :
160*0Sstevel@tonic-gate 		    &encr_req, &params, B_TRUE);
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 		switch (error) {
163*0Sstevel@tonic-gate 		case CRYPTO_SUCCESS: {
164*0Sstevel@tonic-gate 			off_t saveoffset;
165*0Sstevel@tonic-gate 			size_t savelen;
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate 			/*
168*0Sstevel@tonic-gate 			 * The encryption step is done. Reuse the encr_req
169*0Sstevel@tonic-gate 			 * for submitting the MAC step.
170*0Sstevel@tonic-gate 			 */
171*0Sstevel@tonic-gate 			if (next_req == NULL) {
172*0Sstevel@tonic-gate 				saveoffset = ct->dd_offset1;
173*0Sstevel@tonic-gate 				savelen = ct->dd_len1;
174*0Sstevel@tonic-gate 			} else {
175*0Sstevel@tonic-gate 				saveoffset = next_req->kr_saveoffset =
176*0Sstevel@tonic-gate 				    ct->dd_offset1;
177*0Sstevel@tonic-gate 				savelen = next_req->kr_savelen = ct->dd_len1;
178*0Sstevel@tonic-gate 				encr_req.cr_callback_func = kcf_last_req;
179*0Sstevel@tonic-gate 			}
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate 			ct->dd_offset1 = ct->dd_offset2;
182*0Sstevel@tonic-gate 			ct->dd_len1 = ct->dd_len2;
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 			error = crypto_mac(mac_mech, (crypto_data_t *)ct,
185*0Sstevel@tonic-gate 			    mac_key, mac_tmpl, mac, (crq == NULL) ? NULL :
186*0Sstevel@tonic-gate 			    &encr_req);
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 			if (error != CRYPTO_QUEUED) {
189*0Sstevel@tonic-gate 				ct->dd_offset1 = saveoffset;
190*0Sstevel@tonic-gate 				ct->dd_len1 = savelen;
191*0Sstevel@tonic-gate 			}
192*0Sstevel@tonic-gate 			break;
193*0Sstevel@tonic-gate 		}
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 		case CRYPTO_QUEUED:
196*0Sstevel@tonic-gate 			if ((crq != NULL) &&
197*0Sstevel@tonic-gate 			    !(crq->cr_flag & CRYPTO_SKIP_REQID))
198*0Sstevel@tonic-gate 				crq->cr_reqid = encr_req.cr_reqid;
199*0Sstevel@tonic-gate 			break;
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 		default:
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate 			/* Add pd to the linked list of providers tried. */
204*0Sstevel@tonic-gate 			if (IS_RECOVERABLE(error)) {
205*0Sstevel@tonic-gate 				if (kcf_insert_triedlist(&list, pd,
206*0Sstevel@tonic-gate 				    KCF_KMFLAG(crq)) != NULL)
207*0Sstevel@tonic-gate 					goto retry;
208*0Sstevel@tonic-gate 			}
209*0Sstevel@tonic-gate 		}
210*0Sstevel@tonic-gate 		if (error != CRYPTO_QUEUED && next_req != NULL)
211*0Sstevel@tonic-gate 			kmem_free(next_req, sizeof (kcf_dual_req_t));
212*0Sstevel@tonic-gate 		if (list != NULL)
213*0Sstevel@tonic-gate 			kcf_free_triedlist(list);
214*0Sstevel@tonic-gate 		KCF_PROV_REFRELE(pd);
215*0Sstevel@tonic-gate 		return (error);
216*0Sstevel@tonic-gate 	}
217*0Sstevel@tonic-gate 	if ((!mac_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
218*0Sstevel@tonic-gate 		if ((mac_tmpl != NULL) &&
219*0Sstevel@tonic-gate 		    (prov_mac_mechid != CRYPTO_MECH_INVALID)) {
220*0Sstevel@tonic-gate 			ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
221*0Sstevel@tonic-gate 			if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 				if (next_req != NULL)
224*0Sstevel@tonic-gate 					kmem_free(next_req,
225*0Sstevel@tonic-gate 					    sizeof (kcf_dual_req_t));
226*0Sstevel@tonic-gate 				if (list != NULL)
227*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
230*0Sstevel@tonic-gate 				/* Which one is the the old one ? */
231*0Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
232*0Sstevel@tonic-gate 			}
233*0Sstevel@tonic-gate 			spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
234*0Sstevel@tonic-gate 		}
235*0Sstevel@tonic-gate 		mac_tmpl_checked = B_TRUE;
236*0Sstevel@tonic-gate 	}
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 	/* The fast path for SW providers. */
239*0Sstevel@tonic-gate 	if (CHECK_FASTPATH(crq, pd)) {
240*0Sstevel@tonic-gate 		crypto_mechanism_t lencr_mech;
241*0Sstevel@tonic-gate 		crypto_mechanism_t lmac_mech;
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate 		/* careful! structs assignments */
244*0Sstevel@tonic-gate 		lencr_mech = *encr_mech;
245*0Sstevel@tonic-gate 		lencr_mech.cm_type = prov_encr_mechid;
246*0Sstevel@tonic-gate 		lmac_mech = *mac_mech;
247*0Sstevel@tonic-gate 		lmac_mech.cm_type = prov_mac_mechid;
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate 		error = KCF_PROV_ENCRYPT_MAC_ATOMIC(pd, pd->pd_sid,
250*0Sstevel@tonic-gate 		    &lencr_mech, encr_key, &lmac_mech, mac_key, pt, ct,
251*0Sstevel@tonic-gate 		    mac, spi_encr_tmpl, spi_mac_tmpl, KCF_SWFP_RHNDL(crq));
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
254*0Sstevel@tonic-gate 	} else {
255*0Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_ATOMIC,
256*0Sstevel@tonic-gate 		    pd->pd_sid, encr_key, mac_key, pt, ct, mac, spi_encr_tmpl,
257*0Sstevel@tonic-gate 		    spi_mac_tmpl);
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate 		cmops = &(params.rp_u.encrypt_mac_params);
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate 		/* careful! structs assignments */
262*0Sstevel@tonic-gate 		cmops->em_encr_mech = *encr_mech;
263*0Sstevel@tonic-gate 		cmops->em_encr_mech.cm_type = prov_encr_mechid;
264*0Sstevel@tonic-gate 		cmops->em_framework_encr_mechtype = encr_mech->cm_type;
265*0Sstevel@tonic-gate 		cmops->em_mac_mech = *mac_mech;
266*0Sstevel@tonic-gate 		cmops->em_mac_mech.cm_type = prov_mac_mechid;
267*0Sstevel@tonic-gate 		cmops->em_framework_mac_mechtype = mac_mech->cm_type;
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, NULL, crq, &params, B_FALSE);
270*0Sstevel@tonic-gate 	}
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate 	if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED &&
273*0Sstevel@tonic-gate 	    IS_RECOVERABLE(error)) {
274*0Sstevel@tonic-gate 		/* Add pd to the linked list of providers tried. */
275*0Sstevel@tonic-gate 		if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL)
276*0Sstevel@tonic-gate 			goto retry;
277*0Sstevel@tonic-gate 	}
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate 	if (next_req != NULL)
280*0Sstevel@tonic-gate 		kmem_free(next_req, sizeof (kcf_dual_req_t));
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	if (list != NULL)
283*0Sstevel@tonic-gate 		kcf_free_triedlist(list);
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate 	KCF_PROV_REFRELE(pd);
286*0Sstevel@tonic-gate 	return (error);
287*0Sstevel@tonic-gate }
288*0Sstevel@tonic-gate 
289*0Sstevel@tonic-gate /*
290*0Sstevel@tonic-gate  * Starts a multi-part dual encrypt/mac operation. The provider and session
291*0Sstevel@tonic-gate  * to use are determined by the KCF dispatcher.
292*0Sstevel@tonic-gate  */
293*0Sstevel@tonic-gate /* ARGSUSED */
294*0Sstevel@tonic-gate int
295*0Sstevel@tonic-gate crypto_encrypt_mac_init(crypto_mechanism_t *encr_mech,
296*0Sstevel@tonic-gate     crypto_mechanism_t *mac_mech, crypto_key_t *encr_key,
297*0Sstevel@tonic-gate     crypto_key_t *mac_key, crypto_ctx_template_t encr_tmpl,
298*0Sstevel@tonic-gate     crypto_ctx_template_t mac_tmpl, crypto_context_t *ctxp,
299*0Sstevel@tonic-gate     crypto_call_req_t *cr)
300*0Sstevel@tonic-gate {
301*0Sstevel@tonic-gate 	/*
302*0Sstevel@tonic-gate 	 * First try to find a provider for the encryption mechanism, that
303*0Sstevel@tonic-gate 	 * is also capable of the MAC mechanism.
304*0Sstevel@tonic-gate 	 */
305*0Sstevel@tonic-gate 	int error;
306*0Sstevel@tonic-gate 	kcf_mech_entry_t *me;
307*0Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
308*0Sstevel@tonic-gate 	kcf_ctx_template_t *ctx_encr_tmpl, *ctx_mac_tmpl;
309*0Sstevel@tonic-gate 	kcf_req_params_t params;
310*0Sstevel@tonic-gate 	kcf_encrypt_mac_ops_params_t *cmops;
311*0Sstevel@tonic-gate 	crypto_spi_ctx_template_t spi_encr_tmpl = NULL, spi_mac_tmpl = NULL;
312*0Sstevel@tonic-gate 	crypto_mech_type_t prov_encr_mechid, prov_mac_mechid;
313*0Sstevel@tonic-gate 	kcf_prov_tried_t *list = NULL;
314*0Sstevel@tonic-gate 	boolean_t encr_tmpl_checked = B_FALSE;
315*0Sstevel@tonic-gate 	boolean_t mac_tmpl_checked = B_FALSE;
316*0Sstevel@tonic-gate 	crypto_ctx_t *ctx = NULL;
317*0Sstevel@tonic-gate 	kcf_context_t *encr_kcf_context = NULL, *mac_kcf_context;
318*0Sstevel@tonic-gate 	crypto_call_flag_t save_flag;
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate retry:
321*0Sstevel@tonic-gate 	/* pd is returned held on success */
322*0Sstevel@tonic-gate 	pd = kcf_get_dual_provider(encr_mech, mac_mech, &me, &prov_encr_mechid,
323*0Sstevel@tonic-gate 	    &prov_mac_mechid, &error, list,
324*0Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_MAC, CRYPTO_FG_MAC,
325*0Sstevel@tonic-gate 	    CHECK_RESTRICT(cr), 0);
326*0Sstevel@tonic-gate 	if (pd == NULL) {
327*0Sstevel@tonic-gate 		if (list != NULL)
328*0Sstevel@tonic-gate 			kcf_free_triedlist(list);
329*0Sstevel@tonic-gate 		return (error);
330*0Sstevel@tonic-gate 	}
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate 	/*
333*0Sstevel@tonic-gate 	 * For SW providers, check the validity of the context template
334*0Sstevel@tonic-gate 	 * It is very rare that the generation number mis-matches, so
335*0Sstevel@tonic-gate 	 * is acceptable to fail here, and let the consumer recover by
336*0Sstevel@tonic-gate 	 * freeing this tmpl and create a new one for the key and new SW
337*0Sstevel@tonic-gate 	 * provider
338*0Sstevel@tonic-gate 	 * Warning! will need to change when multiple software providers
339*0Sstevel@tonic-gate 	 * per mechanism are supported.
340*0Sstevel@tonic-gate 	 */
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 	if ((!encr_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
343*0Sstevel@tonic-gate 		if (encr_tmpl != NULL) {
344*0Sstevel@tonic-gate 			ctx_encr_tmpl = (kcf_ctx_template_t *)encr_tmpl;
345*0Sstevel@tonic-gate 			if (ctx_encr_tmpl->ct_generation != me->me_gen_swprov) {
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 				if (list != NULL)
348*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
349*0Sstevel@tonic-gate 				if (encr_kcf_context != NULL)
350*0Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(encr_kcf_context);
351*0Sstevel@tonic-gate 
352*0Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
353*0Sstevel@tonic-gate 				/* Which one is the the old one ? */
354*0Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
355*0Sstevel@tonic-gate 			}
356*0Sstevel@tonic-gate 			spi_encr_tmpl = ctx_encr_tmpl->ct_prov_tmpl;
357*0Sstevel@tonic-gate 		}
358*0Sstevel@tonic-gate 		encr_tmpl_checked = B_TRUE;
359*0Sstevel@tonic-gate 	}
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate 	if (prov_mac_mechid == CRYPTO_MECH_INVALID) {
362*0Sstevel@tonic-gate 		/* Need to emulate with 2 internal calls */
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 		/*
365*0Sstevel@tonic-gate 		 * We avoid code complexity by limiting the pure async.
366*0Sstevel@tonic-gate 		 * case to be done using only a SW provider.
367*0Sstevel@tonic-gate 		 * XXX - Redo the emulation code below so that we can
368*0Sstevel@tonic-gate 		 * remove this limitation.
369*0Sstevel@tonic-gate 		 */
370*0Sstevel@tonic-gate 		if (cr != NULL && pd->pd_prov_type == CRYPTO_HW_PROVIDER) {
371*0Sstevel@tonic-gate 			if ((kcf_insert_triedlist(&list, pd, KCF_KMFLAG(cr))
372*0Sstevel@tonic-gate 			    != NULL))
373*0Sstevel@tonic-gate 				goto retry;
374*0Sstevel@tonic-gate 			if (list != NULL)
375*0Sstevel@tonic-gate 				kcf_free_triedlist(list);
376*0Sstevel@tonic-gate 			if (encr_kcf_context != NULL)
377*0Sstevel@tonic-gate 				KCF_CONTEXT_REFRELE(encr_kcf_context);
378*0Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
379*0Sstevel@tonic-gate 			return (CRYPTO_HOST_MEMORY);
380*0Sstevel@tonic-gate 		}
381*0Sstevel@tonic-gate 
382*0Sstevel@tonic-gate 		if (ctx == NULL && pd->pd_prov_type == CRYPTO_SW_PROVIDER) {
383*0Sstevel@tonic-gate 			ctx = kcf_new_ctx(cr, pd, pd->pd_sid);
384*0Sstevel@tonic-gate 			if (ctx == NULL) {
385*0Sstevel@tonic-gate 				if (list != NULL)
386*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
387*0Sstevel@tonic-gate 				if (encr_kcf_context != NULL)
388*0Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(encr_kcf_context);
389*0Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
390*0Sstevel@tonic-gate 				return (CRYPTO_HOST_MEMORY);
391*0Sstevel@tonic-gate 			}
392*0Sstevel@tonic-gate 			encr_kcf_context = (kcf_context_t *)
393*0Sstevel@tonic-gate 			    ctx->cc_framework_private;
394*0Sstevel@tonic-gate 		}
395*0Sstevel@tonic-gate 		/*
396*0Sstevel@tonic-gate 		 * Trade-off speed vs avoidance of code complexity and
397*0Sstevel@tonic-gate 		 * duplication:
398*0Sstevel@tonic-gate 		 * Could do all the combinations of fastpath / synch / asynch
399*0Sstevel@tonic-gate 		 * for the encryption and the mac steps. Early attempts
400*0Sstevel@tonic-gate 		 * showed the code grew wild and bug-prone, for little gain.
401*0Sstevel@tonic-gate 		 * Therefore, the adaptative asynch case is not implemented.
402*0Sstevel@tonic-gate 		 * It's either pure synchronous, or pure asynchronous.
403*0Sstevel@tonic-gate 		 * We still preserve a fastpath for the pure synchronous
404*0Sstevel@tonic-gate 		 * requests to SW providers.
405*0Sstevel@tonic-gate 		 */
406*0Sstevel@tonic-gate 		if (cr == NULL) {
407*0Sstevel@tonic-gate 			crypto_context_t mac_context;
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate 			if (pd->pd_prov_type == CRYPTO_SW_PROVIDER) {
410*0Sstevel@tonic-gate 				crypto_mechanism_t lmech = *encr_mech;
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 				lmech.cm_type = prov_encr_mechid;
413*0Sstevel@tonic-gate 
414*0Sstevel@tonic-gate 				error = KCF_PROV_ENCRYPT_INIT(pd, ctx, &lmech,
415*0Sstevel@tonic-gate 				    encr_key, spi_encr_tmpl,
416*0Sstevel@tonic-gate 				    KCF_RHNDL(KM_SLEEP));
417*0Sstevel@tonic-gate 			} else {
418*0Sstevel@tonic-gate 				/*
419*0Sstevel@tonic-gate 				 * If we did the 'goto retry' then ctx may not
420*0Sstevel@tonic-gate 				 * be NULL.  In general, we can't reuse another
421*0Sstevel@tonic-gate 				 * provider's context, so we free it now so
422*0Sstevel@tonic-gate 				 * we don't leak it.
423*0Sstevel@tonic-gate 				 */
424*0Sstevel@tonic-gate 				if (ctx != NULL) {
425*0Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE((kcf_context_t *)
426*0Sstevel@tonic-gate 					    ctx->cc_framework_private);
427*0Sstevel@tonic-gate 					encr_kcf_context = NULL;
428*0Sstevel@tonic-gate 				}
429*0Sstevel@tonic-gate 				error = crypto_encrypt_init_prov(pd, pd->pd_sid,
430*0Sstevel@tonic-gate 				    encr_mech, encr_key, &encr_tmpl,
431*0Sstevel@tonic-gate 				    (crypto_context_t *)&ctx, NULL);
432*0Sstevel@tonic-gate 
433*0Sstevel@tonic-gate 				if (error == CRYPTO_SUCCESS) {
434*0Sstevel@tonic-gate 					encr_kcf_context = (kcf_context_t *)
435*0Sstevel@tonic-gate 					    ctx->cc_framework_private;
436*0Sstevel@tonic-gate 				}
437*0Sstevel@tonic-gate 			}
438*0Sstevel@tonic-gate 			KCF_PROV_INCRSTATS(pd, error);
439*0Sstevel@tonic-gate 
440*0Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
441*0Sstevel@tonic-gate 
442*0Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS) {
443*0Sstevel@tonic-gate 				/* Can't be CRYPTO_QUEUED. return the failure */
444*0Sstevel@tonic-gate 				if (list != NULL)
445*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
446*0Sstevel@tonic-gate 				if (encr_kcf_context != NULL)
447*0Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(encr_kcf_context);
448*0Sstevel@tonic-gate 
449*0Sstevel@tonic-gate 				return (error);
450*0Sstevel@tonic-gate 			}
451*0Sstevel@tonic-gate 			error = crypto_mac_init(mac_mech, mac_key, mac_tmpl,
452*0Sstevel@tonic-gate 			    &mac_context, NULL);
453*0Sstevel@tonic-gate 
454*0Sstevel@tonic-gate 			if (list != NULL)
455*0Sstevel@tonic-gate 				kcf_free_triedlist(list);
456*0Sstevel@tonic-gate 
457*0Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS) {
458*0Sstevel@tonic-gate 				/* Should this be an ASSERT() ? */
459*0Sstevel@tonic-gate 
460*0Sstevel@tonic-gate 				KCF_CONTEXT_REFRELE(encr_kcf_context);
461*0Sstevel@tonic-gate 			} else {
462*0Sstevel@tonic-gate 				encr_kcf_context = (kcf_context_t *)
463*0Sstevel@tonic-gate 				    ctx->cc_framework_private;
464*0Sstevel@tonic-gate 				mac_kcf_context = (kcf_context_t *)
465*0Sstevel@tonic-gate 				    ((crypto_ctx_t *)mac_context)->
466*0Sstevel@tonic-gate 				    cc_framework_private;
467*0Sstevel@tonic-gate 
468*0Sstevel@tonic-gate 				encr_kcf_context->kc_secondctx =
469*0Sstevel@tonic-gate 				    mac_kcf_context;
470*0Sstevel@tonic-gate 				KCF_CONTEXT_REFHOLD(mac_kcf_context);
471*0Sstevel@tonic-gate 
472*0Sstevel@tonic-gate 				*ctxp = (crypto_context_t)ctx;
473*0Sstevel@tonic-gate 			}
474*0Sstevel@tonic-gate 
475*0Sstevel@tonic-gate 			return (error);
476*0Sstevel@tonic-gate 		}
477*0Sstevel@tonic-gate 
478*0Sstevel@tonic-gate 		/* submit a pure asynchronous request. */
479*0Sstevel@tonic-gate 		save_flag = cr->cr_flag;
480*0Sstevel@tonic-gate 		cr->cr_flag |= CRYPTO_ALWAYS_QUEUE;
481*0Sstevel@tonic-gate 
482*0Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_INIT,
483*0Sstevel@tonic-gate 		    pd->pd_sid, encr_key, mac_key, NULL, NULL, NULL,
484*0Sstevel@tonic-gate 		    spi_encr_tmpl, spi_mac_tmpl);
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate 		cmops = &(params.rp_u.encrypt_mac_params);
487*0Sstevel@tonic-gate 
488*0Sstevel@tonic-gate 		/* careful! structs assignments */
489*0Sstevel@tonic-gate 		cmops->em_encr_mech = *encr_mech;
490*0Sstevel@tonic-gate 		/*
491*0Sstevel@tonic-gate 		 * cmops->em_encr_mech.cm_type will be set when we get to
492*0Sstevel@tonic-gate 		 * kcf_emulate_dual() routine.
493*0Sstevel@tonic-gate 		 */
494*0Sstevel@tonic-gate 		cmops->em_framework_encr_mechtype = encr_mech->cm_type;
495*0Sstevel@tonic-gate 		cmops->em_mac_mech = *mac_mech;
496*0Sstevel@tonic-gate 
497*0Sstevel@tonic-gate 		/*
498*0Sstevel@tonic-gate 		 * cmops->em_mac_mech.cm_type will be set when we know the
499*0Sstevel@tonic-gate 		 * MAC provider.
500*0Sstevel@tonic-gate 		 */
501*0Sstevel@tonic-gate 		cmops->em_framework_mac_mechtype = mac_mech->cm_type;
502*0Sstevel@tonic-gate 
503*0Sstevel@tonic-gate 		/*
504*0Sstevel@tonic-gate 		 * non-NULL ctx->kc_secondctx tells common_submit_request
505*0Sstevel@tonic-gate 		 * that this request uses separate cipher and MAC contexts.
506*0Sstevel@tonic-gate 		 * That function will set ctx->kc_secondctx to the new
507*0Sstevel@tonic-gate 		 * MAC context, once it gets one.
508*0Sstevel@tonic-gate 		 */
509*0Sstevel@tonic-gate 		encr_kcf_context->kc_secondctx = encr_kcf_context;
510*0Sstevel@tonic-gate 
511*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
512*0Sstevel@tonic-gate 
513*0Sstevel@tonic-gate 		cr->cr_flag = save_flag;
514*0Sstevel@tonic-gate 
515*0Sstevel@tonic-gate 		if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED) {
516*0Sstevel@tonic-gate 			KCF_CONTEXT_REFRELE(encr_kcf_context);
517*0Sstevel@tonic-gate 		}
518*0Sstevel@tonic-gate 		if (list != NULL)
519*0Sstevel@tonic-gate 			kcf_free_triedlist(list);
520*0Sstevel@tonic-gate 		*ctxp = (crypto_context_t)ctx;
521*0Sstevel@tonic-gate 		KCF_PROV_REFRELE(pd);
522*0Sstevel@tonic-gate 		return (error);
523*0Sstevel@tonic-gate 	}
524*0Sstevel@tonic-gate 
525*0Sstevel@tonic-gate 	if ((!mac_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
526*0Sstevel@tonic-gate 		if ((mac_tmpl != NULL) &&
527*0Sstevel@tonic-gate 		    (prov_mac_mechid != CRYPTO_MECH_INVALID)) {
528*0Sstevel@tonic-gate 			ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
529*0Sstevel@tonic-gate 			if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
530*0Sstevel@tonic-gate 
531*0Sstevel@tonic-gate 				if (list != NULL)
532*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
533*0Sstevel@tonic-gate 
534*0Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
535*0Sstevel@tonic-gate 				/* Which one is the the old one ? */
536*0Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
537*0Sstevel@tonic-gate 			}
538*0Sstevel@tonic-gate 			spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
539*0Sstevel@tonic-gate 		}
540*0Sstevel@tonic-gate 		mac_tmpl_checked = B_TRUE;
541*0Sstevel@tonic-gate 	}
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate 	if (ctx == NULL) {
544*0Sstevel@tonic-gate 		ctx = kcf_new_ctx(cr, pd, pd->pd_sid);
545*0Sstevel@tonic-gate 		if (ctx == NULL) {
546*0Sstevel@tonic-gate 			if (list != NULL)
547*0Sstevel@tonic-gate 				kcf_free_triedlist(list);
548*0Sstevel@tonic-gate 
549*0Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
550*0Sstevel@tonic-gate 			return (CRYPTO_HOST_MEMORY);
551*0Sstevel@tonic-gate 		}
552*0Sstevel@tonic-gate 		encr_kcf_context = (kcf_context_t *)ctx->cc_framework_private;
553*0Sstevel@tonic-gate 	}
554*0Sstevel@tonic-gate 
555*0Sstevel@tonic-gate 	/* The fast path for SW providers. */
556*0Sstevel@tonic-gate 	if (CHECK_FASTPATH(cr, pd)) {
557*0Sstevel@tonic-gate 		crypto_mechanism_t lencr_mech;
558*0Sstevel@tonic-gate 		crypto_mechanism_t lmac_mech;
559*0Sstevel@tonic-gate 
560*0Sstevel@tonic-gate 		/* careful! structs assignments */
561*0Sstevel@tonic-gate 		lencr_mech = *encr_mech;
562*0Sstevel@tonic-gate 		lencr_mech.cm_type = prov_encr_mechid;
563*0Sstevel@tonic-gate 		lmac_mech = *mac_mech;
564*0Sstevel@tonic-gate 		lmac_mech.cm_type = prov_mac_mechid;
565*0Sstevel@tonic-gate 
566*0Sstevel@tonic-gate 		error = KCF_PROV_ENCRYPT_MAC_INIT(pd, ctx, &lencr_mech,
567*0Sstevel@tonic-gate 		    encr_key, &lmac_mech, mac_key, spi_encr_tmpl, spi_mac_tmpl,
568*0Sstevel@tonic-gate 		    KCF_SWFP_RHNDL(cr));
569*0Sstevel@tonic-gate 
570*0Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
571*0Sstevel@tonic-gate 	} else {
572*0Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_INIT,
573*0Sstevel@tonic-gate 		    pd->pd_sid, encr_key, mac_key, NULL, NULL, NULL,
574*0Sstevel@tonic-gate 		    spi_encr_tmpl, spi_mac_tmpl);
575*0Sstevel@tonic-gate 
576*0Sstevel@tonic-gate 		cmops = &(params.rp_u.encrypt_mac_params);
577*0Sstevel@tonic-gate 
578*0Sstevel@tonic-gate 		/* careful! structs assignments */
579*0Sstevel@tonic-gate 		cmops->em_encr_mech = *encr_mech;
580*0Sstevel@tonic-gate 		cmops->em_encr_mech.cm_type = prov_encr_mechid;
581*0Sstevel@tonic-gate 		cmops->em_framework_encr_mechtype = encr_mech->cm_type;
582*0Sstevel@tonic-gate 		cmops->em_mac_mech = *mac_mech;
583*0Sstevel@tonic-gate 		cmops->em_mac_mech.cm_type = prov_mac_mechid;
584*0Sstevel@tonic-gate 		cmops->em_framework_mac_mechtype = mac_mech->cm_type;
585*0Sstevel@tonic-gate 
586*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
587*0Sstevel@tonic-gate 	}
588*0Sstevel@tonic-gate 
589*0Sstevel@tonic-gate 	if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED) {
590*0Sstevel@tonic-gate 		if ((IS_RECOVERABLE(error)) &&
591*0Sstevel@tonic-gate 		    (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(cr)) != NULL))
592*0Sstevel@tonic-gate 			goto retry;
593*0Sstevel@tonic-gate 
594*0Sstevel@tonic-gate 		KCF_CONTEXT_REFRELE(encr_kcf_context);
595*0Sstevel@tonic-gate 	} else
596*0Sstevel@tonic-gate 		*ctxp = (crypto_context_t)ctx;
597*0Sstevel@tonic-gate 
598*0Sstevel@tonic-gate 	if (list != NULL)
599*0Sstevel@tonic-gate 		kcf_free_triedlist(list);
600*0Sstevel@tonic-gate 
601*0Sstevel@tonic-gate 	KCF_PROV_REFRELE(pd);
602*0Sstevel@tonic-gate 	return (error);
603*0Sstevel@tonic-gate }
604*0Sstevel@tonic-gate 
605*0Sstevel@tonic-gate /*
606*0Sstevel@tonic-gate  * Continues a multi-part dual encrypt/mac operation.
607*0Sstevel@tonic-gate  */
608*0Sstevel@tonic-gate /* ARGSUSED */
609*0Sstevel@tonic-gate int
610*0Sstevel@tonic-gate crypto_encrypt_mac_update(crypto_context_t context,
611*0Sstevel@tonic-gate     crypto_data_t *pt, crypto_dual_data_t *ct, crypto_call_req_t *cr)
612*0Sstevel@tonic-gate {
613*0Sstevel@tonic-gate 	crypto_ctx_t *ctx = (crypto_ctx_t *)context, *mac_ctx;
614*0Sstevel@tonic-gate 	kcf_context_t *kcf_ctx, *kcf_mac_ctx;
615*0Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
616*0Sstevel@tonic-gate 	int error;
617*0Sstevel@tonic-gate 	kcf_req_params_t params;
618*0Sstevel@tonic-gate 
619*0Sstevel@tonic-gate 	if ((ctx == NULL) ||
620*0Sstevel@tonic-gate 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
621*0Sstevel@tonic-gate 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
622*0Sstevel@tonic-gate 		return (CRYPTO_INVALID_CONTEXT);
623*0Sstevel@tonic-gate 	}
624*0Sstevel@tonic-gate 
625*0Sstevel@tonic-gate 	KCF_PROV_REFHOLD(pd);
626*0Sstevel@tonic-gate 
627*0Sstevel@tonic-gate 	if ((kcf_mac_ctx = kcf_ctx->kc_secondctx) != NULL) {
628*0Sstevel@tonic-gate 		off_t save_offset;
629*0Sstevel@tonic-gate 		size_t save_len;
630*0Sstevel@tonic-gate 		crypto_call_flag_t save_flag;
631*0Sstevel@tonic-gate 
632*0Sstevel@tonic-gate 		if (kcf_mac_ctx->kc_prov_desc == NULL) {
633*0Sstevel@tonic-gate 			error = CRYPTO_INVALID_CONTEXT;
634*0Sstevel@tonic-gate 			goto out;
635*0Sstevel@tonic-gate 		}
636*0Sstevel@tonic-gate 		mac_ctx = &kcf_mac_ctx->kc_glbl_ctx;
637*0Sstevel@tonic-gate 
638*0Sstevel@tonic-gate 		/* First we submit the encryption request */
639*0Sstevel@tonic-gate 		if (cr == NULL) {
640*0Sstevel@tonic-gate 			/*
641*0Sstevel@tonic-gate 			 * 'ct' is always not NULL.
642*0Sstevel@tonic-gate 			 * A NULL 'pt' means in-place.
643*0Sstevel@tonic-gate 			 */
644*0Sstevel@tonic-gate 			if (pt == NULL)
645*0Sstevel@tonic-gate 				error = crypto_encrypt_update(context,
646*0Sstevel@tonic-gate 				    (crypto_data_t *)ct, NULL, NULL);
647*0Sstevel@tonic-gate 			else
648*0Sstevel@tonic-gate 				error = crypto_encrypt_update(context, pt,
649*0Sstevel@tonic-gate 				    (crypto_data_t *)ct, NULL);
650*0Sstevel@tonic-gate 
651*0Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS)
652*0Sstevel@tonic-gate 				goto out;
653*0Sstevel@tonic-gate 
654*0Sstevel@tonic-gate 			/*
655*0Sstevel@tonic-gate 			 * call  mac_update when there is data to throw in
656*0Sstevel@tonic-gate 			 * the mix. Either an explicitly non-zero ct->dd_len2,
657*0Sstevel@tonic-gate 			 * or the last ciphertext portion.
658*0Sstevel@tonic-gate 			 */
659*0Sstevel@tonic-gate 			save_offset = ct->dd_offset1;
660*0Sstevel@tonic-gate 			save_len = ct->dd_len1;
661*0Sstevel@tonic-gate 			if (ct->dd_len2 == 0) {
662*0Sstevel@tonic-gate 				/*
663*0Sstevel@tonic-gate 				 * The previous encrypt step was an
664*0Sstevel@tonic-gate 				 * accumulation only and didn't produce any
665*0Sstevel@tonic-gate 				 * partial output
666*0Sstevel@tonic-gate 				 */
667*0Sstevel@tonic-gate 				if (ct->dd_len1 == 0)
668*0Sstevel@tonic-gate 					goto out;
669*0Sstevel@tonic-gate 			} else {
670*0Sstevel@tonic-gate 				ct->dd_offset1 = ct->dd_offset2;
671*0Sstevel@tonic-gate 				ct->dd_len1 = ct->dd_len2;
672*0Sstevel@tonic-gate 			}
673*0Sstevel@tonic-gate 			error = crypto_mac_update((crypto_context_t)mac_ctx,
674*0Sstevel@tonic-gate 			    (crypto_data_t *)ct, NULL);
675*0Sstevel@tonic-gate 
676*0Sstevel@tonic-gate 			ct->dd_offset1 = save_offset;
677*0Sstevel@tonic-gate 			ct->dd_len1 = save_len;
678*0Sstevel@tonic-gate 
679*0Sstevel@tonic-gate 			goto out;
680*0Sstevel@tonic-gate 		}
681*0Sstevel@tonic-gate 		/* submit a pure asynchronous request. */
682*0Sstevel@tonic-gate 		save_flag = cr->cr_flag;
683*0Sstevel@tonic-gate 		cr->cr_flag |= CRYPTO_ALWAYS_QUEUE;
684*0Sstevel@tonic-gate 
685*0Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_UPDATE,
686*0Sstevel@tonic-gate 		    pd->pd_sid, NULL, NULL, pt, ct, NULL, NULL, NULL)
687*0Sstevel@tonic-gate 
688*0Sstevel@tonic-gate 
689*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
690*0Sstevel@tonic-gate 
691*0Sstevel@tonic-gate 		cr->cr_flag = save_flag;
692*0Sstevel@tonic-gate 		goto out;
693*0Sstevel@tonic-gate 	}
694*0Sstevel@tonic-gate 
695*0Sstevel@tonic-gate 	/* The fast path for SW providers. */
696*0Sstevel@tonic-gate 	if (CHECK_FASTPATH(cr, pd)) {
697*0Sstevel@tonic-gate 		error = KCF_PROV_ENCRYPT_MAC_UPDATE(pd, ctx, pt, ct, NULL);
698*0Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
699*0Sstevel@tonic-gate 	} else {
700*0Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_UPDATE,
701*0Sstevel@tonic-gate 		    pd->pd_sid, NULL, NULL, pt, ct, NULL, NULL, NULL);
702*0Sstevel@tonic-gate 
703*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
704*0Sstevel@tonic-gate 	}
705*0Sstevel@tonic-gate out:
706*0Sstevel@tonic-gate 	KCF_PROV_REFRELE(pd);
707*0Sstevel@tonic-gate 	return (error);
708*0Sstevel@tonic-gate }
709*0Sstevel@tonic-gate 
710*0Sstevel@tonic-gate /*
711*0Sstevel@tonic-gate  * Terminates a multi-part dual encrypt/mac operation.
712*0Sstevel@tonic-gate  */
713*0Sstevel@tonic-gate /* ARGSUSED */
714*0Sstevel@tonic-gate int crypto_encrypt_mac_final(crypto_context_t context, crypto_dual_data_t *ct,
715*0Sstevel@tonic-gate     crypto_data_t *mac, crypto_call_req_t *cr)
716*0Sstevel@tonic-gate {
717*0Sstevel@tonic-gate 	crypto_ctx_t *ctx = (crypto_ctx_t *)context, *mac_ctx;
718*0Sstevel@tonic-gate 	kcf_context_t *kcf_ctx, *kcf_mac_ctx;
719*0Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
720*0Sstevel@tonic-gate 	int error;
721*0Sstevel@tonic-gate 	kcf_req_params_t params;
722*0Sstevel@tonic-gate 
723*0Sstevel@tonic-gate 	if ((ctx == NULL) ||
724*0Sstevel@tonic-gate 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
725*0Sstevel@tonic-gate 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
726*0Sstevel@tonic-gate 		return (CRYPTO_INVALID_CONTEXT);
727*0Sstevel@tonic-gate 	}
728*0Sstevel@tonic-gate 
729*0Sstevel@tonic-gate 	KCF_PROV_REFHOLD(pd);
730*0Sstevel@tonic-gate 
731*0Sstevel@tonic-gate 	if ((kcf_mac_ctx = kcf_ctx->kc_secondctx) != NULL) {
732*0Sstevel@tonic-gate 		off_t save_offset;
733*0Sstevel@tonic-gate 		size_t save_len;
734*0Sstevel@tonic-gate 		crypto_context_t mac_context;
735*0Sstevel@tonic-gate 		crypto_call_flag_t save_flag;
736*0Sstevel@tonic-gate 
737*0Sstevel@tonic-gate 		if (kcf_mac_ctx->kc_prov_desc == NULL) {
738*0Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
739*0Sstevel@tonic-gate 			return (CRYPTO_INVALID_CONTEXT);
740*0Sstevel@tonic-gate 		}
741*0Sstevel@tonic-gate 		mac_ctx = &kcf_mac_ctx->kc_glbl_ctx;
742*0Sstevel@tonic-gate 		mac_context = (crypto_context_t)mac_ctx;
743*0Sstevel@tonic-gate 
744*0Sstevel@tonic-gate 		if (cr == NULL) {
745*0Sstevel@tonic-gate 			/* Get the last chunk of ciphertext */
746*0Sstevel@tonic-gate 			error = crypto_encrypt_final(context,
747*0Sstevel@tonic-gate 			    (crypto_data_t *)ct, NULL);
748*0Sstevel@tonic-gate 
749*0Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
750*0Sstevel@tonic-gate 
751*0Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS)  {
752*0Sstevel@tonic-gate 				/*
753*0Sstevel@tonic-gate 				 * Needed here, because the caller of
754*0Sstevel@tonic-gate 				 * crypto_encrypt_mac_final() lost all
755*0Sstevel@tonic-gate 				 * refs to the mac_ctx.
756*0Sstevel@tonic-gate 				 */
757*0Sstevel@tonic-gate 				crypto_cancel_ctx(mac_context);
758*0Sstevel@tonic-gate 				return (error);
759*0Sstevel@tonic-gate 			}
760*0Sstevel@tonic-gate 			if (ct->dd_len2 > 0) {
761*0Sstevel@tonic-gate 				save_offset = ct->dd_offset1;
762*0Sstevel@tonic-gate 				save_len = ct->dd_len1;
763*0Sstevel@tonic-gate 				ct->dd_offset1 = ct->dd_offset2;
764*0Sstevel@tonic-gate 				ct->dd_len1 = ct->dd_len2;
765*0Sstevel@tonic-gate 
766*0Sstevel@tonic-gate 				error = crypto_mac_update(mac_context,
767*0Sstevel@tonic-gate 				    (crypto_data_t *)ct, NULL);
768*0Sstevel@tonic-gate 
769*0Sstevel@tonic-gate 				ct->dd_offset1 = save_offset;
770*0Sstevel@tonic-gate 				ct->dd_len1 = save_len;
771*0Sstevel@tonic-gate 
772*0Sstevel@tonic-gate 				if (error != CRYPTO_SUCCESS)  {
773*0Sstevel@tonic-gate 					crypto_cancel_ctx(mac_context);
774*0Sstevel@tonic-gate 					return (error);
775*0Sstevel@tonic-gate 				}
776*0Sstevel@tonic-gate 			}
777*0Sstevel@tonic-gate 
778*0Sstevel@tonic-gate 			/* and finally, collect the MAC */
779*0Sstevel@tonic-gate 			error = crypto_mac_final(mac_context, mac, NULL);
780*0Sstevel@tonic-gate 
781*0Sstevel@tonic-gate 			return (error);
782*0Sstevel@tonic-gate 		}
783*0Sstevel@tonic-gate 		/* submit a pure asynchronous request. */
784*0Sstevel@tonic-gate 		save_flag = cr->cr_flag;
785*0Sstevel@tonic-gate 		cr->cr_flag |= CRYPTO_ALWAYS_QUEUE;
786*0Sstevel@tonic-gate 
787*0Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_FINAL,
788*0Sstevel@tonic-gate 		    pd->pd_sid, NULL, NULL, NULL, ct, mac, NULL, NULL)
789*0Sstevel@tonic-gate 
790*0Sstevel@tonic-gate 
791*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
792*0Sstevel@tonic-gate 
793*0Sstevel@tonic-gate 		cr->cr_flag = save_flag;
794*0Sstevel@tonic-gate 		KCF_PROV_REFRELE(pd);
795*0Sstevel@tonic-gate 		return (error);
796*0Sstevel@tonic-gate 	}
797*0Sstevel@tonic-gate 	/* The fast path for SW providers. */
798*0Sstevel@tonic-gate 	if (CHECK_FASTPATH(cr, pd)) {
799*0Sstevel@tonic-gate 		error = KCF_PROV_ENCRYPT_MAC_FINAL(pd, ctx, ct, mac, NULL);
800*0Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
801*0Sstevel@tonic-gate 	} else {
802*0Sstevel@tonic-gate 		KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_FINAL,
803*0Sstevel@tonic-gate 		    pd->pd_sid, NULL, NULL, NULL, ct, mac, NULL, NULL);
804*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
805*0Sstevel@tonic-gate 	}
806*0Sstevel@tonic-gate out:
807*0Sstevel@tonic-gate 	KCF_PROV_REFRELE(pd);
808*0Sstevel@tonic-gate 	/* Release the hold done in kcf_new_ctx() during init step. */
809*0Sstevel@tonic-gate 	KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
810*0Sstevel@tonic-gate 	return (error);
811*0Sstevel@tonic-gate }
812*0Sstevel@tonic-gate 
813*0Sstevel@tonic-gate /*
814*0Sstevel@tonic-gate  * Performs an atomic dual mac/decrypt operation. The provider to use
815*0Sstevel@tonic-gate  * is determined by the KCF dispatcher.
816*0Sstevel@tonic-gate  */
817*0Sstevel@tonic-gate int
818*0Sstevel@tonic-gate crypto_mac_decrypt(crypto_mechanism_t *mac_mech,
819*0Sstevel@tonic-gate     crypto_mechanism_t *decr_mech, crypto_dual_data_t *ct,
820*0Sstevel@tonic-gate     crypto_key_t *mac_key, crypto_key_t *decr_key,
821*0Sstevel@tonic-gate     crypto_ctx_template_t mac_tmpl, crypto_ctx_template_t decr_tmpl,
822*0Sstevel@tonic-gate     crypto_data_t *mac, crypto_data_t *pt, crypto_call_req_t *crq)
823*0Sstevel@tonic-gate {
824*0Sstevel@tonic-gate 	return (crypto_mac_decrypt_common(mac_mech, decr_mech, ct, mac_key,
825*0Sstevel@tonic-gate 	    decr_key, mac_tmpl, decr_tmpl, mac, pt, crq, B_FALSE));
826*0Sstevel@tonic-gate }
827*0Sstevel@tonic-gate 
828*0Sstevel@tonic-gate /*
829*0Sstevel@tonic-gate  * Performs an atomic dual mac/decrypt operation. The provider to use
830*0Sstevel@tonic-gate  * is determined by the KCF dispatcher. 'mac' specifies the expected
831*0Sstevel@tonic-gate  * value for the MAC. The decryption is not performed if the computed
832*0Sstevel@tonic-gate  * MAC does not match the expected MAC.
833*0Sstevel@tonic-gate  */
834*0Sstevel@tonic-gate int
835*0Sstevel@tonic-gate crypto_mac_verify_decrypt(crypto_mechanism_t *mac_mech,
836*0Sstevel@tonic-gate     crypto_mechanism_t *decr_mech, crypto_dual_data_t *ct,
837*0Sstevel@tonic-gate     crypto_key_t *mac_key, crypto_key_t *decr_key,
838*0Sstevel@tonic-gate     crypto_ctx_template_t mac_tmpl, crypto_ctx_template_t decr_tmpl,
839*0Sstevel@tonic-gate     crypto_data_t *mac, crypto_data_t *pt, crypto_call_req_t *crq)
840*0Sstevel@tonic-gate {
841*0Sstevel@tonic-gate 	return (crypto_mac_decrypt_common(mac_mech, decr_mech, ct, mac_key,
842*0Sstevel@tonic-gate 	    decr_key, mac_tmpl, decr_tmpl, mac, pt, crq, B_TRUE));
843*0Sstevel@tonic-gate }
844*0Sstevel@tonic-gate 
845*0Sstevel@tonic-gate /*
846*0Sstevel@tonic-gate  * Called by both crypto_mac_decrypt() and crypto_mac_verify_decrypt().
847*0Sstevel@tonic-gate  * optionally verified if the MACs match before calling the decryption step.
848*0Sstevel@tonic-gate  */
849*0Sstevel@tonic-gate static int
850*0Sstevel@tonic-gate crypto_mac_decrypt_common(crypto_mechanism_t *mac_mech,
851*0Sstevel@tonic-gate     crypto_mechanism_t *decr_mech, crypto_dual_data_t *ct,
852*0Sstevel@tonic-gate     crypto_key_t *mac_key, crypto_key_t *decr_key,
853*0Sstevel@tonic-gate     crypto_ctx_template_t mac_tmpl, crypto_ctx_template_t decr_tmpl,
854*0Sstevel@tonic-gate     crypto_data_t *mac, crypto_data_t *pt, crypto_call_req_t *crq,
855*0Sstevel@tonic-gate     boolean_t do_verify)
856*0Sstevel@tonic-gate {
857*0Sstevel@tonic-gate 	/*
858*0Sstevel@tonic-gate 	 * First try to find a provider for the decryption mechanism, that
859*0Sstevel@tonic-gate 	 * is also capable of the MAC mechanism.
860*0Sstevel@tonic-gate 	 * We still favor optimizing the costlier decryption.
861*0Sstevel@tonic-gate 	 */
862*0Sstevel@tonic-gate 	int error;
863*0Sstevel@tonic-gate 	kcf_mech_entry_t *me;
864*0Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
865*0Sstevel@tonic-gate 	kcf_ctx_template_t *ctx_decr_tmpl, *ctx_mac_tmpl;
866*0Sstevel@tonic-gate 	kcf_req_params_t params;
867*0Sstevel@tonic-gate 	kcf_mac_decrypt_ops_params_t *cmops;
868*0Sstevel@tonic-gate 	crypto_spi_ctx_template_t spi_decr_tmpl = NULL, spi_mac_tmpl = NULL;
869*0Sstevel@tonic-gate 	crypto_mech_type_t prov_decr_mechid, prov_mac_mechid;
870*0Sstevel@tonic-gate 	kcf_prov_tried_t *list = NULL;
871*0Sstevel@tonic-gate 	boolean_t decr_tmpl_checked = B_FALSE;
872*0Sstevel@tonic-gate 	boolean_t mac_tmpl_checked = B_FALSE;
873*0Sstevel@tonic-gate 	kcf_dual_req_t *next_req = NULL;
874*0Sstevel@tonic-gate 	crypto_call_req_t mac_req, *mac_reqp = NULL;
875*0Sstevel@tonic-gate 
876*0Sstevel@tonic-gate retry:
877*0Sstevel@tonic-gate 	/* pd is returned held on success */
878*0Sstevel@tonic-gate 	pd = kcf_get_dual_provider(decr_mech, mac_mech, &me, &prov_decr_mechid,
879*0Sstevel@tonic-gate 	    &prov_mac_mechid, &error, list,
880*0Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
881*0Sstevel@tonic-gate 	    CRYPTO_FG_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
882*0Sstevel@tonic-gate 	    CHECK_RESTRICT(crq), ct->dd_len2);
883*0Sstevel@tonic-gate 	if (pd == NULL) {
884*0Sstevel@tonic-gate 		if (list != NULL)
885*0Sstevel@tonic-gate 			kcf_free_triedlist(list);
886*0Sstevel@tonic-gate 		if (next_req != NULL)
887*0Sstevel@tonic-gate 			kmem_free(next_req, sizeof (kcf_dual_req_t));
888*0Sstevel@tonic-gate 		return (CRYPTO_MECH_NOT_SUPPORTED);
889*0Sstevel@tonic-gate 	}
890*0Sstevel@tonic-gate 
891*0Sstevel@tonic-gate 	/*
892*0Sstevel@tonic-gate 	 * For SW providers, check the validity of the context template
893*0Sstevel@tonic-gate 	 * It is very rare that the generation number mis-matches, so
894*0Sstevel@tonic-gate 	 * is acceptable to fail here, and let the consumer recover by
895*0Sstevel@tonic-gate 	 * freeing this tmpl and create a new one for the key and new SW
896*0Sstevel@tonic-gate 	 * provider
897*0Sstevel@tonic-gate 	 */
898*0Sstevel@tonic-gate 
899*0Sstevel@tonic-gate 	if ((!decr_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
900*0Sstevel@tonic-gate 		if (decr_tmpl != NULL) {
901*0Sstevel@tonic-gate 			ctx_decr_tmpl = (kcf_ctx_template_t *)decr_tmpl;
902*0Sstevel@tonic-gate 			if (ctx_decr_tmpl->ct_generation != me->me_gen_swprov) {
903*0Sstevel@tonic-gate 				if (next_req != NULL)
904*0Sstevel@tonic-gate 					kmem_free(next_req,
905*0Sstevel@tonic-gate 					    sizeof (kcf_dual_req_t));
906*0Sstevel@tonic-gate 				if (list != NULL)
907*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
908*0Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
909*0Sstevel@tonic-gate 
910*0Sstevel@tonic-gate 				/* Which one is the the old one ? */
911*0Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
912*0Sstevel@tonic-gate 			}
913*0Sstevel@tonic-gate 			spi_decr_tmpl = ctx_decr_tmpl->ct_prov_tmpl;
914*0Sstevel@tonic-gate 		}
915*0Sstevel@tonic-gate 		decr_tmpl_checked = B_TRUE;
916*0Sstevel@tonic-gate 	}
917*0Sstevel@tonic-gate 	if (prov_mac_mechid == CRYPTO_MECH_INVALID) {
918*0Sstevel@tonic-gate 		/* Need to emulate with 2 internal calls */
919*0Sstevel@tonic-gate 
920*0Sstevel@tonic-gate 		/* Prepare the call_req to be submitted for the MAC step */
921*0Sstevel@tonic-gate 
922*0Sstevel@tonic-gate 		if (crq != NULL) {
923*0Sstevel@tonic-gate 
924*0Sstevel@tonic-gate 			if (next_req == NULL) {
925*0Sstevel@tonic-gate 				/*
926*0Sstevel@tonic-gate 				 * allocate, initialize and prepare the
927*0Sstevel@tonic-gate 				 * params for the next step only in the
928*0Sstevel@tonic-gate 				 * first pass (not on every retry).
929*0Sstevel@tonic-gate 				 */
930*0Sstevel@tonic-gate 				next_req = kcf_alloc_req(crq);
931*0Sstevel@tonic-gate 
932*0Sstevel@tonic-gate 				if (next_req == NULL) {
933*0Sstevel@tonic-gate 					KCF_PROV_REFRELE(pd);
934*0Sstevel@tonic-gate 					if (list != NULL)
935*0Sstevel@tonic-gate 						kcf_free_triedlist(list);
936*0Sstevel@tonic-gate 					return (CRYPTO_HOST_MEMORY);
937*0Sstevel@tonic-gate 				}
938*0Sstevel@tonic-gate 				KCF_WRAP_DECRYPT_OPS_PARAMS(
939*0Sstevel@tonic-gate 				    &(next_req->kr_params), KCF_OP_ATOMIC,
940*0Sstevel@tonic-gate 				    NULL, decr_mech, decr_key,
941*0Sstevel@tonic-gate 				    (crypto_data_t *)ct, pt, spi_decr_tmpl);
942*0Sstevel@tonic-gate 			}
943*0Sstevel@tonic-gate 
944*0Sstevel@tonic-gate 			mac_req.cr_flag = (crq != NULL) ? crq->cr_flag : 0;
945*0Sstevel@tonic-gate 			mac_req.cr_flag |= CRYPTO_SETDUAL;
946*0Sstevel@tonic-gate 			mac_req.cr_callback_func = kcf_next_req;
947*0Sstevel@tonic-gate 			mac_req.cr_callback_arg = next_req;
948*0Sstevel@tonic-gate 			mac_reqp = &mac_req;
949*0Sstevel@tonic-gate 		}
950*0Sstevel@tonic-gate 
951*0Sstevel@tonic-gate 		/* 'pd' is the decryption provider. */
952*0Sstevel@tonic-gate 
953*0Sstevel@tonic-gate 		if (do_verify)
954*0Sstevel@tonic-gate 			error = crypto_mac_verify(mac_mech, (crypto_data_t *)ct,
955*0Sstevel@tonic-gate 			    mac_key, mac_tmpl, mac,
956*0Sstevel@tonic-gate 			    (crq == NULL) ? NULL : mac_reqp);
957*0Sstevel@tonic-gate 		else
958*0Sstevel@tonic-gate 			error = crypto_mac(mac_mech, (crypto_data_t *)ct,
959*0Sstevel@tonic-gate 			    mac_key, mac_tmpl, mac,
960*0Sstevel@tonic-gate 			    (crq == NULL) ? NULL : mac_reqp);
961*0Sstevel@tonic-gate 
962*0Sstevel@tonic-gate 		switch (error) {
963*0Sstevel@tonic-gate 		case CRYPTO_SUCCESS: {
964*0Sstevel@tonic-gate 			off_t saveoffset;
965*0Sstevel@tonic-gate 			size_t savelen;
966*0Sstevel@tonic-gate 
967*0Sstevel@tonic-gate 			if (next_req == NULL) {
968*0Sstevel@tonic-gate 				saveoffset = ct->dd_offset1;
969*0Sstevel@tonic-gate 				savelen = ct->dd_len1;
970*0Sstevel@tonic-gate 			} else {
971*0Sstevel@tonic-gate 				saveoffset = next_req->kr_saveoffset =
972*0Sstevel@tonic-gate 				    ct->dd_offset1;
973*0Sstevel@tonic-gate 				savelen = next_req->kr_savelen = ct->dd_len1;
974*0Sstevel@tonic-gate 
975*0Sstevel@tonic-gate 				ASSERT(mac_reqp != NULL);
976*0Sstevel@tonic-gate 				mac_req.cr_flag &= ~CRYPTO_SETDUAL;
977*0Sstevel@tonic-gate 				mac_req.cr_callback_func = kcf_last_req;
978*0Sstevel@tonic-gate 			}
979*0Sstevel@tonic-gate 			ct->dd_offset1 = ct->dd_offset2;
980*0Sstevel@tonic-gate 			ct->dd_len1 = ct->dd_len2;
981*0Sstevel@tonic-gate 
982*0Sstevel@tonic-gate 			if (CHECK_FASTPATH(crq, pd)) {
983*0Sstevel@tonic-gate 				crypto_mechanism_t lmech;
984*0Sstevel@tonic-gate 
985*0Sstevel@tonic-gate 				lmech = *decr_mech;
986*0Sstevel@tonic-gate 				KCF_SET_PROVIDER_MECHNUM(decr_mech->cm_type,
987*0Sstevel@tonic-gate 				    pd, &lmech);
988*0Sstevel@tonic-gate 
989*0Sstevel@tonic-gate 				error = KCF_PROV_DECRYPT_ATOMIC(pd, pd->pd_sid,
990*0Sstevel@tonic-gate 				    &lmech, decr_key, (crypto_data_t *)ct,
991*0Sstevel@tonic-gate 				    (crypto_data_t *)pt, spi_decr_tmpl,
992*0Sstevel@tonic-gate 				    KCF_SWFP_RHNDL(mac_reqp));
993*0Sstevel@tonic-gate 
994*0Sstevel@tonic-gate 				KCF_PROV_INCRSTATS(pd, error);
995*0Sstevel@tonic-gate 			} else {
996*0Sstevel@tonic-gate 				KCF_WRAP_DECRYPT_OPS_PARAMS(&params,
997*0Sstevel@tonic-gate 				    KCF_OP_ATOMIC, pd->pd_sid, decr_mech,
998*0Sstevel@tonic-gate 				    decr_key, (crypto_data_t *)ct, pt,
999*0Sstevel@tonic-gate 				    spi_decr_tmpl);
1000*0Sstevel@tonic-gate 
1001*0Sstevel@tonic-gate 				error = kcf_submit_request(pd, NULL,
1002*0Sstevel@tonic-gate 				    (crq == NULL) ? NULL : mac_reqp,
1003*0Sstevel@tonic-gate 				    &params, B_FALSE);
1004*0Sstevel@tonic-gate 			}
1005*0Sstevel@tonic-gate 			if (error != CRYPTO_QUEUED) {
1006*0Sstevel@tonic-gate 				KCF_PROV_INCRSTATS(pd, error);
1007*0Sstevel@tonic-gate 				ct->dd_offset1 = saveoffset;
1008*0Sstevel@tonic-gate 				ct->dd_len1 = savelen;
1009*0Sstevel@tonic-gate 			}
1010*0Sstevel@tonic-gate 			break;
1011*0Sstevel@tonic-gate 		}
1012*0Sstevel@tonic-gate 
1013*0Sstevel@tonic-gate 		case CRYPTO_QUEUED:
1014*0Sstevel@tonic-gate 			if ((crq != NULL) && (crq->cr_flag & CRYPTO_SKIP_REQID))
1015*0Sstevel@tonic-gate 				crq->cr_reqid = mac_req.cr_reqid;
1016*0Sstevel@tonic-gate 			break;
1017*0Sstevel@tonic-gate 
1018*0Sstevel@tonic-gate 		default:
1019*0Sstevel@tonic-gate 			if (IS_RECOVERABLE(error)) {
1020*0Sstevel@tonic-gate 				if (kcf_insert_triedlist(&list, pd,
1021*0Sstevel@tonic-gate 				    KCF_KMFLAG(crq)) != NULL)
1022*0Sstevel@tonic-gate 					goto retry;
1023*0Sstevel@tonic-gate 			}
1024*0Sstevel@tonic-gate 		}
1025*0Sstevel@tonic-gate 		if (error != CRYPTO_QUEUED && next_req != NULL)
1026*0Sstevel@tonic-gate 			kmem_free(next_req, sizeof (kcf_dual_req_t));
1027*0Sstevel@tonic-gate 		if (list != NULL)
1028*0Sstevel@tonic-gate 			kcf_free_triedlist(list);
1029*0Sstevel@tonic-gate 		KCF_PROV_REFRELE(pd);
1030*0Sstevel@tonic-gate 		return (error);
1031*0Sstevel@tonic-gate 	}
1032*0Sstevel@tonic-gate 
1033*0Sstevel@tonic-gate 	if ((!mac_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
1034*0Sstevel@tonic-gate 		if ((mac_tmpl != NULL) &&
1035*0Sstevel@tonic-gate 		    (prov_mac_mechid != CRYPTO_MECH_INVALID)) {
1036*0Sstevel@tonic-gate 			ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
1037*0Sstevel@tonic-gate 			if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
1038*0Sstevel@tonic-gate 				if (next_req != NULL)
1039*0Sstevel@tonic-gate 					kmem_free(next_req,
1040*0Sstevel@tonic-gate 					    sizeof (kcf_dual_req_t));
1041*0Sstevel@tonic-gate 				if (list != NULL)
1042*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
1043*0Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
1044*0Sstevel@tonic-gate 
1045*0Sstevel@tonic-gate 				/* Which one is the the old one ? */
1046*0Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
1047*0Sstevel@tonic-gate 			}
1048*0Sstevel@tonic-gate 			spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
1049*0Sstevel@tonic-gate 		}
1050*0Sstevel@tonic-gate 		mac_tmpl_checked = B_TRUE;
1051*0Sstevel@tonic-gate 	}
1052*0Sstevel@tonic-gate 
1053*0Sstevel@tonic-gate 	/* The fast path for SW providers. */
1054*0Sstevel@tonic-gate 	if (CHECK_FASTPATH(crq, pd)) {
1055*0Sstevel@tonic-gate 		crypto_mechanism_t lmac_mech;
1056*0Sstevel@tonic-gate 		crypto_mechanism_t ldecr_mech;
1057*0Sstevel@tonic-gate 
1058*0Sstevel@tonic-gate 		/* careful! structs assignments */
1059*0Sstevel@tonic-gate 		ldecr_mech = *decr_mech;
1060*0Sstevel@tonic-gate 		ldecr_mech.cm_type = prov_decr_mechid;
1061*0Sstevel@tonic-gate 		lmac_mech = *mac_mech;
1062*0Sstevel@tonic-gate 		lmac_mech.cm_type = prov_mac_mechid;
1063*0Sstevel@tonic-gate 
1064*0Sstevel@tonic-gate 		if (do_verify)
1065*0Sstevel@tonic-gate 			error = KCF_PROV_MAC_VERIFY_DECRYPT_ATOMIC(pd,
1066*0Sstevel@tonic-gate 			    pd->pd_sid, &lmac_mech, mac_key, &ldecr_mech,
1067*0Sstevel@tonic-gate 			    decr_key, ct, mac, pt, spi_mac_tmpl, spi_decr_tmpl,
1068*0Sstevel@tonic-gate 			    KCF_SWFP_RHNDL(crq));
1069*0Sstevel@tonic-gate 		else
1070*0Sstevel@tonic-gate 			error = KCF_PROV_MAC_DECRYPT_ATOMIC(pd, pd->pd_sid,
1071*0Sstevel@tonic-gate 			    &lmac_mech, mac_key, &ldecr_mech, decr_key,
1072*0Sstevel@tonic-gate 			    ct, mac, pt, spi_mac_tmpl, spi_decr_tmpl,
1073*0Sstevel@tonic-gate 			    KCF_SWFP_RHNDL(crq));
1074*0Sstevel@tonic-gate 
1075*0Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
1076*0Sstevel@tonic-gate 	} else {
1077*0Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params,
1078*0Sstevel@tonic-gate 		    (do_verify) ? KCF_OP_MAC_VERIFY_DECRYPT_ATOMIC :
1079*0Sstevel@tonic-gate 		    KCF_OP_ATOMIC, pd->pd_sid, mac_key, decr_key, ct, mac, pt,
1080*0Sstevel@tonic-gate 		    spi_mac_tmpl, spi_decr_tmpl);
1081*0Sstevel@tonic-gate 
1082*0Sstevel@tonic-gate 		cmops = &(params.rp_u.mac_decrypt_params);
1083*0Sstevel@tonic-gate 
1084*0Sstevel@tonic-gate 		/* careful! structs assignments */
1085*0Sstevel@tonic-gate 		cmops->md_decr_mech = *decr_mech;
1086*0Sstevel@tonic-gate 		cmops->md_decr_mech.cm_type = prov_decr_mechid;
1087*0Sstevel@tonic-gate 		cmops->md_framework_decr_mechtype = decr_mech->cm_type;
1088*0Sstevel@tonic-gate 		cmops->md_mac_mech = *mac_mech;
1089*0Sstevel@tonic-gate 		cmops->md_mac_mech.cm_type = prov_mac_mechid;
1090*0Sstevel@tonic-gate 		cmops->md_framework_mac_mechtype = mac_mech->cm_type;
1091*0Sstevel@tonic-gate 
1092*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, NULL, crq, &params, B_FALSE);
1093*0Sstevel@tonic-gate 	}
1094*0Sstevel@tonic-gate 
1095*0Sstevel@tonic-gate 	if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED &&
1096*0Sstevel@tonic-gate 	    IS_RECOVERABLE(error)) {
1097*0Sstevel@tonic-gate 		/* Add pd to the linked list of providers tried. */
1098*0Sstevel@tonic-gate 		if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL)
1099*0Sstevel@tonic-gate 			goto retry;
1100*0Sstevel@tonic-gate 	}
1101*0Sstevel@tonic-gate 
1102*0Sstevel@tonic-gate 	if (list != NULL)
1103*0Sstevel@tonic-gate 		kcf_free_triedlist(list);
1104*0Sstevel@tonic-gate 
1105*0Sstevel@tonic-gate 	if (next_req != NULL)
1106*0Sstevel@tonic-gate 		kmem_free(next_req, sizeof (kcf_dual_req_t));
1107*0Sstevel@tonic-gate 	KCF_PROV_REFRELE(pd);
1108*0Sstevel@tonic-gate 	return (error);
1109*0Sstevel@tonic-gate }
1110*0Sstevel@tonic-gate 
1111*0Sstevel@tonic-gate /*
1112*0Sstevel@tonic-gate  * Starts a multi-part dual mac/decrypt operation. The provider to
1113*0Sstevel@tonic-gate  * use is determined by the KCF dispatcher.
1114*0Sstevel@tonic-gate  */
1115*0Sstevel@tonic-gate /* ARGSUSED */
1116*0Sstevel@tonic-gate int
1117*0Sstevel@tonic-gate crypto_mac_decrypt_init(crypto_mechanism_t *mac_mech,
1118*0Sstevel@tonic-gate     crypto_mechanism_t *decr_mech, crypto_key_t *mac_key,
1119*0Sstevel@tonic-gate     crypto_key_t *decr_key, crypto_ctx_template_t mac_tmpl,
1120*0Sstevel@tonic-gate     crypto_ctx_template_t decr_tmpl, crypto_context_t *ctxp,
1121*0Sstevel@tonic-gate     crypto_call_req_t *cr)
1122*0Sstevel@tonic-gate {
1123*0Sstevel@tonic-gate 	/*
1124*0Sstevel@tonic-gate 	 * First try to find a provider for the decryption mechanism, that
1125*0Sstevel@tonic-gate 	 * is also capable of the MAC mechanism.
1126*0Sstevel@tonic-gate 	 * We still favor optimizing the costlier decryption.
1127*0Sstevel@tonic-gate 	 */
1128*0Sstevel@tonic-gate 	int error;
1129*0Sstevel@tonic-gate 	kcf_mech_entry_t *me;
1130*0Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
1131*0Sstevel@tonic-gate 	kcf_ctx_template_t *ctx_decr_tmpl, *ctx_mac_tmpl;
1132*0Sstevel@tonic-gate 	kcf_req_params_t params;
1133*0Sstevel@tonic-gate 	kcf_mac_decrypt_ops_params_t *mdops;
1134*0Sstevel@tonic-gate 	crypto_spi_ctx_template_t spi_decr_tmpl = NULL, spi_mac_tmpl = NULL;
1135*0Sstevel@tonic-gate 	crypto_mech_type_t prov_decr_mechid, prov_mac_mechid;
1136*0Sstevel@tonic-gate 	kcf_prov_tried_t *list = NULL;
1137*0Sstevel@tonic-gate 	boolean_t decr_tmpl_checked = B_FALSE;
1138*0Sstevel@tonic-gate 	boolean_t mac_tmpl_checked = B_FALSE;
1139*0Sstevel@tonic-gate 	crypto_ctx_t *ctx = NULL;
1140*0Sstevel@tonic-gate 	kcf_context_t *decr_kcf_context = NULL, *mac_kcf_context = NULL;
1141*0Sstevel@tonic-gate 	crypto_call_flag_t save_flag;
1142*0Sstevel@tonic-gate 
1143*0Sstevel@tonic-gate retry:
1144*0Sstevel@tonic-gate 	/* pd is returned held on success */
1145*0Sstevel@tonic-gate 	pd = kcf_get_dual_provider(decr_mech, mac_mech, &me, &prov_decr_mechid,
1146*0Sstevel@tonic-gate 	    &prov_mac_mechid, &error, list,
1147*0Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_MAC_DECRYPT, CRYPTO_FG_MAC,
1148*0Sstevel@tonic-gate 	    CHECK_RESTRICT(cr), 0);
1149*0Sstevel@tonic-gate 	if (pd == NULL) {
1150*0Sstevel@tonic-gate 		if (list != NULL)
1151*0Sstevel@tonic-gate 			kcf_free_triedlist(list);
1152*0Sstevel@tonic-gate 		return (error);
1153*0Sstevel@tonic-gate 	}
1154*0Sstevel@tonic-gate 
1155*0Sstevel@tonic-gate 	/*
1156*0Sstevel@tonic-gate 	 * For SW providers, check the validity of the context template
1157*0Sstevel@tonic-gate 	 * It is very rare that the generation number mis-matches, so
1158*0Sstevel@tonic-gate 	 * is acceptable to fail here, and let the consumer recover by
1159*0Sstevel@tonic-gate 	 * freeing this tmpl and create a new one for the key and new SW
1160*0Sstevel@tonic-gate 	 * provider
1161*0Sstevel@tonic-gate 	 * Warning! will need to change when multiple software providers
1162*0Sstevel@tonic-gate 	 * per mechanism are supported.
1163*0Sstevel@tonic-gate 	 */
1164*0Sstevel@tonic-gate 
1165*0Sstevel@tonic-gate 	if ((!decr_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
1166*0Sstevel@tonic-gate 		if (decr_tmpl != NULL) {
1167*0Sstevel@tonic-gate 			ctx_decr_tmpl = (kcf_ctx_template_t *)decr_tmpl;
1168*0Sstevel@tonic-gate 			if (ctx_decr_tmpl->ct_generation != me->me_gen_swprov) {
1169*0Sstevel@tonic-gate 
1170*0Sstevel@tonic-gate 				if (list != NULL)
1171*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
1172*0Sstevel@tonic-gate 				if (decr_kcf_context != NULL)
1173*0Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(decr_kcf_context);
1174*0Sstevel@tonic-gate 
1175*0Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
1176*0Sstevel@tonic-gate 				/* Which one is the the old one ? */
1177*0Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
1178*0Sstevel@tonic-gate 			}
1179*0Sstevel@tonic-gate 			spi_decr_tmpl = ctx_decr_tmpl->ct_prov_tmpl;
1180*0Sstevel@tonic-gate 		}
1181*0Sstevel@tonic-gate 		decr_tmpl_checked = B_TRUE;
1182*0Sstevel@tonic-gate 	}
1183*0Sstevel@tonic-gate 
1184*0Sstevel@tonic-gate 	if (prov_mac_mechid == CRYPTO_MECH_INVALID) {
1185*0Sstevel@tonic-gate 		/* Need to emulate with 2 internal calls */
1186*0Sstevel@tonic-gate 
1187*0Sstevel@tonic-gate 		/*
1188*0Sstevel@tonic-gate 		 * We avoid code complexity by limiting the pure async.
1189*0Sstevel@tonic-gate 		 * case to be done using only a SW provider.
1190*0Sstevel@tonic-gate 		 * XXX - Redo the emulation code below so that we can
1191*0Sstevel@tonic-gate 		 * remove this limitation.
1192*0Sstevel@tonic-gate 		 */
1193*0Sstevel@tonic-gate 		if (cr != NULL && pd->pd_prov_type == CRYPTO_HW_PROVIDER) {
1194*0Sstevel@tonic-gate 			if ((kcf_insert_triedlist(&list, pd, KCF_KMFLAG(cr))
1195*0Sstevel@tonic-gate 			    != NULL))
1196*0Sstevel@tonic-gate 				goto retry;
1197*0Sstevel@tonic-gate 			if (list != NULL)
1198*0Sstevel@tonic-gate 				kcf_free_triedlist(list);
1199*0Sstevel@tonic-gate 			if (decr_kcf_context != NULL)
1200*0Sstevel@tonic-gate 				KCF_CONTEXT_REFRELE(decr_kcf_context);
1201*0Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
1202*0Sstevel@tonic-gate 			return (CRYPTO_HOST_MEMORY);
1203*0Sstevel@tonic-gate 		}
1204*0Sstevel@tonic-gate 
1205*0Sstevel@tonic-gate 		if (ctx == NULL && pd->pd_prov_type == CRYPTO_SW_PROVIDER) {
1206*0Sstevel@tonic-gate 			ctx = kcf_new_ctx(cr, pd, pd->pd_sid);
1207*0Sstevel@tonic-gate 			if (ctx == NULL) {
1208*0Sstevel@tonic-gate 				if (list != NULL)
1209*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
1210*0Sstevel@tonic-gate 				if (decr_kcf_context != NULL)
1211*0Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(decr_kcf_context);
1212*0Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
1213*0Sstevel@tonic-gate 				return (CRYPTO_HOST_MEMORY);
1214*0Sstevel@tonic-gate 			}
1215*0Sstevel@tonic-gate 			decr_kcf_context = (kcf_context_t *)
1216*0Sstevel@tonic-gate 			    ctx->cc_framework_private;
1217*0Sstevel@tonic-gate 		}
1218*0Sstevel@tonic-gate 		/*
1219*0Sstevel@tonic-gate 		 * Trade-off speed vs avoidance of code complexity and
1220*0Sstevel@tonic-gate 		 * duplication:
1221*0Sstevel@tonic-gate 		 * Could do all the combinations of fastpath / synch / asynch
1222*0Sstevel@tonic-gate 		 * for the decryption and the mac steps. Early attempts
1223*0Sstevel@tonic-gate 		 * showed the code grew wild and bug-prone, for little gain.
1224*0Sstevel@tonic-gate 		 * Therefore, the adaptative asynch case is not implemented.
1225*0Sstevel@tonic-gate 		 * It's either pure synchronous, or pure asynchronous.
1226*0Sstevel@tonic-gate 		 * We still preserve a fastpath for the pure synchronous
1227*0Sstevel@tonic-gate 		 * requests to SW providers.
1228*0Sstevel@tonic-gate 		 */
1229*0Sstevel@tonic-gate 		if (cr == NULL) {
1230*0Sstevel@tonic-gate 			crypto_context_t mac_context;
1231*0Sstevel@tonic-gate 
1232*0Sstevel@tonic-gate 			error = crypto_mac_init(mac_mech, mac_key, mac_tmpl,
1233*0Sstevel@tonic-gate 			    &mac_context, NULL);
1234*0Sstevel@tonic-gate 
1235*0Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS) {
1236*0Sstevel@tonic-gate 				/* Can't be CRYPTO_QUEUED. return the failure */
1237*0Sstevel@tonic-gate 				if (list != NULL)
1238*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
1239*0Sstevel@tonic-gate 
1240*0Sstevel@tonic-gate 				if (decr_kcf_context != NULL)
1241*0Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(decr_kcf_context);
1242*0Sstevel@tonic-gate 				return (error);
1243*0Sstevel@tonic-gate 			}
1244*0Sstevel@tonic-gate 			if (pd->pd_prov_type == CRYPTO_SW_PROVIDER) {
1245*0Sstevel@tonic-gate 				crypto_mechanism_t lmech = *decr_mech;
1246*0Sstevel@tonic-gate 
1247*0Sstevel@tonic-gate 				lmech.cm_type = prov_decr_mechid;
1248*0Sstevel@tonic-gate 
1249*0Sstevel@tonic-gate 				error = KCF_PROV_DECRYPT_INIT(pd, ctx, &lmech,
1250*0Sstevel@tonic-gate 				    decr_key, spi_decr_tmpl,
1251*0Sstevel@tonic-gate 				    KCF_RHNDL(KM_SLEEP));
1252*0Sstevel@tonic-gate 			} else {
1253*0Sstevel@tonic-gate 				/*
1254*0Sstevel@tonic-gate 				 * If we did the 'goto retry' then ctx may not
1255*0Sstevel@tonic-gate 				 * be NULL.  In general, we can't reuse another
1256*0Sstevel@tonic-gate 				 * provider's context, so we free it now so
1257*0Sstevel@tonic-gate 				 * we don't leak it.
1258*0Sstevel@tonic-gate 				 */
1259*0Sstevel@tonic-gate 				if (ctx != NULL) {
1260*0Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE((kcf_context_t *)
1261*0Sstevel@tonic-gate 					    ctx->cc_framework_private);
1262*0Sstevel@tonic-gate 					decr_kcf_context = NULL;
1263*0Sstevel@tonic-gate 				}
1264*0Sstevel@tonic-gate 				error = crypto_decrypt_init_prov(pd, pd->pd_sid,
1265*0Sstevel@tonic-gate 				    decr_mech, decr_key, &decr_tmpl,
1266*0Sstevel@tonic-gate 				    (crypto_context_t *)&ctx, NULL);
1267*0Sstevel@tonic-gate 
1268*0Sstevel@tonic-gate 				if (error == CRYPTO_SUCCESS) {
1269*0Sstevel@tonic-gate 					decr_kcf_context = (kcf_context_t *)
1270*0Sstevel@tonic-gate 					    ctx->cc_framework_private;
1271*0Sstevel@tonic-gate 				}
1272*0Sstevel@tonic-gate 			}
1273*0Sstevel@tonic-gate 
1274*0Sstevel@tonic-gate 			KCF_PROV_INCRSTATS(pd, error);
1275*0Sstevel@tonic-gate 
1276*0Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
1277*0Sstevel@tonic-gate 
1278*0Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS) {
1279*0Sstevel@tonic-gate 				/* Can't be CRYPTO_QUEUED. return the failure */
1280*0Sstevel@tonic-gate 				if (list != NULL)
1281*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
1282*0Sstevel@tonic-gate 				if (mac_kcf_context != NULL)
1283*0Sstevel@tonic-gate 					KCF_CONTEXT_REFRELE(mac_kcf_context);
1284*0Sstevel@tonic-gate 
1285*0Sstevel@tonic-gate 				return (error);
1286*0Sstevel@tonic-gate 			}
1287*0Sstevel@tonic-gate 			mac_kcf_context = (kcf_context_t *)
1288*0Sstevel@tonic-gate 			    ((crypto_ctx_t *)mac_context)->
1289*0Sstevel@tonic-gate 			    cc_framework_private;
1290*0Sstevel@tonic-gate 
1291*0Sstevel@tonic-gate 			decr_kcf_context = (kcf_context_t *)
1292*0Sstevel@tonic-gate 			    ctx->cc_framework_private;
1293*0Sstevel@tonic-gate 
1294*0Sstevel@tonic-gate 			/*
1295*0Sstevel@tonic-gate 			 * Here also, the mac context is second. The callback
1296*0Sstevel@tonic-gate 			 * case can't overwrite the context returned to
1297*0Sstevel@tonic-gate 			 * the caller.
1298*0Sstevel@tonic-gate 			 */
1299*0Sstevel@tonic-gate 			decr_kcf_context->kc_secondctx = mac_kcf_context;
1300*0Sstevel@tonic-gate 			KCF_CONTEXT_REFHOLD(mac_kcf_context);
1301*0Sstevel@tonic-gate 
1302*0Sstevel@tonic-gate 			*ctxp = (crypto_context_t)ctx;
1303*0Sstevel@tonic-gate 
1304*0Sstevel@tonic-gate 			return (error);
1305*0Sstevel@tonic-gate 		}
1306*0Sstevel@tonic-gate 		/* submit a pure asynchronous request. */
1307*0Sstevel@tonic-gate 		save_flag = cr->cr_flag;
1308*0Sstevel@tonic-gate 		cr->cr_flag |= CRYPTO_ALWAYS_QUEUE;
1309*0Sstevel@tonic-gate 
1310*0Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_INIT,
1311*0Sstevel@tonic-gate 		    pd->pd_sid, mac_key, decr_key, NULL, NULL, NULL,
1312*0Sstevel@tonic-gate 		    spi_mac_tmpl, spi_decr_tmpl);
1313*0Sstevel@tonic-gate 
1314*0Sstevel@tonic-gate 		mdops = &(params.rp_u.mac_decrypt_params);
1315*0Sstevel@tonic-gate 
1316*0Sstevel@tonic-gate 		/* careful! structs assignments */
1317*0Sstevel@tonic-gate 		mdops->md_decr_mech = *decr_mech;
1318*0Sstevel@tonic-gate 		/*
1319*0Sstevel@tonic-gate 		 * mdops->md_decr_mech.cm_type will be set when we get to
1320*0Sstevel@tonic-gate 		 * kcf_emulate_dual() routine.
1321*0Sstevel@tonic-gate 		 */
1322*0Sstevel@tonic-gate 		mdops->md_framework_decr_mechtype = decr_mech->cm_type;
1323*0Sstevel@tonic-gate 		mdops->md_mac_mech = *mac_mech;
1324*0Sstevel@tonic-gate 
1325*0Sstevel@tonic-gate 		/*
1326*0Sstevel@tonic-gate 		 * mdops->md_mac_mech.cm_type will be set when we know the
1327*0Sstevel@tonic-gate 		 * MAC provider.
1328*0Sstevel@tonic-gate 		 */
1329*0Sstevel@tonic-gate 		mdops->md_framework_mac_mechtype = mac_mech->cm_type;
1330*0Sstevel@tonic-gate 
1331*0Sstevel@tonic-gate 		/*
1332*0Sstevel@tonic-gate 		 * non-NULL ctx->kc_secondctx tells common_submit_request
1333*0Sstevel@tonic-gate 		 * that this request uses separate cipher and MAC contexts.
1334*0Sstevel@tonic-gate 		 * That function will set the MAC context's kc_secondctx to
1335*0Sstevel@tonic-gate 		 * this decrypt context.
1336*0Sstevel@tonic-gate 		 */
1337*0Sstevel@tonic-gate 		decr_kcf_context->kc_secondctx = decr_kcf_context;
1338*0Sstevel@tonic-gate 
1339*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
1340*0Sstevel@tonic-gate 
1341*0Sstevel@tonic-gate 		cr->cr_flag = save_flag;
1342*0Sstevel@tonic-gate 
1343*0Sstevel@tonic-gate 		if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED) {
1344*0Sstevel@tonic-gate 			KCF_CONTEXT_REFRELE(decr_kcf_context);
1345*0Sstevel@tonic-gate 		}
1346*0Sstevel@tonic-gate 		if (list != NULL)
1347*0Sstevel@tonic-gate 			kcf_free_triedlist(list);
1348*0Sstevel@tonic-gate 		*ctxp =  ctx;
1349*0Sstevel@tonic-gate 		KCF_PROV_REFRELE(pd);
1350*0Sstevel@tonic-gate 		return (error);
1351*0Sstevel@tonic-gate 	}
1352*0Sstevel@tonic-gate 
1353*0Sstevel@tonic-gate 	if ((!mac_tmpl_checked) && (pd->pd_prov_type == CRYPTO_SW_PROVIDER)) {
1354*0Sstevel@tonic-gate 		if ((mac_tmpl != NULL) &&
1355*0Sstevel@tonic-gate 		    (prov_mac_mechid != CRYPTO_MECH_INVALID)) {
1356*0Sstevel@tonic-gate 			ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
1357*0Sstevel@tonic-gate 			if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
1358*0Sstevel@tonic-gate 
1359*0Sstevel@tonic-gate 				if (list != NULL)
1360*0Sstevel@tonic-gate 					kcf_free_triedlist(list);
1361*0Sstevel@tonic-gate 
1362*0Sstevel@tonic-gate 				KCF_PROV_REFRELE(pd);
1363*0Sstevel@tonic-gate 				/* Which one is the the old one ? */
1364*0Sstevel@tonic-gate 				return (CRYPTO_OLD_CTX_TEMPLATE);
1365*0Sstevel@tonic-gate 			}
1366*0Sstevel@tonic-gate 			spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
1367*0Sstevel@tonic-gate 		}
1368*0Sstevel@tonic-gate 		mac_tmpl_checked = B_TRUE;
1369*0Sstevel@tonic-gate 	}
1370*0Sstevel@tonic-gate 
1371*0Sstevel@tonic-gate 	if (ctx == NULL) {
1372*0Sstevel@tonic-gate 		ctx = kcf_new_ctx(cr, pd, pd->pd_sid);
1373*0Sstevel@tonic-gate 		if (ctx == NULL) {
1374*0Sstevel@tonic-gate 			error = CRYPTO_HOST_MEMORY;
1375*0Sstevel@tonic-gate 			if (list != NULL)
1376*0Sstevel@tonic-gate 				kcf_free_triedlist(list);
1377*0Sstevel@tonic-gate 			return (CRYPTO_HOST_MEMORY);
1378*0Sstevel@tonic-gate 		}
1379*0Sstevel@tonic-gate 		decr_kcf_context = (kcf_context_t *)ctx->cc_framework_private;
1380*0Sstevel@tonic-gate 	}
1381*0Sstevel@tonic-gate 
1382*0Sstevel@tonic-gate 	/* The fast path for SW providers. */
1383*0Sstevel@tonic-gate 	if (CHECK_FASTPATH(cr, pd)) {
1384*0Sstevel@tonic-gate 		crypto_mechanism_t ldecr_mech;
1385*0Sstevel@tonic-gate 		crypto_mechanism_t lmac_mech;
1386*0Sstevel@tonic-gate 
1387*0Sstevel@tonic-gate 		/* careful! structs assignments */
1388*0Sstevel@tonic-gate 		ldecr_mech = *decr_mech;
1389*0Sstevel@tonic-gate 		ldecr_mech.cm_type = prov_decr_mechid;
1390*0Sstevel@tonic-gate 		lmac_mech = *mac_mech;
1391*0Sstevel@tonic-gate 		lmac_mech.cm_type = prov_mac_mechid;
1392*0Sstevel@tonic-gate 
1393*0Sstevel@tonic-gate 		error = KCF_PROV_MAC_DECRYPT_INIT(pd, ctx, &lmac_mech,
1394*0Sstevel@tonic-gate 		    mac_key, &ldecr_mech, decr_key, spi_mac_tmpl, spi_decr_tmpl,
1395*0Sstevel@tonic-gate 		    KCF_SWFP_RHNDL(cr));
1396*0Sstevel@tonic-gate 
1397*0Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
1398*0Sstevel@tonic-gate 	} else {
1399*0Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_INIT,
1400*0Sstevel@tonic-gate 		    pd->pd_sid, mac_key, decr_key, NULL, NULL, NULL,
1401*0Sstevel@tonic-gate 		    spi_mac_tmpl, spi_decr_tmpl);
1402*0Sstevel@tonic-gate 
1403*0Sstevel@tonic-gate 		mdops = &(params.rp_u.mac_decrypt_params);
1404*0Sstevel@tonic-gate 
1405*0Sstevel@tonic-gate 		/* careful! structs assignments */
1406*0Sstevel@tonic-gate 		mdops->md_decr_mech = *decr_mech;
1407*0Sstevel@tonic-gate 		mdops->md_decr_mech.cm_type = prov_decr_mechid;
1408*0Sstevel@tonic-gate 		mdops->md_framework_decr_mechtype = decr_mech->cm_type;
1409*0Sstevel@tonic-gate 		mdops->md_mac_mech = *mac_mech;
1410*0Sstevel@tonic-gate 		mdops->md_mac_mech.cm_type = prov_mac_mechid;
1411*0Sstevel@tonic-gate 		mdops->md_framework_mac_mechtype = mac_mech->cm_type;
1412*0Sstevel@tonic-gate 
1413*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
1414*0Sstevel@tonic-gate 	}
1415*0Sstevel@tonic-gate 
1416*0Sstevel@tonic-gate 	if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED) {
1417*0Sstevel@tonic-gate 		if ((IS_RECOVERABLE(error)) &&
1418*0Sstevel@tonic-gate 		    (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(cr)) != NULL))
1419*0Sstevel@tonic-gate 			goto retry;
1420*0Sstevel@tonic-gate 
1421*0Sstevel@tonic-gate 		KCF_CONTEXT_REFRELE(decr_kcf_context);
1422*0Sstevel@tonic-gate 	} else
1423*0Sstevel@tonic-gate 		*ctxp = (crypto_context_t)ctx;
1424*0Sstevel@tonic-gate 
1425*0Sstevel@tonic-gate 	if (list != NULL)
1426*0Sstevel@tonic-gate 		kcf_free_triedlist(list);
1427*0Sstevel@tonic-gate 
1428*0Sstevel@tonic-gate 	KCF_PROV_REFRELE(pd);
1429*0Sstevel@tonic-gate 	return (error);
1430*0Sstevel@tonic-gate }
1431*0Sstevel@tonic-gate 
1432*0Sstevel@tonic-gate /*
1433*0Sstevel@tonic-gate  * Continues a multi-part dual mac/decrypt operation.
1434*0Sstevel@tonic-gate  */
1435*0Sstevel@tonic-gate /* ARGSUSED */
1436*0Sstevel@tonic-gate int
1437*0Sstevel@tonic-gate crypto_mac_decrypt_update(crypto_context_t context,
1438*0Sstevel@tonic-gate     crypto_dual_data_t *ct, crypto_data_t *pt, crypto_call_req_t *cr)
1439*0Sstevel@tonic-gate {
1440*0Sstevel@tonic-gate 	crypto_ctx_t *ctx = (crypto_ctx_t *)context, *mac_ctx;
1441*0Sstevel@tonic-gate 	kcf_context_t *kcf_ctx, *kcf_mac_ctx;
1442*0Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
1443*0Sstevel@tonic-gate 	int error;
1444*0Sstevel@tonic-gate 	kcf_req_params_t params;
1445*0Sstevel@tonic-gate 
1446*0Sstevel@tonic-gate 	if ((ctx == NULL) ||
1447*0Sstevel@tonic-gate 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
1448*0Sstevel@tonic-gate 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
1449*0Sstevel@tonic-gate 		return (CRYPTO_INVALID_CONTEXT);
1450*0Sstevel@tonic-gate 	}
1451*0Sstevel@tonic-gate 
1452*0Sstevel@tonic-gate 	KCF_PROV_REFHOLD(pd);
1453*0Sstevel@tonic-gate 
1454*0Sstevel@tonic-gate 	if ((kcf_mac_ctx = kcf_ctx->kc_secondctx) != NULL) {
1455*0Sstevel@tonic-gate 		off_t save_offset;
1456*0Sstevel@tonic-gate 		size_t save_len;
1457*0Sstevel@tonic-gate 		crypto_call_flag_t save_flag;
1458*0Sstevel@tonic-gate 
1459*0Sstevel@tonic-gate 		if (kcf_mac_ctx->kc_prov_desc == NULL) {
1460*0Sstevel@tonic-gate 			error = CRYPTO_INVALID_CONTEXT;
1461*0Sstevel@tonic-gate 			goto out;
1462*0Sstevel@tonic-gate 		}
1463*0Sstevel@tonic-gate 		mac_ctx = &kcf_mac_ctx->kc_glbl_ctx;
1464*0Sstevel@tonic-gate 
1465*0Sstevel@tonic-gate 		/* First we submit the MAC request */
1466*0Sstevel@tonic-gate 		if (cr == NULL) {
1467*0Sstevel@tonic-gate 			/*
1468*0Sstevel@tonic-gate 			 * 'ct' is always not NULL.
1469*0Sstevel@tonic-gate 			 */
1470*0Sstevel@tonic-gate 			error = crypto_mac_update((crypto_context_t)mac_ctx,
1471*0Sstevel@tonic-gate 			    (crypto_data_t *)ct, NULL);
1472*0Sstevel@tonic-gate 
1473*0Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS)
1474*0Sstevel@tonic-gate 				goto out;
1475*0Sstevel@tonic-gate 
1476*0Sstevel@tonic-gate 			/* Decrypt a different length only when told so */
1477*0Sstevel@tonic-gate 
1478*0Sstevel@tonic-gate 			save_offset = ct->dd_offset1;
1479*0Sstevel@tonic-gate 			save_len = ct->dd_len1;
1480*0Sstevel@tonic-gate 
1481*0Sstevel@tonic-gate 			if (ct->dd_len2 > 0) {
1482*0Sstevel@tonic-gate 				ct->dd_offset1 = ct->dd_offset2;
1483*0Sstevel@tonic-gate 				ct->dd_len1 = ct->dd_len2;
1484*0Sstevel@tonic-gate 			}
1485*0Sstevel@tonic-gate 
1486*0Sstevel@tonic-gate 			error = crypto_decrypt_update(context,
1487*0Sstevel@tonic-gate 			    (crypto_data_t *)ct, pt, NULL);
1488*0Sstevel@tonic-gate 
1489*0Sstevel@tonic-gate 			ct->dd_offset1 = save_offset;
1490*0Sstevel@tonic-gate 			ct->dd_len1 = save_len;
1491*0Sstevel@tonic-gate 
1492*0Sstevel@tonic-gate 			goto out;
1493*0Sstevel@tonic-gate 		}
1494*0Sstevel@tonic-gate 		/* submit a pure asynchronous request. */
1495*0Sstevel@tonic-gate 		save_flag = cr->cr_flag;
1496*0Sstevel@tonic-gate 		cr->cr_flag |= CRYPTO_ALWAYS_QUEUE;
1497*0Sstevel@tonic-gate 
1498*0Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE,
1499*0Sstevel@tonic-gate 		    pd->pd_sid, NULL, NULL, ct, NULL, pt, NULL, NULL)
1500*0Sstevel@tonic-gate 
1501*0Sstevel@tonic-gate 
1502*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
1503*0Sstevel@tonic-gate 
1504*0Sstevel@tonic-gate 		cr->cr_flag = save_flag;
1505*0Sstevel@tonic-gate 		goto out;
1506*0Sstevel@tonic-gate 	}
1507*0Sstevel@tonic-gate 
1508*0Sstevel@tonic-gate 	/* The fast path for SW providers. */
1509*0Sstevel@tonic-gate 	if (CHECK_FASTPATH(cr, pd)) {
1510*0Sstevel@tonic-gate 		error = KCF_PROV_MAC_DECRYPT_UPDATE(pd, ctx, ct, pt, NULL);
1511*0Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
1512*0Sstevel@tonic-gate 	} else {
1513*0Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE,
1514*0Sstevel@tonic-gate 		    pd->pd_sid, NULL, NULL, ct, NULL, pt, NULL, NULL);
1515*0Sstevel@tonic-gate 
1516*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
1517*0Sstevel@tonic-gate 	}
1518*0Sstevel@tonic-gate out:
1519*0Sstevel@tonic-gate 	KCF_PROV_REFRELE(pd);
1520*0Sstevel@tonic-gate 	return (error);
1521*0Sstevel@tonic-gate }
1522*0Sstevel@tonic-gate 
1523*0Sstevel@tonic-gate /*
1524*0Sstevel@tonic-gate  * Terminates a multi-part dual mac/decrypt operation.
1525*0Sstevel@tonic-gate  */
1526*0Sstevel@tonic-gate /* ARGSUSED */
1527*0Sstevel@tonic-gate int
1528*0Sstevel@tonic-gate crypto_mac_decrypt_final(crypto_context_t context, crypto_data_t *mac,
1529*0Sstevel@tonic-gate     crypto_data_t *pt, crypto_call_req_t *cr)
1530*0Sstevel@tonic-gate {
1531*0Sstevel@tonic-gate 	crypto_ctx_t *ctx = (crypto_ctx_t *)context, *mac_ctx;
1532*0Sstevel@tonic-gate 	kcf_context_t *kcf_ctx, *kcf_mac_ctx;
1533*0Sstevel@tonic-gate 	kcf_provider_desc_t *pd;
1534*0Sstevel@tonic-gate 	int error;
1535*0Sstevel@tonic-gate 	kcf_req_params_t params;
1536*0Sstevel@tonic-gate 
1537*0Sstevel@tonic-gate 	if ((ctx == NULL) ||
1538*0Sstevel@tonic-gate 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
1539*0Sstevel@tonic-gate 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
1540*0Sstevel@tonic-gate 		return (CRYPTO_INVALID_CONTEXT);
1541*0Sstevel@tonic-gate 	}
1542*0Sstevel@tonic-gate 
1543*0Sstevel@tonic-gate 	KCF_PROV_REFHOLD(pd);
1544*0Sstevel@tonic-gate 
1545*0Sstevel@tonic-gate 	if ((kcf_mac_ctx = kcf_ctx->kc_secondctx) != NULL) {
1546*0Sstevel@tonic-gate 		crypto_call_flag_t save_flag;
1547*0Sstevel@tonic-gate 
1548*0Sstevel@tonic-gate 		if (kcf_mac_ctx->kc_prov_desc == NULL) {
1549*0Sstevel@tonic-gate 			error = CRYPTO_INVALID_CONTEXT;
1550*0Sstevel@tonic-gate 			goto out;
1551*0Sstevel@tonic-gate 		}
1552*0Sstevel@tonic-gate 		mac_ctx = &kcf_mac_ctx->kc_glbl_ctx;
1553*0Sstevel@tonic-gate 
1554*0Sstevel@tonic-gate 		/* First we collect the MAC */
1555*0Sstevel@tonic-gate 		if (cr == NULL) {
1556*0Sstevel@tonic-gate 
1557*0Sstevel@tonic-gate 			error = crypto_mac_final((crypto_context_t)mac_ctx,
1558*0Sstevel@tonic-gate 			    mac, NULL);
1559*0Sstevel@tonic-gate 
1560*0Sstevel@tonic-gate 			if (error != CRYPTO_SUCCESS) {
1561*0Sstevel@tonic-gate 				crypto_cancel_ctx(ctx);
1562*0Sstevel@tonic-gate 			} else {
1563*0Sstevel@tonic-gate 				/* Get the last chunk of plaintext */
1564*0Sstevel@tonic-gate 				error = crypto_decrypt_final(context, pt, NULL);
1565*0Sstevel@tonic-gate 			}
1566*0Sstevel@tonic-gate 
1567*0Sstevel@tonic-gate 			KCF_PROV_REFRELE(pd);
1568*0Sstevel@tonic-gate 			return (error);
1569*0Sstevel@tonic-gate 		}
1570*0Sstevel@tonic-gate 		/* submit a pure asynchronous request. */
1571*0Sstevel@tonic-gate 		save_flag = cr->cr_flag;
1572*0Sstevel@tonic-gate 		cr->cr_flag |= CRYPTO_ALWAYS_QUEUE;
1573*0Sstevel@tonic-gate 
1574*0Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_FINAL,
1575*0Sstevel@tonic-gate 		    pd->pd_sid, NULL, NULL, NULL, mac, pt, NULL, NULL)
1576*0Sstevel@tonic-gate 
1577*0Sstevel@tonic-gate 
1578*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
1579*0Sstevel@tonic-gate 
1580*0Sstevel@tonic-gate 		cr->cr_flag = save_flag;
1581*0Sstevel@tonic-gate 
1582*0Sstevel@tonic-gate 		KCF_PROV_REFRELE(pd);
1583*0Sstevel@tonic-gate 		return (error);
1584*0Sstevel@tonic-gate 	}
1585*0Sstevel@tonic-gate 
1586*0Sstevel@tonic-gate 	/* The fast path for SW providers. */
1587*0Sstevel@tonic-gate 	if (CHECK_FASTPATH(cr, pd)) {
1588*0Sstevel@tonic-gate 		error = KCF_PROV_MAC_DECRYPT_FINAL(pd, ctx, mac, pt, NULL);
1589*0Sstevel@tonic-gate 		KCF_PROV_INCRSTATS(pd, error);
1590*0Sstevel@tonic-gate 	} else {
1591*0Sstevel@tonic-gate 		KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_FINAL,
1592*0Sstevel@tonic-gate 		    pd->pd_sid, NULL, NULL, NULL, mac, pt, NULL, NULL);
1593*0Sstevel@tonic-gate 
1594*0Sstevel@tonic-gate 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
1595*0Sstevel@tonic-gate 	}
1596*0Sstevel@tonic-gate out:
1597*0Sstevel@tonic-gate 	KCF_PROV_REFRELE(pd);
1598*0Sstevel@tonic-gate 	/* Release the hold done in kcf_new_ctx() during init step. */
1599*0Sstevel@tonic-gate 	KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
1600*0Sstevel@tonic-gate 	return (error);
1601*0Sstevel@tonic-gate }
1602*0Sstevel@tonic-gate 
1603*0Sstevel@tonic-gate /*
1604*0Sstevel@tonic-gate  * Digest/Encrypt dual operation. Project-private entry point, not part of
1605*0Sstevel@tonic-gate  * the k-API.
1606*0Sstevel@tonic-gate  */
1607*0Sstevel@tonic-gate /* ARGSUSED */
1608*0Sstevel@tonic-gate int
1609*0Sstevel@tonic-gate crypto_digest_encrypt_update(crypto_context_t digest_ctx,
1610*0Sstevel@tonic-gate     crypto_context_t encrypt_ctx, crypto_data_t *plaintext,
1611*0Sstevel@tonic-gate     crypto_data_t *ciphertext, crypto_call_req_t *crq)
1612*0Sstevel@tonic-gate {
1613*0Sstevel@tonic-gate 	/*
1614*0Sstevel@tonic-gate 	 * RFE 4688647:
1615*0Sstevel@tonic-gate 	 * core functions needed by ioctl interface missing from impl.h
1616*0Sstevel@tonic-gate 	 */
1617*0Sstevel@tonic-gate 	return (CRYPTO_NOT_SUPPORTED);
1618*0Sstevel@tonic-gate }
1619*0Sstevel@tonic-gate 
1620*0Sstevel@tonic-gate /*
1621*0Sstevel@tonic-gate  * Decrypt/Digest dual operation. Project-private entry point, not part of
1622*0Sstevel@tonic-gate  * the k-API.
1623*0Sstevel@tonic-gate  */
1624*0Sstevel@tonic-gate /* ARGSUSED */
1625*0Sstevel@tonic-gate int
1626*0Sstevel@tonic-gate crypto_decrypt_digest_update(crypto_context_t decryptctx,
1627*0Sstevel@tonic-gate     crypto_context_t encrypt_ctx, crypto_data_t *ciphertext,
1628*0Sstevel@tonic-gate     crypto_data_t *plaintext, crypto_call_req_t *crq)
1629*0Sstevel@tonic-gate {
1630*0Sstevel@tonic-gate 	/*
1631*0Sstevel@tonic-gate 	 * RFE 4688647:
1632*0Sstevel@tonic-gate 	 * core functions needed by ioctl interface missing from impl.h
1633*0Sstevel@tonic-gate 	 */
1634*0Sstevel@tonic-gate 	return (CRYPTO_NOT_SUPPORTED);
1635*0Sstevel@tonic-gate }
1636*0Sstevel@tonic-gate 
1637*0Sstevel@tonic-gate /*
1638*0Sstevel@tonic-gate  * Sign/Encrypt dual operation. Project-private entry point, not part of
1639*0Sstevel@tonic-gate  * the k-API.
1640*0Sstevel@tonic-gate  */
1641*0Sstevel@tonic-gate /* ARGSUSED */
1642*0Sstevel@tonic-gate int
1643*0Sstevel@tonic-gate crypto_sign_encrypt_update(crypto_context_t sign_ctx,
1644*0Sstevel@tonic-gate     crypto_context_t encrypt_ctx, crypto_data_t *plaintext,
1645*0Sstevel@tonic-gate     crypto_data_t *ciphertext, crypto_call_req_t *crq)
1646*0Sstevel@tonic-gate {
1647*0Sstevel@tonic-gate 	/*
1648*0Sstevel@tonic-gate 	 * RFE 4688647:
1649*0Sstevel@tonic-gate 	 * core functions needed by ioctl interface missing from impl.h
1650*0Sstevel@tonic-gate 	 */
1651*0Sstevel@tonic-gate 	return (CRYPTO_NOT_SUPPORTED);
1652*0Sstevel@tonic-gate }
1653*0Sstevel@tonic-gate 
1654*0Sstevel@tonic-gate /*
1655*0Sstevel@tonic-gate  * Decrypt/Verify dual operation. Project-private entry point, not part of
1656*0Sstevel@tonic-gate  * the k-API.
1657*0Sstevel@tonic-gate  */
1658*0Sstevel@tonic-gate /* ARGSUSED */
1659*0Sstevel@tonic-gate int
1660*0Sstevel@tonic-gate crypto_decrypt_verify_update(crypto_context_t decrypt_ctx,
1661*0Sstevel@tonic-gate     crypto_context_t verify_ctx, crypto_data_t *ciphertext,
1662*0Sstevel@tonic-gate     crypto_data_t *plaintext, crypto_call_req_t *crq)
1663*0Sstevel@tonic-gate {
1664*0Sstevel@tonic-gate 	/*
1665*0Sstevel@tonic-gate 	 * RFE 4688647:
1666*0Sstevel@tonic-gate 	 * core functions needed by ioctl interface missing from impl.h
1667*0Sstevel@tonic-gate 	 */
1668*0Sstevel@tonic-gate 	return (CRYPTO_NOT_SUPPORTED);
1669*0Sstevel@tonic-gate }
1670