1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * Blowfish provider for the Kernel Cryptographic Framework (KCF) 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <sys/types.h> 34*0Sstevel@tonic-gate #include <sys/systm.h> 35*0Sstevel@tonic-gate #include <sys/modctl.h> 36*0Sstevel@tonic-gate #include <sys/cmn_err.h> 37*0Sstevel@tonic-gate #include <sys/ddi.h> 38*0Sstevel@tonic-gate #include <sys/crypto/common.h> 39*0Sstevel@tonic-gate #include <sys/crypto/spi.h> 40*0Sstevel@tonic-gate #include <sys/sysmacros.h> 41*0Sstevel@tonic-gate #include <sys/strsun.h> 42*0Sstevel@tonic-gate #include <sys/note.h> 43*0Sstevel@tonic-gate #include <blowfish_impl.h> 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate extern struct mod_ops mod_cryptoops; 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate /* 48*0Sstevel@tonic-gate * Module linkage information for the kernel. 49*0Sstevel@tonic-gate */ 50*0Sstevel@tonic-gate static struct modlcrypto modlcrypto = { 51*0Sstevel@tonic-gate &mod_cryptoops, 52*0Sstevel@tonic-gate "Blowfish Kernel SW Provider %I%" 53*0Sstevel@tonic-gate }; 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate static struct modlinkage modlinkage = { 56*0Sstevel@tonic-gate MODREV_1, 57*0Sstevel@tonic-gate (void *)&modlcrypto, 58*0Sstevel@tonic-gate NULL 59*0Sstevel@tonic-gate }; 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate /* 62*0Sstevel@tonic-gate * CSPI information (entry points, provider info, etc.) 63*0Sstevel@tonic-gate */ 64*0Sstevel@tonic-gate typedef enum blowfish_mech_type { 65*0Sstevel@tonic-gate BF_ECB_MECH_INFO_TYPE, /* SUN_CKM_BF_ECB */ 66*0Sstevel@tonic-gate BF_CBC_MECH_INFO_TYPE /* SUN_CKM_BF_CBC */ 67*0Sstevel@tonic-gate } blowfish_mech_type_t; 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* 70*0Sstevel@tonic-gate * bc_keysched: Pointer to key schedule. 71*0Sstevel@tonic-gate * 72*0Sstevel@tonic-gate * bc_keysched_len: Length of the key schedule. 73*0Sstevel@tonic-gate * 74*0Sstevel@tonic-gate * bc_remainder: This is for residual data, i.e. data that can't 75*0Sstevel@tonic-gate * be processed because there are too few bytes. 76*0Sstevel@tonic-gate * Must wait until more data arrives. 77*0Sstevel@tonic-gate * 78*0Sstevel@tonic-gate * bc_remainder_len: Number of bytes in bc_remainder. 79*0Sstevel@tonic-gate * 80*0Sstevel@tonic-gate * bc_iv: Scratch buffer that sometimes contains the IV. 81*0Sstevel@tonic-gate * 82*0Sstevel@tonic-gate * bc_lastblock: Scratch buffer. 83*0Sstevel@tonic-gate * 84*0Sstevel@tonic-gate * bc_lastp: Pointer to previous block of ciphertext. 85*0Sstevel@tonic-gate * 86*0Sstevel@tonic-gate * bc_copy_to: Pointer to where encrypted residual data needs 87*0Sstevel@tonic-gate * to be copied. 88*0Sstevel@tonic-gate * 89*0Sstevel@tonic-gate * bc_flags: BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE 90*0Sstevel@tonic-gate * When a context is freed, it is necessary 91*0Sstevel@tonic-gate * to know whether the key schedule was allocated 92*0Sstevel@tonic-gate * by the caller, or by blowfish_common_init(). 93*0Sstevel@tonic-gate * If allocated by the latter, then it needs to be freed. 94*0Sstevel@tonic-gate * 95*0Sstevel@tonic-gate * BLOWFISH_CBC_MODE 96*0Sstevel@tonic-gate * If flag is not set, the mode is BLOWFISH_ECB_MODE. 97*0Sstevel@tonic-gate * 98*0Sstevel@tonic-gate */ 99*0Sstevel@tonic-gate typedef struct blowfish_ctx { 100*0Sstevel@tonic-gate void *bc_keysched; 101*0Sstevel@tonic-gate size_t bc_keysched_len; 102*0Sstevel@tonic-gate uint64_t bc_iv; 103*0Sstevel@tonic-gate uint64_t bc_lastblock; 104*0Sstevel@tonic-gate uint64_t bc_remainder; 105*0Sstevel@tonic-gate size_t bc_remainder_len; 106*0Sstevel@tonic-gate uint8_t *bc_lastp; 107*0Sstevel@tonic-gate uint8_t *bc_copy_to; 108*0Sstevel@tonic-gate uint32_t bc_flags; 109*0Sstevel@tonic-gate } blowfish_ctx_t; 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate #define BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE 0x00000001 112*0Sstevel@tonic-gate #define BLOWFISH_CBC_MODE 0x00000002 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate #define BLOWFISH_COPY_BLOCK(src, dst) \ 115*0Sstevel@tonic-gate (dst)[0] = (src)[0]; \ 116*0Sstevel@tonic-gate (dst)[1] = (src)[1]; \ 117*0Sstevel@tonic-gate (dst)[2] = (src)[2]; \ 118*0Sstevel@tonic-gate (dst)[3] = (src)[3]; \ 119*0Sstevel@tonic-gate (dst)[4] = (src)[4]; \ 120*0Sstevel@tonic-gate (dst)[5] = (src)[5]; \ 121*0Sstevel@tonic-gate (dst)[6] = (src)[6]; \ 122*0Sstevel@tonic-gate (dst)[7] = (src)[7] 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate #define BLOWFISH_XOR_BLOCK(src, dst) \ 125*0Sstevel@tonic-gate (dst)[0] ^= (src)[0]; \ 126*0Sstevel@tonic-gate (dst)[1] ^= (src)[1]; \ 127*0Sstevel@tonic-gate (dst)[2] ^= (src)[2]; \ 128*0Sstevel@tonic-gate (dst)[3] ^= (src)[3]; \ 129*0Sstevel@tonic-gate (dst)[4] ^= (src)[4]; \ 130*0Sstevel@tonic-gate (dst)[5] ^= (src)[5]; \ 131*0Sstevel@tonic-gate (dst)[6] ^= (src)[6]; \ 132*0Sstevel@tonic-gate (dst)[7] ^= (src)[7] 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate /* 135*0Sstevel@tonic-gate * Mechanism info structure passed to KCF during registration. 136*0Sstevel@tonic-gate */ 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate static crypto_mech_info_t blowfish_mech_info_tab[] = { 139*0Sstevel@tonic-gate /* BLOWFISH_ECB */ 140*0Sstevel@tonic-gate {SUN_CKM_BF_ECB, BF_ECB_MECH_INFO_TYPE, 141*0Sstevel@tonic-gate CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC | 142*0Sstevel@tonic-gate CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC, 143*0Sstevel@tonic-gate BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 144*0Sstevel@tonic-gate /* BLOWFISH_CBC */ 145*0Sstevel@tonic-gate {SUN_CKM_BF_CBC, BF_CBC_MECH_INFO_TYPE, 146*0Sstevel@tonic-gate CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC | 147*0Sstevel@tonic-gate CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC, 148*0Sstevel@tonic-gate BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS} 149*0Sstevel@tonic-gate }; 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate #define BLOWFISH_VALID_MECH(mech) \ 152*0Sstevel@tonic-gate (((mech)->cm_type == BF_ECB_MECH_INFO_TYPE || \ 153*0Sstevel@tonic-gate (mech)->cm_type == BF_CBC_MECH_INFO_TYPE) ? 1 : 0) 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate /* operations are in-place if the output buffer is NULL */ 156*0Sstevel@tonic-gate #define BLOWFISH_ARG_INPLACE(input, output) \ 157*0Sstevel@tonic-gate if ((output) == NULL) \ 158*0Sstevel@tonic-gate (output) = (input); 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate static void blowfish_provider_status(crypto_provider_handle_t, uint_t *); 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate static crypto_control_ops_t blowfish_control_ops = { 163*0Sstevel@tonic-gate blowfish_provider_status 164*0Sstevel@tonic-gate }; 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate static int blowfish_common_init(crypto_ctx_t *, crypto_mechanism_t *, 167*0Sstevel@tonic-gate crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 168*0Sstevel@tonic-gate static int blowfish_common_init_ctx(blowfish_ctx_t *, 169*0Sstevel@tonic-gate crypto_spi_ctx_template_t *, crypto_mechanism_t *, crypto_key_t *, int); 170*0Sstevel@tonic-gate static int blowfish_encrypt_final(crypto_ctx_t *, crypto_data_t *, 171*0Sstevel@tonic-gate crypto_req_handle_t); 172*0Sstevel@tonic-gate static int blowfish_decrypt_final(crypto_ctx_t *, crypto_data_t *, 173*0Sstevel@tonic-gate crypto_req_handle_t); 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate static int blowfish_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 176*0Sstevel@tonic-gate crypto_req_handle_t); 177*0Sstevel@tonic-gate static int blowfish_encrypt_update(crypto_ctx_t *, crypto_data_t *, 178*0Sstevel@tonic-gate crypto_data_t *, crypto_req_handle_t); 179*0Sstevel@tonic-gate static int blowfish_encrypt_atomic(crypto_provider_handle_t, 180*0Sstevel@tonic-gate crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, 181*0Sstevel@tonic-gate crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate static int blowfish_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 184*0Sstevel@tonic-gate crypto_req_handle_t); 185*0Sstevel@tonic-gate static int blowfish_decrypt_update(crypto_ctx_t *, crypto_data_t *, 186*0Sstevel@tonic-gate crypto_data_t *, crypto_req_handle_t); 187*0Sstevel@tonic-gate static int blowfish_decrypt_atomic(crypto_provider_handle_t, 188*0Sstevel@tonic-gate crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, 189*0Sstevel@tonic-gate crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate static crypto_cipher_ops_t blowfish_cipher_ops = { 192*0Sstevel@tonic-gate blowfish_common_init, 193*0Sstevel@tonic-gate blowfish_encrypt, 194*0Sstevel@tonic-gate blowfish_encrypt_update, 195*0Sstevel@tonic-gate blowfish_encrypt_final, 196*0Sstevel@tonic-gate blowfish_encrypt_atomic, 197*0Sstevel@tonic-gate blowfish_common_init, 198*0Sstevel@tonic-gate blowfish_decrypt, 199*0Sstevel@tonic-gate blowfish_decrypt_update, 200*0Sstevel@tonic-gate blowfish_decrypt_final, 201*0Sstevel@tonic-gate blowfish_decrypt_atomic 202*0Sstevel@tonic-gate }; 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate static int blowfish_create_ctx_template(crypto_provider_handle_t, 205*0Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *, 206*0Sstevel@tonic-gate size_t *, crypto_req_handle_t); 207*0Sstevel@tonic-gate static int blowfish_free_context(crypto_ctx_t *); 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate static crypto_ctx_ops_t blowfish_ctx_ops = { 210*0Sstevel@tonic-gate blowfish_create_ctx_template, 211*0Sstevel@tonic-gate blowfish_free_context 212*0Sstevel@tonic-gate }; 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate static crypto_ops_t blowfish_crypto_ops = { 215*0Sstevel@tonic-gate &blowfish_control_ops, 216*0Sstevel@tonic-gate NULL, 217*0Sstevel@tonic-gate &blowfish_cipher_ops, 218*0Sstevel@tonic-gate NULL, 219*0Sstevel@tonic-gate NULL, 220*0Sstevel@tonic-gate NULL, 221*0Sstevel@tonic-gate NULL, 222*0Sstevel@tonic-gate NULL, 223*0Sstevel@tonic-gate NULL, 224*0Sstevel@tonic-gate NULL, 225*0Sstevel@tonic-gate NULL, 226*0Sstevel@tonic-gate NULL, 227*0Sstevel@tonic-gate NULL, 228*0Sstevel@tonic-gate &blowfish_ctx_ops 229*0Sstevel@tonic-gate }; 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate static crypto_provider_info_t blowfish_prov_info = { 232*0Sstevel@tonic-gate CRYPTO_SPI_VERSION_1, 233*0Sstevel@tonic-gate "Blowfish Software Provider", 234*0Sstevel@tonic-gate CRYPTO_SW_PROVIDER, 235*0Sstevel@tonic-gate {&modlinkage}, 236*0Sstevel@tonic-gate NULL, 237*0Sstevel@tonic-gate &blowfish_crypto_ops, 238*0Sstevel@tonic-gate sizeof (blowfish_mech_info_tab)/sizeof (crypto_mech_info_t), 239*0Sstevel@tonic-gate blowfish_mech_info_tab 240*0Sstevel@tonic-gate }; 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate static int blowfish_encrypt_contiguous_blocks(blowfish_ctx_t *, char *, size_t, 243*0Sstevel@tonic-gate crypto_data_t *); 244*0Sstevel@tonic-gate static int blowfish_decrypt_contiguous_blocks(blowfish_ctx_t *, char *, size_t, 245*0Sstevel@tonic-gate crypto_data_t *); 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate static crypto_kcf_provider_handle_t blowfish_prov_handle = NULL; 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate int 250*0Sstevel@tonic-gate _init(void) 251*0Sstevel@tonic-gate { 252*0Sstevel@tonic-gate int ret; 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate /* 255*0Sstevel@tonic-gate * Register with KCF. If the registration fails, return error. 256*0Sstevel@tonic-gate */ 257*0Sstevel@tonic-gate if ((ret = crypto_register_provider(&blowfish_prov_info, 258*0Sstevel@tonic-gate &blowfish_prov_handle)) != CRYPTO_SUCCESS) { 259*0Sstevel@tonic-gate cmn_err(CE_WARN, "%s _init: crypto_register_provider() " 260*0Sstevel@tonic-gate "failed (0x%x)", CRYPTO_PROVIDER_NAME, ret); 261*0Sstevel@tonic-gate return (EACCES); 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate if ((ret = mod_install(&modlinkage)) != 0) { 265*0Sstevel@tonic-gate int rv; 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate ASSERT(blowfish_prov_handle != NULL); 268*0Sstevel@tonic-gate /* We should not return if the unregister returns busy. */ 269*0Sstevel@tonic-gate while ((rv = crypto_unregister_provider(blowfish_prov_handle)) 270*0Sstevel@tonic-gate == CRYPTO_BUSY) { 271*0Sstevel@tonic-gate cmn_err(CE_WARN, 272*0Sstevel@tonic-gate "%s _init: crypto_unregister_provider() " 273*0Sstevel@tonic-gate "failed (0x%x). Retrying.", 274*0Sstevel@tonic-gate CRYPTO_PROVIDER_NAME, rv); 275*0Sstevel@tonic-gate /* wait 10 seconds and try again */ 276*0Sstevel@tonic-gate delay(10 * drv_usectohz(1000000)); 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate return (ret); 281*0Sstevel@tonic-gate } 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate int 284*0Sstevel@tonic-gate _fini(void) 285*0Sstevel@tonic-gate { 286*0Sstevel@tonic-gate int ret; 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate /* 289*0Sstevel@tonic-gate * Unregister from KCF if previous registration succeeded. 290*0Sstevel@tonic-gate */ 291*0Sstevel@tonic-gate if (blowfish_prov_handle != NULL) { 292*0Sstevel@tonic-gate if ((ret = crypto_unregister_provider(blowfish_prov_handle)) != 293*0Sstevel@tonic-gate CRYPTO_SUCCESS) { 294*0Sstevel@tonic-gate cmn_err(CE_WARN, 295*0Sstevel@tonic-gate "%s _fini: crypto_unregister_provider() " 296*0Sstevel@tonic-gate "failed (0x%x)", CRYPTO_PROVIDER_NAME, ret); 297*0Sstevel@tonic-gate return (EBUSY); 298*0Sstevel@tonic-gate } 299*0Sstevel@tonic-gate blowfish_prov_handle = NULL; 300*0Sstevel@tonic-gate } 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate return (mod_remove(&modlinkage)); 303*0Sstevel@tonic-gate } 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate int 306*0Sstevel@tonic-gate _info(struct modinfo *modinfop) 307*0Sstevel@tonic-gate { 308*0Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 309*0Sstevel@tonic-gate } 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate /* 312*0Sstevel@tonic-gate * Initialize key schedules for blowfish 313*0Sstevel@tonic-gate */ 314*0Sstevel@tonic-gate static int 315*0Sstevel@tonic-gate init_keysched(crypto_key_t *key, void *keysched) 316*0Sstevel@tonic-gate { 317*0Sstevel@tonic-gate /* EXPORT DELETE START */ 318*0Sstevel@tonic-gate /* 319*0Sstevel@tonic-gate * Only keys by value are supported by this module. 320*0Sstevel@tonic-gate */ 321*0Sstevel@tonic-gate switch (key->ck_format) { 322*0Sstevel@tonic-gate case CRYPTO_KEY_RAW: 323*0Sstevel@tonic-gate if (key->ck_length < BLOWFISH_MINBITS || 324*0Sstevel@tonic-gate key->ck_length > BLOWFISH_MAXBITS) { 325*0Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE); 326*0Sstevel@tonic-gate } 327*0Sstevel@tonic-gate break; 328*0Sstevel@tonic-gate default: 329*0Sstevel@tonic-gate return (CRYPTO_KEY_TYPE_INCONSISTENT); 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate blowfish_init_keysched(key->ck_data, key->ck_length, keysched); 333*0Sstevel@tonic-gate /* EXPORT DELETE END */ 334*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 335*0Sstevel@tonic-gate } 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate /* 338*0Sstevel@tonic-gate * KCF software provider control entry points. 339*0Sstevel@tonic-gate */ 340*0Sstevel@tonic-gate /* ARGSUSED */ 341*0Sstevel@tonic-gate static void 342*0Sstevel@tonic-gate blowfish_provider_status(crypto_provider_handle_t provider, uint_t *status) 343*0Sstevel@tonic-gate { 344*0Sstevel@tonic-gate *status = CRYPTO_PROVIDER_READY; 345*0Sstevel@tonic-gate } 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate /* 348*0Sstevel@tonic-gate * KCF software provider encrypt entry points. 349*0Sstevel@tonic-gate */ 350*0Sstevel@tonic-gate static int 351*0Sstevel@tonic-gate blowfish_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 352*0Sstevel@tonic-gate crypto_key_t *key, crypto_spi_ctx_template_t template, 353*0Sstevel@tonic-gate crypto_req_handle_t req) 354*0Sstevel@tonic-gate { 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate /* EXPORT DELETE START */ 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate blowfish_ctx_t *blowfish_ctx; 359*0Sstevel@tonic-gate int rv; 360*0Sstevel@tonic-gate int kmflag; 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate /* 363*0Sstevel@tonic-gate * Only keys by value are supported by this module. 364*0Sstevel@tonic-gate */ 365*0Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) { 366*0Sstevel@tonic-gate return (CRYPTO_KEY_TYPE_INCONSISTENT); 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate if (!BLOWFISH_VALID_MECH(mechanism)) 370*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate if (mechanism->cm_param != NULL && 373*0Sstevel@tonic-gate mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 374*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_PARAM_INVALID); 375*0Sstevel@tonic-gate 376*0Sstevel@tonic-gate /* 377*0Sstevel@tonic-gate * Allocate a blowfish context. 378*0Sstevel@tonic-gate */ 379*0Sstevel@tonic-gate kmflag = crypto_kmflag(req); 380*0Sstevel@tonic-gate blowfish_ctx = kmem_zalloc(sizeof (blowfish_ctx_t), kmflag); 381*0Sstevel@tonic-gate if (blowfish_ctx == NULL) 382*0Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate rv = blowfish_common_init_ctx(blowfish_ctx, template, mechanism, 385*0Sstevel@tonic-gate key, kmflag); 386*0Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 387*0Sstevel@tonic-gate kmem_free(blowfish_ctx, sizeof (blowfish_ctx_t)); 388*0Sstevel@tonic-gate return (rv); 389*0Sstevel@tonic-gate } 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate ctx->cc_provider_private = blowfish_ctx; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate /* EXPORT DELETE END */ 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 396*0Sstevel@tonic-gate } 397*0Sstevel@tonic-gate 398*0Sstevel@tonic-gate /* 399*0Sstevel@tonic-gate * Helper blowfish encrypt update function for iov input data. 400*0Sstevel@tonic-gate */ 401*0Sstevel@tonic-gate static int 402*0Sstevel@tonic-gate blowfish_cipher_update_iov(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input, 403*0Sstevel@tonic-gate crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t, 404*0Sstevel@tonic-gate crypto_data_t *)) 405*0Sstevel@tonic-gate { 406*0Sstevel@tonic-gate if (input->cd_miscdata != NULL) { 407*0Sstevel@tonic-gate if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) { 408*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 409*0Sstevel@tonic-gate blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata; 410*0Sstevel@tonic-gate } else { 411*0Sstevel@tonic-gate uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0]; 412*0Sstevel@tonic-gate uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate BLOWFISH_COPY_BLOCK(miscdata8, iv8); 415*0Sstevel@tonic-gate } 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate if (input->cd_raw.iov_len < input->cd_length) 419*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate return (cipher)(blowfish_ctx, input->cd_raw.iov_base + input->cd_offset, 422*0Sstevel@tonic-gate input->cd_length, (input == output) ? NULL : output); 423*0Sstevel@tonic-gate } 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate /* 426*0Sstevel@tonic-gate * Helper blowfish encrypt update function for uio input data. 427*0Sstevel@tonic-gate */ 428*0Sstevel@tonic-gate static int 429*0Sstevel@tonic-gate blowfish_cipher_update_uio(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input, 430*0Sstevel@tonic-gate crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t, 431*0Sstevel@tonic-gate crypto_data_t *)) 432*0Sstevel@tonic-gate { 433*0Sstevel@tonic-gate uio_t *uiop = input->cd_uio; 434*0Sstevel@tonic-gate off_t offset = input->cd_offset; 435*0Sstevel@tonic-gate size_t length = input->cd_length; 436*0Sstevel@tonic-gate uint_t vec_idx; 437*0Sstevel@tonic-gate size_t cur_len; 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate if (input->cd_miscdata != NULL) { 440*0Sstevel@tonic-gate if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) { 441*0Sstevel@tonic-gate /*LINTED: pointer alignment */ 442*0Sstevel@tonic-gate blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata; 443*0Sstevel@tonic-gate } else { 444*0Sstevel@tonic-gate uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0]; 445*0Sstevel@tonic-gate uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate BLOWFISH_COPY_BLOCK(miscdata8, iv8); 448*0Sstevel@tonic-gate } 449*0Sstevel@tonic-gate } 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate if (input->cd_uio->uio_segflg != UIO_SYSSPACE) { 452*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 453*0Sstevel@tonic-gate } 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate /* 456*0Sstevel@tonic-gate * Jump to the first iovec containing data to be 457*0Sstevel@tonic-gate * processed. 458*0Sstevel@tonic-gate */ 459*0Sstevel@tonic-gate for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && 460*0Sstevel@tonic-gate offset >= uiop->uio_iov[vec_idx].iov_len; 461*0Sstevel@tonic-gate offset -= uiop->uio_iov[vec_idx++].iov_len); 462*0Sstevel@tonic-gate if (vec_idx == uiop->uio_iovcnt) { 463*0Sstevel@tonic-gate /* 464*0Sstevel@tonic-gate * The caller specified an offset that is larger than the 465*0Sstevel@tonic-gate * total size of the buffers it provided. 466*0Sstevel@tonic-gate */ 467*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate /* 471*0Sstevel@tonic-gate * Now process the iovecs. 472*0Sstevel@tonic-gate */ 473*0Sstevel@tonic-gate while (vec_idx < uiop->uio_iovcnt && length > 0) { 474*0Sstevel@tonic-gate cur_len = MIN(uiop->uio_iov[vec_idx].iov_len - 475*0Sstevel@tonic-gate offset, length); 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate (cipher)(blowfish_ctx, uiop->uio_iov[vec_idx].iov_base + 478*0Sstevel@tonic-gate offset, cur_len, (input == output) ? NULL : output); 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate length -= cur_len; 481*0Sstevel@tonic-gate vec_idx++; 482*0Sstevel@tonic-gate offset = 0; 483*0Sstevel@tonic-gate } 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate if (vec_idx == uiop->uio_iovcnt && length > 0) { 486*0Sstevel@tonic-gate /* 487*0Sstevel@tonic-gate * The end of the specified iovec's was reached but 488*0Sstevel@tonic-gate * the length requested could not be processed, i.e. 489*0Sstevel@tonic-gate * The caller requested to digest more data than it provided. 490*0Sstevel@tonic-gate */ 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 496*0Sstevel@tonic-gate } 497*0Sstevel@tonic-gate 498*0Sstevel@tonic-gate /* 499*0Sstevel@tonic-gate * Helper blowfish encrypt update function for mblk input data. 500*0Sstevel@tonic-gate */ 501*0Sstevel@tonic-gate static int 502*0Sstevel@tonic-gate blowfish_cipher_update_mp(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input, 503*0Sstevel@tonic-gate crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t, 504*0Sstevel@tonic-gate crypto_data_t *)) 505*0Sstevel@tonic-gate { 506*0Sstevel@tonic-gate off_t offset = input->cd_offset; 507*0Sstevel@tonic-gate size_t length = input->cd_length; 508*0Sstevel@tonic-gate mblk_t *mp; 509*0Sstevel@tonic-gate size_t cur_len; 510*0Sstevel@tonic-gate 511*0Sstevel@tonic-gate if (input->cd_miscdata != NULL) { 512*0Sstevel@tonic-gate if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) { 513*0Sstevel@tonic-gate /*LINTED: pointer alignment */ 514*0Sstevel@tonic-gate blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata; 515*0Sstevel@tonic-gate } else { 516*0Sstevel@tonic-gate uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0]; 517*0Sstevel@tonic-gate uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate BLOWFISH_COPY_BLOCK(miscdata8, iv8); 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate } 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate /* 524*0Sstevel@tonic-gate * Jump to the first mblk_t containing data to be processed. 525*0Sstevel@tonic-gate */ 526*0Sstevel@tonic-gate for (mp = input->cd_mp; mp != NULL && offset >= MBLKL(mp); 527*0Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 528*0Sstevel@tonic-gate if (mp == NULL) { 529*0Sstevel@tonic-gate /* 530*0Sstevel@tonic-gate * The caller specified an offset that is larger than the 531*0Sstevel@tonic-gate * total size of the buffers it provided. 532*0Sstevel@tonic-gate */ 533*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 534*0Sstevel@tonic-gate } 535*0Sstevel@tonic-gate 536*0Sstevel@tonic-gate /* 537*0Sstevel@tonic-gate * Now do the processing on the mblk chain. 538*0Sstevel@tonic-gate */ 539*0Sstevel@tonic-gate while (mp != NULL && length > 0) { 540*0Sstevel@tonic-gate cur_len = MIN(MBLKL(mp) - offset, length); 541*0Sstevel@tonic-gate (cipher)(blowfish_ctx, (char *)(mp->b_rptr + offset), cur_len, 542*0Sstevel@tonic-gate (input == output) ? NULL : output); 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate length -= cur_len; 545*0Sstevel@tonic-gate offset = 0; 546*0Sstevel@tonic-gate mp = mp->b_cont; 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate if (mp == NULL && length > 0) { 550*0Sstevel@tonic-gate /* 551*0Sstevel@tonic-gate * The end of the mblk was reached but the length requested 552*0Sstevel@tonic-gate * could not be processed, i.e. The caller requested 553*0Sstevel@tonic-gate * to digest more data than it provided. 554*0Sstevel@tonic-gate */ 555*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 556*0Sstevel@tonic-gate } 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 559*0Sstevel@tonic-gate } 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate /* ARGSUSED */ 562*0Sstevel@tonic-gate static int 563*0Sstevel@tonic-gate blowfish_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext, 564*0Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_req_handle_t req) 565*0Sstevel@tonic-gate { 566*0Sstevel@tonic-gate int ret; 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate /* EXPORT DELETE START */ 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate blowfish_ctx_t *blowfish_ctx; 571*0Sstevel@tonic-gate 572*0Sstevel@tonic-gate /* 573*0Sstevel@tonic-gate * Plaintext must be a multiple of blowfish block size. 574*0Sstevel@tonic-gate * This test only works for non-padded mechanisms 575*0Sstevel@tonic-gate * when blocksize is 2^N. 576*0Sstevel@tonic-gate */ 577*0Sstevel@tonic-gate if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 578*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 581*0Sstevel@tonic-gate blowfish_ctx = ctx->cc_provider_private; 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate /* 586*0Sstevel@tonic-gate * We need to just return the length needed to store the output. 587*0Sstevel@tonic-gate * We should not destroy the context for the following case. 588*0Sstevel@tonic-gate */ 589*0Sstevel@tonic-gate if (ciphertext->cd_length < plaintext->cd_length) { 590*0Sstevel@tonic-gate ciphertext->cd_length = plaintext->cd_length; 591*0Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate /* 595*0Sstevel@tonic-gate * Do an update on the specified input data. 596*0Sstevel@tonic-gate */ 597*0Sstevel@tonic-gate ret = blowfish_encrypt_update(ctx, plaintext, ciphertext, req); 598*0Sstevel@tonic-gate ASSERT(blowfish_ctx->bc_remainder_len == 0); 599*0Sstevel@tonic-gate (void) blowfish_free_context(ctx); 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate /* EXPORT DELETE END */ 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate /* LINTED */ 604*0Sstevel@tonic-gate return (ret); 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate /* ARGSUSED */ 608*0Sstevel@tonic-gate static int 609*0Sstevel@tonic-gate blowfish_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 610*0Sstevel@tonic-gate crypto_data_t *plaintext, crypto_req_handle_t req) 611*0Sstevel@tonic-gate { 612*0Sstevel@tonic-gate int ret; 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate /* EXPORT DELETE START */ 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate blowfish_ctx_t *blowfish_ctx; 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate /* 619*0Sstevel@tonic-gate * Ciphertext must be a multiple of blowfish block size. 620*0Sstevel@tonic-gate * This test only works for non-padded mechanisms 621*0Sstevel@tonic-gate * when blocksize is 2^N. 622*0Sstevel@tonic-gate */ 623*0Sstevel@tonic-gate if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 624*0Sstevel@tonic-gate return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 625*0Sstevel@tonic-gate 626*0Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 627*0Sstevel@tonic-gate blowfish_ctx = ctx->cc_provider_private; 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 630*0Sstevel@tonic-gate 631*0Sstevel@tonic-gate /* 632*0Sstevel@tonic-gate * We need to just return the length needed to store the output. 633*0Sstevel@tonic-gate * We should not destroy the context for the following case. 634*0Sstevel@tonic-gate */ 635*0Sstevel@tonic-gate if (plaintext->cd_length < ciphertext->cd_length) { 636*0Sstevel@tonic-gate plaintext->cd_length = ciphertext->cd_length; 637*0Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 638*0Sstevel@tonic-gate } 639*0Sstevel@tonic-gate 640*0Sstevel@tonic-gate /* 641*0Sstevel@tonic-gate * Do an update on the specified input data. 642*0Sstevel@tonic-gate */ 643*0Sstevel@tonic-gate ret = blowfish_decrypt_update(ctx, ciphertext, plaintext, req); 644*0Sstevel@tonic-gate ASSERT(blowfish_ctx->bc_remainder_len == 0); 645*0Sstevel@tonic-gate (void) blowfish_free_context(ctx); 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate /* EXPORT DELETE END */ 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate /* LINTED */ 650*0Sstevel@tonic-gate return (ret); 651*0Sstevel@tonic-gate } 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate /* ARGSUSED */ 654*0Sstevel@tonic-gate static int 655*0Sstevel@tonic-gate blowfish_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext, 656*0Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_req_handle_t req) 657*0Sstevel@tonic-gate { 658*0Sstevel@tonic-gate off_t saved_offset; 659*0Sstevel@tonic-gate size_t saved_length, out_len; 660*0Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 663*0Sstevel@tonic-gate 664*0Sstevel@tonic-gate BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate /* compute number of bytes that will hold the ciphertext */ 667*0Sstevel@tonic-gate out_len = 668*0Sstevel@tonic-gate ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len; 669*0Sstevel@tonic-gate out_len += plaintext->cd_length; 670*0Sstevel@tonic-gate out_len &= ~(BLOWFISH_BLOCK_LEN - 1); 671*0Sstevel@tonic-gate 672*0Sstevel@tonic-gate /* return length needed to store the output */ 673*0Sstevel@tonic-gate if (ciphertext->cd_length < out_len) { 674*0Sstevel@tonic-gate ciphertext->cd_length = out_len; 675*0Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 676*0Sstevel@tonic-gate } 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate saved_offset = ciphertext->cd_offset; 679*0Sstevel@tonic-gate saved_length = ciphertext->cd_length; 680*0Sstevel@tonic-gate 681*0Sstevel@tonic-gate /* 682*0Sstevel@tonic-gate * Do the blowfish update on the specified input data. 683*0Sstevel@tonic-gate */ 684*0Sstevel@tonic-gate switch (plaintext->cd_format) { 685*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 686*0Sstevel@tonic-gate ret = blowfish_cipher_update_iov(ctx->cc_provider_private, 687*0Sstevel@tonic-gate plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 688*0Sstevel@tonic-gate break; 689*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 690*0Sstevel@tonic-gate ret = blowfish_cipher_update_uio(ctx->cc_provider_private, 691*0Sstevel@tonic-gate plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 692*0Sstevel@tonic-gate break; 693*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 694*0Sstevel@tonic-gate ret = blowfish_cipher_update_mp(ctx->cc_provider_private, 695*0Sstevel@tonic-gate plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 696*0Sstevel@tonic-gate break; 697*0Sstevel@tonic-gate default: 698*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 699*0Sstevel@tonic-gate } 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 702*0Sstevel@tonic-gate if (plaintext != ciphertext) 703*0Sstevel@tonic-gate ciphertext->cd_length = 704*0Sstevel@tonic-gate ciphertext->cd_offset - saved_offset; 705*0Sstevel@tonic-gate } else { 706*0Sstevel@tonic-gate ciphertext->cd_length = saved_length; 707*0Sstevel@tonic-gate } 708*0Sstevel@tonic-gate ciphertext->cd_offset = saved_offset; 709*0Sstevel@tonic-gate 710*0Sstevel@tonic-gate return (ret); 711*0Sstevel@tonic-gate } 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate /* ARGSUSED */ 714*0Sstevel@tonic-gate static int 715*0Sstevel@tonic-gate blowfish_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 716*0Sstevel@tonic-gate crypto_data_t *plaintext, crypto_req_handle_t req) 717*0Sstevel@tonic-gate { 718*0Sstevel@tonic-gate off_t saved_offset; 719*0Sstevel@tonic-gate size_t saved_length, out_len; 720*0Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 723*0Sstevel@tonic-gate 724*0Sstevel@tonic-gate BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate /* compute number of bytes that will hold the plaintext */ 727*0Sstevel@tonic-gate out_len = 728*0Sstevel@tonic-gate ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len; 729*0Sstevel@tonic-gate out_len += ciphertext->cd_length; 730*0Sstevel@tonic-gate out_len &= ~(BLOWFISH_BLOCK_LEN - 1); 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate /* return length needed to store the output */ 733*0Sstevel@tonic-gate if (plaintext->cd_length < out_len) { 734*0Sstevel@tonic-gate plaintext->cd_length = out_len; 735*0Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 736*0Sstevel@tonic-gate } 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate saved_offset = plaintext->cd_offset; 739*0Sstevel@tonic-gate saved_length = plaintext->cd_length; 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate /* 742*0Sstevel@tonic-gate * Do the blowfish update on the specified input data. 743*0Sstevel@tonic-gate */ 744*0Sstevel@tonic-gate switch (ciphertext->cd_format) { 745*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 746*0Sstevel@tonic-gate ret = blowfish_cipher_update_iov(ctx->cc_provider_private, 747*0Sstevel@tonic-gate ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 748*0Sstevel@tonic-gate break; 749*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 750*0Sstevel@tonic-gate ret = blowfish_cipher_update_uio(ctx->cc_provider_private, 751*0Sstevel@tonic-gate ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 752*0Sstevel@tonic-gate break; 753*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 754*0Sstevel@tonic-gate ret = blowfish_cipher_update_mp(ctx->cc_provider_private, 755*0Sstevel@tonic-gate ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 756*0Sstevel@tonic-gate break; 757*0Sstevel@tonic-gate default: 758*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 759*0Sstevel@tonic-gate } 760*0Sstevel@tonic-gate 761*0Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 762*0Sstevel@tonic-gate if (ciphertext != plaintext) 763*0Sstevel@tonic-gate plaintext->cd_length = 764*0Sstevel@tonic-gate plaintext->cd_offset - saved_offset; 765*0Sstevel@tonic-gate } else { 766*0Sstevel@tonic-gate plaintext->cd_length = saved_length; 767*0Sstevel@tonic-gate } 768*0Sstevel@tonic-gate plaintext->cd_offset = saved_offset; 769*0Sstevel@tonic-gate 770*0Sstevel@tonic-gate return (ret); 771*0Sstevel@tonic-gate } 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate /* ARGSUSED */ 774*0Sstevel@tonic-gate static int 775*0Sstevel@tonic-gate blowfish_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data, 776*0Sstevel@tonic-gate crypto_req_handle_t req) 777*0Sstevel@tonic-gate { 778*0Sstevel@tonic-gate 779*0Sstevel@tonic-gate /* EXPORT DELETE START */ 780*0Sstevel@tonic-gate 781*0Sstevel@tonic-gate blowfish_ctx_t *blowfish_ctx; 782*0Sstevel@tonic-gate 783*0Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 784*0Sstevel@tonic-gate blowfish_ctx = ctx->cc_provider_private; 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate /* 787*0Sstevel@tonic-gate * There must be no unprocessed data. 788*0Sstevel@tonic-gate * This happens if the length of the last data is 789*0Sstevel@tonic-gate * not a multiple of the BLOWFISH block length. 790*0Sstevel@tonic-gate */ 791*0Sstevel@tonic-gate if (blowfish_ctx->bc_remainder_len > 0) 792*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 793*0Sstevel@tonic-gate 794*0Sstevel@tonic-gate (void) blowfish_free_context(ctx); 795*0Sstevel@tonic-gate data->cd_length = 0; 796*0Sstevel@tonic-gate 797*0Sstevel@tonic-gate /* EXPORT DELETE END */ 798*0Sstevel@tonic-gate 799*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 800*0Sstevel@tonic-gate } 801*0Sstevel@tonic-gate 802*0Sstevel@tonic-gate /* ARGSUSED */ 803*0Sstevel@tonic-gate static int 804*0Sstevel@tonic-gate blowfish_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data, 805*0Sstevel@tonic-gate crypto_req_handle_t req) 806*0Sstevel@tonic-gate { 807*0Sstevel@tonic-gate 808*0Sstevel@tonic-gate /* EXPORT DELETE START */ 809*0Sstevel@tonic-gate 810*0Sstevel@tonic-gate blowfish_ctx_t *blowfish_ctx; 811*0Sstevel@tonic-gate 812*0Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 813*0Sstevel@tonic-gate blowfish_ctx = ctx->cc_provider_private; 814*0Sstevel@tonic-gate 815*0Sstevel@tonic-gate /* 816*0Sstevel@tonic-gate * There must be no unprocessed ciphertext. 817*0Sstevel@tonic-gate * This happens if the length of the last ciphertext is 818*0Sstevel@tonic-gate * not a multiple of the BLOWFISH block length. 819*0Sstevel@tonic-gate */ 820*0Sstevel@tonic-gate if (blowfish_ctx->bc_remainder_len > 0) 821*0Sstevel@tonic-gate return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 822*0Sstevel@tonic-gate 823*0Sstevel@tonic-gate (void) blowfish_free_context(ctx); 824*0Sstevel@tonic-gate data->cd_length = 0; 825*0Sstevel@tonic-gate 826*0Sstevel@tonic-gate /* EXPORT DELETE END */ 827*0Sstevel@tonic-gate 828*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 829*0Sstevel@tonic-gate } 830*0Sstevel@tonic-gate 831*0Sstevel@tonic-gate /* ARGSUSED */ 832*0Sstevel@tonic-gate static int 833*0Sstevel@tonic-gate blowfish_encrypt_atomic(crypto_provider_handle_t provider, 834*0Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 835*0Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext, 836*0Sstevel@tonic-gate crypto_spi_ctx_template_t template, crypto_req_handle_t req) 837*0Sstevel@tonic-gate { 838*0Sstevel@tonic-gate blowfish_ctx_t blowfish_ctx; /* on the stack */ 839*0Sstevel@tonic-gate off_t saved_offset; 840*0Sstevel@tonic-gate size_t saved_length; 841*0Sstevel@tonic-gate int ret; 842*0Sstevel@tonic-gate 843*0Sstevel@tonic-gate BLOWFISH_ARG_INPLACE(plaintext, ciphertext); 844*0Sstevel@tonic-gate 845*0Sstevel@tonic-gate /* 846*0Sstevel@tonic-gate * Plaintext must be a multiple of blowfish block size. 847*0Sstevel@tonic-gate * This test only works for non-padded mechanisms 848*0Sstevel@tonic-gate * when blocksize is 2^N. 849*0Sstevel@tonic-gate */ 850*0Sstevel@tonic-gate if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 851*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 852*0Sstevel@tonic-gate 853*0Sstevel@tonic-gate /* return length needed to store the output */ 854*0Sstevel@tonic-gate if (ciphertext->cd_length < plaintext->cd_length) { 855*0Sstevel@tonic-gate ciphertext->cd_length = plaintext->cd_length; 856*0Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 857*0Sstevel@tonic-gate } 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate if (!BLOWFISH_VALID_MECH(mechanism)) 860*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 861*0Sstevel@tonic-gate 862*0Sstevel@tonic-gate if (mechanism->cm_param_len != 0 && 863*0Sstevel@tonic-gate mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 864*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_PARAM_INVALID); 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate bzero(&blowfish_ctx, sizeof (blowfish_ctx_t)); 867*0Sstevel@tonic-gate 868*0Sstevel@tonic-gate ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism, 869*0Sstevel@tonic-gate key, crypto_kmflag(req)); 870*0Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) 871*0Sstevel@tonic-gate return (ret); 872*0Sstevel@tonic-gate 873*0Sstevel@tonic-gate saved_offset = ciphertext->cd_offset; 874*0Sstevel@tonic-gate saved_length = ciphertext->cd_length; 875*0Sstevel@tonic-gate 876*0Sstevel@tonic-gate /* 877*0Sstevel@tonic-gate * Do an update on the specified input data. 878*0Sstevel@tonic-gate */ 879*0Sstevel@tonic-gate switch (plaintext->cd_format) { 880*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 881*0Sstevel@tonic-gate ret = blowfish_cipher_update_iov(&blowfish_ctx, 882*0Sstevel@tonic-gate plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 883*0Sstevel@tonic-gate break; 884*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 885*0Sstevel@tonic-gate ret = blowfish_cipher_update_uio(&blowfish_ctx, 886*0Sstevel@tonic-gate plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 887*0Sstevel@tonic-gate break; 888*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 889*0Sstevel@tonic-gate ret = blowfish_cipher_update_mp(&blowfish_ctx, 890*0Sstevel@tonic-gate plaintext, ciphertext, blowfish_encrypt_contiguous_blocks); 891*0Sstevel@tonic-gate break; 892*0Sstevel@tonic-gate default: 893*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 894*0Sstevel@tonic-gate } 895*0Sstevel@tonic-gate 896*0Sstevel@tonic-gate if (blowfish_ctx.bc_flags & BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) { 897*0Sstevel@tonic-gate bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len); 898*0Sstevel@tonic-gate kmem_free(blowfish_ctx.bc_keysched, 899*0Sstevel@tonic-gate blowfish_ctx.bc_keysched_len); 900*0Sstevel@tonic-gate } 901*0Sstevel@tonic-gate 902*0Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 903*0Sstevel@tonic-gate ASSERT(blowfish_ctx.bc_remainder_len == 0); 904*0Sstevel@tonic-gate if (plaintext != ciphertext) 905*0Sstevel@tonic-gate ciphertext->cd_length = 906*0Sstevel@tonic-gate ciphertext->cd_offset - saved_offset; 907*0Sstevel@tonic-gate } else { 908*0Sstevel@tonic-gate ciphertext->cd_length = saved_length; 909*0Sstevel@tonic-gate } 910*0Sstevel@tonic-gate ciphertext->cd_offset = saved_offset; 911*0Sstevel@tonic-gate 912*0Sstevel@tonic-gate return (ret); 913*0Sstevel@tonic-gate } 914*0Sstevel@tonic-gate 915*0Sstevel@tonic-gate /* ARGSUSED */ 916*0Sstevel@tonic-gate static int 917*0Sstevel@tonic-gate blowfish_decrypt_atomic(crypto_provider_handle_t provider, 918*0Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 919*0Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext, 920*0Sstevel@tonic-gate crypto_spi_ctx_template_t template, crypto_req_handle_t req) 921*0Sstevel@tonic-gate { 922*0Sstevel@tonic-gate blowfish_ctx_t blowfish_ctx; /* on the stack */ 923*0Sstevel@tonic-gate off_t saved_offset; 924*0Sstevel@tonic-gate size_t saved_length; 925*0Sstevel@tonic-gate int ret; 926*0Sstevel@tonic-gate 927*0Sstevel@tonic-gate BLOWFISH_ARG_INPLACE(ciphertext, plaintext); 928*0Sstevel@tonic-gate 929*0Sstevel@tonic-gate /* 930*0Sstevel@tonic-gate * Ciphertext must be a multiple of blowfish block size. 931*0Sstevel@tonic-gate * This test only works for non-padded mechanisms 932*0Sstevel@tonic-gate * when blocksize is 2^N. 933*0Sstevel@tonic-gate */ 934*0Sstevel@tonic-gate if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0) 935*0Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate /* return length needed to store the output */ 938*0Sstevel@tonic-gate if (plaintext->cd_length < ciphertext->cd_length) { 939*0Sstevel@tonic-gate plaintext->cd_length = ciphertext->cd_length; 940*0Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 941*0Sstevel@tonic-gate } 942*0Sstevel@tonic-gate 943*0Sstevel@tonic-gate if (!BLOWFISH_VALID_MECH(mechanism)) 944*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 945*0Sstevel@tonic-gate 946*0Sstevel@tonic-gate if (mechanism->cm_param_len != 0 && 947*0Sstevel@tonic-gate mechanism->cm_param_len != BLOWFISH_BLOCK_LEN) 948*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_PARAM_INVALID); 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate bzero(&blowfish_ctx, sizeof (blowfish_ctx_t)); 951*0Sstevel@tonic-gate 952*0Sstevel@tonic-gate ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism, 953*0Sstevel@tonic-gate key, crypto_kmflag(req)); 954*0Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) 955*0Sstevel@tonic-gate return (ret); 956*0Sstevel@tonic-gate 957*0Sstevel@tonic-gate saved_offset = plaintext->cd_offset; 958*0Sstevel@tonic-gate saved_length = plaintext->cd_length; 959*0Sstevel@tonic-gate 960*0Sstevel@tonic-gate /* 961*0Sstevel@tonic-gate * Do an update on the specified input data. 962*0Sstevel@tonic-gate */ 963*0Sstevel@tonic-gate switch (ciphertext->cd_format) { 964*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 965*0Sstevel@tonic-gate ret = blowfish_cipher_update_iov(&blowfish_ctx, 966*0Sstevel@tonic-gate ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 967*0Sstevel@tonic-gate break; 968*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: 969*0Sstevel@tonic-gate ret = blowfish_cipher_update_uio(&blowfish_ctx, 970*0Sstevel@tonic-gate ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 971*0Sstevel@tonic-gate break; 972*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 973*0Sstevel@tonic-gate ret = blowfish_cipher_update_mp(&blowfish_ctx, 974*0Sstevel@tonic-gate ciphertext, plaintext, blowfish_decrypt_contiguous_blocks); 975*0Sstevel@tonic-gate break; 976*0Sstevel@tonic-gate default: 977*0Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 978*0Sstevel@tonic-gate } 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate if (blowfish_ctx.bc_flags & BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) { 981*0Sstevel@tonic-gate bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len); 982*0Sstevel@tonic-gate kmem_free(blowfish_ctx.bc_keysched, 983*0Sstevel@tonic-gate blowfish_ctx.bc_keysched_len); 984*0Sstevel@tonic-gate } 985*0Sstevel@tonic-gate 986*0Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 987*0Sstevel@tonic-gate ASSERT(blowfish_ctx.bc_remainder_len == 0); 988*0Sstevel@tonic-gate if (ciphertext != plaintext) 989*0Sstevel@tonic-gate plaintext->cd_length = 990*0Sstevel@tonic-gate plaintext->cd_offset - saved_offset; 991*0Sstevel@tonic-gate } else { 992*0Sstevel@tonic-gate plaintext->cd_length = saved_length; 993*0Sstevel@tonic-gate } 994*0Sstevel@tonic-gate plaintext->cd_offset = saved_offset; 995*0Sstevel@tonic-gate 996*0Sstevel@tonic-gate return (ret); 997*0Sstevel@tonic-gate } 998*0Sstevel@tonic-gate 999*0Sstevel@tonic-gate /* 1000*0Sstevel@tonic-gate * KCF software provider context template entry points. 1001*0Sstevel@tonic-gate */ 1002*0Sstevel@tonic-gate /* ARGSUSED */ 1003*0Sstevel@tonic-gate static int 1004*0Sstevel@tonic-gate blowfish_create_ctx_template(crypto_provider_handle_t provider, 1005*0Sstevel@tonic-gate crypto_mechanism_t *mechanism, crypto_key_t *key, 1006*0Sstevel@tonic-gate crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req) 1007*0Sstevel@tonic-gate { 1008*0Sstevel@tonic-gate 1009*0Sstevel@tonic-gate /* EXPORT DELETE START */ 1010*0Sstevel@tonic-gate 1011*0Sstevel@tonic-gate void *keysched; 1012*0Sstevel@tonic-gate size_t size; 1013*0Sstevel@tonic-gate int rv; 1014*0Sstevel@tonic-gate 1015*0Sstevel@tonic-gate if (!BLOWFISH_VALID_MECH(mechanism)) 1016*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 1017*0Sstevel@tonic-gate 1018*0Sstevel@tonic-gate if ((keysched = blowfish_alloc_keysched(&size, 1019*0Sstevel@tonic-gate crypto_kmflag(req))) == NULL) { 1020*0Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 1021*0Sstevel@tonic-gate } 1022*0Sstevel@tonic-gate 1023*0Sstevel@tonic-gate /* 1024*0Sstevel@tonic-gate * Initialize key schedule. Key length information is stored 1025*0Sstevel@tonic-gate * in the key. 1026*0Sstevel@tonic-gate */ 1027*0Sstevel@tonic-gate if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) { 1028*0Sstevel@tonic-gate bzero(keysched, size); 1029*0Sstevel@tonic-gate kmem_free(keysched, size); 1030*0Sstevel@tonic-gate return (rv); 1031*0Sstevel@tonic-gate } 1032*0Sstevel@tonic-gate 1033*0Sstevel@tonic-gate *tmpl = keysched; 1034*0Sstevel@tonic-gate *tmpl_size = size; 1035*0Sstevel@tonic-gate 1036*0Sstevel@tonic-gate /* EXPORT DELETE END */ 1037*0Sstevel@tonic-gate 1038*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 1039*0Sstevel@tonic-gate } 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate /* ARGSUSED */ 1042*0Sstevel@tonic-gate static int 1043*0Sstevel@tonic-gate blowfish_free_context(crypto_ctx_t *ctx) 1044*0Sstevel@tonic-gate { 1045*0Sstevel@tonic-gate blowfish_ctx_t *blowfish_ctx = ctx->cc_provider_private; 1046*0Sstevel@tonic-gate 1047*0Sstevel@tonic-gate if (blowfish_ctx != NULL) { 1048*0Sstevel@tonic-gate if (blowfish_ctx->bc_flags & 1049*0Sstevel@tonic-gate BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) { 1050*0Sstevel@tonic-gate ASSERT(blowfish_ctx->bc_keysched_len != 0); 1051*0Sstevel@tonic-gate bzero(blowfish_ctx->bc_keysched, 1052*0Sstevel@tonic-gate blowfish_ctx->bc_keysched_len); 1053*0Sstevel@tonic-gate kmem_free(blowfish_ctx->bc_keysched, 1054*0Sstevel@tonic-gate blowfish_ctx->bc_keysched_len); 1055*0Sstevel@tonic-gate } 1056*0Sstevel@tonic-gate kmem_free(blowfish_ctx, sizeof (blowfish_ctx_t)); 1057*0Sstevel@tonic-gate ctx->cc_provider_private = NULL; 1058*0Sstevel@tonic-gate } 1059*0Sstevel@tonic-gate 1060*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 1061*0Sstevel@tonic-gate } 1062*0Sstevel@tonic-gate 1063*0Sstevel@tonic-gate /* 1064*0Sstevel@tonic-gate * Initialize by setting iov_or_mp to point to the current iovec or mp, 1065*0Sstevel@tonic-gate * and by setting current_offset to an offset within the current iovec or mp . 1066*0Sstevel@tonic-gate */ 1067*0Sstevel@tonic-gate static void 1068*0Sstevel@tonic-gate blowfish_init_ptrs(crypto_data_t *out, void **iov_or_mp, 1069*0Sstevel@tonic-gate offset_t *current_offset) 1070*0Sstevel@tonic-gate { 1071*0Sstevel@tonic-gate offset_t offset; 1072*0Sstevel@tonic-gate 1073*0Sstevel@tonic-gate switch (out->cd_format) { 1074*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: 1075*0Sstevel@tonic-gate *current_offset = out->cd_offset; 1076*0Sstevel@tonic-gate break; 1077*0Sstevel@tonic-gate 1078*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: { 1079*0Sstevel@tonic-gate uio_t *uiop = out->cd_uio; 1080*0Sstevel@tonic-gate uint_t vec_idx; 1081*0Sstevel@tonic-gate 1082*0Sstevel@tonic-gate offset = out->cd_offset; 1083*0Sstevel@tonic-gate for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && 1084*0Sstevel@tonic-gate offset >= uiop->uio_iov[vec_idx].iov_len; 1085*0Sstevel@tonic-gate offset -= uiop->uio_iov[vec_idx++].iov_len); 1086*0Sstevel@tonic-gate 1087*0Sstevel@tonic-gate *current_offset = offset; 1088*0Sstevel@tonic-gate *iov_or_mp = (void *)(uintptr_t)vec_idx; 1089*0Sstevel@tonic-gate break; 1090*0Sstevel@tonic-gate } 1091*0Sstevel@tonic-gate 1092*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: { 1093*0Sstevel@tonic-gate mblk_t *mp; 1094*0Sstevel@tonic-gate 1095*0Sstevel@tonic-gate offset = out->cd_offset; 1096*0Sstevel@tonic-gate for (mp = out->cd_mp; mp != NULL && offset >= MBLKL(mp); 1097*0Sstevel@tonic-gate offset -= MBLKL(mp), mp = mp->b_cont); 1098*0Sstevel@tonic-gate 1099*0Sstevel@tonic-gate *current_offset = offset; 1100*0Sstevel@tonic-gate *iov_or_mp = mp; 1101*0Sstevel@tonic-gate break; 1102*0Sstevel@tonic-gate 1103*0Sstevel@tonic-gate } 1104*0Sstevel@tonic-gate } /* end switch */ 1105*0Sstevel@tonic-gate } 1106*0Sstevel@tonic-gate 1107*0Sstevel@tonic-gate /* 1108*0Sstevel@tonic-gate * Get pointers for where in the output to copy a block of encrypted or 1109*0Sstevel@tonic-gate * decrypted data. The iov_or_mp argument stores a pointer to the current 1110*0Sstevel@tonic-gate * iovec or mp, and offset stores an offset into the current iovec or mp. 1111*0Sstevel@tonic-gate */ 1112*0Sstevel@tonic-gate static void 1113*0Sstevel@tonic-gate blowfish_get_ptrs(crypto_data_t *out, void **iov_or_mp, 1114*0Sstevel@tonic-gate offset_t *current_offset, uint8_t **out_data_1, size_t *out_data_1_len, 1115*0Sstevel@tonic-gate uint8_t **out_data_2) 1116*0Sstevel@tonic-gate { 1117*0Sstevel@tonic-gate offset_t offset; 1118*0Sstevel@tonic-gate 1119*0Sstevel@tonic-gate switch (out->cd_format) { 1120*0Sstevel@tonic-gate case CRYPTO_DATA_RAW: { 1121*0Sstevel@tonic-gate iovec_t *iov; 1122*0Sstevel@tonic-gate 1123*0Sstevel@tonic-gate offset = *current_offset; 1124*0Sstevel@tonic-gate iov = &out->cd_raw; 1125*0Sstevel@tonic-gate if ((offset + BLOWFISH_BLOCK_LEN) <= iov->iov_len) { 1126*0Sstevel@tonic-gate /* one BLOWFISH block fits */ 1127*0Sstevel@tonic-gate *out_data_1 = (uint8_t *)iov->iov_base + offset; 1128*0Sstevel@tonic-gate *out_data_1_len = BLOWFISH_BLOCK_LEN; 1129*0Sstevel@tonic-gate *out_data_2 = NULL; 1130*0Sstevel@tonic-gate *current_offset = offset + BLOWFISH_BLOCK_LEN; 1131*0Sstevel@tonic-gate } 1132*0Sstevel@tonic-gate break; 1133*0Sstevel@tonic-gate } 1134*0Sstevel@tonic-gate 1135*0Sstevel@tonic-gate case CRYPTO_DATA_UIO: { 1136*0Sstevel@tonic-gate uio_t *uio = out->cd_uio; 1137*0Sstevel@tonic-gate iovec_t *iov; 1138*0Sstevel@tonic-gate offset_t offset; 1139*0Sstevel@tonic-gate uint_t vec_idx; 1140*0Sstevel@tonic-gate uint8_t *p; 1141*0Sstevel@tonic-gate 1142*0Sstevel@tonic-gate offset = *current_offset; 1143*0Sstevel@tonic-gate vec_idx = (uint_t)(uintptr_t)(*iov_or_mp); 1144*0Sstevel@tonic-gate iov = &uio->uio_iov[vec_idx]; 1145*0Sstevel@tonic-gate p = (uint8_t *)iov->iov_base + offset; 1146*0Sstevel@tonic-gate *out_data_1 = p; 1147*0Sstevel@tonic-gate 1148*0Sstevel@tonic-gate if (offset + BLOWFISH_BLOCK_LEN <= iov->iov_len) { 1149*0Sstevel@tonic-gate /* can fit one BLOWFISH block into this iov */ 1150*0Sstevel@tonic-gate *out_data_1_len = BLOWFISH_BLOCK_LEN; 1151*0Sstevel@tonic-gate *out_data_2 = NULL; 1152*0Sstevel@tonic-gate *current_offset = offset + BLOWFISH_BLOCK_LEN; 1153*0Sstevel@tonic-gate } else { 1154*0Sstevel@tonic-gate /* one BLOWFISH block spans two iovecs */ 1155*0Sstevel@tonic-gate *out_data_1_len = iov->iov_len - offset; 1156*0Sstevel@tonic-gate if (vec_idx == uio->uio_iovcnt) 1157*0Sstevel@tonic-gate return; 1158*0Sstevel@tonic-gate vec_idx++; 1159*0Sstevel@tonic-gate iov = &uio->uio_iov[vec_idx]; 1160*0Sstevel@tonic-gate *out_data_2 = (uint8_t *)iov->iov_base; 1161*0Sstevel@tonic-gate *current_offset = BLOWFISH_BLOCK_LEN - *out_data_1_len; 1162*0Sstevel@tonic-gate } 1163*0Sstevel@tonic-gate *iov_or_mp = (void *)(uintptr_t)vec_idx; 1164*0Sstevel@tonic-gate break; 1165*0Sstevel@tonic-gate } 1166*0Sstevel@tonic-gate 1167*0Sstevel@tonic-gate case CRYPTO_DATA_MBLK: { 1168*0Sstevel@tonic-gate mblk_t *mp; 1169*0Sstevel@tonic-gate uint8_t *p; 1170*0Sstevel@tonic-gate 1171*0Sstevel@tonic-gate offset = *current_offset; 1172*0Sstevel@tonic-gate mp = (mblk_t *)*iov_or_mp; 1173*0Sstevel@tonic-gate p = mp->b_rptr + offset; 1174*0Sstevel@tonic-gate *out_data_1 = p; 1175*0Sstevel@tonic-gate if ((p + BLOWFISH_BLOCK_LEN) <= mp->b_wptr) { 1176*0Sstevel@tonic-gate /* can fit one BLOWFISH block into this mblk */ 1177*0Sstevel@tonic-gate *out_data_1_len = BLOWFISH_BLOCK_LEN; 1178*0Sstevel@tonic-gate *out_data_2 = NULL; 1179*0Sstevel@tonic-gate *current_offset = offset + BLOWFISH_BLOCK_LEN; 1180*0Sstevel@tonic-gate } else { 1181*0Sstevel@tonic-gate /* one BLOWFISH block spans two mblks */ 1182*0Sstevel@tonic-gate *out_data_1_len = mp->b_wptr - p; 1183*0Sstevel@tonic-gate if ((mp = mp->b_cont) == NULL) 1184*0Sstevel@tonic-gate return; 1185*0Sstevel@tonic-gate *out_data_2 = mp->b_rptr; 1186*0Sstevel@tonic-gate *current_offset = BLOWFISH_BLOCK_LEN - *out_data_1_len; 1187*0Sstevel@tonic-gate } 1188*0Sstevel@tonic-gate *iov_or_mp = mp; 1189*0Sstevel@tonic-gate break; 1190*0Sstevel@tonic-gate } 1191*0Sstevel@tonic-gate } /* end switch */ 1192*0Sstevel@tonic-gate } 1193*0Sstevel@tonic-gate 1194*0Sstevel@tonic-gate /* 1195*0Sstevel@tonic-gate * Encrypt multiple blocks of data. 1196*0Sstevel@tonic-gate */ 1197*0Sstevel@tonic-gate static int 1198*0Sstevel@tonic-gate blowfish_encrypt_contiguous_blocks(blowfish_ctx_t *ctx, char *data, 1199*0Sstevel@tonic-gate size_t length, crypto_data_t *out) 1200*0Sstevel@tonic-gate { 1201*0Sstevel@tonic-gate /* EXPORT DELETE START */ 1202*0Sstevel@tonic-gate size_t remainder = length; 1203*0Sstevel@tonic-gate size_t need; 1204*0Sstevel@tonic-gate uint8_t *datap = (uint8_t *)data; 1205*0Sstevel@tonic-gate uint8_t *blockp; 1206*0Sstevel@tonic-gate uint8_t *lastp; 1207*0Sstevel@tonic-gate uint32_t tmp[2]; 1208*0Sstevel@tonic-gate void *iov_or_mp; 1209*0Sstevel@tonic-gate offset_t offset; 1210*0Sstevel@tonic-gate uint8_t *out_data_1; 1211*0Sstevel@tonic-gate uint8_t *out_data_2; 1212*0Sstevel@tonic-gate size_t out_data_1_len; 1213*0Sstevel@tonic-gate 1214*0Sstevel@tonic-gate if (length + ctx->bc_remainder_len < BLOWFISH_BLOCK_LEN) { 1215*0Sstevel@tonic-gate /* accumulate bytes here and return */ 1216*0Sstevel@tonic-gate bcopy(datap, 1217*0Sstevel@tonic-gate (uint8_t *)&ctx->bc_remainder + ctx->bc_remainder_len, 1218*0Sstevel@tonic-gate length); 1219*0Sstevel@tonic-gate ctx->bc_remainder_len += length; 1220*0Sstevel@tonic-gate ctx->bc_copy_to = datap; 1221*0Sstevel@tonic-gate return (0); 1222*0Sstevel@tonic-gate } 1223*0Sstevel@tonic-gate 1224*0Sstevel@tonic-gate lastp = (uint8_t *)&ctx->bc_iv; 1225*0Sstevel@tonic-gate if (out != NULL) 1226*0Sstevel@tonic-gate blowfish_init_ptrs(out, &iov_or_mp, &offset); 1227*0Sstevel@tonic-gate 1228*0Sstevel@tonic-gate do { 1229*0Sstevel@tonic-gate /* Unprocessed data from last call. */ 1230*0Sstevel@tonic-gate if (ctx->bc_remainder_len > 0) { 1231*0Sstevel@tonic-gate need = BLOWFISH_BLOCK_LEN - ctx->bc_remainder_len; 1232*0Sstevel@tonic-gate 1233*0Sstevel@tonic-gate if (need > remainder) 1234*0Sstevel@tonic-gate return (1); 1235*0Sstevel@tonic-gate 1236*0Sstevel@tonic-gate bcopy(datap, &((uint8_t *)&ctx->bc_remainder) 1237*0Sstevel@tonic-gate [ctx->bc_remainder_len], need); 1238*0Sstevel@tonic-gate 1239*0Sstevel@tonic-gate blockp = (uint8_t *)&ctx->bc_remainder; 1240*0Sstevel@tonic-gate } else { 1241*0Sstevel@tonic-gate blockp = datap; 1242*0Sstevel@tonic-gate } 1243*0Sstevel@tonic-gate 1244*0Sstevel@tonic-gate /* don't write on the plaintext */ 1245*0Sstevel@tonic-gate if (out != NULL) { 1246*0Sstevel@tonic-gate if (IS_P2ALIGNED(blockp, sizeof (uint32_t))) { 1247*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1248*0Sstevel@tonic-gate tmp[0] = *(uint32_t *)blockp; 1249*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1250*0Sstevel@tonic-gate tmp[1] = *(uint32_t *)&blockp[4]; 1251*0Sstevel@tonic-gate } else { 1252*0Sstevel@tonic-gate #ifdef _BIG_ENDIAN 1253*0Sstevel@tonic-gate tmp[0] = (((uint32_t)blockp[0] << 24) | 1254*0Sstevel@tonic-gate ((uint32_t)blockp[1] << 16) | 1255*0Sstevel@tonic-gate ((uint32_t)blockp[2] << 8) | 1256*0Sstevel@tonic-gate (uint32_t)blockp[3]); 1257*0Sstevel@tonic-gate 1258*0Sstevel@tonic-gate tmp[1] = (((uint32_t)blockp[4] << 24) | 1259*0Sstevel@tonic-gate ((uint32_t)blockp[5] << 16) | 1260*0Sstevel@tonic-gate ((uint32_t)blockp[6] << 8) | 1261*0Sstevel@tonic-gate (uint32_t)blockp[7]); 1262*0Sstevel@tonic-gate #else 1263*0Sstevel@tonic-gate tmp[0] = (((uint32_t)blockp[7] << 24) | 1264*0Sstevel@tonic-gate ((uint32_t)blockp[6] << 16) | 1265*0Sstevel@tonic-gate ((uint32_t)blockp[5] << 8) | 1266*0Sstevel@tonic-gate (uint32_t)blockp[4]); 1267*0Sstevel@tonic-gate 1268*0Sstevel@tonic-gate tmp[1] = (((uint32_t)blockp[3] << 24) | 1269*0Sstevel@tonic-gate ((uint32_t)blockp[2] << 16) | 1270*0Sstevel@tonic-gate ((uint32_t)blockp[1] << 8) | 1271*0Sstevel@tonic-gate (uint32_t)blockp[0]); 1272*0Sstevel@tonic-gate #endif /* _BIG_ENDIAN */ 1273*0Sstevel@tonic-gate } 1274*0Sstevel@tonic-gate blockp = (uint8_t *)tmp; 1275*0Sstevel@tonic-gate } 1276*0Sstevel@tonic-gate 1277*0Sstevel@tonic-gate if (ctx->bc_flags & BLOWFISH_CBC_MODE) { 1278*0Sstevel@tonic-gate /* 1279*0Sstevel@tonic-gate * XOR the previous cipher block or IV with the 1280*0Sstevel@tonic-gate * current clear block. Check for alignment. 1281*0Sstevel@tonic-gate */ 1282*0Sstevel@tonic-gate if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) && 1283*0Sstevel@tonic-gate IS_P2ALIGNED(lastp, sizeof (uint32_t))) { 1284*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1285*0Sstevel@tonic-gate *(uint32_t *)&blockp[0] ^= 1286*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1287*0Sstevel@tonic-gate *(uint32_t *)&lastp[0]; 1288*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1289*0Sstevel@tonic-gate *(uint32_t *)&blockp[4] ^= 1290*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1291*0Sstevel@tonic-gate *(uint32_t *)&lastp[4]; 1292*0Sstevel@tonic-gate } else { 1293*0Sstevel@tonic-gate BLOWFISH_XOR_BLOCK(lastp, blockp); 1294*0Sstevel@tonic-gate } 1295*0Sstevel@tonic-gate } 1296*0Sstevel@tonic-gate 1297*0Sstevel@tonic-gate if (out == NULL) { 1298*0Sstevel@tonic-gate blowfish_encrypt_block(ctx->bc_keysched, blockp, 1299*0Sstevel@tonic-gate blockp); 1300*0Sstevel@tonic-gate 1301*0Sstevel@tonic-gate ctx->bc_lastp = blockp; 1302*0Sstevel@tonic-gate lastp = blockp; 1303*0Sstevel@tonic-gate 1304*0Sstevel@tonic-gate if (ctx->bc_remainder_len > 0) { 1305*0Sstevel@tonic-gate bcopy(blockp, ctx->bc_copy_to, 1306*0Sstevel@tonic-gate ctx->bc_remainder_len); 1307*0Sstevel@tonic-gate bcopy(blockp + ctx->bc_remainder_len, datap, 1308*0Sstevel@tonic-gate need); 1309*0Sstevel@tonic-gate } 1310*0Sstevel@tonic-gate } else { 1311*0Sstevel@tonic-gate blowfish_encrypt_block(ctx->bc_keysched, blockp, lastp); 1312*0Sstevel@tonic-gate blowfish_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 1313*0Sstevel@tonic-gate &out_data_1_len, &out_data_2); 1314*0Sstevel@tonic-gate 1315*0Sstevel@tonic-gate /* copy block to where it belongs */ 1316*0Sstevel@tonic-gate bcopy(lastp, out_data_1, out_data_1_len); 1317*0Sstevel@tonic-gate if (out_data_2 != NULL) { 1318*0Sstevel@tonic-gate bcopy(lastp + out_data_1_len, out_data_2, 1319*0Sstevel@tonic-gate BLOWFISH_BLOCK_LEN - out_data_1_len); 1320*0Sstevel@tonic-gate } 1321*0Sstevel@tonic-gate 1322*0Sstevel@tonic-gate /* update offset */ 1323*0Sstevel@tonic-gate out->cd_offset += BLOWFISH_BLOCK_LEN; 1324*0Sstevel@tonic-gate } 1325*0Sstevel@tonic-gate 1326*0Sstevel@tonic-gate /* Update pointer to next block of data to be processed. */ 1327*0Sstevel@tonic-gate if (ctx->bc_remainder_len != 0) { 1328*0Sstevel@tonic-gate datap += need; 1329*0Sstevel@tonic-gate ctx->bc_remainder_len = 0; 1330*0Sstevel@tonic-gate } else { 1331*0Sstevel@tonic-gate datap += BLOWFISH_BLOCK_LEN; 1332*0Sstevel@tonic-gate } 1333*0Sstevel@tonic-gate 1334*0Sstevel@tonic-gate remainder = (size_t)&data[length] - (size_t)datap; 1335*0Sstevel@tonic-gate 1336*0Sstevel@tonic-gate /* Incomplete last block. */ 1337*0Sstevel@tonic-gate if (remainder > 0 && remainder < BLOWFISH_BLOCK_LEN) { 1338*0Sstevel@tonic-gate bcopy(datap, &ctx->bc_remainder, remainder); 1339*0Sstevel@tonic-gate ctx->bc_remainder_len = remainder; 1340*0Sstevel@tonic-gate ctx->bc_copy_to = datap; 1341*0Sstevel@tonic-gate goto out; 1342*0Sstevel@tonic-gate } 1343*0Sstevel@tonic-gate ctx->bc_copy_to = NULL; 1344*0Sstevel@tonic-gate 1345*0Sstevel@tonic-gate } while (remainder > 0); 1346*0Sstevel@tonic-gate 1347*0Sstevel@tonic-gate out: 1348*0Sstevel@tonic-gate if (ctx->bc_lastp != NULL) { 1349*0Sstevel@tonic-gate if (IS_P2ALIGNED(ctx->bc_lastp, sizeof (uint32_t))) { 1350*0Sstevel@tonic-gate uint8_t *iv8 = (uint8_t *)&ctx->bc_iv; 1351*0Sstevel@tonic-gate uint8_t *last8 = (uint8_t *)ctx->bc_lastp; 1352*0Sstevel@tonic-gate 1353*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1354*0Sstevel@tonic-gate *(uint32_t *)iv8 = *(uint32_t *)last8; 1355*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1356*0Sstevel@tonic-gate *(uint32_t *)&iv8[4] = *(uint32_t *)&last8[4]; 1357*0Sstevel@tonic-gate } else { 1358*0Sstevel@tonic-gate uint8_t *iv8 = (uint8_t *)&ctx->bc_iv; 1359*0Sstevel@tonic-gate uint8_t *last8 = ctx->bc_lastp; 1360*0Sstevel@tonic-gate 1361*0Sstevel@tonic-gate BLOWFISH_COPY_BLOCK(last8, iv8); 1362*0Sstevel@tonic-gate } 1363*0Sstevel@tonic-gate ctx->bc_lastp = (uint8_t *)&ctx->bc_iv; 1364*0Sstevel@tonic-gate } 1365*0Sstevel@tonic-gate /* EXPORT DELETE END */ 1366*0Sstevel@tonic-gate 1367*0Sstevel@tonic-gate return (0); 1368*0Sstevel@tonic-gate } 1369*0Sstevel@tonic-gate 1370*0Sstevel@tonic-gate #define OTHER(a, ctx) \ 1371*0Sstevel@tonic-gate (((a) == &(ctx)->bc_lastblock) ? &(ctx)->bc_iv : &(ctx)->bc_lastblock) 1372*0Sstevel@tonic-gate 1373*0Sstevel@tonic-gate static int 1374*0Sstevel@tonic-gate blowfish_decrypt_contiguous_blocks(blowfish_ctx_t *ctx, char *data, 1375*0Sstevel@tonic-gate size_t length, crypto_data_t *out) 1376*0Sstevel@tonic-gate { 1377*0Sstevel@tonic-gate /* EXPORT DELETE START */ 1378*0Sstevel@tonic-gate size_t remainder = length; 1379*0Sstevel@tonic-gate size_t need; 1380*0Sstevel@tonic-gate uint8_t *datap = (uint8_t *)data; 1381*0Sstevel@tonic-gate uint8_t *blockp; 1382*0Sstevel@tonic-gate uint8_t *lastp; 1383*0Sstevel@tonic-gate uint32_t tmp[2]; 1384*0Sstevel@tonic-gate void *iov_or_mp; 1385*0Sstevel@tonic-gate offset_t offset; 1386*0Sstevel@tonic-gate uint8_t *out_data_1; 1387*0Sstevel@tonic-gate uint8_t *out_data_2; 1388*0Sstevel@tonic-gate size_t out_data_1_len; 1389*0Sstevel@tonic-gate 1390*0Sstevel@tonic-gate if (length + ctx->bc_remainder_len < BLOWFISH_BLOCK_LEN) { 1391*0Sstevel@tonic-gate /* accumulate bytes here and return */ 1392*0Sstevel@tonic-gate bcopy(datap, 1393*0Sstevel@tonic-gate (uint8_t *)&ctx->bc_remainder + ctx->bc_remainder_len, 1394*0Sstevel@tonic-gate length); 1395*0Sstevel@tonic-gate ctx->bc_remainder_len += length; 1396*0Sstevel@tonic-gate ctx->bc_copy_to = datap; 1397*0Sstevel@tonic-gate return (0); 1398*0Sstevel@tonic-gate } 1399*0Sstevel@tonic-gate 1400*0Sstevel@tonic-gate lastp = ctx->bc_lastp; 1401*0Sstevel@tonic-gate if (out != NULL) 1402*0Sstevel@tonic-gate blowfish_init_ptrs(out, &iov_or_mp, &offset); 1403*0Sstevel@tonic-gate 1404*0Sstevel@tonic-gate do { 1405*0Sstevel@tonic-gate /* Unprocessed data from last call. */ 1406*0Sstevel@tonic-gate if (ctx->bc_remainder_len > 0) { 1407*0Sstevel@tonic-gate need = BLOWFISH_BLOCK_LEN - ctx->bc_remainder_len; 1408*0Sstevel@tonic-gate 1409*0Sstevel@tonic-gate if (need > remainder) 1410*0Sstevel@tonic-gate return (1); 1411*0Sstevel@tonic-gate 1412*0Sstevel@tonic-gate bcopy(datap, &((uint8_t *)&ctx->bc_remainder) 1413*0Sstevel@tonic-gate [ctx->bc_remainder_len], need); 1414*0Sstevel@tonic-gate 1415*0Sstevel@tonic-gate blockp = (uint8_t *)&ctx->bc_remainder; 1416*0Sstevel@tonic-gate } else { 1417*0Sstevel@tonic-gate blockp = datap; 1418*0Sstevel@tonic-gate } 1419*0Sstevel@tonic-gate 1420*0Sstevel@tonic-gate if (ctx->bc_flags & BLOWFISH_CBC_MODE) { 1421*0Sstevel@tonic-gate 1422*0Sstevel@tonic-gate /* Save current ciphertext block */ 1423*0Sstevel@tonic-gate if (IS_P2ALIGNED(blockp, sizeof (uint32_t))) { 1424*0Sstevel@tonic-gate uint32_t *tmp32; 1425*0Sstevel@tonic-gate 1426*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1427*0Sstevel@tonic-gate tmp32 = (uint32_t *)OTHER((uint64_t *)lastp, 1428*0Sstevel@tonic-gate ctx); 1429*0Sstevel@tonic-gate 1430*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1431*0Sstevel@tonic-gate *tmp32++ = *(uint32_t *)blockp; 1432*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1433*0Sstevel@tonic-gate *tmp32++ = *(uint32_t *)&blockp[4]; 1434*0Sstevel@tonic-gate } else { 1435*0Sstevel@tonic-gate uint8_t *tmp8; 1436*0Sstevel@tonic-gate tmp8 = (uint8_t *)OTHER((uint64_t *)lastp, ctx); 1437*0Sstevel@tonic-gate 1438*0Sstevel@tonic-gate BLOWFISH_COPY_BLOCK(blockp, tmp8); 1439*0Sstevel@tonic-gate } 1440*0Sstevel@tonic-gate } 1441*0Sstevel@tonic-gate 1442*0Sstevel@tonic-gate if (out != NULL) { 1443*0Sstevel@tonic-gate blowfish_decrypt_block(ctx->bc_keysched, blockp, 1444*0Sstevel@tonic-gate (uint8_t *)tmp); 1445*0Sstevel@tonic-gate blockp = (uint8_t *)tmp; 1446*0Sstevel@tonic-gate } else { 1447*0Sstevel@tonic-gate blowfish_decrypt_block(ctx->bc_keysched, blockp, 1448*0Sstevel@tonic-gate blockp); 1449*0Sstevel@tonic-gate } 1450*0Sstevel@tonic-gate 1451*0Sstevel@tonic-gate if (ctx->bc_flags & BLOWFISH_CBC_MODE) { 1452*0Sstevel@tonic-gate /* 1453*0Sstevel@tonic-gate * XOR the previous cipher block or IV with the 1454*0Sstevel@tonic-gate * currently decrypted block. Check for alignment. 1455*0Sstevel@tonic-gate */ 1456*0Sstevel@tonic-gate if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) && 1457*0Sstevel@tonic-gate IS_P2ALIGNED(lastp, sizeof (uint32_t))) { 1458*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1459*0Sstevel@tonic-gate *(uint32_t *)blockp ^= *(uint32_t *)lastp; 1460*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1461*0Sstevel@tonic-gate *(uint32_t *)&blockp[4] ^= 1462*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1463*0Sstevel@tonic-gate *(uint32_t *)&lastp[4]; 1464*0Sstevel@tonic-gate } else { 1465*0Sstevel@tonic-gate BLOWFISH_XOR_BLOCK(lastp, blockp); 1466*0Sstevel@tonic-gate } 1467*0Sstevel@tonic-gate 1468*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1469*0Sstevel@tonic-gate lastp = (uint8_t *)OTHER((uint64_t *)lastp, ctx); 1470*0Sstevel@tonic-gate } 1471*0Sstevel@tonic-gate 1472*0Sstevel@tonic-gate if (out != NULL) { 1473*0Sstevel@tonic-gate blowfish_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 1474*0Sstevel@tonic-gate &out_data_1_len, &out_data_2); 1475*0Sstevel@tonic-gate /* copy temporary block to where it belongs */ 1476*0Sstevel@tonic-gate bcopy(&tmp, out_data_1, out_data_1_len); 1477*0Sstevel@tonic-gate if (out_data_2 != NULL) { 1478*0Sstevel@tonic-gate bcopy((uint8_t *)&tmp + out_data_1_len, 1479*0Sstevel@tonic-gate out_data_2, 1480*0Sstevel@tonic-gate BLOWFISH_BLOCK_LEN - out_data_1_len); 1481*0Sstevel@tonic-gate } 1482*0Sstevel@tonic-gate 1483*0Sstevel@tonic-gate /* update offset */ 1484*0Sstevel@tonic-gate out->cd_offset += BLOWFISH_BLOCK_LEN; 1485*0Sstevel@tonic-gate } else if (ctx->bc_remainder_len > 0) { 1486*0Sstevel@tonic-gate /* copy temporary block to where it belongs */ 1487*0Sstevel@tonic-gate bcopy(blockp, ctx->bc_copy_to, ctx->bc_remainder_len); 1488*0Sstevel@tonic-gate bcopy(blockp + ctx->bc_remainder_len, datap, need); 1489*0Sstevel@tonic-gate } 1490*0Sstevel@tonic-gate 1491*0Sstevel@tonic-gate /* Update pointer to next block of data to be processed. */ 1492*0Sstevel@tonic-gate if (ctx->bc_remainder_len != 0) { 1493*0Sstevel@tonic-gate datap += need; 1494*0Sstevel@tonic-gate ctx->bc_remainder_len = 0; 1495*0Sstevel@tonic-gate } else { 1496*0Sstevel@tonic-gate datap += BLOWFISH_BLOCK_LEN; 1497*0Sstevel@tonic-gate } 1498*0Sstevel@tonic-gate 1499*0Sstevel@tonic-gate remainder = (size_t)&data[length] - (size_t)datap; 1500*0Sstevel@tonic-gate 1501*0Sstevel@tonic-gate /* Incomplete last block. */ 1502*0Sstevel@tonic-gate if (remainder > 0 && remainder < BLOWFISH_BLOCK_LEN) { 1503*0Sstevel@tonic-gate bcopy(datap, (uchar_t *)&ctx->bc_remainder, remainder); 1504*0Sstevel@tonic-gate ctx->bc_remainder_len = remainder; 1505*0Sstevel@tonic-gate ctx->bc_lastp = lastp; 1506*0Sstevel@tonic-gate ctx->bc_copy_to = datap; 1507*0Sstevel@tonic-gate return (0); 1508*0Sstevel@tonic-gate } 1509*0Sstevel@tonic-gate ctx->bc_copy_to = NULL; 1510*0Sstevel@tonic-gate 1511*0Sstevel@tonic-gate } while (remainder > 0); 1512*0Sstevel@tonic-gate 1513*0Sstevel@tonic-gate ctx->bc_lastp = lastp; 1514*0Sstevel@tonic-gate /* EXPORT DELETE END */ 1515*0Sstevel@tonic-gate return (0); 1516*0Sstevel@tonic-gate } 1517*0Sstevel@tonic-gate 1518*0Sstevel@tonic-gate /* ARGSUSED */ 1519*0Sstevel@tonic-gate static int 1520*0Sstevel@tonic-gate blowfish_common_init_ctx(blowfish_ctx_t *blowfish_ctx, 1521*0Sstevel@tonic-gate crypto_spi_ctx_template_t *template, crypto_mechanism_t *mechanism, 1522*0Sstevel@tonic-gate crypto_key_t *key, int kmflag) 1523*0Sstevel@tonic-gate { 1524*0Sstevel@tonic-gate int rv = CRYPTO_SUCCESS; 1525*0Sstevel@tonic-gate 1526*0Sstevel@tonic-gate /* EXPORT DELETE START */ 1527*0Sstevel@tonic-gate 1528*0Sstevel@tonic-gate void *keysched; 1529*0Sstevel@tonic-gate size_t size; 1530*0Sstevel@tonic-gate 1531*0Sstevel@tonic-gate if (template == NULL) { 1532*0Sstevel@tonic-gate if ((keysched = blowfish_alloc_keysched(&size, kmflag)) == NULL) 1533*0Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 1534*0Sstevel@tonic-gate /* 1535*0Sstevel@tonic-gate * Initialize key schedule. 1536*0Sstevel@tonic-gate * Key length is stored in the key. 1537*0Sstevel@tonic-gate */ 1538*0Sstevel@tonic-gate if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) 1539*0Sstevel@tonic-gate kmem_free(keysched, size); 1540*0Sstevel@tonic-gate 1541*0Sstevel@tonic-gate blowfish_ctx->bc_flags = BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE; 1542*0Sstevel@tonic-gate blowfish_ctx->bc_keysched_len = size; 1543*0Sstevel@tonic-gate } else { 1544*0Sstevel@tonic-gate keysched = template; 1545*0Sstevel@tonic-gate } 1546*0Sstevel@tonic-gate 1547*0Sstevel@tonic-gate if (mechanism->cm_type == BF_CBC_MECH_INFO_TYPE) { 1548*0Sstevel@tonic-gate /* 1549*0Sstevel@tonic-gate * Copy IV into BLOWFISH context. 1550*0Sstevel@tonic-gate * 1551*0Sstevel@tonic-gate * If cm_param == NULL then the IV comes from the 1552*0Sstevel@tonic-gate * cd_miscdata field in the crypto_data structure. 1553*0Sstevel@tonic-gate */ 1554*0Sstevel@tonic-gate if (mechanism->cm_param != NULL) { 1555*0Sstevel@tonic-gate ASSERT(mechanism->cm_param_len == BLOWFISH_BLOCK_LEN); 1556*0Sstevel@tonic-gate if (IS_P2ALIGNED(mechanism->cm_param, 1557*0Sstevel@tonic-gate sizeof (uint64_t))) { 1558*0Sstevel@tonic-gate /* LINTED: pointer alignment */ 1559*0Sstevel@tonic-gate blowfish_ctx->bc_iv = 1560*0Sstevel@tonic-gate *(uint64_t *)mechanism->cm_param; 1561*0Sstevel@tonic-gate } else { 1562*0Sstevel@tonic-gate uint8_t *iv8; 1563*0Sstevel@tonic-gate uint8_t *p8; 1564*0Sstevel@tonic-gate iv8 = (uint8_t *)&blowfish_ctx->bc_iv; 1565*0Sstevel@tonic-gate p8 = (uint8_t *)&mechanism->cm_param[0]; 1566*0Sstevel@tonic-gate 1567*0Sstevel@tonic-gate BLOWFISH_COPY_BLOCK(p8, iv8); 1568*0Sstevel@tonic-gate } 1569*0Sstevel@tonic-gate } 1570*0Sstevel@tonic-gate 1571*0Sstevel@tonic-gate blowfish_ctx->bc_lastp = (uint8_t *)&blowfish_ctx->bc_iv; 1572*0Sstevel@tonic-gate blowfish_ctx->bc_flags |= BLOWFISH_CBC_MODE; 1573*0Sstevel@tonic-gate } 1574*0Sstevel@tonic-gate blowfish_ctx->bc_keysched = keysched; 1575*0Sstevel@tonic-gate 1576*0Sstevel@tonic-gate /* EXPORT DELETE END */ 1577*0Sstevel@tonic-gate 1578*0Sstevel@tonic-gate return (rv); 1579*0Sstevel@tonic-gate } 1580