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