10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1808Smcpowers * Common Development and Distribution License (the "License"). 6*1808Smcpowers * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*1808Smcpowers * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/errno.h> 290Sstevel@tonic-gate #include <sys/types.h> 300Sstevel@tonic-gate #include <sys/kmem.h> 31904Smcpowers #include <sys/sysmacros.h> 320Sstevel@tonic-gate #include <sys/crypto/common.h> 330Sstevel@tonic-gate #include <sys/crypto/impl.h> 340Sstevel@tonic-gate #include <sys/crypto/api.h> 350Sstevel@tonic-gate #include <sys/crypto/spi.h> 360Sstevel@tonic-gate #include <sys/crypto/sched_impl.h> 370Sstevel@tonic-gate 38904Smcpowers #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f) 39904Smcpowers #define CRYPTO_CIPHER_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, 124*1808Smcpowers CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq), pd, 125*1808Smcpowers &real_provider, CRYPTO_FG_ENCRYPT); 126904Smcpowers } else { 127904Smcpowers error = kcf_get_hardware_provider(mech->cm_type, 128*1808Smcpowers CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq), pd, 129*1808Smcpowers &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); 1600Sstevel@tonic-gate } else { 1610Sstevel@tonic-gate if (func == CRYPTO_FG_ENCRYPT) { 1620Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_INIT, sid, 1630Sstevel@tonic-gate mech, key, NULL, NULL, tmpl); 1640Sstevel@tonic-gate } else { 1650Sstevel@tonic-gate ASSERT(func == CRYPTO_FG_DECRYPT); 1660Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_INIT, sid, 1670Sstevel@tonic-gate mech, key, NULL, NULL, tmpl); 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate 170904Smcpowers error = kcf_submit_request(real_provider, ctx, crq, ¶ms, 171904Smcpowers B_FALSE); 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate 174904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 175904Smcpowers KCF_PROV_REFRELE(real_provider); 176904Smcpowers 1770Sstevel@tonic-gate if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED)) 1780Sstevel@tonic-gate *ctxp = (crypto_context_t)ctx; 1790Sstevel@tonic-gate else { 1800Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx(). */ 1810Sstevel@tonic-gate KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private); 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate return (error); 1850Sstevel@tonic-gate } 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate /* 1880Sstevel@tonic-gate * Same as crypto_cipher_init_prov(), but relies on the scheduler to pick 1890Sstevel@tonic-gate * an appropriate provider. See crypto_cipher_init_prov() comments for more 1900Sstevel@tonic-gate * details. 1910Sstevel@tonic-gate */ 1920Sstevel@tonic-gate static int 1930Sstevel@tonic-gate crypto_cipher_init(crypto_mechanism_t *mech, crypto_key_t *key, 1940Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 1950Sstevel@tonic-gate crypto_call_req_t *crq, crypto_func_group_t func) 1960Sstevel@tonic-gate { 1970Sstevel@tonic-gate int error; 1980Sstevel@tonic-gate kcf_mech_entry_t *me; 1990Sstevel@tonic-gate kcf_provider_desc_t *pd; 2000Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 2010Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 2020Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate retry: 2050Sstevel@tonic-gate /* pd is returned held */ 2060Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 2070Sstevel@tonic-gate list, func, CHECK_RESTRICT(crq), 0)) == NULL) { 2080Sstevel@tonic-gate if (list != NULL) 2090Sstevel@tonic-gate kcf_free_triedlist(list); 2100Sstevel@tonic-gate return (error); 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate /* 2140Sstevel@tonic-gate * For SW providers, check the validity of the context template 2150Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 2160Sstevel@tonic-gate * is acceptable to fail here, and let the consumer recover by 2170Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 2180Sstevel@tonic-gate * provider 2190Sstevel@tonic-gate */ 2200Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 2210Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 2220Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 2230Sstevel@tonic-gate if (list != NULL) 2240Sstevel@tonic-gate kcf_free_triedlist(list); 2250Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 2260Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 2270Sstevel@tonic-gate } else { 2280Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate } 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate error = crypto_cipher_init_prov(pd, pd->pd_sid, mech, key, 2330Sstevel@tonic-gate spi_ctx_tmpl, ctxp, crq, func); 2340Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 2350Sstevel@tonic-gate IS_RECOVERABLE(error)) { 2360Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 2370Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 2380Sstevel@tonic-gate goto retry; 2390Sstevel@tonic-gate } 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate if (list != NULL) 2420Sstevel@tonic-gate kcf_free_triedlist(list); 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 2450Sstevel@tonic-gate return (error); 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate /* 2490Sstevel@tonic-gate * crypto_encrypt_prov() 2500Sstevel@tonic-gate * 2510Sstevel@tonic-gate * Arguments: 2520Sstevel@tonic-gate * pd: provider descriptor 2530Sstevel@tonic-gate * sid: session id 2540Sstevel@tonic-gate * mech: crypto_mechanism_t pointer. 2550Sstevel@tonic-gate * mech_type is a valid value previously returned by 2560Sstevel@tonic-gate * crypto_mech2id(); 2570Sstevel@tonic-gate * When the mech's parameter is not NULL, its definition depends 2580Sstevel@tonic-gate * on the standard definition of the mechanism. 2590Sstevel@tonic-gate * key: pointer to a crypto_key_t structure. 2600Sstevel@tonic-gate * plaintext: The message to be encrypted 2610Sstevel@tonic-gate * ciphertext: Storage for the encrypted message. The length needed 2620Sstevel@tonic-gate * depends on the mechanism, and the plaintext's size. 2630Sstevel@tonic-gate * tmpl: a crypto_ctx_template_t, opaque template of a context of an 2640Sstevel@tonic-gate * encryption with the 'mech' using 'key'. 'tmpl' is created by 2650Sstevel@tonic-gate * a previous call to crypto_create_ctx_template(). 2660Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 2670Sstevel@tonic-gate * 2680Sstevel@tonic-gate * Description: 2690Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 2700Sstevel@tonic-gate * single-part encryption of 'plaintext' with the mechanism 'mech', using 2710Sstevel@tonic-gate * the key 'key'. 2720Sstevel@tonic-gate * When complete and successful, 'ciphertext' will contain the encrypted 2730Sstevel@tonic-gate * message. 2740Sstevel@tonic-gate * 2750Sstevel@tonic-gate * Context: 2760Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 2770Sstevel@tonic-gate * 2780Sstevel@tonic-gate * Returns: 2790Sstevel@tonic-gate * See comment in the beginning of the file. 2800Sstevel@tonic-gate */ 2810Sstevel@tonic-gate int 282904Smcpowers crypto_encrypt_prov(crypto_provider_t provider, crypto_session_id_t sid, 283904Smcpowers crypto_mechanism_t *mech, crypto_data_t *plaintext, crypto_key_t *key, 284904Smcpowers crypto_ctx_template_t tmpl, crypto_data_t *ciphertext, 285904Smcpowers crypto_call_req_t *crq) 2860Sstevel@tonic-gate { 2870Sstevel@tonic-gate kcf_req_params_t params; 288904Smcpowers kcf_provider_desc_t *pd = provider; 289904Smcpowers kcf_provider_desc_t *real_provider = pd; 290904Smcpowers int error; 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 293904Smcpowers 294904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 295904Smcpowers error = kcf_get_hardware_provider(mech->cm_type, 296*1808Smcpowers CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq), pd, 297*1808Smcpowers &real_provider, CRYPTO_FG_ENCRYPT_ATOMIC); 298904Smcpowers 299904Smcpowers if (error != CRYPTO_SUCCESS) 300904Smcpowers return (error); 301904Smcpowers } 302904Smcpowers 3030Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, sid, mech, key, 3040Sstevel@tonic-gate plaintext, ciphertext, tmpl); 3050Sstevel@tonic-gate 306904Smcpowers error = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); 307904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 308904Smcpowers KCF_PROV_REFRELE(real_provider); 309904Smcpowers 310904Smcpowers return (error); 3110Sstevel@tonic-gate } 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate /* 3140Sstevel@tonic-gate * Same as crypto_encrypt_prov(), but relies on the scheduler to pick 3150Sstevel@tonic-gate * a provider. See crypto_encrypt_prov() for more details. 3160Sstevel@tonic-gate */ 3170Sstevel@tonic-gate int 3180Sstevel@tonic-gate crypto_encrypt(crypto_mechanism_t *mech, crypto_data_t *plaintext, 3190Sstevel@tonic-gate crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *ciphertext, 3200Sstevel@tonic-gate crypto_call_req_t *crq) 3210Sstevel@tonic-gate { 3220Sstevel@tonic-gate int error; 3230Sstevel@tonic-gate kcf_mech_entry_t *me; 3240Sstevel@tonic-gate kcf_req_params_t params; 3250Sstevel@tonic-gate kcf_provider_desc_t *pd; 3260Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 3270Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 3280Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate retry: 3310Sstevel@tonic-gate /* pd is returned held */ 3320Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 3330Sstevel@tonic-gate list, CRYPTO_FG_ENCRYPT_ATOMIC, CHECK_RESTRICT(crq), 3340Sstevel@tonic-gate plaintext->cd_length)) == NULL) { 3350Sstevel@tonic-gate if (list != NULL) 3360Sstevel@tonic-gate kcf_free_triedlist(list); 3370Sstevel@tonic-gate return (error); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate /* 3410Sstevel@tonic-gate * For SW providers, check the validity of the context template 3420Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 3430Sstevel@tonic-gate * is acceptable to fail here, and let the consumer recover by 3440Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 3450Sstevel@tonic-gate * provider 3460Sstevel@tonic-gate */ 3470Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 3480Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 3490Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 3500Sstevel@tonic-gate if (list != NULL) 3510Sstevel@tonic-gate kcf_free_triedlist(list); 3520Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 3530Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 3540Sstevel@tonic-gate } else { 3550Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 3560Sstevel@tonic-gate } 3570Sstevel@tonic-gate } 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate /* The fast path for SW providers. */ 3600Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) { 3610Sstevel@tonic-gate crypto_mechanism_t lmech; 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate lmech = *mech; 3640Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate error = KCF_PROV_ENCRYPT_ATOMIC(pd, pd->pd_sid, &lmech, key, 3670Sstevel@tonic-gate plaintext, ciphertext, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq)); 3680Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 3690Sstevel@tonic-gate } else { 3700Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, pd->pd_sid, 3710Sstevel@tonic-gate mech, key, plaintext, ciphertext, spi_ctx_tmpl); 3720Sstevel@tonic-gate error = kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE); 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 3760Sstevel@tonic-gate IS_RECOVERABLE(error)) { 3770Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 3780Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 3790Sstevel@tonic-gate goto retry; 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate if (list != NULL) 3830Sstevel@tonic-gate kcf_free_triedlist(list); 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 3860Sstevel@tonic-gate return (error); 3870Sstevel@tonic-gate } 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate /* 3900Sstevel@tonic-gate * crypto_encrypt_init_prov() 3910Sstevel@tonic-gate * 3920Sstevel@tonic-gate * Calls crypto_cipher_init_prov() to initialize an encryption operation. 3930Sstevel@tonic-gate */ 3940Sstevel@tonic-gate int 395904Smcpowers crypto_encrypt_init_prov(crypto_provider_t pd, crypto_session_id_t sid, 3960Sstevel@tonic-gate crypto_mechanism_t *mech, crypto_key_t *key, 3970Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 3980Sstevel@tonic-gate crypto_call_req_t *crq) 3990Sstevel@tonic-gate { 4000Sstevel@tonic-gate return (crypto_cipher_init_prov(pd, sid, mech, key, tmpl, ctxp, crq, 4010Sstevel@tonic-gate CRYPTO_FG_ENCRYPT)); 4020Sstevel@tonic-gate } 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate /* 4050Sstevel@tonic-gate * crypto_encrypt_init() 4060Sstevel@tonic-gate * 4070Sstevel@tonic-gate * Calls crypto_cipher_init() to initialize an encryption operation 4080Sstevel@tonic-gate */ 4090Sstevel@tonic-gate int 4100Sstevel@tonic-gate crypto_encrypt_init(crypto_mechanism_t *mech, crypto_key_t *key, 4110Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 4120Sstevel@tonic-gate crypto_call_req_t *crq) 4130Sstevel@tonic-gate { 4140Sstevel@tonic-gate return (crypto_cipher_init(mech, key, tmpl, ctxp, crq, 4150Sstevel@tonic-gate CRYPTO_FG_ENCRYPT)); 4160Sstevel@tonic-gate } 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate /* 4190Sstevel@tonic-gate * crypto_encrypt_update() 4200Sstevel@tonic-gate * 4210Sstevel@tonic-gate * Arguments: 4220Sstevel@tonic-gate * context: A crypto_context_t initialized by encrypt_init(). 4230Sstevel@tonic-gate * plaintext: The message part to be encrypted 4240Sstevel@tonic-gate * ciphertext: Storage for the encrypted message part. 4250Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 4260Sstevel@tonic-gate * 4270Sstevel@tonic-gate * Description: 4280Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 4290Sstevel@tonic-gate * part of an encryption operation. 4300Sstevel@tonic-gate * 4310Sstevel@tonic-gate * Context: 4320Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 4330Sstevel@tonic-gate * 4340Sstevel@tonic-gate * Returns: 4350Sstevel@tonic-gate * See comment in the beginning of the file. 4360Sstevel@tonic-gate */ 4370Sstevel@tonic-gate int 4380Sstevel@tonic-gate crypto_encrypt_update(crypto_context_t context, crypto_data_t *plaintext, 4390Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_call_req_t *cr) 4400Sstevel@tonic-gate { 4410Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 4420Sstevel@tonic-gate kcf_context_t *kcf_ctx; 4430Sstevel@tonic-gate kcf_provider_desc_t *pd; 4440Sstevel@tonic-gate int error; 4450Sstevel@tonic-gate kcf_req_params_t params; 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate if ((ctx == NULL) || 4480Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 4490Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 4500Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate 453904Smcpowers ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 4540Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate /* The fast path for SW providers. */ 4570Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 4580Sstevel@tonic-gate error = KCF_PROV_ENCRYPT_UPDATE(pd, ctx, plaintext, 4590Sstevel@tonic-gate ciphertext, NULL); 4600Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 4610Sstevel@tonic-gate } else { 462904Smcpowers KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_UPDATE, 463904Smcpowers ctx->cc_session, NULL, NULL, plaintext, ciphertext, NULL); 4640Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 4650Sstevel@tonic-gate } 4660Sstevel@tonic-gate 4670Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 4680Sstevel@tonic-gate return (error); 4690Sstevel@tonic-gate } 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate /* 4720Sstevel@tonic-gate * crypto_encrypt_final() 4730Sstevel@tonic-gate * 4740Sstevel@tonic-gate * Arguments: 4750Sstevel@tonic-gate * context: A crypto_context_t initialized by encrypt_init(). 4760Sstevel@tonic-gate * ciphertext: Storage for the last part of encrypted message 4770Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 4780Sstevel@tonic-gate * 4790Sstevel@tonic-gate * Description: 4800Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs the 4810Sstevel@tonic-gate * final part of an encryption operation. 4820Sstevel@tonic-gate * 4830Sstevel@tonic-gate * Context: 4840Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 4850Sstevel@tonic-gate * 4860Sstevel@tonic-gate * Returns: 4870Sstevel@tonic-gate * See comment in the beginning of the file. 4880Sstevel@tonic-gate */ 4890Sstevel@tonic-gate int 4900Sstevel@tonic-gate crypto_encrypt_final(crypto_context_t context, crypto_data_t *ciphertext, 4910Sstevel@tonic-gate crypto_call_req_t *cr) 4920Sstevel@tonic-gate { 4930Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 4940Sstevel@tonic-gate kcf_context_t *kcf_ctx; 4950Sstevel@tonic-gate kcf_provider_desc_t *pd; 4960Sstevel@tonic-gate int error; 4970Sstevel@tonic-gate kcf_req_params_t params; 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate if ((ctx == NULL) || 5000Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 5010Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 5020Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 5030Sstevel@tonic-gate } 5040Sstevel@tonic-gate 505904Smcpowers ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 5060Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate /* The fast path for SW providers. */ 5090Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 5100Sstevel@tonic-gate error = KCF_PROV_ENCRYPT_FINAL(pd, ctx, ciphertext, NULL); 5110Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 5120Sstevel@tonic-gate } else { 513904Smcpowers KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_FINAL, 514904Smcpowers ctx->cc_session, NULL, NULL, NULL, ciphertext, NULL); 5150Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 5190Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 5200Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 5210Sstevel@tonic-gate return (error); 5220Sstevel@tonic-gate } 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate /* 5250Sstevel@tonic-gate * crypto_decrypt_prov() 5260Sstevel@tonic-gate * 5270Sstevel@tonic-gate * Arguments: 5280Sstevel@tonic-gate * pd: provider descriptor 5290Sstevel@tonic-gate * sid: session id 5300Sstevel@tonic-gate * mech: crypto_mechanism_t pointer. 5310Sstevel@tonic-gate * mech_type is a valid value previously returned by 5320Sstevel@tonic-gate * crypto_mech2id(); 5330Sstevel@tonic-gate * When the mech's parameter is not NULL, its definition depends 5340Sstevel@tonic-gate * on the standard definition of the mechanism. 5350Sstevel@tonic-gate * key: pointer to a crypto_key_t structure. 5360Sstevel@tonic-gate * ciphertext: The message to be encrypted 5370Sstevel@tonic-gate * plaintext: Storage for the encrypted message. The length needed 5380Sstevel@tonic-gate * depends on the mechanism, and the plaintext's size. 5390Sstevel@tonic-gate * tmpl: a crypto_ctx_template_t, opaque template of a context of an 5400Sstevel@tonic-gate * encryption with the 'mech' using 'key'. 'tmpl' is created by 5410Sstevel@tonic-gate * a previous call to crypto_create_ctx_template(). 5420Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 5430Sstevel@tonic-gate * 5440Sstevel@tonic-gate * Description: 5450Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 5460Sstevel@tonic-gate * single-part decryption of 'ciphertext' with the mechanism 'mech', using 5470Sstevel@tonic-gate * the key 'key'. 5480Sstevel@tonic-gate * When complete and successful, 'plaintext' will contain the decrypted 5490Sstevel@tonic-gate * message. 5500Sstevel@tonic-gate * 5510Sstevel@tonic-gate * Context: 5520Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 5530Sstevel@tonic-gate * 5540Sstevel@tonic-gate * Returns: 5550Sstevel@tonic-gate * See comment in the beginning of the file. 5560Sstevel@tonic-gate */ 5570Sstevel@tonic-gate int 558904Smcpowers crypto_decrypt_prov(crypto_provider_t provider, crypto_session_id_t sid, 559904Smcpowers crypto_mechanism_t *mech, crypto_data_t *ciphertext, crypto_key_t *key, 560904Smcpowers crypto_ctx_template_t tmpl, crypto_data_t *plaintext, 561904Smcpowers crypto_call_req_t *crq) 5620Sstevel@tonic-gate { 5630Sstevel@tonic-gate kcf_req_params_t params; 564904Smcpowers kcf_provider_desc_t *pd = provider; 565904Smcpowers kcf_provider_desc_t *real_provider = pd; 566904Smcpowers int rv; 5670Sstevel@tonic-gate 5680Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 569904Smcpowers 570904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 571904Smcpowers rv = kcf_get_hardware_provider(mech->cm_type, 572*1808Smcpowers CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq), pd, 573*1808Smcpowers &real_provider, CRYPTO_FG_DECRYPT_ATOMIC); 574904Smcpowers 575904Smcpowers if (rv != CRYPTO_SUCCESS) 576904Smcpowers return (rv); 577904Smcpowers } 578904Smcpowers 5790Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, sid, mech, key, 5800Sstevel@tonic-gate ciphertext, plaintext, tmpl); 5810Sstevel@tonic-gate 582904Smcpowers rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); 583904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 584904Smcpowers KCF_PROV_REFRELE(real_provider); 585904Smcpowers 586904Smcpowers return (rv); 5870Sstevel@tonic-gate } 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate /* 5900Sstevel@tonic-gate * Same as crypto_decrypt_prov(), but relies on the KCF scheduler to 5910Sstevel@tonic-gate * choose a provider. See crypto_decrypt_prov() comments for more 5920Sstevel@tonic-gate * information. 5930Sstevel@tonic-gate */ 5940Sstevel@tonic-gate int 5950Sstevel@tonic-gate crypto_decrypt(crypto_mechanism_t *mech, crypto_data_t *ciphertext, 5960Sstevel@tonic-gate crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *plaintext, 5970Sstevel@tonic-gate crypto_call_req_t *crq) 5980Sstevel@tonic-gate { 5990Sstevel@tonic-gate int error; 6000Sstevel@tonic-gate kcf_mech_entry_t *me; 6010Sstevel@tonic-gate kcf_req_params_t params; 6020Sstevel@tonic-gate kcf_provider_desc_t *pd; 6030Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 6040Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 6050Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate retry: 6080Sstevel@tonic-gate /* pd is returned held */ 6090Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 6100Sstevel@tonic-gate list, CRYPTO_FG_DECRYPT_ATOMIC, CHECK_RESTRICT(crq), 6110Sstevel@tonic-gate ciphertext->cd_length)) == NULL) { 6120Sstevel@tonic-gate if (list != NULL) 6130Sstevel@tonic-gate kcf_free_triedlist(list); 6140Sstevel@tonic-gate return (error); 6150Sstevel@tonic-gate } 6160Sstevel@tonic-gate 6170Sstevel@tonic-gate /* 6180Sstevel@tonic-gate * For SW providers, check the validity of the context template 6190Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 6200Sstevel@tonic-gate * is acceptable to fail here, and let the consumer recover by 6210Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 6220Sstevel@tonic-gate * provider 6230Sstevel@tonic-gate */ 6240Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 6250Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 6260Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 6270Sstevel@tonic-gate if (list != NULL) 6280Sstevel@tonic-gate kcf_free_triedlist(list); 6290Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 6300Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 6310Sstevel@tonic-gate } else { 6320Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 6330Sstevel@tonic-gate } 6340Sstevel@tonic-gate } 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate /* The fast path for SW providers. */ 6370Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) { 6380Sstevel@tonic-gate crypto_mechanism_t lmech; 6390Sstevel@tonic-gate 6400Sstevel@tonic-gate lmech = *mech; 6410Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate error = KCF_PROV_DECRYPT_ATOMIC(pd, pd->pd_sid, &lmech, key, 6440Sstevel@tonic-gate ciphertext, plaintext, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq)); 6450Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 6460Sstevel@tonic-gate } else { 6470Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, pd->pd_sid, 6480Sstevel@tonic-gate mech, key, ciphertext, plaintext, spi_ctx_tmpl); 6490Sstevel@tonic-gate error = kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE); 6500Sstevel@tonic-gate } 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 6530Sstevel@tonic-gate IS_RECOVERABLE(error)) { 6540Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 6550Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 6560Sstevel@tonic-gate goto retry; 6570Sstevel@tonic-gate } 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate if (list != NULL) 6600Sstevel@tonic-gate kcf_free_triedlist(list); 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 6630Sstevel@tonic-gate return (error); 6640Sstevel@tonic-gate } 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate /* 6670Sstevel@tonic-gate * crypto_decrypt_init_prov() 6680Sstevel@tonic-gate * 6690Sstevel@tonic-gate * Calls crypto_cipher_init_prov() to initialize a decryption operation 6700Sstevel@tonic-gate */ 6710Sstevel@tonic-gate int 672904Smcpowers crypto_decrypt_init_prov(crypto_provider_t pd, crypto_session_id_t sid, 6730Sstevel@tonic-gate crypto_mechanism_t *mech, crypto_key_t *key, 6740Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 6750Sstevel@tonic-gate crypto_call_req_t *crq) 6760Sstevel@tonic-gate { 6770Sstevel@tonic-gate return (crypto_cipher_init_prov(pd, sid, mech, key, tmpl, ctxp, crq, 6780Sstevel@tonic-gate CRYPTO_FG_DECRYPT)); 6790Sstevel@tonic-gate } 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate /* 6820Sstevel@tonic-gate * crypto_decrypt_init() 6830Sstevel@tonic-gate * 6840Sstevel@tonic-gate * Calls crypto_cipher_init() to initialize a decryption operation 6850Sstevel@tonic-gate */ 6860Sstevel@tonic-gate int 6870Sstevel@tonic-gate crypto_decrypt_init(crypto_mechanism_t *mech, crypto_key_t *key, 6880Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 6890Sstevel@tonic-gate crypto_call_req_t *crq) 6900Sstevel@tonic-gate { 6910Sstevel@tonic-gate return (crypto_cipher_init(mech, key, tmpl, ctxp, crq, 6920Sstevel@tonic-gate CRYPTO_FG_DECRYPT)); 6930Sstevel@tonic-gate } 6940Sstevel@tonic-gate 6950Sstevel@tonic-gate /* 6960Sstevel@tonic-gate * crypto_decrypt_update() 6970Sstevel@tonic-gate * 6980Sstevel@tonic-gate * Arguments: 6990Sstevel@tonic-gate * context: A crypto_context_t initialized by decrypt_init(). 7000Sstevel@tonic-gate * ciphertext: The message part to be decrypted 7010Sstevel@tonic-gate * plaintext: Storage for the decrypted message part. 7020Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 7030Sstevel@tonic-gate * 7040Sstevel@tonic-gate * Description: 7050Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a 7060Sstevel@tonic-gate * part of an decryption operation. 7070Sstevel@tonic-gate * 7080Sstevel@tonic-gate * Context: 7090Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 7100Sstevel@tonic-gate * 7110Sstevel@tonic-gate * Returns: 7120Sstevel@tonic-gate * See comment in the beginning of the file. 7130Sstevel@tonic-gate */ 7140Sstevel@tonic-gate int 7150Sstevel@tonic-gate crypto_decrypt_update(crypto_context_t context, crypto_data_t *ciphertext, 7160Sstevel@tonic-gate crypto_data_t *plaintext, crypto_call_req_t *cr) 7170Sstevel@tonic-gate { 7180Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 7190Sstevel@tonic-gate kcf_context_t *kcf_ctx; 7200Sstevel@tonic-gate kcf_provider_desc_t *pd; 7210Sstevel@tonic-gate int error; 7220Sstevel@tonic-gate kcf_req_params_t params; 7230Sstevel@tonic-gate 7240Sstevel@tonic-gate if ((ctx == NULL) || 7250Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 7260Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 7270Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 7280Sstevel@tonic-gate } 7290Sstevel@tonic-gate 730904Smcpowers ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 7310Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 7320Sstevel@tonic-gate 7330Sstevel@tonic-gate /* The fast path for SW providers. */ 7340Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 7350Sstevel@tonic-gate error = KCF_PROV_DECRYPT_UPDATE(pd, ctx, ciphertext, 7360Sstevel@tonic-gate plaintext, NULL); 7370Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 7380Sstevel@tonic-gate } else { 739904Smcpowers KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_UPDATE, 740904Smcpowers ctx->cc_session, NULL, NULL, ciphertext, plaintext, NULL); 7410Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 7420Sstevel@tonic-gate } 7430Sstevel@tonic-gate 7440Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 7450Sstevel@tonic-gate return (error); 7460Sstevel@tonic-gate } 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate /* 7490Sstevel@tonic-gate * crypto_decrypt_final() 7500Sstevel@tonic-gate * 7510Sstevel@tonic-gate * Arguments: 7520Sstevel@tonic-gate * context: A crypto_context_t initialized by decrypt_init(). 7530Sstevel@tonic-gate * plaintext: Storage for the last part of the decrypted message 7540Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info. 7550Sstevel@tonic-gate * 7560Sstevel@tonic-gate * Description: 7570Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs the 7580Sstevel@tonic-gate * final part of a decryption operation. 7590Sstevel@tonic-gate * 7600Sstevel@tonic-gate * Context: 7610Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'. 7620Sstevel@tonic-gate * 7630Sstevel@tonic-gate * Returns: 7640Sstevel@tonic-gate * See comment in the beginning of the file. 7650Sstevel@tonic-gate */ 7660Sstevel@tonic-gate int 7670Sstevel@tonic-gate crypto_decrypt_final(crypto_context_t context, crypto_data_t *plaintext, 7680Sstevel@tonic-gate crypto_call_req_t *cr) 7690Sstevel@tonic-gate { 7700Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 7710Sstevel@tonic-gate kcf_context_t *kcf_ctx; 7720Sstevel@tonic-gate kcf_provider_desc_t *pd; 7730Sstevel@tonic-gate int error; 7740Sstevel@tonic-gate kcf_req_params_t params; 7750Sstevel@tonic-gate 7760Sstevel@tonic-gate if ((ctx == NULL) || 7770Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 7780Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 7790Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 7800Sstevel@tonic-gate } 7810Sstevel@tonic-gate 782904Smcpowers ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 7830Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate /* The fast path for SW providers. */ 7860Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 787904Smcpowers error = KCF_PROV_DECRYPT_FINAL(pd, ctx, plaintext, 788904Smcpowers NULL); 7890Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 7900Sstevel@tonic-gate } else { 791904Smcpowers KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_FINAL, 792904Smcpowers ctx->cc_session, NULL, NULL, NULL, plaintext, NULL); 7930Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 7940Sstevel@tonic-gate } 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 7970Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 7980Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 7990Sstevel@tonic-gate return (error); 8000Sstevel@tonic-gate } 8010Sstevel@tonic-gate 8020Sstevel@tonic-gate /* 8030Sstevel@tonic-gate * See comments for crypto_encrypt_update(). 8040Sstevel@tonic-gate */ 8050Sstevel@tonic-gate int 8060Sstevel@tonic-gate crypto_encrypt_single(crypto_context_t context, crypto_data_t *plaintext, 8070Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_call_req_t *cr) 8080Sstevel@tonic-gate { 8090Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 8100Sstevel@tonic-gate kcf_context_t *kcf_ctx; 8110Sstevel@tonic-gate kcf_provider_desc_t *pd; 8120Sstevel@tonic-gate int error; 8130Sstevel@tonic-gate kcf_req_params_t params; 8140Sstevel@tonic-gate 8150Sstevel@tonic-gate if ((ctx == NULL) || 8160Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 8170Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 8180Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 8190Sstevel@tonic-gate } 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 8220Sstevel@tonic-gate 8230Sstevel@tonic-gate /* The fast path for SW providers. */ 8240Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 8250Sstevel@tonic-gate error = KCF_PROV_ENCRYPT(pd, ctx, plaintext, 8260Sstevel@tonic-gate ciphertext, NULL); 8270Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 8280Sstevel@tonic-gate } else { 8290Sstevel@tonic-gate KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_SINGLE, pd->pd_sid, 8300Sstevel@tonic-gate NULL, NULL, plaintext, ciphertext, NULL); 8310Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 8320Sstevel@tonic-gate } 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 8350Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 8360Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 8370Sstevel@tonic-gate return (error); 8380Sstevel@tonic-gate } 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate /* 8410Sstevel@tonic-gate * See comments for crypto_decrypt_update(). 8420Sstevel@tonic-gate */ 8430Sstevel@tonic-gate int 8440Sstevel@tonic-gate crypto_decrypt_single(crypto_context_t context, crypto_data_t *ciphertext, 8450Sstevel@tonic-gate crypto_data_t *plaintext, crypto_call_req_t *cr) 8460Sstevel@tonic-gate { 8470Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 8480Sstevel@tonic-gate kcf_context_t *kcf_ctx; 8490Sstevel@tonic-gate kcf_provider_desc_t *pd; 8500Sstevel@tonic-gate int error; 8510Sstevel@tonic-gate kcf_req_params_t params; 8520Sstevel@tonic-gate 8530Sstevel@tonic-gate if ((ctx == NULL) || 8540Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 8550Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 8560Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 8570Sstevel@tonic-gate } 8580Sstevel@tonic-gate 8590Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 8600Sstevel@tonic-gate 8610Sstevel@tonic-gate /* The fast path for SW providers. */ 8620Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) { 8630Sstevel@tonic-gate error = KCF_PROV_DECRYPT(pd, ctx, ciphertext, 8640Sstevel@tonic-gate plaintext, NULL); 8650Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 8660Sstevel@tonic-gate } else { 8670Sstevel@tonic-gate KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_SINGLE, pd->pd_sid, 8680Sstevel@tonic-gate NULL, NULL, ciphertext, plaintext, NULL); 8690Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 8700Sstevel@tonic-gate } 8710Sstevel@tonic-gate 8720Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 8730Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 8740Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 8750Sstevel@tonic-gate return (error); 8760Sstevel@tonic-gate } 877