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