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