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 * Message authentication codes routines. 40*0Sstevel@tonic-gate */ 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate /* 43*0Sstevel@tonic-gate * The following are the possible returned values common to all the routines 44*0Sstevel@tonic-gate * below. The applicability of some of these return values depends on the 45*0Sstevel@tonic-gate * presence of the arguments. 46*0Sstevel@tonic-gate * 47*0Sstevel@tonic-gate * CRYPTO_SUCCESS: The operation completed successfully. 48*0Sstevel@tonic-gate * CRYPTO_QUEUED: A request was submitted successfully. The callback 49*0Sstevel@tonic-gate * routine will be called when the operation is done. 50*0Sstevel@tonic-gate * CRYPTO_INVALID_MECH_NUMBER, CRYPTO_INVALID_MECH_PARAM, or 51*0Sstevel@tonic-gate * CRYPTO_INVALID_MECH for problems with the 'mech'. 52*0Sstevel@tonic-gate * CRYPTO_INVALID_DATA for bogus 'data' 53*0Sstevel@tonic-gate * CRYPTO_HOST_MEMORY for failure to allocate memory to handle this work. 54*0Sstevel@tonic-gate * CRYPTO_INVALID_CONTEXT: Not a valid context. 55*0Sstevel@tonic-gate * CRYPTO_BUSY: Cannot process the request now. Schedule a 56*0Sstevel@tonic-gate * crypto_bufcall(), or try later. 57*0Sstevel@tonic-gate * CRYPTO_NOT_SUPPORTED and CRYPTO_MECH_NOT_SUPPORTED: No provider is 58*0Sstevel@tonic-gate * capable of a function or a mechanism. 59*0Sstevel@tonic-gate * CRYPTO_INVALID_KEY: bogus 'key' argument. 60*0Sstevel@tonic-gate * CRYPTO_INVALID_MAC: bogus 'mac' argument. 61*0Sstevel@tonic-gate */ 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate /* 64*0Sstevel@tonic-gate * crypto_mac_prov() 65*0Sstevel@tonic-gate * 66*0Sstevel@tonic-gate * Arguments: 67*0Sstevel@tonic-gate * mech: crypto_mechanism_t pointer. 68*0Sstevel@tonic-gate * mech_type is a valid value previously returned by 69*0Sstevel@tonic-gate * crypto_mech2id(); 70*0Sstevel@tonic-gate * When the mech's parameter is not NULL, its definition depends 71*0Sstevel@tonic-gate * on the standard definition of the mechanism. 72*0Sstevel@tonic-gate * key: pointer to a crypto_key_t structure. 73*0Sstevel@tonic-gate * data: The message to compute the MAC for. 74*0Sstevel@tonic-gate * mac: Storage for the MAC. The length needed depends on the mechanism. 75*0Sstevel@tonic-gate * tmpl: a crypto_ctx_template_t, opaque template of a context of a 76*0Sstevel@tonic-gate * MAC with the 'mech' using 'key'. 'tmpl' is created by 77*0Sstevel@tonic-gate * a previous call to crypto_create_ctx_template(). 78*0Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 79*0Sstevel@tonic-gate * 80*0Sstevel@tonic-gate * Description: 81*0Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 82*0Sstevel@tonic-gate * single-part message authentication of 'data' with the mechanism 83*0Sstevel@tonic-gate * 'mech', using * the key 'key', on the specified provider with 84*0Sstevel@tonic-gate * the specified session id. 85*0Sstevel@tonic-gate * When complete and successful, 'mac' will contain the message 86*0Sstevel@tonic-gate * authentication code. 87*0Sstevel@tonic-gate * 88*0Sstevel@tonic-gate * Context: 89*0Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'crq'. 90*0Sstevel@tonic-gate * 91*0Sstevel@tonic-gate * Returns: 92*0Sstevel@tonic-gate * See comment in the beginning of the file. 93*0Sstevel@tonic-gate */ 94*0Sstevel@tonic-gate int 95*0Sstevel@tonic-gate crypto_mac_prov(crypto_mechanism_t *mech, crypto_data_t *data, 96*0Sstevel@tonic-gate crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *mac, 97*0Sstevel@tonic-gate crypto_call_req_t *crq, kcf_provider_desc_t *pd, crypto_session_id_t sid) 98*0Sstevel@tonic-gate { 99*0Sstevel@tonic-gate kcf_req_params_t params; 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 102*0Sstevel@tonic-gate KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, sid, mech, key, 103*0Sstevel@tonic-gate data, mac, tmpl); 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate return (kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE)); 106*0Sstevel@tonic-gate } 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate /* 109*0Sstevel@tonic-gate * Same as crypto_mac_prov(), but relies on the KCF scheduler to choose 110*0Sstevel@tonic-gate * a provider. See crypto_mac() comments for more information. 111*0Sstevel@tonic-gate */ 112*0Sstevel@tonic-gate int 113*0Sstevel@tonic-gate crypto_mac(crypto_mechanism_t *mech, crypto_data_t *data, 114*0Sstevel@tonic-gate crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *mac, 115*0Sstevel@tonic-gate crypto_call_req_t *crq) 116*0Sstevel@tonic-gate { 117*0Sstevel@tonic-gate int error; 118*0Sstevel@tonic-gate kcf_mech_entry_t *me; 119*0Sstevel@tonic-gate kcf_req_params_t params; 120*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 121*0Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 122*0Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 123*0Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate retry: 126*0Sstevel@tonic-gate /* The pd is returned held */ 127*0Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 128*0Sstevel@tonic-gate list, CRYPTO_FG_MAC_ATOMIC, CHECK_RESTRICT(crq), 129*0Sstevel@tonic-gate data->cd_length)) == NULL) { 130*0Sstevel@tonic-gate if (list != NULL) 131*0Sstevel@tonic-gate kcf_free_triedlist(list); 132*0Sstevel@tonic-gate return (error); 133*0Sstevel@tonic-gate } 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate /* 136*0Sstevel@tonic-gate * For SW providers, check the validity of the context template 137*0Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 138*0Sstevel@tonic-gate * is acceptable to fail here, and let the consumer recover by 139*0Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 140*0Sstevel@tonic-gate * provider 141*0Sstevel@tonic-gate */ 142*0Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 143*0Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 144*0Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 145*0Sstevel@tonic-gate if (list != NULL) 146*0Sstevel@tonic-gate kcf_free_triedlist(list); 147*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 148*0Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 149*0Sstevel@tonic-gate } else { 150*0Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate /* The fast path for SW providers. */ 155*0Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) { 156*0Sstevel@tonic-gate crypto_mechanism_t lmech; 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate lmech = *mech; 159*0Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate error = KCF_PROV_MAC_ATOMIC(pd, pd->pd_sid, &lmech, key, data, 162*0Sstevel@tonic-gate mac, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq)); 163*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 164*0Sstevel@tonic-gate } else { 165*0Sstevel@tonic-gate KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, pd->pd_sid, 166*0Sstevel@tonic-gate mech, key, data, mac, spi_ctx_tmpl); 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate error = kcf_submit_request(pd, NULL, crq, ¶ms, 169*0Sstevel@tonic-gate KCF_ISDUALREQ(crq)); 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 173*0Sstevel@tonic-gate IS_RECOVERABLE(error)) { 174*0Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 175*0Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 176*0Sstevel@tonic-gate goto retry; 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate if (list != NULL) 180*0Sstevel@tonic-gate kcf_free_triedlist(list); 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 183*0Sstevel@tonic-gate return (error); 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate /* 187*0Sstevel@tonic-gate * Single part operation to compute the MAC corresponding to the specified 188*0Sstevel@tonic-gate * 'data' and to verify that it matches the MAC specified by 'mac'. 189*0Sstevel@tonic-gate * The other arguments are the same as the function crypto_mac_prov(). 190*0Sstevel@tonic-gate */ 191*0Sstevel@tonic-gate int 192*0Sstevel@tonic-gate crypto_mac_verify_prov(crypto_mechanism_t *mech, crypto_data_t *data, 193*0Sstevel@tonic-gate crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *mac, 194*0Sstevel@tonic-gate crypto_call_req_t *crq, kcf_provider_desc_t *pd, crypto_session_id_t sid) 195*0Sstevel@tonic-gate { 196*0Sstevel@tonic-gate kcf_req_params_t params; 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 199*0Sstevel@tonic-gate KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_MAC_VERIFY_ATOMIC, sid, mech, 200*0Sstevel@tonic-gate key, data, mac, tmpl); 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate return (kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE)); 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate /* 206*0Sstevel@tonic-gate * Same as crypto_mac_verify_prov(), but relies on the KCF scheduler to choose 207*0Sstevel@tonic-gate * a provider. See crypto_mac_verify_prov() comments for more information. 208*0Sstevel@tonic-gate */ 209*0Sstevel@tonic-gate int 210*0Sstevel@tonic-gate crypto_mac_verify(crypto_mechanism_t *mech, crypto_data_t *data, 211*0Sstevel@tonic-gate crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *mac, 212*0Sstevel@tonic-gate crypto_call_req_t *crq) 213*0Sstevel@tonic-gate { 214*0Sstevel@tonic-gate int error; 215*0Sstevel@tonic-gate kcf_mech_entry_t *me; 216*0Sstevel@tonic-gate kcf_req_params_t params; 217*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 218*0Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 219*0Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 220*0Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate retry: 223*0Sstevel@tonic-gate /* The pd is returned held */ 224*0Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 225*0Sstevel@tonic-gate list, CRYPTO_FG_MAC_ATOMIC, CHECK_RESTRICT(crq), 226*0Sstevel@tonic-gate data->cd_length)) == NULL) { 227*0Sstevel@tonic-gate if (list != NULL) 228*0Sstevel@tonic-gate kcf_free_triedlist(list); 229*0Sstevel@tonic-gate return (error); 230*0Sstevel@tonic-gate } 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate /* 233*0Sstevel@tonic-gate * For SW providers, check the validity of the context template 234*0Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 235*0Sstevel@tonic-gate * is acceptable to fail here, and let the consumer recover by 236*0Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 237*0Sstevel@tonic-gate * provider 238*0Sstevel@tonic-gate */ 239*0Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 240*0Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 241*0Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 242*0Sstevel@tonic-gate if (list != NULL) 243*0Sstevel@tonic-gate kcf_free_triedlist(list); 244*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 245*0Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 246*0Sstevel@tonic-gate } else { 247*0Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 248*0Sstevel@tonic-gate } 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate /* The fast path for SW providers. */ 252*0Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) { 253*0Sstevel@tonic-gate crypto_mechanism_t lmech; 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate lmech = *mech; 256*0Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gate error = KCF_PROV_MAC_VERIFY_ATOMIC(pd, pd->pd_sid, &lmech, key, 259*0Sstevel@tonic-gate data, mac, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq)); 260*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 261*0Sstevel@tonic-gate } else { 262*0Sstevel@tonic-gate KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_MAC_VERIFY_ATOMIC, 263*0Sstevel@tonic-gate pd->pd_sid, mech, key, data, mac, spi_ctx_tmpl); 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate error = kcf_submit_request(pd, NULL, crq, ¶ms, 266*0Sstevel@tonic-gate KCF_ISDUALREQ(crq)); 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 270*0Sstevel@tonic-gate IS_RECOVERABLE(error)) { 271*0Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 272*0Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 273*0Sstevel@tonic-gate goto retry; 274*0Sstevel@tonic-gate } 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate if (list != NULL) 277*0Sstevel@tonic-gate kcf_free_triedlist(list); 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 280*0Sstevel@tonic-gate return (error); 281*0Sstevel@tonic-gate } 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate /* 285*0Sstevel@tonic-gate * crypto_mac_init_prov() 286*0Sstevel@tonic-gate * 287*0Sstevel@tonic-gate * Arguments: 288*0Sstevel@tonic-gate * pd: pointer to the descriptor of the provider to use for this 289*0Sstevel@tonic-gate * operation. 290*0Sstevel@tonic-gate * sid: provider session id. 291*0Sstevel@tonic-gate * mech: crypto_mechanism_t pointer. 292*0Sstevel@tonic-gate * mech_type is a valid value previously returned by 293*0Sstevel@tonic-gate * crypto_mech2id(); 294*0Sstevel@tonic-gate * When the mech's parameter is not NULL, its definition depends 295*0Sstevel@tonic-gate * on the standard definition of the mechanism. 296*0Sstevel@tonic-gate * key: pointer to a crypto_key_t structure. 297*0Sstevel@tonic-gate * tmpl: a crypto_ctx_template_t, opaque template of a context of a 298*0Sstevel@tonic-gate * MAC with the 'mech' using 'key'. 'tmpl' is created by 299*0Sstevel@tonic-gate * a previous call to crypto_create_ctx_template(). 300*0Sstevel@tonic-gate * ctxp: Pointer to a crypto_context_t. 301*0Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 302*0Sstevel@tonic-gate * 303*0Sstevel@tonic-gate * Description: 304*0Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs the 305*0Sstevel@tonic-gate * initialization of a MAC operation on the specified provider with 306*0Sstevel@tonic-gate * the specified session. 307*0Sstevel@tonic-gate * When possible and applicable, will internally use the pre-computed MAC 308*0Sstevel@tonic-gate * context from the context template, tmpl. 309*0Sstevel@tonic-gate * When complete and successful, 'ctxp' will contain a crypto_context_t 310*0Sstevel@tonic-gate * valid for later calls to mac_update() and mac_final(). 311*0Sstevel@tonic-gate * The caller should hold a reference on the specified provider 312*0Sstevel@tonic-gate * descriptor before calling this function. 313*0Sstevel@tonic-gate * 314*0Sstevel@tonic-gate * Context: 315*0Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 316*0Sstevel@tonic-gate * 317*0Sstevel@tonic-gate * Returns: 318*0Sstevel@tonic-gate * See comment in the beginning of the file. 319*0Sstevel@tonic-gate */ 320*0Sstevel@tonic-gate int 321*0Sstevel@tonic-gate crypto_mac_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid, 322*0Sstevel@tonic-gate crypto_mechanism_t *mech, crypto_key_t *key, crypto_spi_ctx_template_t tmpl, 323*0Sstevel@tonic-gate crypto_context_t *ctxp, crypto_call_req_t *crq) 324*0Sstevel@tonic-gate { 325*0Sstevel@tonic-gate int error; 326*0Sstevel@tonic-gate crypto_ctx_t *ctx; 327*0Sstevel@tonic-gate kcf_req_params_t params; 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate /* First, allocate and initialize the canonical context */ 332*0Sstevel@tonic-gate if ((ctx = kcf_new_ctx(crq, pd, sid)) == NULL) 333*0Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate /* The fast path for SW providers. */ 336*0Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) { 337*0Sstevel@tonic-gate crypto_mechanism_t lmech; 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate lmech = *mech; 340*0Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 341*0Sstevel@tonic-gate error = KCF_PROV_MAC_INIT(pd, ctx, &lmech, key, tmpl, 342*0Sstevel@tonic-gate KCF_SWFP_RHNDL(crq)); 343*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 344*0Sstevel@tonic-gate } else { 345*0Sstevel@tonic-gate KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_INIT, sid, mech, key, 346*0Sstevel@tonic-gate NULL, NULL, tmpl); 347*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, crq, ¶ms, B_FALSE); 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED)) 351*0Sstevel@tonic-gate *ctxp = (crypto_context_t)ctx; 352*0Sstevel@tonic-gate else { 353*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx(). */ 354*0Sstevel@tonic-gate KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private); 355*0Sstevel@tonic-gate } 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate return (error); 358*0Sstevel@tonic-gate } 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate /* 361*0Sstevel@tonic-gate * Same as crypto_mac_init_prov(), but relies on the KCF scheduler to 362*0Sstevel@tonic-gate * choose a provider. See crypto_mac_init_prov() comments for more 363*0Sstevel@tonic-gate * information. 364*0Sstevel@tonic-gate */ 365*0Sstevel@tonic-gate int 366*0Sstevel@tonic-gate crypto_mac_init(crypto_mechanism_t *mech, crypto_key_t *key, 367*0Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 368*0Sstevel@tonic-gate crypto_call_req_t *crq) 369*0Sstevel@tonic-gate { 370*0Sstevel@tonic-gate int error; 371*0Sstevel@tonic-gate kcf_mech_entry_t *me; 372*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 373*0Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 374*0Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 375*0Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate retry: 378*0Sstevel@tonic-gate /* The pd is returned held */ 379*0Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 380*0Sstevel@tonic-gate list, CRYPTO_FG_MAC, CHECK_RESTRICT(crq), 0)) == NULL) { 381*0Sstevel@tonic-gate if (list != NULL) 382*0Sstevel@tonic-gate kcf_free_triedlist(list); 383*0Sstevel@tonic-gate return (error); 384*0Sstevel@tonic-gate } 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate /* 387*0Sstevel@tonic-gate * For SW providers, check the validity of the context template 388*0Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 389*0Sstevel@tonic-gate * is acceptable to fail here, and let the consumer recover by 390*0Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 391*0Sstevel@tonic-gate * provider 392*0Sstevel@tonic-gate */ 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 395*0Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 396*0Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 397*0Sstevel@tonic-gate if (list != NULL) 398*0Sstevel@tonic-gate kcf_free_triedlist(list); 399*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 400*0Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 401*0Sstevel@tonic-gate } else { 402*0Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 403*0Sstevel@tonic-gate } 404*0Sstevel@tonic-gate } 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate error = crypto_mac_init_prov(pd, pd->pd_sid, mech, key, spi_ctx_tmpl, 407*0Sstevel@tonic-gate ctxp, crq); 408*0Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 409*0Sstevel@tonic-gate IS_RECOVERABLE(error)) { 410*0Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 411*0Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 412*0Sstevel@tonic-gate goto retry; 413*0Sstevel@tonic-gate } 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gate if (list != NULL) 416*0Sstevel@tonic-gate kcf_free_triedlist(list); 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 419*0Sstevel@tonic-gate return (error); 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate /* 423*0Sstevel@tonic-gate * crypto_mac_update() 424*0Sstevel@tonic-gate * 425*0Sstevel@tonic-gate * Arguments: 426*0Sstevel@tonic-gate * context: A crypto_context_t initialized by mac_init(). 427*0Sstevel@tonic-gate * data: The message part to be MAC'ed 428*0Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 429*0Sstevel@tonic-gate * 430*0Sstevel@tonic-gate * Description: 431*0Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 432*0Sstevel@tonic-gate * part of a MAC operation. 433*0Sstevel@tonic-gate * 434*0Sstevel@tonic-gate * Context: 435*0Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 436*0Sstevel@tonic-gate * 437*0Sstevel@tonic-gate * Returns: 438*0Sstevel@tonic-gate * See comment in the beginning of the file. 439*0Sstevel@tonic-gate */ 440*0Sstevel@tonic-gate int 441*0Sstevel@tonic-gate crypto_mac_update(crypto_context_t context, crypto_data_t *data, 442*0Sstevel@tonic-gate crypto_call_req_t *cr) 443*0Sstevel@tonic-gate { 444*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 445*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 446*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 447*0Sstevel@tonic-gate int error; 448*0Sstevel@tonic-gate kcf_req_params_t params; 449*0Sstevel@tonic-gate 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate if ((ctx == NULL) || 452*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 453*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 454*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 455*0Sstevel@tonic-gate } 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate /* The fast path for SW providers. */ 460*0Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 461*0Sstevel@tonic-gate error = KCF_PROV_MAC_UPDATE(pd, ctx, data, NULL); 462*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 463*0Sstevel@tonic-gate } else { 464*0Sstevel@tonic-gate KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_UPDATE, pd->pd_sid, 465*0Sstevel@tonic-gate NULL, NULL, data, NULL, NULL); 466*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 467*0Sstevel@tonic-gate } 468*0Sstevel@tonic-gate 469*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 470*0Sstevel@tonic-gate return (error); 471*0Sstevel@tonic-gate } 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate /* 474*0Sstevel@tonic-gate * crypto_mac_final() 475*0Sstevel@tonic-gate * 476*0Sstevel@tonic-gate * Arguments: 477*0Sstevel@tonic-gate * context: A crypto_context_t initialized by mac_init(). 478*0Sstevel@tonic-gate * mac: Storage for the message authentication code. 479*0Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 480*0Sstevel@tonic-gate * 481*0Sstevel@tonic-gate * Description: 482*0Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 483*0Sstevel@tonic-gate * part of a message authentication operation. 484*0Sstevel@tonic-gate * 485*0Sstevel@tonic-gate * Context: 486*0Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 487*0Sstevel@tonic-gate * 488*0Sstevel@tonic-gate * Returns: 489*0Sstevel@tonic-gate * See comment in the beginning of the file. 490*0Sstevel@tonic-gate */ 491*0Sstevel@tonic-gate int 492*0Sstevel@tonic-gate crypto_mac_final(crypto_context_t context, crypto_data_t *mac, 493*0Sstevel@tonic-gate crypto_call_req_t *cr) 494*0Sstevel@tonic-gate { 495*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 496*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 497*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 498*0Sstevel@tonic-gate int error; 499*0Sstevel@tonic-gate kcf_req_params_t params; 500*0Sstevel@tonic-gate 501*0Sstevel@tonic-gate if ((ctx == NULL) || 502*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 503*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 504*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 505*0Sstevel@tonic-gate } 506*0Sstevel@tonic-gate 507*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 508*0Sstevel@tonic-gate 509*0Sstevel@tonic-gate /* The fast path for SW providers. */ 510*0Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 511*0Sstevel@tonic-gate error = KCF_PROV_MAC_FINAL(pd, ctx, mac, NULL); 512*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 513*0Sstevel@tonic-gate } else { 514*0Sstevel@tonic-gate KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_FINAL, pd->pd_sid, NULL, 515*0Sstevel@tonic-gate NULL, NULL, mac, NULL); 516*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 517*0Sstevel@tonic-gate } 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 520*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 521*0Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 522*0Sstevel@tonic-gate return (error); 523*0Sstevel@tonic-gate } 524*0Sstevel@tonic-gate 525*0Sstevel@tonic-gate /* 526*0Sstevel@tonic-gate * See comments for crypto_mac_update() and crypto_mac_final(). 527*0Sstevel@tonic-gate */ 528*0Sstevel@tonic-gate int 529*0Sstevel@tonic-gate crypto_mac_single(crypto_context_t context, crypto_data_t *data, 530*0Sstevel@tonic-gate crypto_data_t *mac, crypto_call_req_t *cr) 531*0Sstevel@tonic-gate { 532*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 533*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 534*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 535*0Sstevel@tonic-gate int error; 536*0Sstevel@tonic-gate kcf_req_params_t params; 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate if ((ctx == NULL) || 540*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 541*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 542*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 543*0Sstevel@tonic-gate } 544*0Sstevel@tonic-gate 545*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 546*0Sstevel@tonic-gate 547*0Sstevel@tonic-gate /* The fast path for SW providers. */ 548*0Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 549*0Sstevel@tonic-gate error = KCF_PROV_MAC(pd, ctx, data, mac, NULL); 550*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 551*0Sstevel@tonic-gate } else { 552*0Sstevel@tonic-gate KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_SINGLE, pd->pd_sid, 553*0Sstevel@tonic-gate NULL, NULL, data, mac, NULL); 554*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 555*0Sstevel@tonic-gate } 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 558*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 559*0Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 560*0Sstevel@tonic-gate return (error); 561*0Sstevel@tonic-gate } 562