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
55072Smcpowers * Common Development and Distribution License (the "License").
65072Smcpowers * 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*11751SAnthony.Scarpino@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * Blowfish provider for the Kernel Cryptographic Framework (KCF)
280Sstevel@tonic-gate */
290Sstevel@tonic-gate
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <sys/systm.h>
320Sstevel@tonic-gate #include <sys/modctl.h>
330Sstevel@tonic-gate #include <sys/cmn_err.h>
340Sstevel@tonic-gate #include <sys/ddi.h>
350Sstevel@tonic-gate #include <sys/crypto/common.h>
360Sstevel@tonic-gate #include <sys/crypto/spi.h>
370Sstevel@tonic-gate #include <sys/sysmacros.h>
380Sstevel@tonic-gate #include <sys/strsun.h>
390Sstevel@tonic-gate #include <sys/note.h>
407188Smcpowers #include <modes/modes.h>
417188Smcpowers #include <blowfish/blowfish_impl.h>
420Sstevel@tonic-gate
430Sstevel@tonic-gate extern struct mod_ops mod_cryptoops;
440Sstevel@tonic-gate
450Sstevel@tonic-gate /*
460Sstevel@tonic-gate * Module linkage information for the kernel.
470Sstevel@tonic-gate */
480Sstevel@tonic-gate static struct modlcrypto modlcrypto = {
490Sstevel@tonic-gate &mod_cryptoops,
505072Smcpowers "Blowfish Kernel SW Provider"
510Sstevel@tonic-gate };
520Sstevel@tonic-gate
530Sstevel@tonic-gate static struct modlinkage modlinkage = {
540Sstevel@tonic-gate MODREV_1,
550Sstevel@tonic-gate (void *)&modlcrypto,
560Sstevel@tonic-gate NULL
570Sstevel@tonic-gate };
580Sstevel@tonic-gate
590Sstevel@tonic-gate /*
600Sstevel@tonic-gate * CSPI information (entry points, provider info, etc.)
610Sstevel@tonic-gate */
620Sstevel@tonic-gate typedef enum blowfish_mech_type {
63676Sizick BLOWFISH_ECB_MECH_INFO_TYPE, /* SUN_CKM_BLOWFISH_ECB */
64676Sizick BLOWFISH_CBC_MECH_INFO_TYPE /* SUN_CKM_BLOWFISH_CBC */
650Sstevel@tonic-gate } blowfish_mech_type_t;
660Sstevel@tonic-gate
670Sstevel@tonic-gate
680Sstevel@tonic-gate #define BLOWFISH_COPY_BLOCK(src, dst) \
690Sstevel@tonic-gate (dst)[0] = (src)[0]; \
700Sstevel@tonic-gate (dst)[1] = (src)[1]; \
710Sstevel@tonic-gate (dst)[2] = (src)[2]; \
720Sstevel@tonic-gate (dst)[3] = (src)[3]; \
730Sstevel@tonic-gate (dst)[4] = (src)[4]; \
740Sstevel@tonic-gate (dst)[5] = (src)[5]; \
750Sstevel@tonic-gate (dst)[6] = (src)[6]; \
760Sstevel@tonic-gate (dst)[7] = (src)[7]
770Sstevel@tonic-gate
780Sstevel@tonic-gate #define BLOWFISH_XOR_BLOCK(src, dst) \
790Sstevel@tonic-gate (dst)[0] ^= (src)[0]; \
800Sstevel@tonic-gate (dst)[1] ^= (src)[1]; \
810Sstevel@tonic-gate (dst)[2] ^= (src)[2]; \
820Sstevel@tonic-gate (dst)[3] ^= (src)[3]; \
830Sstevel@tonic-gate (dst)[4] ^= (src)[4]; \
840Sstevel@tonic-gate (dst)[5] ^= (src)[5]; \
850Sstevel@tonic-gate (dst)[6] ^= (src)[6]; \
860Sstevel@tonic-gate (dst)[7] ^= (src)[7]
870Sstevel@tonic-gate
880Sstevel@tonic-gate /*
890Sstevel@tonic-gate * Mechanism info structure passed to KCF during registration.
900Sstevel@tonic-gate */
910Sstevel@tonic-gate
920Sstevel@tonic-gate static crypto_mech_info_t blowfish_mech_info_tab[] = {
930Sstevel@tonic-gate /* BLOWFISH_ECB */
94676Sizick {SUN_CKM_BLOWFISH_ECB, BLOWFISH_ECB_MECH_INFO_TYPE,
950Sstevel@tonic-gate CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
960Sstevel@tonic-gate CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
970Sstevel@tonic-gate BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS},
980Sstevel@tonic-gate /* BLOWFISH_CBC */
99676Sizick {SUN_CKM_BLOWFISH_CBC, BLOWFISH_CBC_MECH_INFO_TYPE,
1000Sstevel@tonic-gate CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
1010Sstevel@tonic-gate CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
1020Sstevel@tonic-gate BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS}
1030Sstevel@tonic-gate };
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate #define BLOWFISH_VALID_MECH(mech) \
106676Sizick (((mech)->cm_type == BLOWFISH_ECB_MECH_INFO_TYPE || \
107676Sizick (mech)->cm_type == BLOWFISH_CBC_MECH_INFO_TYPE) ? 1 : 0)
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate /* operations are in-place if the output buffer is NULL */
1100Sstevel@tonic-gate #define BLOWFISH_ARG_INPLACE(input, output) \
1110Sstevel@tonic-gate if ((output) == NULL) \
1120Sstevel@tonic-gate (output) = (input);
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate static void blowfish_provider_status(crypto_provider_handle_t, uint_t *);
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate static crypto_control_ops_t blowfish_control_ops = {
1170Sstevel@tonic-gate blowfish_provider_status
1180Sstevel@tonic-gate };
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate static int blowfish_common_init(crypto_ctx_t *, crypto_mechanism_t *,
1210Sstevel@tonic-gate crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
1220Sstevel@tonic-gate static int blowfish_common_init_ctx(blowfish_ctx_t *,
1230Sstevel@tonic-gate crypto_spi_ctx_template_t *, crypto_mechanism_t *, crypto_key_t *, int);
1240Sstevel@tonic-gate static int blowfish_encrypt_final(crypto_ctx_t *, crypto_data_t *,
1250Sstevel@tonic-gate crypto_req_handle_t);
1260Sstevel@tonic-gate static int blowfish_decrypt_final(crypto_ctx_t *, crypto_data_t *,
1270Sstevel@tonic-gate crypto_req_handle_t);
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate static int blowfish_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
1300Sstevel@tonic-gate crypto_req_handle_t);
1310Sstevel@tonic-gate static int blowfish_encrypt_update(crypto_ctx_t *, crypto_data_t *,
1320Sstevel@tonic-gate crypto_data_t *, crypto_req_handle_t);
1330Sstevel@tonic-gate static int blowfish_encrypt_atomic(crypto_provider_handle_t,
1340Sstevel@tonic-gate crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
1350Sstevel@tonic-gate crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate static int blowfish_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
1380Sstevel@tonic-gate crypto_req_handle_t);
1390Sstevel@tonic-gate static int blowfish_decrypt_update(crypto_ctx_t *, crypto_data_t *,
1400Sstevel@tonic-gate crypto_data_t *, crypto_req_handle_t);
1410Sstevel@tonic-gate static int blowfish_decrypt_atomic(crypto_provider_handle_t,
1420Sstevel@tonic-gate crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
1430Sstevel@tonic-gate crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate static crypto_cipher_ops_t blowfish_cipher_ops = {
1460Sstevel@tonic-gate blowfish_common_init,
1470Sstevel@tonic-gate blowfish_encrypt,
1480Sstevel@tonic-gate blowfish_encrypt_update,
1490Sstevel@tonic-gate blowfish_encrypt_final,
1500Sstevel@tonic-gate blowfish_encrypt_atomic,
1510Sstevel@tonic-gate blowfish_common_init,
1520Sstevel@tonic-gate blowfish_decrypt,
1530Sstevel@tonic-gate blowfish_decrypt_update,
1540Sstevel@tonic-gate blowfish_decrypt_final,
1550Sstevel@tonic-gate blowfish_decrypt_atomic
1560Sstevel@tonic-gate };
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate static int blowfish_create_ctx_template(crypto_provider_handle_t,
1590Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *,
1600Sstevel@tonic-gate size_t *, crypto_req_handle_t);
1610Sstevel@tonic-gate static int blowfish_free_context(crypto_ctx_t *);
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate static crypto_ctx_ops_t blowfish_ctx_ops = {
1640Sstevel@tonic-gate blowfish_create_ctx_template,
1650Sstevel@tonic-gate blowfish_free_context
1660Sstevel@tonic-gate };
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate static crypto_ops_t blowfish_crypto_ops = {
1690Sstevel@tonic-gate &blowfish_control_ops,
1700Sstevel@tonic-gate NULL,
1710Sstevel@tonic-gate &blowfish_cipher_ops,
1720Sstevel@tonic-gate NULL,
1730Sstevel@tonic-gate NULL,
1740Sstevel@tonic-gate NULL,
1750Sstevel@tonic-gate NULL,
1760Sstevel@tonic-gate NULL,
1770Sstevel@tonic-gate NULL,
1780Sstevel@tonic-gate NULL,
1790Sstevel@tonic-gate NULL,
1800Sstevel@tonic-gate NULL,
1810Sstevel@tonic-gate NULL,
1820Sstevel@tonic-gate &blowfish_ctx_ops
1830Sstevel@tonic-gate };
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate static crypto_provider_info_t blowfish_prov_info = {
1860Sstevel@tonic-gate CRYPTO_SPI_VERSION_1,
1870Sstevel@tonic-gate "Blowfish Software Provider",
1880Sstevel@tonic-gate CRYPTO_SW_PROVIDER,
1890Sstevel@tonic-gate {&modlinkage},
1900Sstevel@tonic-gate NULL,
1910Sstevel@tonic-gate &blowfish_crypto_ops,
1920Sstevel@tonic-gate sizeof (blowfish_mech_info_tab)/sizeof (crypto_mech_info_t),
1930Sstevel@tonic-gate blowfish_mech_info_tab
1940Sstevel@tonic-gate };
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate static crypto_kcf_provider_handle_t blowfish_prov_handle = NULL;
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate int
_init(void)2000Sstevel@tonic-gate _init(void)
2010Sstevel@tonic-gate {
2020Sstevel@tonic-gate int ret;
2030Sstevel@tonic-gate
204*11751SAnthony.Scarpino@Sun.COM if ((ret = mod_install(&modlinkage)) != 0)
205*11751SAnthony.Scarpino@Sun.COM return (ret);
206*11751SAnthony.Scarpino@Sun.COM
207*11751SAnthony.Scarpino@Sun.COM /* Register with KCF. If the registration fails, remove the module. */
208*11751SAnthony.Scarpino@Sun.COM if (crypto_register_provider(&blowfish_prov_info,
209*11751SAnthony.Scarpino@Sun.COM &blowfish_prov_handle)) {
210*11751SAnthony.Scarpino@Sun.COM (void) mod_remove(&modlinkage);
2110Sstevel@tonic-gate return (EACCES);
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate
214*11751SAnthony.Scarpino@Sun.COM return (0);
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate int
_fini(void)2180Sstevel@tonic-gate _fini(void)
2190Sstevel@tonic-gate {
220*11751SAnthony.Scarpino@Sun.COM /* Unregister from KCF if module is registered */
2210Sstevel@tonic-gate if (blowfish_prov_handle != NULL) {
222*11751SAnthony.Scarpino@Sun.COM if (crypto_unregister_provider(blowfish_prov_handle))
2230Sstevel@tonic-gate return (EBUSY);
224*11751SAnthony.Scarpino@Sun.COM
2250Sstevel@tonic-gate blowfish_prov_handle = NULL;
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate return (mod_remove(&modlinkage));
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2320Sstevel@tonic-gate _info(struct modinfo *modinfop)
2330Sstevel@tonic-gate {
2340Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate /*
2380Sstevel@tonic-gate * Initialize key schedules for blowfish
2390Sstevel@tonic-gate */
2400Sstevel@tonic-gate static int
init_keysched(crypto_key_t * key,void * keysched)2410Sstevel@tonic-gate init_keysched(crypto_key_t *key, void *keysched)
2420Sstevel@tonic-gate {
2430Sstevel@tonic-gate /* EXPORT DELETE START */
2440Sstevel@tonic-gate /*
2450Sstevel@tonic-gate * Only keys by value are supported by this module.
2460Sstevel@tonic-gate */
2470Sstevel@tonic-gate switch (key->ck_format) {
2480Sstevel@tonic-gate case CRYPTO_KEY_RAW:
2490Sstevel@tonic-gate if (key->ck_length < BLOWFISH_MINBITS ||
2500Sstevel@tonic-gate key->ck_length > BLOWFISH_MAXBITS) {
2510Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE);
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate break;
2540Sstevel@tonic-gate default:
2550Sstevel@tonic-gate return (CRYPTO_KEY_TYPE_INCONSISTENT);
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate blowfish_init_keysched(key->ck_data, key->ck_length, keysched);
2590Sstevel@tonic-gate /* EXPORT DELETE END */
2600Sstevel@tonic-gate return (CRYPTO_SUCCESS);
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate /*
2640Sstevel@tonic-gate * KCF software provider control entry points.
2650Sstevel@tonic-gate */
2660Sstevel@tonic-gate /* ARGSUSED */
2670Sstevel@tonic-gate static void
blowfish_provider_status(crypto_provider_handle_t provider,uint_t * status)2680Sstevel@tonic-gate blowfish_provider_status(crypto_provider_handle_t provider, uint_t *status)
2690Sstevel@tonic-gate {
2700Sstevel@tonic-gate *status = CRYPTO_PROVIDER_READY;
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate /*
2740Sstevel@tonic-gate * KCF software provider encrypt entry points.
2750Sstevel@tonic-gate */
2760Sstevel@tonic-gate static int
blowfish_common_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t template,crypto_req_handle_t req)2770Sstevel@tonic-gate blowfish_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2780Sstevel@tonic-gate crypto_key_t *key, crypto_spi_ctx_template_t template,
2790Sstevel@tonic-gate crypto_req_handle_t req)
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate /* EXPORT DELETE START */
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate blowfish_ctx_t *blowfish_ctx;
2850Sstevel@tonic-gate int rv;
2860Sstevel@tonic-gate int kmflag;
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate /*
2890Sstevel@tonic-gate * Only keys by value are supported by this module.
2900Sstevel@tonic-gate */
2910Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) {
2920Sstevel@tonic-gate return (CRYPTO_KEY_TYPE_INCONSISTENT);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate if (!BLOWFISH_VALID_MECH(mechanism))
2960Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID);
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate if (mechanism->cm_param != NULL &&
2990Sstevel@tonic-gate mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
3000Sstevel@tonic-gate return (CRYPTO_MECHANISM_PARAM_INVALID);
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate kmflag = crypto_kmflag(req);
3037188Smcpowers switch (mechanism->cm_type) {
3047188Smcpowers case BLOWFISH_ECB_MECH_INFO_TYPE:
3057188Smcpowers blowfish_ctx = ecb_alloc_ctx(kmflag);
3067188Smcpowers break;
3077188Smcpowers case BLOWFISH_CBC_MECH_INFO_TYPE:
3087188Smcpowers blowfish_ctx = cbc_alloc_ctx(kmflag);
3097188Smcpowers break;
3107188Smcpowers }
3110Sstevel@tonic-gate if (blowfish_ctx == NULL)
3120Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY);
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate rv = blowfish_common_init_ctx(blowfish_ctx, template, mechanism,
3150Sstevel@tonic-gate key, kmflag);
3160Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) {
3177188Smcpowers crypto_free_mode_ctx(blowfish_ctx);
3180Sstevel@tonic-gate return (rv);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate ctx->cc_provider_private = blowfish_ctx;
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate /* EXPORT DELETE END */
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate return (CRYPTO_SUCCESS);
3260Sstevel@tonic-gate }
3270Sstevel@tonic-gate
3287188Smcpowers static void
blowfish_copy_block64(uint8_t * in,uint64_t * out)3297188Smcpowers blowfish_copy_block64(uint8_t *in, uint64_t *out)
3300Sstevel@tonic-gate {
3317188Smcpowers if (IS_P2ALIGNED(in, sizeof (uint64_t))) {
3327188Smcpowers /* LINTED: pointer alignment */
3337188Smcpowers out[0] = *(uint64_t *)&in[0];
3347188Smcpowers } else {
3357188Smcpowers uint8_t *iv8 = (uint8_t *)&out[0];
3360Sstevel@tonic-gate
3377188Smcpowers BLOWFISH_COPY_BLOCK(in, iv8);
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate /* ARGSUSED */
3420Sstevel@tonic-gate static int
blowfish_encrypt(crypto_ctx_t * ctx,crypto_data_t * plaintext,crypto_data_t * ciphertext,crypto_req_handle_t req)3430Sstevel@tonic-gate blowfish_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
3440Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_req_handle_t req)
3450Sstevel@tonic-gate {
3460Sstevel@tonic-gate int ret;
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate /* EXPORT DELETE START */
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate blowfish_ctx_t *blowfish_ctx;
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate /*
3530Sstevel@tonic-gate * Plaintext must be a multiple of blowfish block size.
3540Sstevel@tonic-gate * This test only works for non-padded mechanisms
3550Sstevel@tonic-gate * when blocksize is 2^N.
3560Sstevel@tonic-gate */
3570Sstevel@tonic-gate if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
3580Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE);
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL);
3610Sstevel@tonic-gate blowfish_ctx = ctx->cc_provider_private;
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate /*
3660Sstevel@tonic-gate * We need to just return the length needed to store the output.
3670Sstevel@tonic-gate * We should not destroy the context for the following case.
3680Sstevel@tonic-gate */
3690Sstevel@tonic-gate if (ciphertext->cd_length < plaintext->cd_length) {
3700Sstevel@tonic-gate ciphertext->cd_length = plaintext->cd_length;
3710Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL);
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate /*
3750Sstevel@tonic-gate * Do an update on the specified input data.
3760Sstevel@tonic-gate */
3770Sstevel@tonic-gate ret = blowfish_encrypt_update(ctx, plaintext, ciphertext, req);
3780Sstevel@tonic-gate ASSERT(blowfish_ctx->bc_remainder_len == 0);
3790Sstevel@tonic-gate (void) blowfish_free_context(ctx);
3800Sstevel@tonic-gate
3810Sstevel@tonic-gate /* EXPORT DELETE END */
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate /* LINTED */
3840Sstevel@tonic-gate return (ret);
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate /* ARGSUSED */
3880Sstevel@tonic-gate static int
blowfish_decrypt(crypto_ctx_t * ctx,crypto_data_t * ciphertext,crypto_data_t * plaintext,crypto_req_handle_t req)3890Sstevel@tonic-gate blowfish_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
3900Sstevel@tonic-gate crypto_data_t *plaintext, crypto_req_handle_t req)
3910Sstevel@tonic-gate {
3920Sstevel@tonic-gate int ret;
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate /* EXPORT DELETE START */
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate blowfish_ctx_t *blowfish_ctx;
3970Sstevel@tonic-gate
3980Sstevel@tonic-gate /*
3990Sstevel@tonic-gate * Ciphertext must be a multiple of blowfish block size.
4000Sstevel@tonic-gate * This test only works for non-padded mechanisms
4010Sstevel@tonic-gate * when blocksize is 2^N.
4020Sstevel@tonic-gate */
4030Sstevel@tonic-gate if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
4040Sstevel@tonic-gate return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL);
4070Sstevel@tonic-gate blowfish_ctx = ctx->cc_provider_private;
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate /*
4120Sstevel@tonic-gate * We need to just return the length needed to store the output.
4130Sstevel@tonic-gate * We should not destroy the context for the following case.
4140Sstevel@tonic-gate */
4150Sstevel@tonic-gate if (plaintext->cd_length < ciphertext->cd_length) {
4160Sstevel@tonic-gate plaintext->cd_length = ciphertext->cd_length;
4170Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL);
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate /*
4210Sstevel@tonic-gate * Do an update on the specified input data.
4220Sstevel@tonic-gate */
4230Sstevel@tonic-gate ret = blowfish_decrypt_update(ctx, ciphertext, plaintext, req);
4240Sstevel@tonic-gate ASSERT(blowfish_ctx->bc_remainder_len == 0);
4250Sstevel@tonic-gate (void) blowfish_free_context(ctx);
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate /* EXPORT DELETE END */
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate /* LINTED */
4300Sstevel@tonic-gate return (ret);
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate /* ARGSUSED */
4340Sstevel@tonic-gate static int
blowfish_encrypt_update(crypto_ctx_t * ctx,crypto_data_t * plaintext,crypto_data_t * ciphertext,crypto_req_handle_t req)4350Sstevel@tonic-gate blowfish_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
4360Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_req_handle_t req)
4370Sstevel@tonic-gate {
4380Sstevel@tonic-gate off_t saved_offset;
4390Sstevel@tonic-gate size_t saved_length, out_len;
4400Sstevel@tonic-gate int ret = CRYPTO_SUCCESS;
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL);
4430Sstevel@tonic-gate
4440Sstevel@tonic-gate BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate /* compute number of bytes that will hold the ciphertext */
4470Sstevel@tonic-gate out_len =
4480Sstevel@tonic-gate ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len;
4490Sstevel@tonic-gate out_len += plaintext->cd_length;
4500Sstevel@tonic-gate out_len &= ~(BLOWFISH_BLOCK_LEN - 1);
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate /* return length needed to store the output */
4530Sstevel@tonic-gate if (ciphertext->cd_length < out_len) {
4540Sstevel@tonic-gate ciphertext->cd_length = out_len;
4550Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL);
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate saved_offset = ciphertext->cd_offset;
4590Sstevel@tonic-gate saved_length = ciphertext->cd_length;
4600Sstevel@tonic-gate
4610Sstevel@tonic-gate /*
4620Sstevel@tonic-gate * Do the blowfish update on the specified input data.
4630Sstevel@tonic-gate */
4640Sstevel@tonic-gate switch (plaintext->cd_format) {
4650Sstevel@tonic-gate case CRYPTO_DATA_RAW:
4667188Smcpowers ret = crypto_update_iov(ctx->cc_provider_private,
4677188Smcpowers plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
4687188Smcpowers blowfish_copy_block64);
4690Sstevel@tonic-gate break;
4700Sstevel@tonic-gate case CRYPTO_DATA_UIO:
4717188Smcpowers ret = crypto_update_uio(ctx->cc_provider_private,
4727188Smcpowers plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
4737188Smcpowers blowfish_copy_block64);
4740Sstevel@tonic-gate break;
4750Sstevel@tonic-gate case CRYPTO_DATA_MBLK:
4767188Smcpowers ret = crypto_update_mp(ctx->cc_provider_private,
4777188Smcpowers plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
4787188Smcpowers blowfish_copy_block64);
4790Sstevel@tonic-gate break;
4800Sstevel@tonic-gate default:
4810Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD;
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) {
4850Sstevel@tonic-gate if (plaintext != ciphertext)
4860Sstevel@tonic-gate ciphertext->cd_length =
4870Sstevel@tonic-gate ciphertext->cd_offset - saved_offset;
4880Sstevel@tonic-gate } else {
4890Sstevel@tonic-gate ciphertext->cd_length = saved_length;
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate ciphertext->cd_offset = saved_offset;
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate return (ret);
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate /* ARGSUSED */
4970Sstevel@tonic-gate static int
blowfish_decrypt_update(crypto_ctx_t * ctx,crypto_data_t * ciphertext,crypto_data_t * plaintext,crypto_req_handle_t req)4980Sstevel@tonic-gate blowfish_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
4990Sstevel@tonic-gate crypto_data_t *plaintext, crypto_req_handle_t req)
5000Sstevel@tonic-gate {
5010Sstevel@tonic-gate off_t saved_offset;
5020Sstevel@tonic-gate size_t saved_length, out_len;
5030Sstevel@tonic-gate int ret = CRYPTO_SUCCESS;
5040Sstevel@tonic-gate
5050Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL);
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate /* compute number of bytes that will hold the plaintext */
5100Sstevel@tonic-gate out_len =
5110Sstevel@tonic-gate ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len;
5120Sstevel@tonic-gate out_len += ciphertext->cd_length;
5130Sstevel@tonic-gate out_len &= ~(BLOWFISH_BLOCK_LEN - 1);
5140Sstevel@tonic-gate
5150Sstevel@tonic-gate /* return length needed to store the output */
5160Sstevel@tonic-gate if (plaintext->cd_length < out_len) {
5170Sstevel@tonic-gate plaintext->cd_length = out_len;
5180Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL);
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate saved_offset = plaintext->cd_offset;
5220Sstevel@tonic-gate saved_length = plaintext->cd_length;
5230Sstevel@tonic-gate
5240Sstevel@tonic-gate /*
5250Sstevel@tonic-gate * Do the blowfish update on the specified input data.
5260Sstevel@tonic-gate */
5270Sstevel@tonic-gate switch (ciphertext->cd_format) {
5280Sstevel@tonic-gate case CRYPTO_DATA_RAW:
5297188Smcpowers ret = crypto_update_iov(ctx->cc_provider_private,
5307188Smcpowers ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
5317188Smcpowers blowfish_copy_block64);
5320Sstevel@tonic-gate break;
5330Sstevel@tonic-gate case CRYPTO_DATA_UIO:
5347188Smcpowers ret = crypto_update_uio(ctx->cc_provider_private,
5357188Smcpowers ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
5367188Smcpowers blowfish_copy_block64);
5370Sstevel@tonic-gate break;
5380Sstevel@tonic-gate case CRYPTO_DATA_MBLK:
5397188Smcpowers ret = crypto_update_mp(ctx->cc_provider_private,
5407188Smcpowers ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
5417188Smcpowers blowfish_copy_block64);
5420Sstevel@tonic-gate break;
5430Sstevel@tonic-gate default:
5440Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD;
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) {
5480Sstevel@tonic-gate if (ciphertext != plaintext)
5490Sstevel@tonic-gate plaintext->cd_length =
5500Sstevel@tonic-gate plaintext->cd_offset - saved_offset;
5510Sstevel@tonic-gate } else {
5520Sstevel@tonic-gate plaintext->cd_length = saved_length;
5530Sstevel@tonic-gate }
5540Sstevel@tonic-gate plaintext->cd_offset = saved_offset;
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate return (ret);
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate /* ARGSUSED */
5600Sstevel@tonic-gate static int
blowfish_encrypt_final(crypto_ctx_t * ctx,crypto_data_t * data,crypto_req_handle_t req)5610Sstevel@tonic-gate blowfish_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
5620Sstevel@tonic-gate crypto_req_handle_t req)
5630Sstevel@tonic-gate {
5640Sstevel@tonic-gate
5650Sstevel@tonic-gate /* EXPORT DELETE START */
5660Sstevel@tonic-gate
5670Sstevel@tonic-gate blowfish_ctx_t *blowfish_ctx;
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL);
5700Sstevel@tonic-gate blowfish_ctx = ctx->cc_provider_private;
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate /*
5730Sstevel@tonic-gate * There must be no unprocessed data.
5740Sstevel@tonic-gate * This happens if the length of the last data is
5750Sstevel@tonic-gate * not a multiple of the BLOWFISH block length.
5760Sstevel@tonic-gate */
5770Sstevel@tonic-gate if (blowfish_ctx->bc_remainder_len > 0)
5780Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE);
5790Sstevel@tonic-gate
5800Sstevel@tonic-gate (void) blowfish_free_context(ctx);
5810Sstevel@tonic-gate data->cd_length = 0;
5820Sstevel@tonic-gate
5830Sstevel@tonic-gate /* EXPORT DELETE END */
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate return (CRYPTO_SUCCESS);
5860Sstevel@tonic-gate }
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate /* ARGSUSED */
5890Sstevel@tonic-gate static int
blowfish_decrypt_final(crypto_ctx_t * ctx,crypto_data_t * data,crypto_req_handle_t req)5900Sstevel@tonic-gate blowfish_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
5910Sstevel@tonic-gate crypto_req_handle_t req)
5920Sstevel@tonic-gate {
5930Sstevel@tonic-gate
5940Sstevel@tonic-gate /* EXPORT DELETE START */
5950Sstevel@tonic-gate
5960Sstevel@tonic-gate blowfish_ctx_t *blowfish_ctx;
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL);
5990Sstevel@tonic-gate blowfish_ctx = ctx->cc_provider_private;
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate /*
6020Sstevel@tonic-gate * There must be no unprocessed ciphertext.
6030Sstevel@tonic-gate * This happens if the length of the last ciphertext is
6040Sstevel@tonic-gate * not a multiple of the BLOWFISH block length.
6050Sstevel@tonic-gate */
6060Sstevel@tonic-gate if (blowfish_ctx->bc_remainder_len > 0)
6070Sstevel@tonic-gate return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
6080Sstevel@tonic-gate
6090Sstevel@tonic-gate (void) blowfish_free_context(ctx);
6100Sstevel@tonic-gate data->cd_length = 0;
6110Sstevel@tonic-gate
6120Sstevel@tonic-gate /* EXPORT DELETE END */
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate return (CRYPTO_SUCCESS);
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate /* ARGSUSED */
6180Sstevel@tonic-gate static int
blowfish_encrypt_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * plaintext,crypto_data_t * ciphertext,crypto_spi_ctx_template_t template,crypto_req_handle_t req)6190Sstevel@tonic-gate blowfish_encrypt_atomic(crypto_provider_handle_t provider,
6200Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
6210Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
6220Sstevel@tonic-gate crypto_spi_ctx_template_t template, crypto_req_handle_t req)
6230Sstevel@tonic-gate {
6240Sstevel@tonic-gate blowfish_ctx_t blowfish_ctx; /* on the stack */
6250Sstevel@tonic-gate off_t saved_offset;
6260Sstevel@tonic-gate size_t saved_length;
6270Sstevel@tonic-gate int ret;
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate /*
6320Sstevel@tonic-gate * Plaintext must be a multiple of blowfish block size.
6330Sstevel@tonic-gate * This test only works for non-padded mechanisms
6340Sstevel@tonic-gate * when blocksize is 2^N.
6350Sstevel@tonic-gate */
6360Sstevel@tonic-gate if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
6370Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE);
6380Sstevel@tonic-gate
6390Sstevel@tonic-gate /* return length needed to store the output */
6400Sstevel@tonic-gate if (ciphertext->cd_length < plaintext->cd_length) {
6410Sstevel@tonic-gate ciphertext->cd_length = plaintext->cd_length;
6420Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL);
6430Sstevel@tonic-gate }
6440Sstevel@tonic-gate
6450Sstevel@tonic-gate if (!BLOWFISH_VALID_MECH(mechanism))
6460Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID);
6470Sstevel@tonic-gate
6480Sstevel@tonic-gate if (mechanism->cm_param_len != 0 &&
6490Sstevel@tonic-gate mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
6500Sstevel@tonic-gate return (CRYPTO_MECHANISM_PARAM_INVALID);
6510Sstevel@tonic-gate
6520Sstevel@tonic-gate bzero(&blowfish_ctx, sizeof (blowfish_ctx_t));
6530Sstevel@tonic-gate
6540Sstevel@tonic-gate ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism,
6550Sstevel@tonic-gate key, crypto_kmflag(req));
6560Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS)
6570Sstevel@tonic-gate return (ret);
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate saved_offset = ciphertext->cd_offset;
6600Sstevel@tonic-gate saved_length = ciphertext->cd_length;
6610Sstevel@tonic-gate
6620Sstevel@tonic-gate /*
6630Sstevel@tonic-gate * Do an update on the specified input data.
6640Sstevel@tonic-gate */
6650Sstevel@tonic-gate switch (plaintext->cd_format) {
6660Sstevel@tonic-gate case CRYPTO_DATA_RAW:
6677188Smcpowers ret = crypto_update_iov(&blowfish_ctx,
6687188Smcpowers plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
6697188Smcpowers blowfish_copy_block64);
6700Sstevel@tonic-gate break;
6710Sstevel@tonic-gate case CRYPTO_DATA_UIO:
6727188Smcpowers ret = crypto_update_uio(&blowfish_ctx,
6737188Smcpowers plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
6747188Smcpowers blowfish_copy_block64);
6750Sstevel@tonic-gate break;
6760Sstevel@tonic-gate case CRYPTO_DATA_MBLK:
6777188Smcpowers ret = crypto_update_mp((void *)&blowfish_ctx,
6787188Smcpowers plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
6797188Smcpowers blowfish_copy_block64);
6800Sstevel@tonic-gate break;
6810Sstevel@tonic-gate default:
6820Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD;
6830Sstevel@tonic-gate }
6840Sstevel@tonic-gate
6857188Smcpowers if (blowfish_ctx.bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
6860Sstevel@tonic-gate bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len);
6870Sstevel@tonic-gate kmem_free(blowfish_ctx.bc_keysched,
6880Sstevel@tonic-gate blowfish_ctx.bc_keysched_len);
6890Sstevel@tonic-gate }
6900Sstevel@tonic-gate
6910Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) {
6920Sstevel@tonic-gate ASSERT(blowfish_ctx.bc_remainder_len == 0);
6930Sstevel@tonic-gate if (plaintext != ciphertext)
6940Sstevel@tonic-gate ciphertext->cd_length =
6950Sstevel@tonic-gate ciphertext->cd_offset - saved_offset;
6960Sstevel@tonic-gate } else {
6970Sstevel@tonic-gate ciphertext->cd_length = saved_length;
6980Sstevel@tonic-gate }
6990Sstevel@tonic-gate ciphertext->cd_offset = saved_offset;
7000Sstevel@tonic-gate
7010Sstevel@tonic-gate return (ret);
7020Sstevel@tonic-gate }
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate /* ARGSUSED */
7050Sstevel@tonic-gate static int
blowfish_decrypt_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * ciphertext,crypto_data_t * plaintext,crypto_spi_ctx_template_t template,crypto_req_handle_t req)7060Sstevel@tonic-gate blowfish_decrypt_atomic(crypto_provider_handle_t provider,
7070Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
7080Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
7090Sstevel@tonic-gate crypto_spi_ctx_template_t template, crypto_req_handle_t req)
7100Sstevel@tonic-gate {
7110Sstevel@tonic-gate blowfish_ctx_t blowfish_ctx; /* on the stack */
7120Sstevel@tonic-gate off_t saved_offset;
7130Sstevel@tonic-gate size_t saved_length;
7140Sstevel@tonic-gate int ret;
7150Sstevel@tonic-gate
7160Sstevel@tonic-gate BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
7170Sstevel@tonic-gate
7180Sstevel@tonic-gate /*
7190Sstevel@tonic-gate * Ciphertext must be a multiple of blowfish block size.
7200Sstevel@tonic-gate * This test only works for non-padded mechanisms
7210Sstevel@tonic-gate * when blocksize is 2^N.
7220Sstevel@tonic-gate */
7230Sstevel@tonic-gate if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
7240Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE);
7250Sstevel@tonic-gate
7260Sstevel@tonic-gate /* return length needed to store the output */
7270Sstevel@tonic-gate if (plaintext->cd_length < ciphertext->cd_length) {
7280Sstevel@tonic-gate plaintext->cd_length = ciphertext->cd_length;
7290Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL);
7300Sstevel@tonic-gate }
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate if (!BLOWFISH_VALID_MECH(mechanism))
7330Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID);
7340Sstevel@tonic-gate
7350Sstevel@tonic-gate if (mechanism->cm_param_len != 0 &&
7360Sstevel@tonic-gate mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
7370Sstevel@tonic-gate return (CRYPTO_MECHANISM_PARAM_INVALID);
7380Sstevel@tonic-gate
7390Sstevel@tonic-gate bzero(&blowfish_ctx, sizeof (blowfish_ctx_t));
7400Sstevel@tonic-gate
7410Sstevel@tonic-gate ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism,
7420Sstevel@tonic-gate key, crypto_kmflag(req));
7430Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS)
7440Sstevel@tonic-gate return (ret);
7450Sstevel@tonic-gate
7460Sstevel@tonic-gate saved_offset = plaintext->cd_offset;
7470Sstevel@tonic-gate saved_length = plaintext->cd_length;
7480Sstevel@tonic-gate
7490Sstevel@tonic-gate /*
7500Sstevel@tonic-gate * Do an update on the specified input data.
7510Sstevel@tonic-gate */
7520Sstevel@tonic-gate switch (ciphertext->cd_format) {
7530Sstevel@tonic-gate case CRYPTO_DATA_RAW:
7547188Smcpowers ret = crypto_update_iov(&blowfish_ctx,
7557188Smcpowers ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
7567188Smcpowers blowfish_copy_block64);
7570Sstevel@tonic-gate break;
7580Sstevel@tonic-gate case CRYPTO_DATA_UIO:
7597188Smcpowers ret = crypto_update_uio(&blowfish_ctx,
7607188Smcpowers ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
7617188Smcpowers blowfish_copy_block64);
7620Sstevel@tonic-gate break;
7630Sstevel@tonic-gate case CRYPTO_DATA_MBLK:
7647188Smcpowers ret = crypto_update_mp(&blowfish_ctx,
7657188Smcpowers ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
7667188Smcpowers blowfish_copy_block64);
7670Sstevel@tonic-gate break;
7680Sstevel@tonic-gate default:
7690Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD;
7700Sstevel@tonic-gate }
7710Sstevel@tonic-gate
7727188Smcpowers if (blowfish_ctx.bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
7730Sstevel@tonic-gate bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len);
7740Sstevel@tonic-gate kmem_free(blowfish_ctx.bc_keysched,
7750Sstevel@tonic-gate blowfish_ctx.bc_keysched_len);
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate
7780Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) {
7790Sstevel@tonic-gate ASSERT(blowfish_ctx.bc_remainder_len == 0);
7800Sstevel@tonic-gate if (ciphertext != plaintext)
7810Sstevel@tonic-gate plaintext->cd_length =
7820Sstevel@tonic-gate plaintext->cd_offset - saved_offset;
7830Sstevel@tonic-gate } else {
7840Sstevel@tonic-gate plaintext->cd_length = saved_length;
7850Sstevel@tonic-gate }
7860Sstevel@tonic-gate plaintext->cd_offset = saved_offset;
7870Sstevel@tonic-gate
7880Sstevel@tonic-gate return (ret);
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate /*
7920Sstevel@tonic-gate * KCF software provider context template entry points.
7930Sstevel@tonic-gate */
7940Sstevel@tonic-gate /* ARGSUSED */
7950Sstevel@tonic-gate static int
blowfish_create_ctx_template(crypto_provider_handle_t provider,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t * tmpl,size_t * tmpl_size,crypto_req_handle_t req)7960Sstevel@tonic-gate blowfish_create_ctx_template(crypto_provider_handle_t provider,
7970Sstevel@tonic-gate crypto_mechanism_t *mechanism, crypto_key_t *key,
7980Sstevel@tonic-gate crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req)
7990Sstevel@tonic-gate {
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate /* EXPORT DELETE START */
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate void *keysched;
8040Sstevel@tonic-gate size_t size;
8050Sstevel@tonic-gate int rv;
8060Sstevel@tonic-gate
8070Sstevel@tonic-gate if (!BLOWFISH_VALID_MECH(mechanism))
8080Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID);
8090Sstevel@tonic-gate
8100Sstevel@tonic-gate if ((keysched = blowfish_alloc_keysched(&size,
8110Sstevel@tonic-gate crypto_kmflag(req))) == NULL) {
8120Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY);
8130Sstevel@tonic-gate }
8140Sstevel@tonic-gate
8150Sstevel@tonic-gate /*
8160Sstevel@tonic-gate * Initialize key schedule. Key length information is stored
8170Sstevel@tonic-gate * in the key.
8180Sstevel@tonic-gate */
8190Sstevel@tonic-gate if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
8200Sstevel@tonic-gate bzero(keysched, size);
8210Sstevel@tonic-gate kmem_free(keysched, size);
8220Sstevel@tonic-gate return (rv);
8230Sstevel@tonic-gate }
8240Sstevel@tonic-gate
8250Sstevel@tonic-gate *tmpl = keysched;
8260Sstevel@tonic-gate *tmpl_size = size;
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate /* EXPORT DELETE END */
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate return (CRYPTO_SUCCESS);
8310Sstevel@tonic-gate }
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate /* ARGSUSED */
8340Sstevel@tonic-gate static int
blowfish_free_context(crypto_ctx_t * ctx)8350Sstevel@tonic-gate blowfish_free_context(crypto_ctx_t *ctx)
8360Sstevel@tonic-gate {
8370Sstevel@tonic-gate blowfish_ctx_t *blowfish_ctx = ctx->cc_provider_private;
8380Sstevel@tonic-gate
8390Sstevel@tonic-gate if (blowfish_ctx != NULL) {
8407188Smcpowers if (blowfish_ctx->bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
8410Sstevel@tonic-gate ASSERT(blowfish_ctx->bc_keysched_len != 0);
8420Sstevel@tonic-gate bzero(blowfish_ctx->bc_keysched,
8430Sstevel@tonic-gate blowfish_ctx->bc_keysched_len);
8440Sstevel@tonic-gate kmem_free(blowfish_ctx->bc_keysched,
8450Sstevel@tonic-gate blowfish_ctx->bc_keysched_len);
8460Sstevel@tonic-gate }
8477188Smcpowers crypto_free_mode_ctx(blowfish_ctx);
8480Sstevel@tonic-gate ctx->cc_provider_private = NULL;
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate
8510Sstevel@tonic-gate return (CRYPTO_SUCCESS);
8520Sstevel@tonic-gate }
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate /* ARGSUSED */
8550Sstevel@tonic-gate static int
blowfish_common_init_ctx(blowfish_ctx_t * blowfish_ctx,crypto_spi_ctx_template_t * template,crypto_mechanism_t * mechanism,crypto_key_t * key,int kmflag)8560Sstevel@tonic-gate blowfish_common_init_ctx(blowfish_ctx_t *blowfish_ctx,
8570Sstevel@tonic-gate crypto_spi_ctx_template_t *template, crypto_mechanism_t *mechanism,
8580Sstevel@tonic-gate crypto_key_t *key, int kmflag)
8590Sstevel@tonic-gate {
8600Sstevel@tonic-gate int rv = CRYPTO_SUCCESS;
8610Sstevel@tonic-gate
8620Sstevel@tonic-gate /* EXPORT DELETE START */
8630Sstevel@tonic-gate
8640Sstevel@tonic-gate void *keysched;
8650Sstevel@tonic-gate size_t size;
8660Sstevel@tonic-gate
8670Sstevel@tonic-gate if (template == NULL) {
8680Sstevel@tonic-gate if ((keysched = blowfish_alloc_keysched(&size, kmflag)) == NULL)
8690Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY);
8700Sstevel@tonic-gate /*
8710Sstevel@tonic-gate * Initialize key schedule.
8720Sstevel@tonic-gate * Key length is stored in the key.
8730Sstevel@tonic-gate */
8740Sstevel@tonic-gate if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS)
8750Sstevel@tonic-gate kmem_free(keysched, size);
8760Sstevel@tonic-gate
8777188Smcpowers blowfish_ctx->bc_flags |= PROVIDER_OWNS_KEY_SCHEDULE;
8780Sstevel@tonic-gate blowfish_ctx->bc_keysched_len = size;
8790Sstevel@tonic-gate } else {
8800Sstevel@tonic-gate keysched = template;
8810Sstevel@tonic-gate }
8827188Smcpowers blowfish_ctx->bc_keysched = keysched;
8830Sstevel@tonic-gate
8847188Smcpowers switch (mechanism->cm_type) {
8857188Smcpowers case BLOWFISH_CBC_MECH_INFO_TYPE:
8867188Smcpowers rv = cbc_init_ctx((cbc_ctx_t *)blowfish_ctx,
8877188Smcpowers mechanism->cm_param, mechanism->cm_param_len,
8887188Smcpowers BLOWFISH_BLOCK_LEN, blowfish_copy_block64);
8897188Smcpowers break;
8907188Smcpowers case BLOWFISH_ECB_MECH_INFO_TYPE:
8917188Smcpowers blowfish_ctx->bc_flags |= ECB_MODE;
8927188Smcpowers }
8930Sstevel@tonic-gate
8947188Smcpowers if (rv != CRYPTO_SUCCESS) {
8957188Smcpowers if (blowfish_ctx->bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
8967188Smcpowers bzero(keysched, size);
8977188Smcpowers kmem_free(keysched, size);
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate }
9000Sstevel@tonic-gate
9010Sstevel@tonic-gate /* EXPORT DELETE END */
9020Sstevel@tonic-gate
9030Sstevel@tonic-gate return (rv);
9040Sstevel@tonic-gate }
905