10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51808Smcpowers * Common Development and Distribution License (the "License"). 61808Smcpowers * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 223367Skrishna * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/errno.h> 290Sstevel@tonic-gate #include <sys/types.h> 300Sstevel@tonic-gate #include <sys/kmem.h> 31904Smcpowers #include <sys/sysmacros.h> 320Sstevel@tonic-gate #include <sys/crypto/common.h> 330Sstevel@tonic-gate #include <sys/crypto/impl.h> 340Sstevel@tonic-gate #include <sys/crypto/api.h> 350Sstevel@tonic-gate #include <sys/crypto/spi.h> 360Sstevel@tonic-gate #include <sys/crypto/sched_impl.h> 370Sstevel@tonic-gate 38904Smcpowers #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f) 39904Smcpowers #define CRYPTO_CIPHER_OFFSET(f) offsetof(crypto_cipher_ops_t, f) 40904Smcpowers 410Sstevel@tonic-gate /* 420Sstevel@tonic-gate * Encryption and decryption routines. 430Sstevel@tonic-gate */ 440Sstevel@tonic-gate 450Sstevel@tonic-gate /* 460Sstevel@tonic-gate * The following are the possible returned values common to all the routines 470Sstevel@tonic-gate * below. The applicability of some of these return values depends on the 480Sstevel@tonic-gate * presence of the arguments. 490Sstevel@tonic-gate * 500Sstevel@tonic-gate * CRYPTO_SUCCESS: The operation completed successfully. 510Sstevel@tonic-gate * CRYPTO_QUEUED: A request was submitted successfully. The callback 520Sstevel@tonic-gate * routine will be called when the operation is done. 530Sstevel@tonic-gate * CRYPTO_INVALID_MECH_NUMBER, CRYPTO_INVALID_MECH_PARAM, or 540Sstevel@tonic-gate * CRYPTO_INVALID_MECH for problems with the 'mech'. 550Sstevel@tonic-gate * CRYPTO_INVALID_DATA for bogus 'data' 560Sstevel@tonic-gate * CRYPTO_HOST_MEMORY for failure to allocate memory to handle this work. 570Sstevel@tonic-gate * CRYPTO_INVALID_CONTEXT: Not a valid context. 580Sstevel@tonic-gate * CRYPTO_BUSY: Cannot process the request now. Schedule a 590Sstevel@tonic-gate * crypto_bufcall(), or try later. 600Sstevel@tonic-gate * CRYPTO_NOT_SUPPORTED and CRYPTO_MECH_NOT_SUPPORTED: No provider is 610Sstevel@tonic-gate * capable of a function or a mechanism. 620Sstevel@tonic-gate * CRYPTO_INVALID_KEY: bogus 'key' argument. 630Sstevel@tonic-gate * CRYPTO_INVALID_PLAINTEXT: bogus 'plaintext' argument. 640Sstevel@tonic-gate * CRYPTO_INVALID_CIPHERTEXT: bogus 'ciphertext' argument. 650Sstevel@tonic-gate */ 660Sstevel@tonic-gate 670Sstevel@tonic-gate /* 680Sstevel@tonic-gate * crypto_cipher_init_prov() 690Sstevel@tonic-gate * 700Sstevel@tonic-gate * Arguments: 710Sstevel@tonic-gate * 720Sstevel@tonic-gate * pd: provider descriptor 730Sstevel@tonic-gate * sid: session id 740Sstevel@tonic-gate * mech: crypto_mechanism_t pointer. 750Sstevel@tonic-gate * mech_type is a valid value previously returned by 760Sstevel@tonic-gate * crypto_mech2id(); 770Sstevel@tonic-gate * When the mech's parameter is not NULL, its definition depends 780Sstevel@tonic-gate * on the standard definition of the mechanism. 790Sstevel@tonic-gate * key: pointer to a crypto_key_t structure. 800Sstevel@tonic-gate * tmpl: a crypto_ctx_template_t, opaque template of a context of an 810Sstevel@tonic-gate * encryption or decryption with the 'mech' using 'key'. 820Sstevel@tonic-gate * 'tmpl' is created by a previous call to 830Sstevel@tonic-gate * crypto_create_ctx_template(). 840Sstevel@tonic-gate * ctxp: Pointer to a crypto_context_t. 850Sstevel@tonic-gate * func: CRYPTO_FG_ENCRYPT or CRYPTO_FG_DECRYPT. 860Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 870Sstevel@tonic-gate * 880Sstevel@tonic-gate * Description: 890Sstevel@tonic-gate * This is a common function invoked internally by both 900Sstevel@tonic-gate * crypto_encrypt_init() and crypto_decrypt_init(). 910Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs the 920Sstevel@tonic-gate * initialization of an encryption or a decryption operation. 930Sstevel@tonic-gate * When possible and applicable, will internally use the pre-expanded key 940Sstevel@tonic-gate * schedule from the context template, tmpl. 950Sstevel@tonic-gate * When complete and successful, 'ctxp' will contain a crypto_context_t 960Sstevel@tonic-gate * valid for later calls to encrypt_update() and encrypt_final(), or 970Sstevel@tonic-gate * decrypt_update() and decrypt_final(). 980Sstevel@tonic-gate * The caller should hold a reference on the specified provider 990Sstevel@tonic-gate * descriptor before calling this function. 1000Sstevel@tonic-gate * 1010Sstevel@tonic-gate * Context: 1020Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 1030Sstevel@tonic-gate * 1040Sstevel@tonic-gate * Returns: 1050Sstevel@tonic-gate * See comment in the beginning of the file. 1060Sstevel@tonic-gate */ 1070Sstevel@tonic-gate static int 108904Smcpowers crypto_cipher_init_prov(crypto_provider_t provider, crypto_session_id_t sid, 1090Sstevel@tonic-gate crypto_mechanism_t *mech, crypto_key_t *key, 1100Sstevel@tonic-gate crypto_spi_ctx_template_t tmpl, crypto_context_t *ctxp, 1110Sstevel@tonic-gate crypto_call_req_t *crq, crypto_func_group_t func) 1120Sstevel@tonic-gate { 1130Sstevel@tonic-gate int error; 1140Sstevel@tonic-gate crypto_ctx_t *ctx; 1150Sstevel@tonic-gate kcf_req_params_t params; 116904Smcpowers kcf_provider_desc_t *pd = provider; 117904Smcpowers kcf_provider_desc_t *real_provider = pd; 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 1200Sstevel@tonic-gate 121904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 122904Smcpowers if (func == CRYPTO_FG_ENCRYPT) { 123904Smcpowers error = kcf_get_hardware_provider(mech->cm_type, 1241808Smcpowers CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq), pd, 1251808Smcpowers &real_provider, CRYPTO_FG_ENCRYPT); 126904Smcpowers } else { 127904Smcpowers error = kcf_get_hardware_provider(mech->cm_type, 1281808Smcpowers CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq), pd, 1291808Smcpowers &real_provider, CRYPTO_FG_DECRYPT); 130904Smcpowers } 131904Smcpowers 132904Smcpowers if (error != CRYPTO_SUCCESS) 133904Smcpowers return (error); 134904Smcpowers } 135904Smcpowers 136904Smcpowers /* Allocate and initialize the canonical context */ 137904Smcpowers if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) { 138904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 139904Smcpowers KCF_PROV_REFRELE(real_provider); 1400Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 141904Smcpowers } 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate /* The fast path for SW providers. */ 1440Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) { 1450Sstevel@tonic-gate crypto_mechanism_t lmech; 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate lmech = *mech; 148904Smcpowers KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech); 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate if (func == CRYPTO_FG_ENCRYPT) 151904Smcpowers error = KCF_PROV_ENCRYPT_INIT(real_provider, ctx, 152904Smcpowers &lmech, key, tmpl, KCF_SWFP_RHNDL(crq)); 1530Sstevel@tonic-gate else { 1540Sstevel@tonic-gate ASSERT(func == CRYPTO_FG_DECRYPT); 1550Sstevel@tonic-gate 156904Smcpowers error = KCF_PROV_DECRYPT_INIT(real_provider, ctx, 157904Smcpowers &lmech, key, tmpl, KCF_SWFP_RHNDL(crq)); 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 160*3708Skrishna 161*3708Skrishna goto done; 162*3708Skrishna } 163*3708Skrishna 164*3708Skrishna /* Check if context sharing is possible */ 165*3708Skrishna if (pd->pd_prov_type == CRYPTO_HW_PROVIDER && 166*3708Skrishna key->ck_format == CRYPTO_KEY_RAW && 167*3708Skrishna KCF_CAN_SHARE_OPSTATE(pd, mech->cm_type)) { 168*3708Skrishna kcf_context_t *tctxp = (kcf_context_t *)ctx; 169*3708Skrishna kcf_provider_desc_t *tpd = NULL; 170*3708Skrishna crypto_mech_info_t *sinfo; 171*3708Skrishna 172*3708Skrishna if ((kcf_get_sw_prov(mech->cm_type, &tpd, &tctxp->kc_mech, 173*3708Skrishna B_FALSE) == CRYPTO_SUCCESS)) { 174*3708Skrishna int tlen; 175*3708Skrishna 176*3708Skrishna sinfo = &(KCF_TO_PROV_MECHINFO(tpd, mech->cm_type)); 177*3708Skrishna /* 178*3708Skrishna * key->ck_length from the consumer is always in bits. 179*3708Skrishna * We convert it to be in the same unit registered by 180*3708Skrishna * the provider in order to do a comparison. 181*3708Skrishna */ 182*3708Skrishna if (sinfo->cm_mech_flags & CRYPTO_KEYSIZE_UNIT_IN_BYTES) 183*3708Skrishna tlen = key->ck_length >> 3; 184*3708Skrishna else 185*3708Skrishna tlen = key->ck_length; 186*3708Skrishna /* 187*3708Skrishna * Check if the software provider can support context 188*3708Skrishna * sharing and support this key length. 189*3708Skrishna */ 190*3708Skrishna if ((sinfo->cm_mech_flags & CRYPTO_CAN_SHARE_OPSTATE) && 191*3708Skrishna (tlen >= sinfo->cm_min_key_length) && 192*3708Skrishna (tlen <= sinfo->cm_max_key_length)) { 193*3708Skrishna ctx->cc_flags = CRYPTO_INIT_OPSTATE; 194*3708Skrishna tctxp->kc_sw_prov_desc = tpd; 195*3708Skrishna } else 196*3708Skrishna KCF_PROV_REFRELE(tpd); 197*3708Skrishna } 198*3708Skrishna } 199*3708Skrishna 200*3708Skrishna if (func == CRYPTO_FG_ENCRYPT) { 201*3708Skrishna KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_INIT, sid, 202*3708Skrishna mech, key, NULL, NULL, tmpl); 2030Sstevel@tonic-gate } else { 204*3708Skrishna ASSERT(func == CRYPTO_FG_DECRYPT); 205*3708Skrishna KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_INIT, sid, 206*3708Skrishna mech, key, NULL, NULL, tmpl); 207*3708Skrishna } 2080Sstevel@tonic-gate 209*3708Skrishna error = kcf_submit_request(real_provider, ctx, crq, ¶ms, 210*3708Skrishna B_FALSE); 2110Sstevel@tonic-gate 212904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 213904Smcpowers KCF_PROV_REFRELE(real_provider); 214904Smcpowers 215*3708Skrishna done: 2160Sstevel@tonic-gate if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED)) 2170Sstevel@tonic-gate *ctxp = (crypto_context_t)ctx; 2180Sstevel@tonic-gate else { 2190Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx(). */ 2200Sstevel@tonic-gate KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private); 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate return (error); 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate /* 2270Sstevel@tonic-gate * Same as crypto_cipher_init_prov(), but relies on the scheduler to pick 2280Sstevel@tonic-gate * an appropriate provider. See crypto_cipher_init_prov() comments for more 2290Sstevel@tonic-gate * details. 2300Sstevel@tonic-gate */ 2310Sstevel@tonic-gate static int 2320Sstevel@tonic-gate crypto_cipher_init(crypto_mechanism_t *mech, crypto_key_t *key, 2330Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 2340Sstevel@tonic-gate crypto_call_req_t *crq, crypto_func_group_t func) 2350Sstevel@tonic-gate { 2360Sstevel@tonic-gate int error; 2370Sstevel@tonic-gate kcf_mech_entry_t *me; 2380Sstevel@tonic-gate kcf_provider_desc_t *pd; 2390Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 2400Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 2410Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate retry: 2440Sstevel@tonic-gate /* pd is returned held */ 2450Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 2460Sstevel@tonic-gate list, func, CHECK_RESTRICT(crq), 0)) == NULL) { 2470Sstevel@tonic-gate if (list != NULL) 2480Sstevel@tonic-gate kcf_free_triedlist(list); 2490Sstevel@tonic-gate return (error); 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate /* 2530Sstevel@tonic-gate * For SW providers, check the validity of the context template 2540Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 2550Sstevel@tonic-gate * is acceptable to fail here, and let the consumer recover by 2560Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 2570Sstevel@tonic-gate * provider 2580Sstevel@tonic-gate */ 2590Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 2600Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 2610Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 2620Sstevel@tonic-gate if (list != NULL) 2630Sstevel@tonic-gate kcf_free_triedlist(list); 2640Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 2650Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 2660Sstevel@tonic-gate } else { 2670Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate error = crypto_cipher_init_prov(pd, pd->pd_sid, mech, key, 2720Sstevel@tonic-gate spi_ctx_tmpl, ctxp, crq, func); 2730Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 2740Sstevel@tonic-gate IS_RECOVERABLE(error)) { 2750Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 2760Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 2770Sstevel@tonic-gate goto retry; 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate if (list != NULL) 2810Sstevel@tonic-gate kcf_free_triedlist(list); 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 2840Sstevel@tonic-gate return (error); 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate /* 2880Sstevel@tonic-gate * crypto_encrypt_prov() 2890Sstevel@tonic-gate * 2900Sstevel@tonic-gate * Arguments: 2910Sstevel@tonic-gate * pd: provider descriptor 2920Sstevel@tonic-gate * sid: session id 2930Sstevel@tonic-gate * mech: crypto_mechanism_t pointer. 2940Sstevel@tonic-gate * mech_type is a valid value previously returned by 2950Sstevel@tonic-gate * crypto_mech2id(); 2960Sstevel@tonic-gate * When the mech's parameter is not NULL, its definition depends 2970Sstevel@tonic-gate * on the standard definition of the mechanism. 2980Sstevel@tonic-gate * key: pointer to a crypto_key_t structure. 2990Sstevel@tonic-gate * plaintext: The message to be encrypted 3000Sstevel@tonic-gate * ciphertext: Storage for the encrypted message. The length needed 3010Sstevel@tonic-gate * depends on the mechanism, and the plaintext's size. 3020Sstevel@tonic-gate * tmpl: a crypto_ctx_template_t, opaque template of a context of an 3030Sstevel@tonic-gate * encryption with the 'mech' using 'key'. 'tmpl' is created by 3040Sstevel@tonic-gate * a previous call to crypto_create_ctx_template(). 3050Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 3060Sstevel@tonic-gate * 3070Sstevel@tonic-gate * Description: 3080Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 3090Sstevel@tonic-gate * single-part encryption of 'plaintext' with the mechanism 'mech', using 3100Sstevel@tonic-gate * the key 'key'. 3110Sstevel@tonic-gate * When complete and successful, 'ciphertext' will contain the encrypted 3120Sstevel@tonic-gate * message. 3130Sstevel@tonic-gate * 3140Sstevel@tonic-gate * Context: 3150Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 3160Sstevel@tonic-gate * 3170Sstevel@tonic-gate * Returns: 3180Sstevel@tonic-gate * See comment in the beginning of the file. 3190Sstevel@tonic-gate */ 3200Sstevel@tonic-gate int 321904Smcpowers crypto_encrypt_prov(crypto_provider_t provider, crypto_session_id_t sid, 322904Smcpowers crypto_mechanism_t *mech, crypto_data_t *plaintext, crypto_key_t *key, 323904Smcpowers crypto_ctx_template_t tmpl, crypto_data_t *ciphertext, 324904Smcpowers crypto_call_req_t *crq) 3250Sstevel@tonic-gate { 3260Sstevel@tonic-gate kcf_req_params_t params; 327904Smcpowers kcf_provider_desc_t *pd = provider; 328904Smcpowers kcf_provider_desc_t *real_provider = pd; 329904Smcpowers int error; 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 332904Smcpowers 333904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 334904Smcpowers error = kcf_get_hardware_provider(mech->cm_type, 3351808Smcpowers CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq), pd, 3361808Smcpowers &real_provider, CRYPTO_FG_ENCRYPT_ATOMIC); 337904Smcpowers 338904Smcpowers if (error != CRYPTO_SUCCESS) 339904Smcpowers return (error); 340904Smcpowers } 341904Smcpowers 3420Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, sid, mech, key, 3430Sstevel@tonic-gate plaintext, ciphertext, tmpl); 3440Sstevel@tonic-gate 345904Smcpowers error = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); 346904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 347904Smcpowers KCF_PROV_REFRELE(real_provider); 348904Smcpowers 349904Smcpowers return (error); 3500Sstevel@tonic-gate } 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate /* 3530Sstevel@tonic-gate * Same as crypto_encrypt_prov(), but relies on the scheduler to pick 3540Sstevel@tonic-gate * a provider. See crypto_encrypt_prov() for more details. 3550Sstevel@tonic-gate */ 3560Sstevel@tonic-gate int 3570Sstevel@tonic-gate crypto_encrypt(crypto_mechanism_t *mech, crypto_data_t *plaintext, 3580Sstevel@tonic-gate crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *ciphertext, 3590Sstevel@tonic-gate crypto_call_req_t *crq) 3600Sstevel@tonic-gate { 3610Sstevel@tonic-gate int error; 3620Sstevel@tonic-gate kcf_mech_entry_t *me; 3630Sstevel@tonic-gate kcf_req_params_t params; 3640Sstevel@tonic-gate kcf_provider_desc_t *pd; 3650Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 3660Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 3670Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate retry: 3700Sstevel@tonic-gate /* pd is returned held */ 3710Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 3720Sstevel@tonic-gate list, CRYPTO_FG_ENCRYPT_ATOMIC, CHECK_RESTRICT(crq), 3730Sstevel@tonic-gate plaintext->cd_length)) == NULL) { 3740Sstevel@tonic-gate if (list != NULL) 3750Sstevel@tonic-gate kcf_free_triedlist(list); 3760Sstevel@tonic-gate return (error); 3770Sstevel@tonic-gate } 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate /* 3800Sstevel@tonic-gate * For SW providers, check the validity of the context template 3810Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 3820Sstevel@tonic-gate * is acceptable to fail here, and let the consumer recover by 3830Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 3840Sstevel@tonic-gate * provider 3850Sstevel@tonic-gate */ 3860Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 3870Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 3880Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 3890Sstevel@tonic-gate if (list != NULL) 3900Sstevel@tonic-gate kcf_free_triedlist(list); 3910Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 3920Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 3930Sstevel@tonic-gate } else { 3940Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate } 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate /* The fast path for SW providers. */ 3990Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) { 4000Sstevel@tonic-gate crypto_mechanism_t lmech; 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate lmech = *mech; 4030Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate error = KCF_PROV_ENCRYPT_ATOMIC(pd, pd->pd_sid, &lmech, key, 4060Sstevel@tonic-gate plaintext, ciphertext, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq)); 4070Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 4080Sstevel@tonic-gate } else { 4090Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, pd->pd_sid, 4100Sstevel@tonic-gate mech, key, plaintext, ciphertext, spi_ctx_tmpl); 4110Sstevel@tonic-gate error = kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE); 4120Sstevel@tonic-gate } 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 4150Sstevel@tonic-gate IS_RECOVERABLE(error)) { 4160Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 4170Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 4180Sstevel@tonic-gate goto retry; 4190Sstevel@tonic-gate } 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate if (list != NULL) 4220Sstevel@tonic-gate kcf_free_triedlist(list); 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 4250Sstevel@tonic-gate return (error); 4260Sstevel@tonic-gate } 4270Sstevel@tonic-gate 4280Sstevel@tonic-gate /* 4290Sstevel@tonic-gate * crypto_encrypt_init_prov() 4300Sstevel@tonic-gate * 4310Sstevel@tonic-gate * Calls crypto_cipher_init_prov() to initialize an encryption operation. 4320Sstevel@tonic-gate */ 4330Sstevel@tonic-gate int 434904Smcpowers crypto_encrypt_init_prov(crypto_provider_t pd, crypto_session_id_t sid, 4350Sstevel@tonic-gate crypto_mechanism_t *mech, crypto_key_t *key, 4360Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 4370Sstevel@tonic-gate crypto_call_req_t *crq) 4380Sstevel@tonic-gate { 4390Sstevel@tonic-gate return (crypto_cipher_init_prov(pd, sid, mech, key, tmpl, ctxp, crq, 4400Sstevel@tonic-gate CRYPTO_FG_ENCRYPT)); 4410Sstevel@tonic-gate } 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate /* 4440Sstevel@tonic-gate * crypto_encrypt_init() 4450Sstevel@tonic-gate * 4460Sstevel@tonic-gate * Calls crypto_cipher_init() to initialize an encryption operation 4470Sstevel@tonic-gate */ 4480Sstevel@tonic-gate int 4490Sstevel@tonic-gate crypto_encrypt_init(crypto_mechanism_t *mech, crypto_key_t *key, 4500Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 4510Sstevel@tonic-gate crypto_call_req_t *crq) 4520Sstevel@tonic-gate { 4530Sstevel@tonic-gate return (crypto_cipher_init(mech, key, tmpl, ctxp, crq, 4540Sstevel@tonic-gate CRYPTO_FG_ENCRYPT)); 4550Sstevel@tonic-gate } 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate /* 4580Sstevel@tonic-gate * crypto_encrypt_update() 4590Sstevel@tonic-gate * 4600Sstevel@tonic-gate * Arguments: 4610Sstevel@tonic-gate * context: A crypto_context_t initialized by encrypt_init(). 4620Sstevel@tonic-gate * plaintext: The message part to be encrypted 4630Sstevel@tonic-gate * ciphertext: Storage for the encrypted message part. 4640Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 4650Sstevel@tonic-gate * 4660Sstevel@tonic-gate * Description: 4670Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 4680Sstevel@tonic-gate * part of an encryption operation. 4690Sstevel@tonic-gate * 4700Sstevel@tonic-gate * Context: 4710Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 4720Sstevel@tonic-gate * 4730Sstevel@tonic-gate * Returns: 4740Sstevel@tonic-gate * See comment in the beginning of the file. 4750Sstevel@tonic-gate */ 4760Sstevel@tonic-gate int 4770Sstevel@tonic-gate crypto_encrypt_update(crypto_context_t context, crypto_data_t *plaintext, 4780Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_call_req_t *cr) 4790Sstevel@tonic-gate { 4800Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 4810Sstevel@tonic-gate kcf_context_t *kcf_ctx; 4820Sstevel@tonic-gate kcf_provider_desc_t *pd; 4830Sstevel@tonic-gate int error; 4840Sstevel@tonic-gate kcf_req_params_t params; 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate if ((ctx == NULL) || 4870Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 4880Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 4890Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 4900Sstevel@tonic-gate } 4910Sstevel@tonic-gate 492904Smcpowers ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate /* The fast path for SW providers. */ 4950Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 4960Sstevel@tonic-gate error = KCF_PROV_ENCRYPT_UPDATE(pd, ctx, plaintext, 4970Sstevel@tonic-gate ciphertext, NULL); 4980Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 499*3708Skrishna return (error); 5000Sstevel@tonic-gate } 5010Sstevel@tonic-gate 502*3708Skrishna /* Check if we should use a software provider for small jobs */ 503*3708Skrishna if ((ctx->cc_flags & CRYPTO_USE_OPSTATE) && cr == NULL) { 504*3708Skrishna if (plaintext->cd_length < kcf_ctx->kc_mech->me_threshold && 505*3708Skrishna kcf_ctx->kc_sw_prov_desc != NULL && 506*3708Skrishna KCF_IS_PROV_USABLE(kcf_ctx->kc_sw_prov_desc)) { 507*3708Skrishna pd = kcf_ctx->kc_sw_prov_desc; 508*3708Skrishna } 509*3708Skrishna } 510*3708Skrishna 511*3708Skrishna KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_UPDATE, 512*3708Skrishna ctx->cc_session, NULL, NULL, plaintext, ciphertext, NULL); 513*3708Skrishna error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 514*3708Skrishna 5150Sstevel@tonic-gate return (error); 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate /* 5190Sstevel@tonic-gate * crypto_encrypt_final() 5200Sstevel@tonic-gate * 5210Sstevel@tonic-gate * Arguments: 5220Sstevel@tonic-gate * context: A crypto_context_t initialized by encrypt_init(). 5230Sstevel@tonic-gate * ciphertext: Storage for the last part of encrypted message 5240Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 5250Sstevel@tonic-gate * 5260Sstevel@tonic-gate * Description: 5270Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs the 5280Sstevel@tonic-gate * final part of an encryption operation. 5290Sstevel@tonic-gate * 5300Sstevel@tonic-gate * Context: 5310Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 5320Sstevel@tonic-gate * 5330Sstevel@tonic-gate * Returns: 5340Sstevel@tonic-gate * See comment in the beginning of the file. 5350Sstevel@tonic-gate */ 5360Sstevel@tonic-gate int 5370Sstevel@tonic-gate crypto_encrypt_final(crypto_context_t context, crypto_data_t *ciphertext, 5380Sstevel@tonic-gate crypto_call_req_t *cr) 5390Sstevel@tonic-gate { 5400Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 5410Sstevel@tonic-gate kcf_context_t *kcf_ctx; 5420Sstevel@tonic-gate kcf_provider_desc_t *pd; 5430Sstevel@tonic-gate int error; 5440Sstevel@tonic-gate kcf_req_params_t params; 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate if ((ctx == NULL) || 5470Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 5480Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 5490Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 5500Sstevel@tonic-gate } 5510Sstevel@tonic-gate 552904Smcpowers ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 5530Sstevel@tonic-gate 5540Sstevel@tonic-gate /* The fast path for SW providers. */ 5550Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 5560Sstevel@tonic-gate error = KCF_PROV_ENCRYPT_FINAL(pd, ctx, ciphertext, NULL); 5570Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 5580Sstevel@tonic-gate } else { 559904Smcpowers KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_FINAL, 560904Smcpowers ctx->cc_session, NULL, NULL, NULL, ciphertext, NULL); 5610Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 5620Sstevel@tonic-gate } 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 5650Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 5660Sstevel@tonic-gate return (error); 5670Sstevel@tonic-gate } 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate /* 5700Sstevel@tonic-gate * crypto_decrypt_prov() 5710Sstevel@tonic-gate * 5720Sstevel@tonic-gate * Arguments: 5730Sstevel@tonic-gate * pd: provider descriptor 5740Sstevel@tonic-gate * sid: session id 5750Sstevel@tonic-gate * mech: crypto_mechanism_t pointer. 5760Sstevel@tonic-gate * mech_type is a valid value previously returned by 5770Sstevel@tonic-gate * crypto_mech2id(); 5780Sstevel@tonic-gate * When the mech's parameter is not NULL, its definition depends 5790Sstevel@tonic-gate * on the standard definition of the mechanism. 5800Sstevel@tonic-gate * key: pointer to a crypto_key_t structure. 5810Sstevel@tonic-gate * ciphertext: The message to be encrypted 5820Sstevel@tonic-gate * plaintext: Storage for the encrypted message. The length needed 5830Sstevel@tonic-gate * depends on the mechanism, and the plaintext's size. 5840Sstevel@tonic-gate * tmpl: a crypto_ctx_template_t, opaque template of a context of an 5850Sstevel@tonic-gate * encryption with the 'mech' using 'key'. 'tmpl' is created by 5860Sstevel@tonic-gate * a previous call to crypto_create_ctx_template(). 5870Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 5880Sstevel@tonic-gate * 5890Sstevel@tonic-gate * Description: 5900Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 5910Sstevel@tonic-gate * single-part decryption of 'ciphertext' with the mechanism 'mech', using 5920Sstevel@tonic-gate * the key 'key'. 5930Sstevel@tonic-gate * When complete and successful, 'plaintext' will contain the decrypted 5940Sstevel@tonic-gate * message. 5950Sstevel@tonic-gate * 5960Sstevel@tonic-gate * Context: 5970Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 5980Sstevel@tonic-gate * 5990Sstevel@tonic-gate * Returns: 6000Sstevel@tonic-gate * See comment in the beginning of the file. 6010Sstevel@tonic-gate */ 6020Sstevel@tonic-gate int 603904Smcpowers crypto_decrypt_prov(crypto_provider_t provider, crypto_session_id_t sid, 604904Smcpowers crypto_mechanism_t *mech, crypto_data_t *ciphertext, crypto_key_t *key, 605904Smcpowers crypto_ctx_template_t tmpl, crypto_data_t *plaintext, 606904Smcpowers crypto_call_req_t *crq) 6070Sstevel@tonic-gate { 6080Sstevel@tonic-gate kcf_req_params_t params; 609904Smcpowers kcf_provider_desc_t *pd = provider; 610904Smcpowers kcf_provider_desc_t *real_provider = pd; 611904Smcpowers int rv; 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 614904Smcpowers 615904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 616904Smcpowers rv = kcf_get_hardware_provider(mech->cm_type, 6171808Smcpowers CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq), pd, 6181808Smcpowers &real_provider, CRYPTO_FG_DECRYPT_ATOMIC); 619904Smcpowers 620904Smcpowers if (rv != CRYPTO_SUCCESS) 621904Smcpowers return (rv); 622904Smcpowers } 623904Smcpowers 6240Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, sid, mech, key, 6250Sstevel@tonic-gate ciphertext, plaintext, tmpl); 6260Sstevel@tonic-gate 627904Smcpowers rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); 628904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 629904Smcpowers KCF_PROV_REFRELE(real_provider); 630904Smcpowers 631904Smcpowers return (rv); 6320Sstevel@tonic-gate } 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate /* 6350Sstevel@tonic-gate * Same as crypto_decrypt_prov(), but relies on the KCF scheduler to 6360Sstevel@tonic-gate * choose a provider. See crypto_decrypt_prov() comments for more 6370Sstevel@tonic-gate * information. 6380Sstevel@tonic-gate */ 6390Sstevel@tonic-gate int 6400Sstevel@tonic-gate crypto_decrypt(crypto_mechanism_t *mech, crypto_data_t *ciphertext, 6410Sstevel@tonic-gate crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *plaintext, 6420Sstevel@tonic-gate crypto_call_req_t *crq) 6430Sstevel@tonic-gate { 6440Sstevel@tonic-gate int error; 6450Sstevel@tonic-gate kcf_mech_entry_t *me; 6460Sstevel@tonic-gate kcf_req_params_t params; 6470Sstevel@tonic-gate kcf_provider_desc_t *pd; 6480Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 6490Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 6500Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate retry: 6530Sstevel@tonic-gate /* pd is returned held */ 6540Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 6550Sstevel@tonic-gate list, CRYPTO_FG_DECRYPT_ATOMIC, CHECK_RESTRICT(crq), 6560Sstevel@tonic-gate ciphertext->cd_length)) == NULL) { 6570Sstevel@tonic-gate if (list != NULL) 6580Sstevel@tonic-gate kcf_free_triedlist(list); 6590Sstevel@tonic-gate return (error); 6600Sstevel@tonic-gate } 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate /* 6630Sstevel@tonic-gate * For SW providers, check the validity of the context template 6640Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 6650Sstevel@tonic-gate * is acceptable to fail here, and let the consumer recover by 6660Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 6670Sstevel@tonic-gate * provider 6680Sstevel@tonic-gate */ 6690Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 6700Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 6710Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 6720Sstevel@tonic-gate if (list != NULL) 6730Sstevel@tonic-gate kcf_free_triedlist(list); 6740Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 6750Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 6760Sstevel@tonic-gate } else { 6770Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 6780Sstevel@tonic-gate } 6790Sstevel@tonic-gate } 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate /* The fast path for SW providers. */ 6820Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) { 6830Sstevel@tonic-gate crypto_mechanism_t lmech; 6840Sstevel@tonic-gate 6850Sstevel@tonic-gate lmech = *mech; 6860Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate error = KCF_PROV_DECRYPT_ATOMIC(pd, pd->pd_sid, &lmech, key, 6890Sstevel@tonic-gate ciphertext, plaintext, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq)); 6900Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 6910Sstevel@tonic-gate } else { 6920Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, pd->pd_sid, 6930Sstevel@tonic-gate mech, key, ciphertext, plaintext, spi_ctx_tmpl); 6940Sstevel@tonic-gate error = kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE); 6950Sstevel@tonic-gate } 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 6980Sstevel@tonic-gate IS_RECOVERABLE(error)) { 6990Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 7000Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 7010Sstevel@tonic-gate goto retry; 7020Sstevel@tonic-gate } 7030Sstevel@tonic-gate 7040Sstevel@tonic-gate if (list != NULL) 7050Sstevel@tonic-gate kcf_free_triedlist(list); 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 7080Sstevel@tonic-gate return (error); 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate /* 7120Sstevel@tonic-gate * crypto_decrypt_init_prov() 7130Sstevel@tonic-gate * 7140Sstevel@tonic-gate * Calls crypto_cipher_init_prov() to initialize a decryption operation 7150Sstevel@tonic-gate */ 7160Sstevel@tonic-gate int 717904Smcpowers crypto_decrypt_init_prov(crypto_provider_t pd, crypto_session_id_t sid, 7180Sstevel@tonic-gate crypto_mechanism_t *mech, crypto_key_t *key, 7190Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 7200Sstevel@tonic-gate crypto_call_req_t *crq) 7210Sstevel@tonic-gate { 7220Sstevel@tonic-gate return (crypto_cipher_init_prov(pd, sid, mech, key, tmpl, ctxp, crq, 7230Sstevel@tonic-gate CRYPTO_FG_DECRYPT)); 7240Sstevel@tonic-gate } 7250Sstevel@tonic-gate 7260Sstevel@tonic-gate /* 7270Sstevel@tonic-gate * crypto_decrypt_init() 7280Sstevel@tonic-gate * 7290Sstevel@tonic-gate * Calls crypto_cipher_init() to initialize a decryption operation 7300Sstevel@tonic-gate */ 7310Sstevel@tonic-gate int 7320Sstevel@tonic-gate crypto_decrypt_init(crypto_mechanism_t *mech, crypto_key_t *key, 7330Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 7340Sstevel@tonic-gate crypto_call_req_t *crq) 7350Sstevel@tonic-gate { 7360Sstevel@tonic-gate return (crypto_cipher_init(mech, key, tmpl, ctxp, crq, 7370Sstevel@tonic-gate CRYPTO_FG_DECRYPT)); 7380Sstevel@tonic-gate } 7390Sstevel@tonic-gate 7400Sstevel@tonic-gate /* 7410Sstevel@tonic-gate * crypto_decrypt_update() 7420Sstevel@tonic-gate * 7430Sstevel@tonic-gate * Arguments: 7440Sstevel@tonic-gate * context: A crypto_context_t initialized by decrypt_init(). 7450Sstevel@tonic-gate * ciphertext: The message part to be decrypted 7460Sstevel@tonic-gate * plaintext: Storage for the decrypted message part. 7470Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 7480Sstevel@tonic-gate * 7490Sstevel@tonic-gate * Description: 7500Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 7510Sstevel@tonic-gate * part of an decryption operation. 7520Sstevel@tonic-gate * 7530Sstevel@tonic-gate * Context: 7540Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 7550Sstevel@tonic-gate * 7560Sstevel@tonic-gate * Returns: 7570Sstevel@tonic-gate * See comment in the beginning of the file. 7580Sstevel@tonic-gate */ 7590Sstevel@tonic-gate int 7600Sstevel@tonic-gate crypto_decrypt_update(crypto_context_t context, crypto_data_t *ciphertext, 7610Sstevel@tonic-gate crypto_data_t *plaintext, crypto_call_req_t *cr) 7620Sstevel@tonic-gate { 7630Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 7640Sstevel@tonic-gate kcf_context_t *kcf_ctx; 7650Sstevel@tonic-gate kcf_provider_desc_t *pd; 7660Sstevel@tonic-gate int error; 7670Sstevel@tonic-gate kcf_req_params_t params; 7680Sstevel@tonic-gate 7690Sstevel@tonic-gate if ((ctx == NULL) || 7700Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 7710Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 7720Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 7730Sstevel@tonic-gate } 7740Sstevel@tonic-gate 775904Smcpowers ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate /* The fast path for SW providers. */ 7780Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 7790Sstevel@tonic-gate error = KCF_PROV_DECRYPT_UPDATE(pd, ctx, ciphertext, 7800Sstevel@tonic-gate plaintext, NULL); 7810Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 782*3708Skrishna return (error); 7830Sstevel@tonic-gate } 7840Sstevel@tonic-gate 785*3708Skrishna /* Check if we should use a software provider for small jobs */ 786*3708Skrishna if ((ctx->cc_flags & CRYPTO_USE_OPSTATE) && cr == NULL) { 787*3708Skrishna if (ciphertext->cd_length < kcf_ctx->kc_mech->me_threshold && 788*3708Skrishna kcf_ctx->kc_sw_prov_desc != NULL && 789*3708Skrishna KCF_IS_PROV_USABLE(kcf_ctx->kc_sw_prov_desc)) { 790*3708Skrishna pd = kcf_ctx->kc_sw_prov_desc; 791*3708Skrishna } 792*3708Skrishna } 793*3708Skrishna 794*3708Skrishna KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_UPDATE, 795*3708Skrishna ctx->cc_session, NULL, NULL, ciphertext, plaintext, NULL); 796*3708Skrishna error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 797*3708Skrishna 7980Sstevel@tonic-gate return (error); 7990Sstevel@tonic-gate } 8000Sstevel@tonic-gate 8010Sstevel@tonic-gate /* 8020Sstevel@tonic-gate * crypto_decrypt_final() 8030Sstevel@tonic-gate * 8040Sstevel@tonic-gate * Arguments: 8050Sstevel@tonic-gate * context: A crypto_context_t initialized by decrypt_init(). 8060Sstevel@tonic-gate * plaintext: Storage for the last part of the decrypted message 8070Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 8080Sstevel@tonic-gate * 8090Sstevel@tonic-gate * Description: 8100Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs the 8110Sstevel@tonic-gate * final part of a decryption operation. 8120Sstevel@tonic-gate * 8130Sstevel@tonic-gate * Context: 8140Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 8150Sstevel@tonic-gate * 8160Sstevel@tonic-gate * Returns: 8170Sstevel@tonic-gate * See comment in the beginning of the file. 8180Sstevel@tonic-gate */ 8190Sstevel@tonic-gate int 8200Sstevel@tonic-gate crypto_decrypt_final(crypto_context_t context, crypto_data_t *plaintext, 8210Sstevel@tonic-gate crypto_call_req_t *cr) 8220Sstevel@tonic-gate { 8230Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 8240Sstevel@tonic-gate kcf_context_t *kcf_ctx; 8250Sstevel@tonic-gate kcf_provider_desc_t *pd; 8260Sstevel@tonic-gate int error; 8270Sstevel@tonic-gate kcf_req_params_t params; 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate if ((ctx == NULL) || 8300Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 8310Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 8320Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 8330Sstevel@tonic-gate } 8340Sstevel@tonic-gate 835904Smcpowers ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate /* The fast path for SW providers. */ 8380Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 839904Smcpowers error = KCF_PROV_DECRYPT_FINAL(pd, ctx, plaintext, 840904Smcpowers NULL); 8410Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 8420Sstevel@tonic-gate } else { 843904Smcpowers KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_FINAL, 844904Smcpowers ctx->cc_session, NULL, NULL, NULL, plaintext, NULL); 8450Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 8460Sstevel@tonic-gate } 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 8490Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 8500Sstevel@tonic-gate return (error); 8510Sstevel@tonic-gate } 8520Sstevel@tonic-gate 8530Sstevel@tonic-gate /* 8540Sstevel@tonic-gate * See comments for crypto_encrypt_update(). 8550Sstevel@tonic-gate */ 8560Sstevel@tonic-gate int 8570Sstevel@tonic-gate crypto_encrypt_single(crypto_context_t context, crypto_data_t *plaintext, 8580Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_call_req_t *cr) 8590Sstevel@tonic-gate { 8600Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 8610Sstevel@tonic-gate kcf_context_t *kcf_ctx; 8620Sstevel@tonic-gate kcf_provider_desc_t *pd; 8630Sstevel@tonic-gate int error; 8640Sstevel@tonic-gate kcf_req_params_t params; 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate if ((ctx == NULL) || 8670Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 8680Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 8690Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 8700Sstevel@tonic-gate } 8710Sstevel@tonic-gate 8720Sstevel@tonic-gate /* The fast path for SW providers. */ 8730Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 8740Sstevel@tonic-gate error = KCF_PROV_ENCRYPT(pd, ctx, plaintext, 8750Sstevel@tonic-gate ciphertext, NULL); 8760Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 8770Sstevel@tonic-gate } else { 8780Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_SINGLE, pd->pd_sid, 8790Sstevel@tonic-gate NULL, NULL, plaintext, ciphertext, NULL); 8800Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 8810Sstevel@tonic-gate } 8820Sstevel@tonic-gate 8830Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 8840Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 8850Sstevel@tonic-gate return (error); 8860Sstevel@tonic-gate } 8870Sstevel@tonic-gate 8880Sstevel@tonic-gate /* 8890Sstevel@tonic-gate * See comments for crypto_decrypt_update(). 8900Sstevel@tonic-gate */ 8910Sstevel@tonic-gate int 8920Sstevel@tonic-gate crypto_decrypt_single(crypto_context_t context, crypto_data_t *ciphertext, 8930Sstevel@tonic-gate crypto_data_t *plaintext, crypto_call_req_t *cr) 8940Sstevel@tonic-gate { 8950Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 8960Sstevel@tonic-gate kcf_context_t *kcf_ctx; 8970Sstevel@tonic-gate kcf_provider_desc_t *pd; 8980Sstevel@tonic-gate int error; 8990Sstevel@tonic-gate kcf_req_params_t params; 9000Sstevel@tonic-gate 9010Sstevel@tonic-gate if ((ctx == NULL) || 9020Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 9030Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 9040Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 9050Sstevel@tonic-gate } 9060Sstevel@tonic-gate 9070Sstevel@tonic-gate /* The fast path for SW providers. */ 9080Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 9090Sstevel@tonic-gate error = KCF_PROV_DECRYPT(pd, ctx, ciphertext, 9100Sstevel@tonic-gate plaintext, NULL); 9110Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 9120Sstevel@tonic-gate } else { 9130Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_SINGLE, pd->pd_sid, 9140Sstevel@tonic-gate NULL, NULL, ciphertext, plaintext, NULL); 9150Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 9160Sstevel@tonic-gate } 9170Sstevel@tonic-gate 9180Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 9190Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 9200Sstevel@tonic-gate return (error); 9210Sstevel@tonic-gate } 922