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 * Encryption and decryption 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_PLAINTEXT: bogus 'plaintext' argument. 61*0Sstevel@tonic-gate * CRYPTO_INVALID_CIPHERTEXT: bogus 'ciphertext' argument. 62*0Sstevel@tonic-gate */ 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate /* 65*0Sstevel@tonic-gate * crypto_cipher_init_prov() 66*0Sstevel@tonic-gate * 67*0Sstevel@tonic-gate * Arguments: 68*0Sstevel@tonic-gate * 69*0Sstevel@tonic-gate * pd: provider descriptor 70*0Sstevel@tonic-gate * sid: session id 71*0Sstevel@tonic-gate * mech: crypto_mechanism_t pointer. 72*0Sstevel@tonic-gate * mech_type is a valid value previously returned by 73*0Sstevel@tonic-gate * crypto_mech2id(); 74*0Sstevel@tonic-gate * When the mech's parameter is not NULL, its definition depends 75*0Sstevel@tonic-gate * on the standard definition of the mechanism. 76*0Sstevel@tonic-gate * key: pointer to a crypto_key_t structure. 77*0Sstevel@tonic-gate * tmpl: a crypto_ctx_template_t, opaque template of a context of an 78*0Sstevel@tonic-gate * encryption or decryption with the 'mech' using 'key'. 79*0Sstevel@tonic-gate * 'tmpl' is created by a previous call to 80*0Sstevel@tonic-gate * crypto_create_ctx_template(). 81*0Sstevel@tonic-gate * ctxp: Pointer to a crypto_context_t. 82*0Sstevel@tonic-gate * func: CRYPTO_FG_ENCRYPT or CRYPTO_FG_DECRYPT. 83*0Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 84*0Sstevel@tonic-gate * 85*0Sstevel@tonic-gate * Description: 86*0Sstevel@tonic-gate * This is a common function invoked internally by both 87*0Sstevel@tonic-gate * crypto_encrypt_init() and crypto_decrypt_init(). 88*0Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs the 89*0Sstevel@tonic-gate * initialization of an encryption or a decryption operation. 90*0Sstevel@tonic-gate * When possible and applicable, will internally use the pre-expanded key 91*0Sstevel@tonic-gate * schedule from the context template, tmpl. 92*0Sstevel@tonic-gate * When complete and successful, 'ctxp' will contain a crypto_context_t 93*0Sstevel@tonic-gate * valid for later calls to encrypt_update() and encrypt_final(), or 94*0Sstevel@tonic-gate * decrypt_update() and decrypt_final(). 95*0Sstevel@tonic-gate * The caller should hold a reference on the specified provider 96*0Sstevel@tonic-gate * descriptor before calling this function. 97*0Sstevel@tonic-gate * 98*0Sstevel@tonic-gate * Context: 99*0Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 100*0Sstevel@tonic-gate * 101*0Sstevel@tonic-gate * Returns: 102*0Sstevel@tonic-gate * See comment in the beginning of the file. 103*0Sstevel@tonic-gate */ 104*0Sstevel@tonic-gate static int 105*0Sstevel@tonic-gate crypto_cipher_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid, 106*0Sstevel@tonic-gate crypto_mechanism_t *mech, crypto_key_t *key, 107*0Sstevel@tonic-gate crypto_spi_ctx_template_t tmpl, crypto_context_t *ctxp, 108*0Sstevel@tonic-gate crypto_call_req_t *crq, crypto_func_group_t func) 109*0Sstevel@tonic-gate { 110*0Sstevel@tonic-gate int error; 111*0Sstevel@tonic-gate crypto_ctx_t *ctx; 112*0Sstevel@tonic-gate kcf_req_params_t params; 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate /* First, allocate and initialize the canonical context */ 117*0Sstevel@tonic-gate if ((ctx = kcf_new_ctx(crq, pd, sid)) == NULL) 118*0Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate /* The fast path for SW providers. */ 121*0Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) { 122*0Sstevel@tonic-gate crypto_mechanism_t lmech; 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate lmech = *mech; 125*0Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate if (func == CRYPTO_FG_ENCRYPT) 128*0Sstevel@tonic-gate error = KCF_PROV_ENCRYPT_INIT(pd, ctx, &lmech, 129*0Sstevel@tonic-gate key, tmpl, KCF_SWFP_RHNDL(crq)); 130*0Sstevel@tonic-gate else { 131*0Sstevel@tonic-gate ASSERT(func == CRYPTO_FG_DECRYPT); 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate error = KCF_PROV_DECRYPT_INIT(pd, ctx, &lmech, 134*0Sstevel@tonic-gate key, tmpl, KCF_SWFP_RHNDL(crq)); 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 137*0Sstevel@tonic-gate } else { 138*0Sstevel@tonic-gate if (func == CRYPTO_FG_ENCRYPT) { 139*0Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_INIT, sid, 140*0Sstevel@tonic-gate mech, key, NULL, NULL, tmpl); 141*0Sstevel@tonic-gate } else { 142*0Sstevel@tonic-gate ASSERT(func == CRYPTO_FG_DECRYPT); 143*0Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_INIT, sid, 144*0Sstevel@tonic-gate mech, key, NULL, NULL, tmpl); 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, crq, ¶ms, B_FALSE); 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED)) 151*0Sstevel@tonic-gate *ctxp = (crypto_context_t)ctx; 152*0Sstevel@tonic-gate else { 153*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx(). */ 154*0Sstevel@tonic-gate KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private); 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate return (error); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* 161*0Sstevel@tonic-gate * Same as crypto_cipher_init_prov(), but relies on the scheduler to pick 162*0Sstevel@tonic-gate * an appropriate provider. See crypto_cipher_init_prov() comments for more 163*0Sstevel@tonic-gate * details. 164*0Sstevel@tonic-gate */ 165*0Sstevel@tonic-gate static int 166*0Sstevel@tonic-gate crypto_cipher_init(crypto_mechanism_t *mech, crypto_key_t *key, 167*0Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 168*0Sstevel@tonic-gate crypto_call_req_t *crq, crypto_func_group_t func) 169*0Sstevel@tonic-gate { 170*0Sstevel@tonic-gate int error; 171*0Sstevel@tonic-gate kcf_mech_entry_t *me; 172*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 173*0Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 174*0Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 175*0Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate retry: 178*0Sstevel@tonic-gate /* pd is returned held */ 179*0Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 180*0Sstevel@tonic-gate list, func, CHECK_RESTRICT(crq), 0)) == NULL) { 181*0Sstevel@tonic-gate if (list != NULL) 182*0Sstevel@tonic-gate kcf_free_triedlist(list); 183*0Sstevel@tonic-gate return (error); 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate /* 187*0Sstevel@tonic-gate * For SW providers, check the validity of the context template 188*0Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 189*0Sstevel@tonic-gate * is acceptable to fail here, and let the consumer recover by 190*0Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 191*0Sstevel@tonic-gate * provider 192*0Sstevel@tonic-gate */ 193*0Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 194*0Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 195*0Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 196*0Sstevel@tonic-gate if (list != NULL) 197*0Sstevel@tonic-gate kcf_free_triedlist(list); 198*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 199*0Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 200*0Sstevel@tonic-gate } else { 201*0Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate error = crypto_cipher_init_prov(pd, pd->pd_sid, mech, key, 206*0Sstevel@tonic-gate spi_ctx_tmpl, ctxp, crq, func); 207*0Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 208*0Sstevel@tonic-gate IS_RECOVERABLE(error)) { 209*0Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 210*0Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 211*0Sstevel@tonic-gate goto retry; 212*0Sstevel@tonic-gate } 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate if (list != NULL) 215*0Sstevel@tonic-gate kcf_free_triedlist(list); 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 218*0Sstevel@tonic-gate return (error); 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate /* 222*0Sstevel@tonic-gate * crypto_encrypt_prov() 223*0Sstevel@tonic-gate * 224*0Sstevel@tonic-gate * Arguments: 225*0Sstevel@tonic-gate * pd: provider descriptor 226*0Sstevel@tonic-gate * sid: session id 227*0Sstevel@tonic-gate * mech: crypto_mechanism_t pointer. 228*0Sstevel@tonic-gate * mech_type is a valid value previously returned by 229*0Sstevel@tonic-gate * crypto_mech2id(); 230*0Sstevel@tonic-gate * When the mech's parameter is not NULL, its definition depends 231*0Sstevel@tonic-gate * on the standard definition of the mechanism. 232*0Sstevel@tonic-gate * key: pointer to a crypto_key_t structure. 233*0Sstevel@tonic-gate * plaintext: The message to be encrypted 234*0Sstevel@tonic-gate * ciphertext: Storage for the encrypted message. The length needed 235*0Sstevel@tonic-gate * depends on the mechanism, and the plaintext's size. 236*0Sstevel@tonic-gate * tmpl: a crypto_ctx_template_t, opaque template of a context of an 237*0Sstevel@tonic-gate * encryption with the 'mech' using 'key'. 'tmpl' is created by 238*0Sstevel@tonic-gate * a previous call to crypto_create_ctx_template(). 239*0Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 240*0Sstevel@tonic-gate * 241*0Sstevel@tonic-gate * Description: 242*0Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 243*0Sstevel@tonic-gate * single-part encryption of 'plaintext' with the mechanism 'mech', using 244*0Sstevel@tonic-gate * the key 'key'. 245*0Sstevel@tonic-gate * When complete and successful, 'ciphertext' will contain the encrypted 246*0Sstevel@tonic-gate * message. 247*0Sstevel@tonic-gate * 248*0Sstevel@tonic-gate * Context: 249*0Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 250*0Sstevel@tonic-gate * 251*0Sstevel@tonic-gate * Returns: 252*0Sstevel@tonic-gate * See comment in the beginning of the file. 253*0Sstevel@tonic-gate */ 254*0Sstevel@tonic-gate int 255*0Sstevel@tonic-gate crypto_encrypt_prov(crypto_mechanism_t *mech, crypto_data_t *plaintext, 256*0Sstevel@tonic-gate crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *ciphertext, 257*0Sstevel@tonic-gate crypto_call_req_t *crq, kcf_provider_desc_t *pd, crypto_session_id_t sid) 258*0Sstevel@tonic-gate { 259*0Sstevel@tonic-gate kcf_req_params_t params; 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 262*0Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, sid, mech, key, 263*0Sstevel@tonic-gate plaintext, ciphertext, tmpl); 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate return (kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE)); 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate /* 269*0Sstevel@tonic-gate * Same as crypto_encrypt_prov(), but relies on the scheduler to pick 270*0Sstevel@tonic-gate * a provider. See crypto_encrypt_prov() for more details. 271*0Sstevel@tonic-gate */ 272*0Sstevel@tonic-gate int 273*0Sstevel@tonic-gate crypto_encrypt(crypto_mechanism_t *mech, crypto_data_t *plaintext, 274*0Sstevel@tonic-gate crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *ciphertext, 275*0Sstevel@tonic-gate crypto_call_req_t *crq) 276*0Sstevel@tonic-gate { 277*0Sstevel@tonic-gate int error; 278*0Sstevel@tonic-gate kcf_mech_entry_t *me; 279*0Sstevel@tonic-gate kcf_req_params_t params; 280*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 281*0Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 282*0Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 283*0Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate retry: 286*0Sstevel@tonic-gate /* pd is returned held */ 287*0Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 288*0Sstevel@tonic-gate list, CRYPTO_FG_ENCRYPT_ATOMIC, CHECK_RESTRICT(crq), 289*0Sstevel@tonic-gate plaintext->cd_length)) == NULL) { 290*0Sstevel@tonic-gate if (list != NULL) 291*0Sstevel@tonic-gate kcf_free_triedlist(list); 292*0Sstevel@tonic-gate return (error); 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate /* 296*0Sstevel@tonic-gate * For SW providers, check the validity of the context template 297*0Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 298*0Sstevel@tonic-gate * is acceptable to fail here, and let the consumer recover by 299*0Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 300*0Sstevel@tonic-gate * provider 301*0Sstevel@tonic-gate */ 302*0Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 303*0Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 304*0Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 305*0Sstevel@tonic-gate if (list != NULL) 306*0Sstevel@tonic-gate kcf_free_triedlist(list); 307*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 308*0Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 309*0Sstevel@tonic-gate } else { 310*0Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate /* The fast path for SW providers. */ 315*0Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) { 316*0Sstevel@tonic-gate crypto_mechanism_t lmech; 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate lmech = *mech; 319*0Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate error = KCF_PROV_ENCRYPT_ATOMIC(pd, pd->pd_sid, &lmech, key, 322*0Sstevel@tonic-gate plaintext, ciphertext, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq)); 323*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 324*0Sstevel@tonic-gate } else { 325*0Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, pd->pd_sid, 326*0Sstevel@tonic-gate mech, key, plaintext, ciphertext, spi_ctx_tmpl); 327*0Sstevel@tonic-gate error = kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE); 328*0Sstevel@tonic-gate } 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 331*0Sstevel@tonic-gate IS_RECOVERABLE(error)) { 332*0Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 333*0Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 334*0Sstevel@tonic-gate goto retry; 335*0Sstevel@tonic-gate } 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate if (list != NULL) 338*0Sstevel@tonic-gate kcf_free_triedlist(list); 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 341*0Sstevel@tonic-gate return (error); 342*0Sstevel@tonic-gate } 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate /* 345*0Sstevel@tonic-gate * crypto_encrypt_init_prov() 346*0Sstevel@tonic-gate * 347*0Sstevel@tonic-gate * Calls crypto_cipher_init_prov() to initialize an encryption operation. 348*0Sstevel@tonic-gate */ 349*0Sstevel@tonic-gate int 350*0Sstevel@tonic-gate crypto_encrypt_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid, 351*0Sstevel@tonic-gate crypto_mechanism_t *mech, crypto_key_t *key, 352*0Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 353*0Sstevel@tonic-gate crypto_call_req_t *crq) 354*0Sstevel@tonic-gate { 355*0Sstevel@tonic-gate return (crypto_cipher_init_prov(pd, sid, mech, key, tmpl, ctxp, crq, 356*0Sstevel@tonic-gate CRYPTO_FG_ENCRYPT)); 357*0Sstevel@tonic-gate } 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate /* 360*0Sstevel@tonic-gate * crypto_encrypt_init() 361*0Sstevel@tonic-gate * 362*0Sstevel@tonic-gate * Calls crypto_cipher_init() to initialize an encryption operation 363*0Sstevel@tonic-gate */ 364*0Sstevel@tonic-gate int 365*0Sstevel@tonic-gate crypto_encrypt_init(crypto_mechanism_t *mech, crypto_key_t *key, 366*0Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 367*0Sstevel@tonic-gate crypto_call_req_t *crq) 368*0Sstevel@tonic-gate { 369*0Sstevel@tonic-gate return (crypto_cipher_init(mech, key, tmpl, ctxp, crq, 370*0Sstevel@tonic-gate CRYPTO_FG_ENCRYPT)); 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate /* 374*0Sstevel@tonic-gate * crypto_encrypt_update() 375*0Sstevel@tonic-gate * 376*0Sstevel@tonic-gate * Arguments: 377*0Sstevel@tonic-gate * context: A crypto_context_t initialized by encrypt_init(). 378*0Sstevel@tonic-gate * plaintext: The message part to be encrypted 379*0Sstevel@tonic-gate * ciphertext: Storage for the encrypted message part. 380*0Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 381*0Sstevel@tonic-gate * 382*0Sstevel@tonic-gate * Description: 383*0Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 384*0Sstevel@tonic-gate * part of an encryption operation. 385*0Sstevel@tonic-gate * 386*0Sstevel@tonic-gate * Context: 387*0Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 388*0Sstevel@tonic-gate * 389*0Sstevel@tonic-gate * Returns: 390*0Sstevel@tonic-gate * See comment in the beginning of the file. 391*0Sstevel@tonic-gate */ 392*0Sstevel@tonic-gate int 393*0Sstevel@tonic-gate crypto_encrypt_update(crypto_context_t context, crypto_data_t *plaintext, 394*0Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_call_req_t *cr) 395*0Sstevel@tonic-gate { 396*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 397*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 398*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 399*0Sstevel@tonic-gate int error; 400*0Sstevel@tonic-gate kcf_req_params_t params; 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate if ((ctx == NULL) || 403*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 404*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 405*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 406*0Sstevel@tonic-gate } 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate /* The fast path for SW providers. */ 411*0Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 412*0Sstevel@tonic-gate error = KCF_PROV_ENCRYPT_UPDATE(pd, ctx, plaintext, 413*0Sstevel@tonic-gate ciphertext, NULL); 414*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 415*0Sstevel@tonic-gate } else { 416*0Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_UPDATE, pd->pd_sid, 417*0Sstevel@tonic-gate NULL, NULL, plaintext, ciphertext, NULL); 418*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 419*0Sstevel@tonic-gate } 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 422*0Sstevel@tonic-gate return (error); 423*0Sstevel@tonic-gate } 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate /* 426*0Sstevel@tonic-gate * crypto_encrypt_final() 427*0Sstevel@tonic-gate * 428*0Sstevel@tonic-gate * Arguments: 429*0Sstevel@tonic-gate * context: A crypto_context_t initialized by encrypt_init(). 430*0Sstevel@tonic-gate * ciphertext: Storage for the last part of encrypted message 431*0Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 432*0Sstevel@tonic-gate * 433*0Sstevel@tonic-gate * Description: 434*0Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs the 435*0Sstevel@tonic-gate * final part of an encryption operation. 436*0Sstevel@tonic-gate * 437*0Sstevel@tonic-gate * Context: 438*0Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 439*0Sstevel@tonic-gate * 440*0Sstevel@tonic-gate * Returns: 441*0Sstevel@tonic-gate * See comment in the beginning of the file. 442*0Sstevel@tonic-gate */ 443*0Sstevel@tonic-gate int 444*0Sstevel@tonic-gate crypto_encrypt_final(crypto_context_t context, crypto_data_t *ciphertext, 445*0Sstevel@tonic-gate crypto_call_req_t *cr) 446*0Sstevel@tonic-gate { 447*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 448*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 449*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 450*0Sstevel@tonic-gate int error; 451*0Sstevel@tonic-gate kcf_req_params_t params; 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate if ((ctx == NULL) || 454*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 455*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 456*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 457*0Sstevel@tonic-gate } 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate /* The fast path for SW providers. */ 462*0Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 463*0Sstevel@tonic-gate error = KCF_PROV_ENCRYPT_FINAL(pd, ctx, ciphertext, NULL); 464*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 465*0Sstevel@tonic-gate } else { 466*0Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_FINAL, pd->pd_sid, 467*0Sstevel@tonic-gate NULL, NULL, NULL, ciphertext, NULL); 468*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 469*0Sstevel@tonic-gate } 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 472*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 473*0Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 474*0Sstevel@tonic-gate return (error); 475*0Sstevel@tonic-gate } 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate /* 478*0Sstevel@tonic-gate * crypto_decrypt_prov() 479*0Sstevel@tonic-gate * 480*0Sstevel@tonic-gate * Arguments: 481*0Sstevel@tonic-gate * pd: provider descriptor 482*0Sstevel@tonic-gate * sid: session id 483*0Sstevel@tonic-gate * mech: crypto_mechanism_t pointer. 484*0Sstevel@tonic-gate * mech_type is a valid value previously returned by 485*0Sstevel@tonic-gate * crypto_mech2id(); 486*0Sstevel@tonic-gate * When the mech's parameter is not NULL, its definition depends 487*0Sstevel@tonic-gate * on the standard definition of the mechanism. 488*0Sstevel@tonic-gate * key: pointer to a crypto_key_t structure. 489*0Sstevel@tonic-gate * ciphertext: The message to be encrypted 490*0Sstevel@tonic-gate * plaintext: Storage for the encrypted message. The length needed 491*0Sstevel@tonic-gate * depends on the mechanism, and the plaintext's size. 492*0Sstevel@tonic-gate * tmpl: a crypto_ctx_template_t, opaque template of a context of an 493*0Sstevel@tonic-gate * encryption with the 'mech' using 'key'. 'tmpl' is created by 494*0Sstevel@tonic-gate * a previous call to crypto_create_ctx_template(). 495*0Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 496*0Sstevel@tonic-gate * 497*0Sstevel@tonic-gate * Description: 498*0Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 499*0Sstevel@tonic-gate * single-part decryption of 'ciphertext' with the mechanism 'mech', using 500*0Sstevel@tonic-gate * the key 'key'. 501*0Sstevel@tonic-gate * When complete and successful, 'plaintext' will contain the decrypted 502*0Sstevel@tonic-gate * message. 503*0Sstevel@tonic-gate * 504*0Sstevel@tonic-gate * Context: 505*0Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 506*0Sstevel@tonic-gate * 507*0Sstevel@tonic-gate * Returns: 508*0Sstevel@tonic-gate * See comment in the beginning of the file. 509*0Sstevel@tonic-gate */ 510*0Sstevel@tonic-gate int 511*0Sstevel@tonic-gate crypto_decrypt_prov(crypto_mechanism_t *mech, crypto_data_t *ciphertext, 512*0Sstevel@tonic-gate crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *plaintext, 513*0Sstevel@tonic-gate crypto_call_req_t *crq, kcf_provider_desc_t *pd, crypto_session_id_t sid) 514*0Sstevel@tonic-gate { 515*0Sstevel@tonic-gate kcf_req_params_t params; 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 518*0Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, sid, mech, key, 519*0Sstevel@tonic-gate ciphertext, plaintext, tmpl); 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate return (kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE)); 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate /* 525*0Sstevel@tonic-gate * Same as crypto_decrypt_prov(), but relies on the KCF scheduler to 526*0Sstevel@tonic-gate * choose a provider. See crypto_decrypt_prov() comments for more 527*0Sstevel@tonic-gate * information. 528*0Sstevel@tonic-gate */ 529*0Sstevel@tonic-gate int 530*0Sstevel@tonic-gate crypto_decrypt(crypto_mechanism_t *mech, crypto_data_t *ciphertext, 531*0Sstevel@tonic-gate crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *plaintext, 532*0Sstevel@tonic-gate crypto_call_req_t *crq) 533*0Sstevel@tonic-gate { 534*0Sstevel@tonic-gate int error; 535*0Sstevel@tonic-gate kcf_mech_entry_t *me; 536*0Sstevel@tonic-gate kcf_req_params_t params; 537*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 538*0Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 539*0Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 540*0Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate retry: 543*0Sstevel@tonic-gate /* pd is returned held */ 544*0Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 545*0Sstevel@tonic-gate list, CRYPTO_FG_DECRYPT_ATOMIC, CHECK_RESTRICT(crq), 546*0Sstevel@tonic-gate ciphertext->cd_length)) == NULL) { 547*0Sstevel@tonic-gate if (list != NULL) 548*0Sstevel@tonic-gate kcf_free_triedlist(list); 549*0Sstevel@tonic-gate return (error); 550*0Sstevel@tonic-gate } 551*0Sstevel@tonic-gate 552*0Sstevel@tonic-gate /* 553*0Sstevel@tonic-gate * For SW providers, check the validity of the context template 554*0Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 555*0Sstevel@tonic-gate * is acceptable to fail here, and let the consumer recover by 556*0Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 557*0Sstevel@tonic-gate * provider 558*0Sstevel@tonic-gate */ 559*0Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 560*0Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 561*0Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 562*0Sstevel@tonic-gate if (list != NULL) 563*0Sstevel@tonic-gate kcf_free_triedlist(list); 564*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 565*0Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 566*0Sstevel@tonic-gate } else { 567*0Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 568*0Sstevel@tonic-gate } 569*0Sstevel@tonic-gate } 570*0Sstevel@tonic-gate 571*0Sstevel@tonic-gate /* The fast path for SW providers. */ 572*0Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) { 573*0Sstevel@tonic-gate crypto_mechanism_t lmech; 574*0Sstevel@tonic-gate 575*0Sstevel@tonic-gate lmech = *mech; 576*0Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 577*0Sstevel@tonic-gate 578*0Sstevel@tonic-gate error = KCF_PROV_DECRYPT_ATOMIC(pd, pd->pd_sid, &lmech, key, 579*0Sstevel@tonic-gate ciphertext, plaintext, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq)); 580*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 581*0Sstevel@tonic-gate } else { 582*0Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, pd->pd_sid, 583*0Sstevel@tonic-gate mech, key, ciphertext, plaintext, spi_ctx_tmpl); 584*0Sstevel@tonic-gate error = kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE); 585*0Sstevel@tonic-gate } 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 588*0Sstevel@tonic-gate IS_RECOVERABLE(error)) { 589*0Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 590*0Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 591*0Sstevel@tonic-gate goto retry; 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate if (list != NULL) 595*0Sstevel@tonic-gate kcf_free_triedlist(list); 596*0Sstevel@tonic-gate 597*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 598*0Sstevel@tonic-gate return (error); 599*0Sstevel@tonic-gate } 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate /* 602*0Sstevel@tonic-gate * crypto_decrypt_init_prov() 603*0Sstevel@tonic-gate * 604*0Sstevel@tonic-gate * Calls crypto_cipher_init_prov() to initialize a decryption operation 605*0Sstevel@tonic-gate */ 606*0Sstevel@tonic-gate int 607*0Sstevel@tonic-gate crypto_decrypt_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid, 608*0Sstevel@tonic-gate crypto_mechanism_t *mech, crypto_key_t *key, 609*0Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 610*0Sstevel@tonic-gate crypto_call_req_t *crq) 611*0Sstevel@tonic-gate { 612*0Sstevel@tonic-gate return (crypto_cipher_init_prov(pd, sid, mech, key, tmpl, ctxp, crq, 613*0Sstevel@tonic-gate CRYPTO_FG_DECRYPT)); 614*0Sstevel@tonic-gate } 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate /* 617*0Sstevel@tonic-gate * crypto_decrypt_init() 618*0Sstevel@tonic-gate * 619*0Sstevel@tonic-gate * Calls crypto_cipher_init() to initialize a decryption operation 620*0Sstevel@tonic-gate */ 621*0Sstevel@tonic-gate int 622*0Sstevel@tonic-gate crypto_decrypt_init(crypto_mechanism_t *mech, crypto_key_t *key, 623*0Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 624*0Sstevel@tonic-gate crypto_call_req_t *crq) 625*0Sstevel@tonic-gate { 626*0Sstevel@tonic-gate return (crypto_cipher_init(mech, key, tmpl, ctxp, crq, 627*0Sstevel@tonic-gate CRYPTO_FG_DECRYPT)); 628*0Sstevel@tonic-gate } 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate /* 631*0Sstevel@tonic-gate * crypto_decrypt_update() 632*0Sstevel@tonic-gate * 633*0Sstevel@tonic-gate * Arguments: 634*0Sstevel@tonic-gate * context: A crypto_context_t initialized by decrypt_init(). 635*0Sstevel@tonic-gate * ciphertext: The message part to be decrypted 636*0Sstevel@tonic-gate * plaintext: Storage for the decrypted message part. 637*0Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 638*0Sstevel@tonic-gate * 639*0Sstevel@tonic-gate * Description: 640*0Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 641*0Sstevel@tonic-gate * part of an decryption operation. 642*0Sstevel@tonic-gate * 643*0Sstevel@tonic-gate * Context: 644*0Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 645*0Sstevel@tonic-gate * 646*0Sstevel@tonic-gate * Returns: 647*0Sstevel@tonic-gate * See comment in the beginning of the file. 648*0Sstevel@tonic-gate */ 649*0Sstevel@tonic-gate int 650*0Sstevel@tonic-gate crypto_decrypt_update(crypto_context_t context, crypto_data_t *ciphertext, 651*0Sstevel@tonic-gate crypto_data_t *plaintext, crypto_call_req_t *cr) 652*0Sstevel@tonic-gate { 653*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 654*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 655*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 656*0Sstevel@tonic-gate int error; 657*0Sstevel@tonic-gate kcf_req_params_t params; 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate if ((ctx == NULL) || 660*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 661*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 662*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 663*0Sstevel@tonic-gate } 664*0Sstevel@tonic-gate 665*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 666*0Sstevel@tonic-gate 667*0Sstevel@tonic-gate /* The fast path for SW providers. */ 668*0Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 669*0Sstevel@tonic-gate error = KCF_PROV_DECRYPT_UPDATE(pd, ctx, ciphertext, 670*0Sstevel@tonic-gate plaintext, NULL); 671*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 672*0Sstevel@tonic-gate } else { 673*0Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_UPDATE, pd->pd_sid, 674*0Sstevel@tonic-gate NULL, NULL, ciphertext, plaintext, NULL); 675*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 676*0Sstevel@tonic-gate } 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 679*0Sstevel@tonic-gate return (error); 680*0Sstevel@tonic-gate } 681*0Sstevel@tonic-gate 682*0Sstevel@tonic-gate /* 683*0Sstevel@tonic-gate * crypto_decrypt_final() 684*0Sstevel@tonic-gate * 685*0Sstevel@tonic-gate * Arguments: 686*0Sstevel@tonic-gate * context: A crypto_context_t initialized by decrypt_init(). 687*0Sstevel@tonic-gate * plaintext: Storage for the last part of the decrypted message 688*0Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 689*0Sstevel@tonic-gate * 690*0Sstevel@tonic-gate * Description: 691*0Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs the 692*0Sstevel@tonic-gate * final part of a decryption operation. 693*0Sstevel@tonic-gate * 694*0Sstevel@tonic-gate * Context: 695*0Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 696*0Sstevel@tonic-gate * 697*0Sstevel@tonic-gate * Returns: 698*0Sstevel@tonic-gate * See comment in the beginning of the file. 699*0Sstevel@tonic-gate */ 700*0Sstevel@tonic-gate int 701*0Sstevel@tonic-gate crypto_decrypt_final(crypto_context_t context, crypto_data_t *plaintext, 702*0Sstevel@tonic-gate crypto_call_req_t *cr) 703*0Sstevel@tonic-gate { 704*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 705*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 706*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 707*0Sstevel@tonic-gate int error; 708*0Sstevel@tonic-gate kcf_req_params_t params; 709*0Sstevel@tonic-gate 710*0Sstevel@tonic-gate if ((ctx == NULL) || 711*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 712*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 713*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 714*0Sstevel@tonic-gate } 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate /* The fast path for SW providers. */ 719*0Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 720*0Sstevel@tonic-gate error = KCF_PROV_DECRYPT_FINAL(pd, ctx, plaintext, NULL); 721*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 722*0Sstevel@tonic-gate } else { 723*0Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_FINAL, pd->pd_sid, 724*0Sstevel@tonic-gate NULL, NULL, NULL, plaintext, NULL); 725*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 726*0Sstevel@tonic-gate } 727*0Sstevel@tonic-gate 728*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 729*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 730*0Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 731*0Sstevel@tonic-gate return (error); 732*0Sstevel@tonic-gate } 733*0Sstevel@tonic-gate 734*0Sstevel@tonic-gate /* 735*0Sstevel@tonic-gate * See comments for crypto_encrypt_update(). 736*0Sstevel@tonic-gate */ 737*0Sstevel@tonic-gate int 738*0Sstevel@tonic-gate crypto_encrypt_single(crypto_context_t context, crypto_data_t *plaintext, 739*0Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_call_req_t *cr) 740*0Sstevel@tonic-gate { 741*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 742*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 743*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 744*0Sstevel@tonic-gate int error; 745*0Sstevel@tonic-gate kcf_req_params_t params; 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate if ((ctx == NULL) || 748*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 749*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 750*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 751*0Sstevel@tonic-gate } 752*0Sstevel@tonic-gate 753*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 754*0Sstevel@tonic-gate 755*0Sstevel@tonic-gate /* The fast path for SW providers. */ 756*0Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 757*0Sstevel@tonic-gate error = KCF_PROV_ENCRYPT(pd, ctx, plaintext, 758*0Sstevel@tonic-gate ciphertext, NULL); 759*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 760*0Sstevel@tonic-gate } else { 761*0Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_SINGLE, pd->pd_sid, 762*0Sstevel@tonic-gate NULL, NULL, plaintext, ciphertext, NULL); 763*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 764*0Sstevel@tonic-gate } 765*0Sstevel@tonic-gate 766*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 767*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 768*0Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 769*0Sstevel@tonic-gate return (error); 770*0Sstevel@tonic-gate } 771*0Sstevel@tonic-gate 772*0Sstevel@tonic-gate /* 773*0Sstevel@tonic-gate * See comments for crypto_decrypt_update(). 774*0Sstevel@tonic-gate */ 775*0Sstevel@tonic-gate int 776*0Sstevel@tonic-gate crypto_decrypt_single(crypto_context_t context, crypto_data_t *ciphertext, 777*0Sstevel@tonic-gate crypto_data_t *plaintext, crypto_call_req_t *cr) 778*0Sstevel@tonic-gate { 779*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 780*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 781*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 782*0Sstevel@tonic-gate int error; 783*0Sstevel@tonic-gate kcf_req_params_t params; 784*0Sstevel@tonic-gate 785*0Sstevel@tonic-gate if ((ctx == NULL) || 786*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 787*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 788*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 789*0Sstevel@tonic-gate } 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate /* The fast path for SW providers. */ 794*0Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 795*0Sstevel@tonic-gate error = KCF_PROV_DECRYPT(pd, ctx, ciphertext, 796*0Sstevel@tonic-gate plaintext, NULL); 797*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 798*0Sstevel@tonic-gate } else { 799*0Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_SINGLE, pd->pd_sid, 800*0Sstevel@tonic-gate NULL, NULL, ciphertext, plaintext, NULL); 801*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 802*0Sstevel@tonic-gate } 803*0Sstevel@tonic-gate 804*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 805*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 806*0Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 807*0Sstevel@tonic-gate return (error); 808*0Sstevel@tonic-gate } 809